[
  {
    "path": ".doc_autogeneration.doxygen",
    "content": "# Doxyfile 1.9.1\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the configuration\n# file that follow. The default is UTF-8 which is also the encoding used for all\n# text before the first occurrence of this tag. Doxygen uses libiconv (or the\n# iconv built into libc) for the transcoding. See\n# https://www.gnu.org/software/libiconv/ for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = OpenPose\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         = 1.7.0\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"The first real-time multi-person system to jointly detect human body, hand, facial, and foot keypoints\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           = .github/Logo_doxygen_black.png\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = doxygen\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all generated output in the proper direction.\n# Possible values are: None, LTR, RTL and Context.\n# The default value is: None.\n\nOUTPUT_TEXT_DIRECTION  = None\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        =\n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    =\n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = NO\n\n# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line\n# such as\n# /***************\n# as being the beginning of a Javadoc-style comment \"banner\". If set to NO, the\n# Javadoc-style will behave just like regular comments and it will not be\n# interpreted by doxygen.\n# The default value is: NO.\n\nJAVADOC_BANNER         = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = NO\n\n# By default Python docstrings are displayed as preformatted text and doxygen's\n# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the\n# doxygen's special commands can be used and the contents of the docstring\n# documentation blocks is shown as doxygen documentation.\n# The default value is: YES.\n\nPYTHON_DOCSTRING       = YES\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 4\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines (in the resulting output). You can put ^^ in the value part of an\n# alias to insert a newline as if a physical newline was in the original file.\n# When you need a literal { or } or , in the value part of an alias you have to\n# escape them by means of a backslash (\\), this can lead to conflicts with the\n# commands \\{ and \\} for these it is advised to use the version @{ and @} or use\n# a double escape (\\\\{ and \\\\})\n\nALIASES                =\n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice\n# sources only. Doxygen will then generate output that is more tailored for that\n# language. For instance, namespaces will be presented as modules, types will be\n# separated into more groups, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_SLICE  = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,\n# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,\n# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:\n# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser\n# tries to guess whether the code is fixed or free formatted code, this is the\n# default for Fortran type files). For instance to make doxygen treat .inc files\n# as Fortran files (default is PHP), and .f files as C (default is Fortran),\n# use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen. When specifying no_extension you should add\n# * to the FILE_PATTERNS.\n#\n# Note see also the list of default file extension mappings.\n\nEXTENSION_MAPPING      =\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See https://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up\n# to that level are automatically included in the table of contents, even if\n# they do not have an id attribute.\n# Note: This feature currently applies only to Markdown headings.\n# Minimum value: 0, maximum value: 99, default value: 5.\n# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.\n\nTOC_INCLUDE_HEADINGS   = 5\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use\n# during processing. When set to 0 doxygen will based this on the number of\n# cores available in the system. You can set it explicitly to a value larger\n# than 0 to get more control over the balance between CPU load and processing\n# speed. At this moment only the input processing can be done using multiple\n# threads. Since this is still an experimental feature the default is set to 1,\n# which efficively disables parallel processing. Please report any issues you\n# encounter. Generating dot graphs in parallel is controlled by the\n# DOT_NUM_THREADS setting.\n# Minimum value: 0, maximum value: 32, default value: 1.\n\nNUM_PROC_THREADS       = 1\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = YES\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual\n# methods of a class will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIV_VIRTUAL   = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = NO\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If this flag is set to YES, the name of an unnamed parameter in a declaration\n# will be determined by the corresponding definition. By default unnamed\n# parameters remain unnamed in the output.\n# The default value is: YES.\n\nRESOLVE_UNNAMED_PARAMS = YES\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# declarations. If set to NO, these declarations will be included in the\n# documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# With the correct setting of option CASE_SENSE_NAMES doxygen will better be\n# able to match the capabilities of the underlying filesystem. In case the\n# filesystem is case sensitive (i.e. it supports files in the same directory\n# whose names only differ in casing), the option must be set to YES to properly\n# deal with such files in case they appear in the input. For filesystems that\n# are not case sensitive the option should be be set to NO to properly deal with\n# output files written for symbols that only differ in casing, such as for two\n# classes, one named CLASS and the other named Class, and to also support\n# references to files without having to specify the exact matching casing. On\n# Windows (including Cygwin) and MacOS, users should typically set this option\n# to NO, whereas on Linux or other Unix flavors it should typically be set to\n# YES.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = NO\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       =\n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    =\n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            =\n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         =\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong or incomplete\n# parameter documentation, but not about the absence of documentation. If\n# EXTRACT_ALL is set to YES then this flag will automatically be disabled.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when\n# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS\n# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but\n# at the end of the doxygen process doxygen will return with a non-zero status.\n# Possible values are: NO, YES and FAIL_ON_WARNINGS.\n# The default value is: NO.\n\nWARN_AS_ERROR          = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = README.md doc/ include/openpose/\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see:\n# https://www.gnu.org/software/libiconv/) for the list of possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# Note the list of default checked file patterns might differ from the list of\n# default file extension mappings.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,\n# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,\n# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,\n# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),\n# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,\n# *.ucf, *.qsf and *.ice.\n\nFILE_PATTERNS          = *.c \\\n                         *.cc \\\n                         *.cxx \\\n                         *.cpp \\\n                         *.c++ \\\n                         *.java \\\n                         *.ii \\\n                         *.ixx \\\n                         *.ipp \\\n                         *.i++ \\\n                         *.inl \\\n                         *.idl \\\n                         *.ddl \\\n                         *.odl \\\n                         *.h \\\n                         *.hh \\\n                         *.hxx \\\n                         *.hpp \\\n                         *.h++ \\\n                         *.cs \\\n                         *.d \\\n                         *.php \\\n                         *.php4 \\\n                         *.php5 \\\n                         *.phtml \\\n                         *.inc \\\n                         *.m \\\n                         *.markdown \\\n                         *.md \\\n                         *.mm \\\n                         *.dox \\\n                         *.py \\\n                         *.pyw \\\n                         *.f90 \\\n                         *.f95 \\\n                         *.f03 \\\n                         *.f08 \\\n                         *.f18 \\\n                         *.f \\\n                         *.for \\\n                         *.vhd \\\n                         *.vhdl \\\n                         *.ucf \\\n                         *.qsf \\\n                         *.ice\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                =\n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       =\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        =\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           =\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             =\n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nINPUT_FILTER           =\n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nFILTER_PATTERNS        =\n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS =\n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE = README.md\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = YES\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# entity all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see https://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the\n# clang parser (see:\n# http://clang.llvm.org/) for more accurate parsing at the cost of reduced\n# performance. This can be particularly helpful with template rich C++ code for\n# which doxygen's built-in parser lacks the necessary type information.\n# Note: The availability of this option depends on whether or not doxygen was\n# generated with the -Duse_libclang=ON option for CMake.\n# The default value is: NO.\n\nCLANG_ASSISTED_PARSING = NO\n\n# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to\n# YES then doxygen will add the directory of each input to the include path.\n# The default value is: YES.\n\nCLANG_ADD_INC_PATHS    = YES\n\n# If clang assisted parsing is enabled you can provide the compiler with command\n# line options that you would normally use when invoking the compiler. Note that\n# the include paths will already be set by doxygen for the files and directories\n# specified with INPUT and INCLUDE_PATH.\n# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.\n\nCLANG_OPTIONS          =\n\n# If clang assisted parsing is enabled you can provide the clang parser with the\n# path to the directory containing a file called compile_commands.json. This\n# file is the compilation database (see:\n# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the\n# options used when the source files were built. This is equivalent to\n# specifying the -p option to a clang tool, such as clang-check. These options\n# will then be passed to the parser. Any options specified with CLANG_OPTIONS\n# will be added as well.\n# Note: The availability of this option depends on whether or not doxygen was\n# generated with the -Duse_libclang=ON option for CMake.\n\nCLANG_DATABASE_PATH    =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            =\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            =\n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        =\n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list). For an example see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  =\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       =\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# https://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 220\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = NO\n\n# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML\n# documentation will contain a main index with vertical navigation menus that\n# are dynamically created via JavaScript. If disabled, the navigation index will\n# consists of multiple levels of tabs that are statically embedded in every HTML\n# page. Disable this option to support browsers that do not have JavaScript,\n# like the Qt help browser.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_MENUS     = YES\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see:\n# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To\n# create a documentation set, doxygen will generate a Makefile in the HTML\n# output directory. Running make will produce the docset in that directory and\n# running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy\n# genXcode/_index.html for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see:\n# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               =\n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           =\n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the main .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     =\n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               =\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   =\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  =\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  =\n\n# The QHG_LOCATION tag can be used to specify the location (absolute path\n# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to\n# run qhelpgenerator on the generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           =\n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = YES\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg\n# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see\n# https://inkscape.org) to generate formulas as SVG images instead of PNGs for\n# the HTML output. These images will generally look nicer at scaled resolutions.\n# Possible values are: png (the default) and svg (looks nicer but requires the\n# pdf2svg or inkscape tool).\n# The default value is: png.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FORMULA_FORMAT    = png\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANSPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# http://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from http://www.mathjax.org before deployment.\n# The default value is: http://cdn.mathjax.org/mathjax/latest.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# The FORMULA_MACROFILE can contain LaTeX \\newcommand and \\renewcommand commands\n# to create new LaTeX commands to be used in formulas as building blocks. See\n# the section \"Including formulas\" for details.\n\nFORMULA_MACROFILE      =\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# https://www.mathjax.org) which uses client side JavaScript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from https://www.mathjax.org before deployment.\n# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = https://cdn.jsdelivr.net/npm/mathjax@2\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see:\n# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using JavaScript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see:\n# https://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see:\n# https://xapian.org/). See the section \"External Indexing and Searching\" for\n# details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       =\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     =\n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when not enabling USE_PDFLATEX the default is latex when enabling\n# USE_PDFLATEX the default is pdflatex and when in the later case latex is\n# chosen this is overwritten by pdflatex. For specific output languages the\n# default can have been set differently, this depends on the implementation of\n# the output language.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# Note: This tag is used in the Makefile / make.bat.\n# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file\n# (.tex).\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to\n# generate index for LaTeX. In case there is no backslash (\\) as first character\n# it will be automatically added in the LaTeX code.\n# Note: This tag is used in the generated output file (.tex).\n# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.\n# The default value is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_MAKEINDEX_CMD    = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         =\n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber,\n# $projectbrief, $projectlogo. Doxygen will replace $title with the empty\n# string, for the replacement values of the other commands the user is referred\n# to HTML_HEADER.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           =\n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           =\n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET =\n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      =\n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as\n# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX\n# files. Set this option to YES, to get a higher quality PDF documentation.\n#\n# See also section LATEX_CMD_NAME for selecting the engine.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# https://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated\n# page will contain the date and time when the page was generated. Setting this\n# to NO can help when comparing the output of multiple runs.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_TIMESTAMP        = NO\n\n# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)\n# path from which the emoji images will be read. If a relative path is entered,\n# it will be relative to the LATEX_OUTPUT directory. If left blank the\n# LATEX_OUTPUT directory will be used.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EMOJI_DIRECTORY  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's\n# configuration file, i.e. a series of assignments. You only have to provide\n# replacements, missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    =\n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's configuration file. A template extensions file can be\n# generated using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    =\n\n# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code\n# with syntax highlighting in the RTF output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_SOURCE_CODE        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             =\n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include\n# namespace members in file scope as well, matching the HTML output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_NS_MEMB_FILE_SCOPE = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the\n# program listings (including syntax highlighting and cross-referencing\n# information) to the DOCBOOK output. Note that enabling this will significantly\n# increase the size of the DOCBOOK output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_PROGRAMLISTING = NO\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures\n# the structure of the code including all documentation. Note that this feature\n# is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to Sqlite3 output\n#---------------------------------------------------------------------------\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           =\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  =\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             =\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      =\n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               =\n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       =\n\n# If the ALLEXTERNALS tag is set to YES, all external class will be listed in\n# the class index. If set to NO, only the inherited external classes will be\n# listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = YES\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            =\n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               =\n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = NO\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font in the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           =\n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag UML_LOOK is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and\n# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS\n# tag is set to YES, doxygen will add type and arguments for attributes and\n# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen\n# will not generate fields with class member information in the UML graphs. The\n# class diagrams will look similar to the default class diagrams but using UML\n# notation for the relationships.\n# Possible values are: NO, YES and NONE.\n# The default value is: NO.\n# This tag requires that the tag UML_LOOK is set to YES.\n\nDOT_UML_DETAILS        = NO\n\n# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters\n# to display on a single line. If the actual line length exceeds this threshold\n# significantly it will wrapped across multiple lines. Some heuristics are apply\n# to avoid ugly line breaks.\n# Minimum value: 0, maximum value: 1000, default value: 17.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_WRAP_THRESHOLD     = 17\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# http://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               =\n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           =\n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           =\n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           =\n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file. If left blank, it is assumed\n# PlantUML is not used or called during a preprocessing step. Doxygen will\n# generate a warning when it encounters a \\startuml command in this case and\n# will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      =\n\n# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a\n# configuration file for plantuml.\n\nPLANTUML_CFG_FILE      =\n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  =\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate\n# files that are used to generate the various graphs.\n#\n# Note: This setting is not only used for dot files but also for msc and\n# plantuml temporary files.\n# The default value is: YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": ".github/CI_deprecated/.travis.yml",
    "content": "# # This will run on Travis' 'new' container-based infrastructure\n\n# # Blacklist\n# branches:\n#   only:\n#     - master\n\n# # Environment variables + OS + other parameters\n# global:\n#   - GH_REPO_NAME: openpose\n#   - DOXYFILE: $CI_BUILD_DIR/.doc_autogeneration.doxygen\n#   # Set this in Environment Variables on travis-ci.org\n#   # - GH_REPO_REF: github.com/<user_name>/openpose.git\n# matrix:\n#   # Use a build matrix to test many builds in parallel\n#   # envvar defaults:\n#   #   WITH_CMAKE: true\n#   #   WITH_PYTHON: false\n#   #   WITH_CUDA: true\n#   #   WITH_CUDNN: true\n#   #   WITH_OPEN_CL: false\n#   #   WITH_MKL: false\n#   include:\n#   # Ubuntu 16.04\n#   # Ubuntu 16.04 - Default - CMake - CUDA\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-default-cmake-cuda8\"\n#     sudo: required\n#   # Ubuntu 16.04 - Python - CMake - CUDA\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-python-cmake-cuda8\" WITH_PYTHON=true\n#     sudo: required\n#     # Generate and deploy documentation\n#     after_success:\n#       - cd $CI_BUILD_DIR\n#       - chmod +x scripts/generate_gh_pages.sh\n#       - ./scripts/generate_gh_pages.sh\n#   # Ubuntu 16.04 - Python - CMake - CPU\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-python-cmake-cpu\" WITH_PYTHON=true WITH_CUDA=false\n#     sudo: required\n#   # Ubuntu 16.04 - Python - CMake - OpenCL\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-python-cmake-opencl\" WITH_PYTHON=true WITH_CUDA=false WITH_OPEN_CL=true\n#     sudo: required\n#   # Ubuntu 16.04 - Python - CMake - CPU - Debug\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-python-cmake-cpu-debug\" WITH_PYTHON=true WITH_CUDA=false WITH_DEBUG=true\n#     sudo: required\n#   # Ubuntu 16.04 - Python - CMake - CPU - Unity\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-python-cmake-cpu-unity\" WITH_PYTHON=true WITH_UNITY=true WITH_CUDA=false\n#     sudo: required\n\n#   # Mac OSX\n#   # Mac OSX - Python - CMake - CPU\n#   - os: osx\n#     osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions\n#     env: NAME=\"OSX-python-cmake-cpu\" WITH_CUDA=false WITH_PYTHON=true\n#     sudo: required\n#   # Mac OSX - Python - CMake - OpenCL\n#   - os: osx\n#     osx_image: xcode10.1 # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions\n#     env: NAME=\"OSX-default-cmake-opencl\" WITH_CUDA=false WITH_OPEN_CL=true\n#     sudo: required\n#   # Mac OSX - Python - CMake - CPU - Debug\n#   - os: osx\n#     osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions\n#     env: NAME=\"OSX-python-cmake-cpu-debug\" WITH_CUDA=false WITH_PYTHON=true WITH_DEBUG=true\n#     sudo: required\n#   # Mac OSX - Python - CMake - CPU - Unity\n#   - os: osx\n#     osx_image: xcode9.4 # xcode10.1 does not work with Python # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions\n#     env: NAME=\"OSX-python-cmake-cpu-unity\" WITH_CUDA=false WITH_PYTHON=true WITH_UNITY=true\n#     sudo: required\n#   # Mac OSX - Default - CMake - CPU\n#   - os: osx\n#     osx_image: xcode10.1 # Versions: https://docs.travis-ci.com/user/languages/objective-c#supported-xcode-versions\n#     env: NAME=\"OSX-default-cmake-cpu\" WITH_CUDA=false\n#     sudo: required\n\n#   # # TO-DO: To be implemented\n#   # # Windows\n#   # # Windows - Default - CMake - CUDA\n#   # - os: windows\n#   #   env: NAME=\"W10-default-cmake-cuda8\"\n\n#   # Ubuntu (others)\n#   # Ubuntu 16.04 - Default - CMake - CPU\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-default-cmake-cpu\" WITH_CUDA=false\n#     sudo: required\n#   # Ubuntu 16.04 - Default - Make - CUDA\n#   - os: linux\n#     dist: xenial\n#     env: NAME=\"U16-default-make-cuda8\" WITH_CMAKE=false\n#     sudo: required\n#   # # TO-DO: To be implemented\n#   # # Ubuntu 16.04 - Default - CMake - CPU MKL\n#   # - os: linux\n#   #   dist: xenial\n#   #   env: NAME=\"U16-default-cmake-cpu-mkl\" WITH_CUDA=false WITH_MKL=true\n#   #   sudo: required\n#   # # Ubuntu 16.04 - Python - CMake - OpenCL\n#   # - os: linux\n#   #   dist: xenial\n#   #   env: NAME=\"U16-python-cmake-opencl\" WITH_PYTHON=true WITH_CUDA=false WITH_OPEN_CL=true\n#   #   sudo: required\n#   # # Unnecessary/redundant ones\n#   # # Ubuntu 16.04 - Default - CMake - CUDA - no cuDNN\n#   # - os: linux\n#   #   dist: xenial\n#   #   env: NAME=\"U16-default-cmake-cuda8-nocudnn\" WITH_CUDNN=false\n#   #   sudo: required\n#   # Ubuntu 14.04 - Default - CMake - CPU\n#   - os: linux\n#     dist: trusty\n#     env: NAME=\"U14-default-cmake-cpu\" WITH_CUDA=false\n#     sudo: required\n#   # Ubuntu 14.04 - Default - Make - CUDA\n#   - os: linux\n#     dist: trusty\n#     env: NAME=\"U14-default-make-cuda8\" WITH_CMAKE=false\n#     sudo: required\n#   # # Unnecessary/redundant ones\n#   # # Ubuntu 14.04 - Default - CMake - CUDA\n#   # - os: linux\n#   #   dist: trusty\n#   #   env: NAME=\"U14-default-cmake-cuda8\"\n#   #   sudo: required\n\n# # Install apt dependencies\n# addons:\n#   apt:\n#     packages:\n#       - doxygen\n#       - doxygen-doc\n#       - doxygen-latex\n#       - doxygen-gui\n#       - graphviz\n\n# # Install Caffe and OP dependencies\n# install:\n#   - if [[ \"$CI_OS_NAME\" == \"linux\" ]]; then sudo bash scripts/CI/install_deps_ubuntu.sh ; fi\n#   - if [[ \"$CI_OS_NAME\" == \"osx\" ]]; then bash scripts/CI/install_deps_osx.sh ; fi\n#   - if [[ \"$CI_OS_NAME\" == \"windows\" ]]; then exit 99 ; fi\n\n# # Running CMake\n# before_script:\n#   - bash scripts/CI/configure.sh\n\n# # Build your code e.g., by calling make\n# script:\n#   - bash scripts/CI/run_make.sh\n#   - bash scripts/CI/run_tests.sh\n"
  },
  {
    "path": ".github/CI_deprecated/Readme_Travis_badges_table_and_backup_instructions.md",
    "content": "In order to recover Travis:\n1. Uncomment all the lines of code in \".travis.yml\" and move it back to the main folder (e.g., at the same level than the global README.md and CMakeLists.txt files).\n2. Move `generate_gh_pages.sh` back to `scripts/generate_gh_pages.sh`.\n3. Re-add the table of badges in the README.md:\n\n|                  |`Default Config`  |`CUDA (+Python)`  |`CPU (+Python)`   |`OpenCL (+Python)`| `Debug`          | `Unity`          |\n| :---:            | :---:            | :---:            | :---:            | :---:            | :---:            | :---:            |\n| **`Linux`**   | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/1)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/2)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/3)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/4)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/5)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/6)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) |\n| **`MacOS`**   | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/7)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/7)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/8)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/9)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/10)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) | [![Status](https://travis-matrix-badges.herokuapp.com/repos/CMU-Perceptual-Computing-Lab/openpose/branches/master/11)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose) |\n| **`Windows`** | [![Status](https://ci.appveyor.com/api/projects/status/5leescxxdwen77kg/branch/master?svg=true)](https://ci.appveyor.com/project/gineshidalgo99/openpose/branch/master) | | | | |\n<!--\nNote: Currently using [travis-matrix-badges](https://github.com/bjfish/travis-matrix-badges) vs. traditional [![Build Status](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose.svg?branch=master)](https://travis-ci.org/CMU-Perceptual-Computing-Lab/openpose)\n-->\n"
  },
  {
    "path": ".github/CI_deprecated/generate_gh_pages.sh",
    "content": "#!/bin/sh\n################################################################################\n# Title         : generate_gh_pages.sh\n# Date created  : 2016/02/22\n# Notes         :\n__AUTHOR__=\"openpose\"\n# Preconditions:\n# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz\n#   must be installed.\n# - Doxygen configuration file must have the destination directory empty and\n#   source code directory with a $(CI_BUILD_DIR) prefix.\n# - An gh-pages branch should already exist. See below for more info on how to\n#   create a gh-pages branch.\n#\n# Required global variables:\n# - CI_BUILD_NUMBER : The number of the current build.\n# - CI_COMMIT       : The commit that the current build is testing.\n# - DOXYFILE            : The Doxygen configuration file.\n# - GH_REPO_NAME        : The name of the repository.\n# - GH_REPO_REF         : The GitHub reference to the repository.\n# - GH_REPO_TOKEN       : Secure token to the github repository.\n#\n# For information on how to encrypt variables for Travis CI please go to\n# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables\n# or https://gist.github.com/vidavidorra/7ed6166a46c537d3cbd2\n# For information on how to create a clean gh-pages branch from the master\n# branch, please go to https://gist.github.com/vidavidorra/846a2fc7dd51f4fe56a0\n#\n# This script will generate Doxygen documentation and push the documentation to\n# the gh-pages branch of a repository specified by GH_REPO_REF.\n# Before this script is used there should already be a gh-pages branch in the\n# repository.\n# \n################################################################################\n\n################################################################################\n##### Setup this script and get the current gh-pages branch.               #####\necho 'Setting up the script...'\n# Exit with nonzero exit code if anything fails\nset -e\n\n# Create a clean working directory for this script.\nmkdir code_docs\ncd code_docs\n\n# Get the current gh-pages branch\ngit clone -b gh-pages https://git@$GH_REPO_REF\ncd $GH_REPO_NAME\n\n##### Configure git.\n# Set the push default to simple i.e. push only the current branch.\ngit config --global push.default simple\n# Pretend to be an user called Travis CI.\ngit config user.name \"Travis CI\"\ngit config user.email \"travis@travis-ci.org\"\n\n# Remove everything currently in the gh-pages branch.\n# GitHub is smart enough to know which files have changed and which files have\n# stayed the same and will only update the changed files. So the gh-pages branch\n# can be safely cleaned, and it is sure that everything pushed later is the new\n# documentation.\nrm -rf *\n\n# Need to create a .nojekyll file to allow filenames starting with an underscore\n# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file.\n# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set\n# to NO, which it is by default. So creating the file just in case.\necho \"\" > .nojekyll\n\n################################################################################\n##### Generate the Doxygen code documentation and log the output.          #####\necho 'Generating Doxygen code documentation...'\n# Redirect both stderr and stdout to the log file AND the console.\necho \"OUTPUT_DIRECTORY       = \" >> $DOXYFILE\ndoxygen $DOXYFILE 2>&1 | tee doxygen.log\n\n################################################################################\n##### Upload the documentation to the gh-pages branch of the repository.   #####\n# Only upload if Doxygen successfully created the documentation.\n# Check this by verifying that the html directory and the file html/index.html\n# both exist. This is a good indication that Doxygen did it's work.\nif [ -d \"html\" ] && [ -f \"html/index.html\" ]; then\n\n    echo 'Uploading documentation to the gh-pages branch...'\n    # Add everything in this directory (the Doxygen code documentation) to the\n    # gh-pages branch.\n    # GitHub is smart enough to know which files have changed and which files have\n    # stayed the same and will only update the changed files.\n    git add --all\n\n    # Commit the added files with a title and description containing the Travis CI\n    # build number and the GitHub commit reference that issued this build.\n    git commit -m \"Deploy code docs to GitHub Pages Travis build: ${CI_BUILD_NUMBER}\" -m \"Commit: ${CI_COMMIT}\"\n\n    # Force push to the remote gh-pages branch.\n    # The output is redirected to /dev/null to hide any sensitive credential data\n    # that might otherwise be exposed.\n    git push --force \"https://${GH_REPO_TOKEN}@${GH_REPO_REF}\" > /dev/null 2>&1\nelse\n    echo '' >&2\n    echo 'Warning: No documentation (html) files have been found!' >&2\n    echo 'Warning: Not going to push the documentation to GitHub!' >&2\n    exit 1\nfi\n"
  },
  {
    "path": ".github/issue_template.md",
    "content": "### Posting rules\n1. **No duplicated posts, only 1 new post opened a day, and up to 2 opened a week**. Otherwise, extrict user bans will occur.\n    - Check the [FAQ](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/05_faq.md) section, other GitHub issues, and general documentation before posting. E.g., **low-speed, out-of-memory, output format, 0-people detected, installation issues, ...**).\n    - Keep posting all your issues in the same post.\n    - No bans if you are unsure whether the post is duplicated!\n2. **Fill all** the **Your System Configuration section** if you are facing an error or unexpected behavior. Some posts (e.g., feature requests) might not require it.\n3. **No questions about training or 3rd party libraries**:\n    - OpenPose only implements testing. For training, check [OpenPose train](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train).\n    - Caffe errors/issues: Check [Caffe](http://caffe.berkeleyvision.org) documentation.\n    - CUDA/cuDNN check failed errors: They are usually fixed by re-installing CUDA, then re-installing the proper cuDNN version, then rebooting, and then re-installing OpenPose. Otherwise, check Nvidia/CUDA/cuDNN forums.\n    - OpenCV errors: Install the default/pre-compiled OpenCV or check for OpenCV online help.\n4. Set a **proper issue title**: Add the OS (Ubuntu, Windows) and be specific (e.g., do not call it: `Error`).\n5. Only English comments.\n6. Remove these posting rules from your post but follow them!\nPosts which do not follow these rules will be **ignored/deleted** and those **users banned** with no further clarification.\n\n\n\n### Issue Summary\n\n\n\n### Executed Command (if any)\nNote: add `--logging_level 0 --disable_multi_thread` to get higher debug information.\n\n\n\n### OpenPose Output (if any)\n\n\n\n### Errors (if any)\n\n\n\n### Type of Issue\nSelect the topic(s) on your post, delete the rest:\n- Compilation/installation error\n- Execution error\n- Help wanted\n- Question\n- Enhancement / offering possible extensions / pull request / etc\n- Other (type your own type)\n\n\n\n### Your System Configuration\n1. **Whole console output** (if errors appeared), paste the error to [PasteBin](https://pastebin.com/) and then paste the link here: LINK\n\n2. **OpenPose version**: Latest GitHub code? Or specific commit (e.g., d52878f)? Or specific version from `Release` section (e.g., 1.2.0)?\n\n3. **General configuration**:\n    - **Installation mode**: CMake, sh script, manual Makefile installation, ... (Ubuntu); CMake, ... (Windows); ...?\n    - **Operating system** (`lsb_release -a` in Ubuntu):\n    - **Operating system version** (e.g., Ubuntu 16, Windows 10, ...):\n    - **Release or Debug mode**? (by default: release):\n    - Compiler (`gcc --version` in Ubuntu or VS version in Windows): 5.4.0, ... (Ubuntu); VS2015 Enterprise Update 3, VS2017 community, ... (Windows); ...?\n\n4. **Non-default settings**:\n    - **3-D Reconstruction module added**? (by default: no):\n    - Any other custom CMake configuration with respect to the default version? (by default: no):\n\n5. **3rd-party software**:\n    - **Caffe version**: Default from OpenPose, custom version, ...?\n    - **CMake version** (`cmake --version` in Ubuntu):\n    - **OpenCV version**: pre-compiled `apt-get install libopencv-dev` (only Ubuntu); OpenPose default (only Windows); compiled from source? If so, 2.4.9, 2.4.12, 3.1, 3.2?; ...?\n\n6. If **GPU mode** issue:\n    - **CUDA version** (`cat /usr/local/cuda/version.txt` in most cases):\n    - **cuDNN version**:\n    - **GPU model** (`nvidia-smi` in Ubuntu):\n\n7. If **CPU-only mode** issue:\n    - **CPU brand & model**:\n    - Total **RAM memory** available:\n\n8. If **Python** API:\n    - **Python version**: 2.7, 3.7, ...?\n    - **Numpy version** (`python -c \"import numpy; print numpy.version.version\"` in Ubuntu):\n\n9. If **Windows** system:\n    - Portable demo or compiled library?\n\n10. If **speed performance** issue:\n    - Report OpenPose timing speed based on the [profiling documentation](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/06_maximizing_openpose_speed.md#profiling-speed).\n"
  },
  {
    "path": ".github/root_index.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <meta http-equiv = \"refresh\" content = \"0; url = web/html/doc/index.html\" />\n    </head>\n    <body>\n    </body>\n</html>\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - bug/typo\n  - enhancement\n# Label to use when marking an issue as stale\nstaleLabel: stale/old\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: false\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\n\non: [push, pull_request]\n\nenv:\n  GH_REPO_NAME: ${{ github.event.repository.name }}\n  DOXYFILE: ${{ github.workspace }}/.doc_autogeneration.doxygen\n  GH_REPO_REF: ${{ github.repositoryUrl }}\n  PYTHON3_VERSION: python3.8\n\njobs:\n  build:\n    name: ${{ matrix.env.NAME }}\n    runs-on: ${{ matrix.os }}\n    env: ${{ matrix.env }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          # Ubuntu\n          # Ubuntu 20.04 - Default - CMake - CUDA\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-default-cmake-cuda\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n          # Ubuntu 18.04 - Default - CMake - CUDA\n          - os: ubuntu-18.04\n            os_name: linux\n            env:\n              NAME: U18-default-cmake-cuda\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n          # Ubuntu 20.04 - Python - CMake - CUDA\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-python-cmake-cuda\n              WITH_CUDNN: false\n              WITH_PYTHON: true\n              CI_OS_NAME: linux\n              CI_BUILD_NUMBER: ${{ github.run_number }}\n              CI_COMMIT: ${{ github.sha }}\n            DOCS: true\n          # Ubuntu 18.04 - Python - CMake - CUDA\n          - os: ubuntu-18.04\n            os_name: linux\n            env:\n              NAME: U18-python-cmake-cuda\n              WITH_CUDNN: false\n              WITH_PYTHON: true\n              CI_OS_NAME: linux\n          # Ubuntu 20.04 - Python - CMake - CPU\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-python-cmake-cpu\n              WITH_PYTHON: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n          # Ubuntu 18.04 - Python - CMake - CPU\n          - os: ubuntu-18.04\n            os_name: linux\n            env:\n              NAME: U18-python-cmake-cpu\n              WITH_PYTHON: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n          # TO-DO (not passing)\n          # # Ubuntu 20.04 - Python - CMake - OpenCL\n          # - os: ubuntu-20.04\n          #   os_name: linux\n          #   env:\n          #     NAME: U20-python-cmake-opencl\n          #     WITH_PYTHON: true\n          #     WITH_CUDA: false\n          #     WITH_CUDNN: false\n          #     WITH_OPEN_CL: true\n          #     CI_OS_NAME: linux\n          # Ubuntu 18.04 - Python - CMake - OpenCL\n          - os: ubuntu-18.04\n            os_name: linux\n            env:\n              NAME: U18-python-cmake-opencl\n              WITH_PYTHON: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_OPEN_CL: true\n              CI_OS_NAME: linux\n          # Ubuntu 20.04 - Python - CMake - CPU - Debug\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-python-cmake-cpu-debug\n              WITH_PYTHON: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_DEBUG: true\n              CI_OS_NAME: linux\n          # Ubuntu 18.04 - Python - CMake - CPU - Debug\n          - os: ubuntu-18.04\n            os_name: linux\n            env:\n              NAME: U18-python-cmake-cpu-debug\n              WITH_PYTHON: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_DEBUG: true\n              CI_OS_NAME: linux\n          # Ubuntu 20.04 - Python - CMake - CPU - Unity\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-python-cmake-cpu-unity\n              WITH_PYTHON: true\n              WITH_UNITY: true\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n          # Ubuntu 20.04 - Default - CMake - CPU\n          - os: ubuntu-20.04\n            os_name: linux\n            env:\n              NAME: U20-default-cmake-cpu\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              CI_OS_NAME: linux\n\n          # Mac OSX\n          # Mac OSX - Python - CMake - CPU\n          - os: macos-10.15\n            os_name: osx\n            env:\n              NAME: OSX-python-cmake-cpu\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_PYTHON: true\n              CI_OS_NAME: osx\n          # Mac OSX - Python - CMake - OpenCL\n          - os: macos-10.15\n            os_name: osx\n            env:\n              NAME: OSX-default-cmake-opencl\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_OPEN_CL: true\n              CI_OS_NAME: osx\n          # Mac OSX - Python - CMake - CPU - Debug\n          - os: macos-10.15\n            os_name: osx\n            env:\n              NAME: OSX-python-cmake-cpu-debug\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_PYTHON: true\n              WITH_DEBUG: true\n              CI_OS_NAME: osx\n          # Mac OSX - Python - CMake - CPU - Unity\n          - os: macos-10.15\n            os_name: osx\n            env:\n              NAME: OSX-python-cmake-cpu-unity\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              WITH_PYTHON: true\n              WITH_UNITY: true\n              CI_OS_NAME: osx\n          # Mac OSX - Default - CMake - CPU\n          - os: macos-10.15\n            os_name: osx\n            env:\n              NAME: OSX-default-cmake-cpu\n              WITH_CUDA: false\n              WITH_CUDNN: false\n              CI_OS_NAME: osx\n\n          # TO-DO (not passing)\n          # Note: CUDA jobs fail in U16 because of an issue with GCC 5.5 (https://github.com/NVIDIA/apex/issues/529). GH Actions doesn't support\n          # GCC 5.4 and CUDA does not support newer than GCC 5.X. Thus, cuDNN (sh file only for Ubuntu 16) is no longer tested.\n          # # Ubuntu 16.04\n          # # Ubuntu 16.04 - Default - CMake - CUDA\n          # - os: ubuntu-16.04\n          #   os_name: linux\n          #   env:\n          #     NAME: U16-default-cmake-cuda8\n          #     CI_OS_NAME: linux\n\n          # # Deprecated (not working for the above issue between CUDA and the Ubuntu16 from GitHub Actions) \n          # # Ubuntu 16.04 - Default - Make - CUDA\n          # - os: ubuntu-16.04\n          #   os_name: linux\n          #   env:\n          #     NAME: U16-default-make-cuda\n          #     WITH_CUDNN: false\n          #     WITH_CMAKE: false\n          #     CI_OS_NAME: linux\n\n          # Ubuntu 16 no longer works\n#           # Ubuntu 16.04 - Python - CMake - CPU\n#           - os: ubuntu-16.04\n#             os_name: linux\n#             env:\n#               NAME: U16-python-cmake-cpu\n#               WITH_PYTHON: true\n#               WITH_CUDA: false\n#               WITH_CUDNN: false\n#               CI_OS_NAME: linux\n#           # Ubuntu 16.04 - Python - CMake - OpenCL\n#           - os: ubuntu-16.04\n#             os_name: linux\n#             env:\n#               NAME: U16-python-cmake-opencl\n#               WITH_PYTHON: true\n#               WITH_CUDA: false\n#               WITH_CUDNN: false\n#               WITH_OPEN_CL: true\n#               CI_OS_NAME: linux\n#           # Ubuntu 16.04 - Python - CMake - CPU - Debug\n#           - os: ubuntu-16.04\n#             os_name: linux\n#             env:\n#               NAME: U16-python-cmake-cpu-debug\n#               WITH_PYTHON: true\n#               WITH_CUDA: false\n#               WITH_CUDNN: false\n#               WITH_DEBUG: true\n#               CI_OS_NAME: linux\n\n    steps:\n    - uses: actions/checkout@v2\n      with:\n        fetch-depth: 0\n        submodules: recursive\n    - uses: actions/setup-python@v5\n      with:\n        python-version: 3.8\n      if: ${{ matrix.env.WITH_PYTHON }}\n    - name: Install (Linux)\n      run: scripts/CI/install_deps_ubuntu.sh\n      if: ${{ matrix.os_name == 'linux' }}\n    - name: Install (Mac OS)\n      run: scripts/CI/install_deps_osx.sh\n      if: ${{ matrix.os_name == 'osx' }}\n\n    - name: Configure\n      run: scripts/CI/configure.sh\n    - name: Make\n      run: scripts/CI/run_make.sh\n    - name: Tests\n      run: scripts/CI/run_tests.sh\n\n    - name: Docs APT packages\n      run: |\n        # The Doxygen apt-get version for Ubuntu 20 is 1.8.17, which has some bugs fixed in 1.9.1\n        # run: sudo apt-get -yq install doxygen doxygen-doc doxygen-latex doxygen-gui graphviz\n        git clone https://github.com/doxygen/doxygen.git && cd doxygen && git checkout Release_1_9_1\n        mkdir build && cd build\n        cmake -G \"Unix Makefiles\" ..\n        make -j`nproc`\n        sudo make install\n      if: ${{ matrix.DOCS }}\n    - name: Generate docs\n      run: |\n        cd ${{ github.workspace }}\n        echo 'Generating Doxygen code documentation...'\n        doxygen $DOXYFILE 2>&1 | tee doxygen.log\n        # Required so Doxygen links/finds the license file\n        cp LICENSE doxygen/html/LICENSE\n        # Required in order to link .github/media/ images with doc without modifying doc links. Remove if using `publish_dir: doxygen/html/`\n        mkdir -p doxygen_final/web/html/ && mv doxygen/html doxygen_final/web/html/doc\n        mkdir -p doxygen_final/web/.github/media/ && cp -rf .github/media/ doxygen_final/web/.github/\n        mkdir -p doxygen_final/web/html/.github/media/ && cp -rf .github/media/ doxygen_final/web/html/.github/\n        mkdir -p doxygen_final/web/html/doc/.github/media/ && cp -rf .github/media/ doxygen_final/web/html/doc/.github/\n        echo 'Copying log...'\n        cp doxygen.log doxygen_final/doxygen.log\n        echo 'Copying index.html to root pointing to actual docs'\n        cp .github/root_index.html doxygen_final/index.html\n      if: ${{ matrix.DOCS }}\n    - name: Deploy Docs\n      uses: peaceiris/actions-gh-pages@v3\n      with:\n        github_token: ${{ secrets.GITHUB_TOKEN }}\n        publish_dir: doxygen_final/\n        # publish_dir: doxygen/html/ # Original one, it would turn [...].github.io/openpose/web/html/doc/ into [...].github.io/openpose/, but images would not work\n        destination_dir: .\n        enable_jekyll: false\n        force_orphan: true\n      if: ${{ matrix.DOCS && github.event_name == 'push' && github.ref == 'refs/heads/master' }}\n"
  },
  {
    "path": ".gitignore",
    "content": "######################### Binary Files #########################\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.cuo\n\n# Compiled Dynamic libraries\n*.so*\n*.dylib\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n\n# Compiled protocol buffers\n*.pb.h\n*.pb.cc\n*_pb2.py\n\n# Compiled python\n*.pyc\n\n# Compiled MATLAB\n*.mex*\n\n# IPython notebook checkpoints\n.ipynb_checkpoints\n\n# LevelDB files\n*.sst\n*.ldb\nLOCK\nCURRENT\nMANIFEST-*\n\n######################### IDEs Files #########################\n# Editor temporaries\n*.swp\n*~\n\n# Sublime Text settings\n*.sublime-workspace\n*.sublime-project\n\n# Eclipse Project settings\n*.*project\n.settings\n\n# QtCreator files\n*.user\n\n# PyCharm files\n.idea\n\n# OSX dir files\n.DS_Store\n._.DS_Store\n\n# Vim files\ncscope.*\ntags\n.clang_complete\n.vim\n\n######################### Windows (Visual Studio) Files #########################\n*.db\n*.deps\n*.obj\n*.opendb\n*.pdb\n\n######################### Windows (Visual Studio) Folders and Compressed files #########################\n*.vs/\n*x64/\n# Allowing this file (removed *.user for Qt)\n!*.vcxproj.user\n\n######################### Caffe Files / Folders #########################\n# User's build configuration\nMakefile\nMakefile.config\n\n# Data and models are either\n\t# 1. reference, and not casually committed\n\t# 2. custom, and live on their own unless they're deliberated contributed\ndistribute/\n*.caffemodel\n*.caffemodel.h5\n*.solverstate\n*.solverstate.h5\n*.binaryproto\n*leveldb\n*lmdb\n\n# Camera parameters\n*.xml\n\n######################### 3rd-party Folders and Zip Files #########################\n3rdparty/caffe/.git\n3rdparty/caffe/.github\n3rdparty/asio/\n3rdparty/eigen/\n3rdparty/windows/caffe/\n3rdparty/windows/caffe_cpu/\n3rdparty/windows/caffe_opencl/\n3rdparty/windows/caffe3rdparty/\n3rdparty/windows/opencv/\n3rdparty/windows/freeglut/\n3rdparty/windows/spinnaker/\n3rdparty/*zip\n3rdparty/windows/*zip\n\n######################### Compilation (build, distribute & bins) Files / Folders #########################\n*.bin\n*.testbin\nbuild\nbuild*\n.build*\n*cmake_build\ndistribute/*\npython/caffe/proto/\n\n######################### Generated Documentation #########################\n_site\ndocs/_site\ndocs/dev\ndocs/gathered\ndoxygen\nhtml/\n\n######################### Video Files #########################\n# Testing videos\n*.mp4\n*.mov\n\n######################### Validation Scripts & Testing #########################\noutput*/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"3rdparty/caffe\"]\n\tpath = 3rdparty/caffe\n\turl = https://github.com/CMU-Perceptual-Computing-Lab/caffe.git\n[submodule \"3rdparty/pybind11\"]\n\tpath = 3rdparty/pybind11\n\turl = https://github.com/pybind/pybind11.git\n"
  },
  {
    "path": "3rdparty/Versions.txt",
    "content": "Asio:\r\n    - Version 1.12.1.\r\n    - Link: https://think-async.com/Asio/Download\r\n\r\nEigen:\r\n    - Version 3.3.8\r\n    - Link: http://eigen.tuxfamily.org/index.php\r\n\r\nUnix:\r\n    - Caffe:\r\n        - Version 1.0.0, extracted from GitHub from its master branch.\r\n        - Link: https://github.com/BVLC/caffe\r\n        - GitHub SHA: 864520713a4c5ffae7382ced5d34e4cadc608473\r\n\r\n    - Spinnaker:\r\n        - Tested on Spinnaker 1.13.0.31 SDK - Linux Ubuntu 16.04 (64-bit) - 05/25/2018 - 41.580MB.\r\n        - Prerequisites: https://www.ptgrey.com/tan/10685\r\n\r\nWindows:\r\n    - Caffe & Caffe dependencies (caffe3rdparty):\r\n        - Version 1.0.0, extracted from GitHub from its master branch.\r\n        - Link: https://github.com/BVLC/caffe/tree/windows\r\n\r\n    - FreeGLUT (only for the 3-D reconstruction demo):\r\n        - Version 3.0.0-2 (MSVC), extracted from their oficial website.\r\n        - Link: https://www.transmissionzero.co.uk/software/freeglut-devel/\r\n\r\n    - OpenCV:\r\n        - Version 4.5.0, extracted from their oficial website: section `Releases`, subsection `OpenCV - 4.5.0`, `Windows` version.\r\n        - Link: https://opencv.org/releases/\r\n\r\n    - Unzip:\r\n        - Version 5.52.\r\n        - Link: http://stahlworks.com/dev/?tool=zipunzip\r\n\r\n    - Wget:\r\n        - Version wget-1.20.3-win64.\r\n        - Link: https://eternallybored.org/misc/wget/\r\n"
  },
  {
    "path": "3rdparty/windows/getCaffe.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\nSET UNZIP_EXE=unzip\\unzip.exe\nSET WGET_EXE=wget\\wget.exe\n\n:: Download temporary zip\necho ----- Downloading Caffe -----\nSET CAFEE_FOLDER=caffe\\\nSET ZIP_NAME=caffe_16_2020_11_14.zip\nSET ZIP_FULL_PATH=%CAFEE_FOLDER%%ZIP_NAME%\n%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %CAFEE_FOLDER%\necho:\n\necho ----- Unzipping Caffe -----\n%UNZIP_EXE% %ZIP_FULL_PATH%\necho:\n\necho ----- Deleting Temporary Zip File %ZIP_FULL_PATH% -----\ndel \"%ZIP_FULL_PATH%\"\n\necho ----- Caffe Downloaded and Unzipped -----\n"
  },
  {
    "path": "3rdparty/windows/getCaffe3rdparty.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\nSET UNZIP_EXE=unzip\\unzip.exe\nSET WGET_EXE=wget\\wget.exe\n\n:: Download temporary zip\necho ----- Downloading Caffe -----\nSET CAFEE_FOLDER=caffe3rdparty\\\nSET ZIP_NAME=caffe3rdparty_16_2020_11_14.zip\nSET ZIP_FULL_PATH=%CAFEE_FOLDER%%ZIP_NAME%\n%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %CAFEE_FOLDER%\necho:\n\necho ----- Unzipping Caffe -----\n%UNZIP_EXE% %ZIP_FULL_PATH%\necho:\n\necho ----- Deleting Temporary Zip File %ZIP_FULL_PATH% -----\ndel \"%ZIP_FULL_PATH%\"\n\necho ----- Caffe Downloaded and Unzipped -----\n"
  },
  {
    "path": "3rdparty/windows/getFreeglut.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\nSET UNZIP_EXE=unzip\\unzip.exe\nSET WGET_EXE=wget\\wget.exe\n\n:: Download temporary zip\necho ----- Downloading Caffe -----\nSET FREEGLUT_FOLDER=freeglut\\\nSET ZIP_NAME=freeglut_2018_01_14.zip\nSET ZIP_FULL_PATH=%FREEGLUT_FOLDER%%ZIP_NAME%\n%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %FREEGLUT_FOLDER%\necho:\n\necho ----- Unzipping Caffe -----\n%UNZIP_EXE% %ZIP_FULL_PATH%\necho:\n\necho ----- Deleting Temporary Zip File %ZIP_FULL_PATH% -----\ndel \"%ZIP_FULL_PATH%\"\n\necho ----- Caffe Downloaded and Unzipped -----\n"
  },
  {
    "path": "3rdparty/windows/getOpenCV.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\nSET UNZIP_EXE=unzip\\unzip.exe\nSET WGET_EXE=wget\\wget.exe\n\n:: Download temporary zip\necho ----- Downloading OpenCV -----\nSET OPENCV_FOLDER=opencv\\\nSET ZIP_NAME=opencv_450_v15_2020_11_18.zip\nSET ZIP_FULL_PATH=%OPENCV_FOLDER%%ZIP_NAME%\n%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %OPENCV_FOLDER%\necho:\n\necho ----- Unzipping OpenCV -----\n%UNZIP_EXE% %ZIP_FULL_PATH%\necho:\n\necho ----- Deleting Temporary Zip File %ZIP_FULL_PATH% -----\ndel \"%ZIP_FULL_PATH%\"\n\necho ----- OpenCV Downloaded and Unzipped -----\n"
  },
  {
    "path": "3rdparty/windows/getSpinnaker.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\nSET UNZIP_EXE=unzip\\unzip.exe\nSET WGET_EXE=wget\\wget.exe\n\n:: Download temporary zip\necho ----- Downloading Caffe -----\nSET SPINNAKER_FOLDER=spinnaker\\\nSET ZIP_NAME=spinnaker_2018_01_24.zip\nSET ZIP_FULL_PATH=%SPINNAKER_FOLDER%%ZIP_NAME%\n%WGET_EXE% -c http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/%ZIP_NAME% -P %SPINNAKER_FOLDER%\necho:\n\necho ----- Unzipping Caffe -----\n%UNZIP_EXE% %ZIP_FULL_PATH%\necho:\n\n:: echo ----- Deleting Temporary Zip File %ZIP_FULL_PATH% -----\n:: del \"%ZIP_FULL_PATH%\"\n\necho ----- Caffe Downloaded and Unzipped -----\n"
  },
  {
    "path": "3rdparty/windows/wget/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "3rdparty/windows/wget/Version_wget-1.20.3-win64.txt",
    "content": "Version wget-1.20.3-win64 from:\n- https://eternallybored.org/misc/wget/\n"
  },
  {
    "path": "3rdparty/windows/wget/wget.html",
    "content": "<!-- Creator     : groff version 1.22.3 -->\n<!-- CreationDate: Sat Apr  6 16:01:09 2019 -->\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n\"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n<meta name=\"generator\" content=\"groff -Thtml, see www.gnu.org\">\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">\n<meta name=\"Content-Style\" content=\"text/css\">\n<style type=\"text/css\">\n       p       { margin-top: 0; margin-bottom: 0; vertical-align: top }\n       pre     { margin-top: 0; margin-bottom: 0; vertical-align: top }\n       table   { margin-top: 0; margin-bottom: 0; vertical-align: top }\n       h1      { text-align: center }\n</style>\n<title>WGET</title>\n\n</head>\n<body>\n\n<h1 align=\"center\">WGET</h1>\n\n<a href=\"#NAME\">NAME</a><br>\n<a href=\"#SYNOPSIS\">SYNOPSIS</a><br>\n<a href=\"#DESCRIPTION\">DESCRIPTION</a><br>\n<a href=\"#OPTIONS\">OPTIONS</a><br>\n<a href=\"#ENVIRONMENT\">ENVIRONMENT</a><br>\n<a href=\"#EXIT STATUS\">EXIT STATUS</a><br>\n<a href=\"#FILES\">FILES</a><br>\n<a href=\"#BUGS\">BUGS</a><br>\n<a href=\"#SEE ALSO\">SEE ALSO</a><br>\n<a href=\"#AUTHOR\">AUTHOR</a><br>\n<a href=\"#COPYRIGHT\">COPYRIGHT</a><br>\n\n<hr>\n\n\n<h2>NAME\n<a name=\"NAME\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget -\nThe non-interactive network downloader.</p>\n\n<h2>SYNOPSIS\n<a name=\"SYNOPSIS\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">wget\n[<i>option</i>]... [ <i><small>URL</small></i> ]...</p>\n\n<h2>DESCRIPTION\n<a name=\"DESCRIPTION\"></a>\n</h2>\n\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><small>GNU</small>\nWget is a free utility for non-interactive download of files\nfrom the Web. It supports <small>HTTP, HTTPS,</small> and\n<small>FTP</small> protocols, as well as retrieval through\n<small>HTTP</small> proxies.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget is\nnon-interactive, meaning that it can work in the background,\nwhile the user is not logged on. This allows you to start a\nretrieval and disconnect from the system, letting Wget\nfinish the work. By contrast, most of the Web browsers\nrequire constant user&rsquo;s presence, which can be a great\nhindrance when transferring a lot of data.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget can follow\nlinks in <small>HTML, XHTML,</small> and <small>CSS</small>\npages, to create local versions of remote web sites, fully\nrecreating the directory structure of the original site.\nThis is sometimes referred to as &quot;recursive\ndownloading.&quot; While doing that, Wget respects the Robot\nExclusion Standard (<i>/robots.txt</i>). Wget can be\ninstructed to convert the links in downloaded files to point\nat the local files, for offline viewing.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget has been\ndesigned for robustness over slow or unstable network\nconnections; if a download fails due to a network problem,\nit will keep retrying until the whole file has been\nretrieved. If the server supports regetting, it will\ninstruct the server to continue the download from where it\nleft off.</p>\n\n<h2>OPTIONS\n<a name=\"OPTIONS\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Option\nSyntax</b> <br>\nSince Wget uses <small>GNU</small> getopt to process\ncommand-line arguments, every option has a long form along\nwith the short one. Long options are more convenient to\nremember, but take time to type. You may freely mix\ndifferent option styles, or specify options after the\ncommand-line arguments. Thus you may write:</p>\n\n<pre style=\"margin-left:11%; margin-top: 1em\">        wget -r --tries=10 http://fly.srk.fer.hr/ -o log</pre>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">The space\nbetween the option accepting an argument and the argument\nmay be omitted. Instead of <b>-o log</b> you can write\n<b>-olog</b>.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">You may put\nseveral options that do not require arguments together,\nlike:</p>\n\n<pre style=\"margin-left:11%; margin-top: 1em\">        wget -drc &lt;URL&gt;</pre>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">This is\ncompletely equivalent to:</p>\n\n<pre style=\"margin-left:11%; margin-top: 1em\">        wget -d -r -c &lt;URL&gt;</pre>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Since the\noptions can be specified after the arguments, you may\nterminate them with <b>--</b>. So the following\nwill try to download <small>URL</small> <b>-x</b>,\nreporting failure to <i>log</i>:</p>\n\n<pre style=\"margin-left:11%; margin-top: 1em\">        wget -o log -- -x</pre>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">The options\nthat accept comma-separated lists all respect the convention\nthat specifying an empty list clears its value. This can be\nuseful to clear the <i>.wgetrc</i> settings. For instance,\nif your <i>.wgetrc</i> sets\n<tt>&quot;exclude_directories&quot;</tt> to\n<i>/cgi-bin</i>, the following example will first\nreset it, and then set it to exclude <i>/~nobody</i> and\n<i>/~somebody</i>. You can also clear the lists in\n<i>.wgetrc</i>.</p>\n\n<pre style=\"margin-left:11%; margin-top: 1em\">        wget -X &quot; -X /~nobody,/~somebody</pre>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Most options\nthat do not accept arguments are <i>boolean</i> options, so\nnamed because their state can be captured with a yes-or-no\n(&quot;boolean&quot;) variable. For example,\n<b>--follow-ftp</b> tells Wget to follow\n<small>FTP</small> links from <small>HTML</small> files and,\non the other hand, <b>--no-glob</b> tells\nit not to perform file globbing on <small>FTP</small> URLs.\nA boolean option is either <i>affirmative</i> or\n<i>negative</i> (beginning with <b>--no</b>).\nAll such options share several properties.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Unless stated\notherwise, it is assumed that the default behavior is the\nopposite of what the option accomplishes. For example, the\ndocumented existence of\n<b>--follow-ftp</b> assumes that the\ndefault is to <i>not</i> follow <small>FTP</small> links\nfrom <small>HTML</small> pages.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Affirmative\noptions can be negated by prepending the\n<b>--no-</b> to the option name; negative\noptions can be negated by omitting the\n<b>--no-</b> prefix. This might seem\nsuperfluous---if the default for an\naffirmative option is to not do something, then why provide\na way to explicitly turn it off? But the startup file may in\nfact change the default. For instance, using\n<tt>&quot;follow_ftp = on&quot;</tt> in <i>.wgetrc</i> makes\nWget <i>follow</i> <small>FTP</small> links by default, and\nusing <b>--no-follow-ftp</b> is the\nonly way to restore the factory default from the command\nline.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Basic\nStartup Options</b></p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-V</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--version</b></p>\n\n<p style=\"margin-left:17%;\">Display the version of\nWget.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-h</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n<p style=\"margin-left:11%;\"><b>--help</b></p>\n\n<p style=\"margin-left:17%;\">Print a help message describing\nall of Wget&rsquo;s command-line options.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-b</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--background</b></p>\n\n<p style=\"margin-left:17%;\">Go to background immediately\nafter startup. If no output file is specified via the\n<b>-o</b>, output is redirected to\n<i>wget-log</i>.</p>\n\n<p style=\"margin-left:11%;\"><b>-e</b> <i>command</i>\n<b><br>\n--execute</b> <i>command</i></p>\n\n<p style=\"margin-left:17%;\">Execute <i>command</i> as if it\nwere a part of <i>.wgetrc</i>. A command thus invoked will\nbe executed <i>after</i> the commands in <i>.wgetrc</i>,\nthus taking precedence over them. If you need to specify\nmore than one wgetrc command, use multiple instances of\n<b>-e</b>.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Logging and\nInput File Options <br>\n-o</b> <i>logfile</i> <b><br>\n--output-file=</b><i>logfile</i></p>\n\n<p style=\"margin-left:17%;\">Log all messages to\n<i>logfile</i>. The messages are normally reported to\nstandard error.</p>\n\n<p style=\"margin-left:11%;\"><b>-a</b> <i>logfile</i>\n<b><br>\n--append-output=</b><i>logfile</i></p>\n\n<p style=\"margin-left:17%;\">Append to <i>logfile</i>. This\nis the same as <b>-o</b>, only it appends to\n<i>logfile</i> instead of overwriting the old log file. If\n<i>logfile</i> does not exist, a new file is created.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-d</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n<p style=\"margin-left:11%;\"><b>--debug</b></p>\n\n<p style=\"margin-left:17%;\">Turn on debug output, meaning\nvarious information important to the developers of Wget if\nit does not work properly. Your system administrator may\nhave chosen to compile Wget without debug support, in which\ncase <b>-d</b> will not work. Please note that\ncompiling with debug support is always\nsafe---Wget compiled with the debug\nsupport will <i>not</i> print any debug info unless\nrequested with <b>-d</b>.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-q</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n<p style=\"margin-left:11%;\"><b>--quiet</b></p>\n\n<p style=\"margin-left:17%;\">Turn off Wget&rsquo;s\noutput.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-v</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--verbose</b></p>\n\n<p style=\"margin-left:17%;\">Turn on verbose output, with\nall the available data. The default output is verbose.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"4%\">\n\n\n<p><b>-nv</b></p></td>\n<td width=\"85%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--no-verbose</b></p>\n\n<p style=\"margin-left:17%;\">Turn off verbose without being\ncompletely quiet (use <b>-q</b> for that), which means\nthat error messages and basic information still get\nprinted.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--report-speed=</b><i>type</i></p>\n\n<p style=\"margin-left:17%;\">Output bandwidth as\n<i>type</i>. The only accepted value is <b>bits</b>.</p>\n\n<p style=\"margin-left:11%;\"><b>-i</b> <i>file</i>\n<b><br>\n--input-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Read URLs from a local or\nexternal <i>file</i>. If <b>-</b> is specified as\n<i>file</i>, URLs are read from the standard input. (Use\n<b>./-</b> to read from a file literally named\n<b>-</b>.)</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If this\nfunction is used, no URLs need be present on the command\nline. If there are URLs both on the command line and in an\ninput file, those on the command lines will be the first\nones to be retrieved. If\n<b>--force-html</b> is not specified, then\n<i>file</i> should consist of a series of URLs, one per\nline.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">However, if you\nspecify <b>--force-html</b>, the document\nwill be regarded as <b>html</b>. In that case you may have\nproblems with relative links, which you can solve either by\nadding <tt>&quot;&lt;base\nhref=&quot;</tt><i>url</i><tt>&quot;&gt;&quot;</tt> to the\ndocuments or by specifying\n<b>--base=</b><i>url</i> on the command\nline.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If the\n<i>file</i> is an external one, the document will be\nautomatically treated as <b>html</b> if the Content-Type\nmatches <b>text/html</b>. Furthermore, the\n<i>file</i>&rsquo;s location will be implicitly used as base\nhref if none was specified.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--input-metalink=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Downloads files covered in\nlocal Metalink <i>file</i>. Metalink version 3 and 4 are\nsupported.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--keep-badhash</b></p>\n\n<p style=\"margin-left:17%;\">Keeps downloaded\nMetalink&rsquo;s files with a bad hash. It appends .badhash\nto the name of Metalink&rsquo;s files which have a checksum\nmismatch, except without overwriting existing files.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--metalink-over-http</b></p>\n\n<p style=\"margin-left:17%;\">Issues <small>HTTP HEAD</small>\nrequest instead of <small>GET</small> and extracts Metalink\nmetadata from response headers. Then it switches to Metalink\ndownload. If no valid Metalink metadata is found, it falls\nback to ordinary <small>HTTP</small> download. Enables\n<b>Content-Type: application/metalink4+xml</b> files\ndownload/processing.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--metalink-index=</b><i>number</i></p>\n\n<p style=\"margin-left:17%;\">Set the Metalink\n<b>application/metalink4+xml</b> metaurl ordinal\n<small>NUMBER.</small> From 1 to the total number of\n&quot;application/metalink4+xml&quot; available. Specify 0\nor <b>inf</b> to choose the first good one. Metaurls, such\nas those from a\n<b>--metalink-over-http</b>, may\nhave been sorted by priority key&rsquo;s value; keep this in\nmind to choose the right <small>NUMBER.</small></p>\n\n\n<p style=\"margin-left:11%;\"><b>--preferred-location</b></p>\n\n<p style=\"margin-left:17%;\">Set preferred location for\nMetalink resources. This has effect if multiple resources\nwith same priority are available.</p>\n\n<p style=\"margin-left:11%;\"><b>--xattr</b></p>\n\n<p style=\"margin-left:17%;\">Enable use of file\nsystem&rsquo;s extended attributes to save the original\n<small>URL</small> and the Referer <small>HTTP</small>\nheader value if used.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Be aware that\nthe <small>URL</small> might contain private information\nlike access tokens or credentials.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-F</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--force-html</b></p>\n\n<p style=\"margin-left:17%;\">When input is read from a file,\nforce it to be treated as an <small>HTML</small> file. This\nenables you to retrieve relative links from existing\n<small>HTML</small> files on your local disk, by adding\n<tt>&quot;&lt;base\nhref=&quot;</tt><i>url</i><tt>&quot;&gt;&quot;</tt> to\n<small>HTML,</small> or using the <b>--base</b>\ncommand-line option.</p>\n\n<p style=\"margin-left:11%;\"><b>-B</b>\n<i><small>URL</small></i> <b><br>\n--base=</b> <i><small>URL</small></i></p>\n\n<p style=\"margin-left:17%;\">Resolves relative links using\n<i><small>URL</small></i> as the point of reference, when\nreading links from an <small>HTML</small> file specified via\nthe <b>-i</b>/<b>--input-file</b>\noption (together with <b>--force-html</b>,\nor when the input file was fetched remotely from a server\ndescribing it as <small>HTML</small> ). This is equivalent\nto the presence of a <tt>&quot;BASE&quot;</tt> tag in the\n<small>HTML</small> input file, with\n<i><small>URL</small></i> as the value for the\n<tt>&quot;href&quot;</tt> attribute.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">For instance,\nif you specify <b>http://foo/bar/a.html</b> for\n<i><small>URL</small></i> , and Wget reads\n<b>../baz/b.html</b> from the input file, it would be\nresolved to <b>http://foo/baz/b.html</b>.</p>\n\n<p style=\"margin-left:11%;\"><b>--config=</b>\n<i><small>FILE</small></i></p>\n\n<p style=\"margin-left:17%;\">Specify the location of a\nstartup file you wish to use instead of the default one(s).\nUse --no-config to disable reading of\nconfig files. If both --config and\n--no-config are given,\n--no-config is ignored.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--rejected-log=</b><i>logfile</i></p>\n\n<p style=\"margin-left:17%;\">Logs all <small>URL</small>\nrejections to <i>logfile</i> as comma separated values. The\nvalues include the reason of rejection, the\n<small>URL</small> and the parent <small>URL</small> it was\nfound in.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Download\nOptions <br>\n--bind-address=</b>\n<i><small>ADDRESS</small></i></p>\n\n<p style=\"margin-left:17%;\">When making client\n<small>TCP/IP</small> connections, bind to\n<i><small>ADDRESS</small></i> on the local machine.\n<i><small>ADDRESS</small></i> may be specified as a hostname\nor <small>IP</small> address. This option can be useful if\nyour machine is bound to multiple IPs.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--bind-dns-address=</b>\n<i><small>ADDRESS</small></i></p>\n\n<p style=\"margin-left:17%;\">[libcares only] This address\noverrides the route for <small>DNS</small> requests. If you\never need to circumvent the standard settings from\n/etc/resolv.conf, this option together with\n<b>--dns-servers</b> is your friend.\n<i><small>ADDRESS</small></i> must be specified either as\nIPv4 or IPv6 address. Wget needs to be built with libcares\nfor this option to be available.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--dns-servers=</b>\n<i><small>ADDRESSES</small></i></p>\n\n<p style=\"margin-left:17%;\">[libcares only] The given\naddress(es) override the standard nameserver addresses, e.g.\nas configured in /etc/resolv.conf.\n<i><small>ADDRESSES</small></i> may be specified either as\nIPv4 or IPv6 addresses, comma-separated. Wget needs to be\nbuilt with libcares for this option to be available.</p>\n\n<p style=\"margin-left:11%;\"><b>-t</b> <i>number</i>\n<b><br>\n--tries=</b><i>number</i></p>\n\n<p style=\"margin-left:17%;\">Set number of tries to\n<i>number</i>. Specify 0 or <b>inf</b> for infinite\nretrying. The default is to retry 20 times, with the\nexception of fatal errors like &quot;connection\nrefused&quot; or &quot;not found&quot; (404), which are not\nretried.</p>\n\n<p style=\"margin-left:11%;\"><b>-O</b> <i>file</i>\n<b><br>\n--output-document=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">The documents will not be\nwritten to the appropriate files, but all will be\nconcatenated together and written to <i>file</i>. If\n<b>-</b> is used as <i>file</i>, documents will be\nprinted to standard output, disabling link conversion. (Use\n<b>./-</b> to print to a file literally named\n<b>-</b>.)</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Use of\n<b>-O</b> is <i>not</i> intended to mean simply\n&quot;use the name <i>file</i> instead of the one in the\n<small>URL</small> ;&quot; rather, it is analogous to shell\nredirection: <b>wget -O file http://foo</b> is\nintended to work like <b>wget -O - http://foo\n&gt; file</b>; <i>file</i> will be truncated immediately,\nand <i>all</i> downloaded content will be written there.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">For this\nreason, <b>-N</b> (for timestamp-checking) is not\nsupported in combination with <b>-O</b>: since\n<i>file</i> is always newly created, it will always have a\nvery new timestamp. A warning will be issued if this\ncombination is used.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Similarly,\nusing <b>-r</b> or <b>-p</b> with\n<b>-O</b> may not work as you expect: Wget won&rsquo;t\njust download the first file to <i>file</i> and then\ndownload the rest to their normal names: <i>all</i>\ndownloaded content will be placed in <i>file</i>. This was\ndisabled in version 1.11, but has been reinstated (with a\nwarning) in 1.11.2, as there are some cases where this\nbehavior can actually have some use.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">A combination\nwith <b>-nc</b> is only accepted if the given output\nfile does not exist.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that a\ncombination with <b>-k</b> is only permitted when\ndownloading a single document, as in that case it will just\nconvert all relative URIs to external ones; <b>-k</b>\nmakes no sense for multiple URIs when they&rsquo;re all\nbeing downloaded to a single file; <b>-k</b> can be\nused only when the output is a regular file.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"4%\">\n\n\n<p><b>-nc</b></p></td>\n<td width=\"85%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--no-clobber</b></p>\n\n<p style=\"margin-left:17%;\">If a file is downloaded more\nthan once in the same directory, Wget&rsquo;s behavior\ndepends on a few options, including <b>-nc</b>. In\ncertain cases, the local file will be <i>clobbered</i>, or\noverwritten, upon repeated download. In other cases it will\nbe preserved.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When running\nWget without <b>-N</b>, <b>-nc</b>,\n<b>-r</b>, or <b>-p</b>, downloading the same\nfile in the same directory will result in the original copy\nof <i>file</i> being preserved and the second copy being\nnamed <i>file</i><b>.1</b>. If that file is downloaded yet\nagain, the third copy will be named <i>file</i><b>.2</b>,\nand so on. (This is also the behavior with <b>-nd</b>,\neven if <b>-r</b> or <b>-p</b> are in effect.)\nWhen <b>-nc</b> is specified, this behavior is\nsuppressed, and Wget will refuse to download newer copies of\n<i>file</i>. Therefore,\n&quot;<tt>&quot;no-clobber&quot;</tt>&quot; is\nactually a misnomer in this\nmode---it&rsquo;s not clobbering\nthat&rsquo;s prevented (as the numeric suffixes were already\npreventing clobbering), but rather the multiple version\nsaving that&rsquo;s prevented.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When running\nWget with <b>-r</b> or <b>-p</b>, but without\n<b>-N</b>, <b>-nd</b>, or <b>-nc</b>,\nre-downloading a file will result in the new copy simply\noverwriting the old. Adding <b>-nc</b> will prevent\nthis behavior, instead causing the original version to be\npreserved and any newer copies on the server to be\nignored.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When running\nWget with <b>-N</b>, with or without <b>-r</b>\nor <b>-p</b>, the decision as to whether or not to\ndownload a newer copy of a file depends on the local and\nremote timestamp and size of the file. <b>-nc</b> may\nnot be specified at the same time as <b>-N</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">A combination\nwith\n<b>-O</b>/<b>--output-document</b>\nis only accepted if the given output file does not\nexist.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that when\n<b>-nc</b> is specified, files with the suffixes\n<b>.html</b> or <b>.htm</b> will be loaded from the local\ndisk and parsed as if they had been retrieved from the\nWeb.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--backups=</b><i>backups</i></p>\n\n<p style=\"margin-left:17%;\">Before (over)writing a file,\nback up an existing file by adding a <b>.1</b> suffix\n(<b>_1</b> on <small>VMS</small> ) to the file name. Such\nbackup files are rotated to <b>.2</b>, <b>.3</b>, and so on,\nup to <i>backups</i> (and lost beyond that).</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-netrc</b></p>\n\n<p style=\"margin-left:17%;\">Do not try to obtain\ncredentials from <i>.netrc</i> file. By default\n<i>.netrc</i> file is searched for credentials in case none\nhave been passed on command line and authentication is\nrequired.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-c</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--continue</b></p>\n\n<p style=\"margin-left:17%;\">Continue getting a\npartially-downloaded file. This is useful when you want to\nfinish up a download started by a previous instance of Wget,\nor by another program. For instance:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -c ftp://sunsite.doc.ic.ac.uk/ls-lR.Z</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">If there is a\nfile named <i>ls-lR.Z</i> in the current directory,\nWget will assume that it is the first portion of the remote\nfile, and will ask the server to continue the retrieval from\nan offset equal to the length of the local file.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that you\ndon&rsquo;t need to specify this option if you just want the\ncurrent invocation of Wget to retry downloading a file\nshould the connection be lost midway through. This is the\ndefault behavior. <b>-c</b> only affects resumption of\ndownloads started <i>prior</i> to this invocation of Wget,\nand whose local files are still sitting around.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Without\n<b>-c</b>, the previous example would just download\nthe remote file to <i>ls-lR.Z.1</i>, leaving the\ntruncated <i>ls-lR.Z</i> file alone.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you use\n<b>-c</b> on a non-empty file, and the server does not\nsupport continued downloading, Wget will restart the\ndownload from scratch and overwrite the existing file\nentirely.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Beginning with\nWget 1.7, if you use <b>-c</b> on a file which is of\nequal size as the one on the server, Wget will refuse to\ndownload the file and print an explanatory message. The same\nhappens when the file is smaller on the server than locally\n(presumably because it was changed on the server since your\nlast download attempt)---because\n&quot;continuing&quot; is not meaningful, no download\noccurs.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">On the other\nside of the coin, while using <b>-c</b>, any file\nthat&rsquo;s bigger on the server than locally will be\nconsidered an incomplete download and only\n<tt>&quot;(length(remote) - length(local))&quot;</tt>\nbytes will be downloaded and tacked onto the end of the\nlocal file. This behavior can be desirable in certain\ncases---for instance, you can use <b>wget\n-c</b> to download just the new portion that&rsquo;s\nbeen appended to a data collection or log file.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">However, if the\nfile is bigger on the server because it&rsquo;s been\n<i>changed</i>, as opposed to just <i>appended</i> to,\nyou&rsquo;ll end up with a garbled file. Wget has no way of\nverifying that the local file is really a valid prefix of\nthe remote file. You need to be especially careful of this\nwhen using <b>-c</b> in conjunction with\n<b>-r</b>, since every file will be considered as an\n&quot;incomplete download&quot; candidate.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Another\ninstance where you&rsquo;ll get a garbled file if you try to\nuse <b>-c</b> is if you have a lame\n<small>HTTP</small> proxy that inserts a &quot;transfer\ninterrupted&quot; string into the local file. In the future\na &quot;rollback&quot; option may be added to deal with this\ncase.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that\n<b>-c</b> only works with <small>FTP</small> servers\nand with <small>HTTP</small> servers that support the\n<tt>&quot;Range&quot;</tt> header.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--start-pos=</b>\n<i><small>OFFSET</small></i></p>\n\n<p style=\"margin-left:17%;\">Start downloading at zero-based\nposition <i><small>OFFSET</small></i> . Offset may be\nexpressed in bytes, kilobytes with the &lsquo;k&rsquo;\nsuffix, or megabytes with the &lsquo;m&rsquo; suffix,\netc.</p>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\"><b>--start-pos</b>\nhas higher precedence over <b>--continue</b>.\nWhen <b>--start-pos</b> and\n<b>--continue</b> are both specified, wget will\nemit a warning then proceed as if\n<b>--continue</b> was absent.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Server support\nfor continued download is required, otherwise\n<b>--start-pos</b> cannot help. See\n<b>-c</b> for details.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--progress=</b><i>type</i></p>\n\n<p style=\"margin-left:17%;\">Select the type of the progress\nindicator you wish to use. Legal indicators are\n&quot;dot&quot; and &quot;bar&quot;.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n&quot;bar&quot; indicator is used by default. It draws an\n<small>ASCII</small> progress bar graphics (a.k.a\n&quot;thermometer&quot; display) indicating the status of\nretrieval. If the output is not a <small>TTY,</small> the\n&quot;dot&quot; bar will be used by default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Use\n<b>--progress=dot</b> to switch to the\n&quot;dot&quot; display. It traces the retrieval by printing\ndots on the screen, each dot representing a fixed amount of\ndownloaded data.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The progress\n<i>type</i> can also take one or more parameters. The\nparameters vary based on the <i>type</i> selected.\nParameters to <i>type</i> are passed by appending them to\nthe type sperated by a colon (:) like this:\n<b>--progress=</b><i>type</i><b>:</b><i>parameter1</i><b>:</b><i>parameter2</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When using the\ndotted retrieval, you may set the <i>style</i> by specifying\nthe type as <b>dot:</b><i>style</i>. Different styles assign\ndifferent meaning to one dot. With the\n<tt>&quot;default&quot;</tt> style each dot represents 1K,\nthere are ten dots in a cluster and 50 dots in a line. The\n<tt>&quot;binary&quot;</tt> style has a more\n&quot;computer&quot;-like\norientation---8K dots, 16-dots\nclusters and 48 dots per line (which makes for 384K lines).\nThe <tt>&quot;mega&quot;</tt> style is suitable for\ndownloading large files---each dot\nrepresents 64K retrieved, there are eight dots in a cluster,\nand 48 dots on each line (so each line contains 3M). If\n<tt>&quot;mega&quot;</tt> is not enough then you can use the\n<tt>&quot;giga&quot;</tt> style---each dot\nrepresents 1M retrieved, there are eight dots in a cluster,\nand 32 dots on each line (so each line contains 32M).</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">With\n<b>--progress=bar</b>, there are currently two\npossible parameters, <i>force</i> and <i>noscroll</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When the output\nis not a <small>TTY,</small> the progress bar always falls\nback to &quot;dot&quot;, even if\n<b>--progress=bar</b> was passed to Wget during\ninvocation. This behaviour can be overridden and the\n&quot;bar&quot; output forced by using the &quot;force&quot;\nparameter as <b>--progress=bar:force</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default, the\n<b>bar</b> style progress bar scroll the name of the file\nfrom left to right for the file being downloaded if the\nfilename exceeds the maximum length allotted for its\ndisplay. In certain cases, such as with\n<b>--progress=bar:force</b>, one may not want\nthe scrolling filename in the progress bar. By passing the\n&quot;noscroll&quot; parameter, Wget can be forced to\ndisplay as much of the filename as possible without\nscrolling through it.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that you\ncan set the default style using the\n<tt>&quot;progress&quot;</tt> command in <i>.wgetrc</i>.\nThat setting may be overridden from the command line. For\nexample, to force the bar output without scrolling, use\n<b>--progress=bar:force:noscroll</b>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--show-progress</b></p>\n\n<p style=\"margin-left:17%;\">Force wget to display the\nprogress bar in any verbosity.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default,\nwget only displays the progress bar in verbose mode. One may\nhowever, want wget to display the progress bar on screen in\nconjunction with any other verbosity modes like\n<b>--no-verbose</b> or\n<b>--quiet</b>. This is often a desired a\nproperty when invoking wget to download several small/large\nfiles. In such a case, wget could simply be invoked with\nthis parameter to get a much cleaner output on the\nscreen.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This option\nwill also force the progress bar to be printed to\n<i>stderr</i> when used alongside the\n<b>--output-file</b> option.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-N</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--timestamping</b></p>\n\n<p style=\"margin-left:17%;\">Turn on time-stamping.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-if-modified-since</b></p>\n\n<p style=\"margin-left:17%;\">Do not send If-Modified-Since\nheader in <b>-N</b> mode. Send preliminary\n<small>HEAD</small> request instead. This has only effect in\n<b>-N</b> mode.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-use-server-timestamps</b></p>\n\n<p style=\"margin-left:17%;\">Don&rsquo;t set the local\nfile&rsquo;s timestamp by the one on the server.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default,\nwhen a file is downloaded, its timestamps are set to match\nthose from the remote file. This allows the use of\n<b>--timestamping</b> on subsequent invocations\nof wget. However, it is sometimes useful to base the local\nfile&rsquo;s timestamp on when it was actually downloaded;\nfor that purpose, the\n<b>--no-use-server-timestamps</b>\noption has been provided.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-S</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--server-response</b></p>\n\n<p style=\"margin-left:17%;\">Print the headers sent by\n<small>HTTP</small> servers and responses sent by\n<small>FTP</small> servers.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--spider</b></p>\n\n<p style=\"margin-left:17%;\">When invoked with this option,\nWget will behave as a Web <i>spider</i>, which means that it\nwill not download the pages, just check that they are there.\nFor example, you can use Wget to check your bookmarks:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget --spider --force-html -i bookmarks.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">This feature\nneeds much more work for Wget to get close to the\nfunctionality of real web spiders.</p>\n\n<p style=\"margin-left:11%;\"><b>-T seconds <br>\n--timeout=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">Set the network timeout to\n<i>seconds</i> seconds. This is equivalent to specifying\n<b>--dns-timeout</b>,\n<b>--connect-timeout</b>, and\n<b>--read-timeout</b>, all at the same\ntime.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When\ninteracting with the network, Wget can check for timeout and\nabort the operation if it takes too long. This prevents\nanomalies like hanging reads and infinite connects. The only\ntimeout enabled by default is a 900-second read\ntimeout. Setting a timeout to 0 disables it altogether.\nUnless you know what you are doing, it is best not to change\nthe default timeout settings.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">All\ntimeout-related options accept decimal values, as well as\nsubsecond values. For example, <b>0.1</b> seconds is a legal\n(though unwise) choice of timeout. Subsecond timeouts are\nuseful for checking server response times or for testing\nnetwork latency.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--dns-timeout=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">Set the <small>DNS</small>\nlookup timeout to <i>seconds</i> seconds. <small>DNS</small>\nlookups that don&rsquo;t complete within the specified time\nwill fail. By default, there is no timeout on\n<small>DNS</small> lookups, other than that implemented by\nsystem libraries.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--connect-timeout=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">Set the connect timeout to\n<i>seconds</i> seconds. <small>TCP</small> connections that\ntake longer to establish will be aborted. By default, there\nis no connect timeout, other than that implemented by system\nlibraries.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--read-timeout=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">Set the read (and write)\ntimeout to <i>seconds</i> seconds. The &quot;time&quot; of\nthis timeout refers to <i>idle time</i>: if, at any point in\nthe download, no data is received for more than the\nspecified number of seconds, reading fails and the download\nis restarted. This option does not directly affect the\nduration of the entire download.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Of course, the\nremote server may choose to terminate the connection sooner\nthan this option requires. The default read timeout is 900\nseconds.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--limit-rate=</b><i>amount</i></p>\n\n<p style=\"margin-left:17%;\">Limit the download speed to\n<i>amount</i> bytes per second. Amount may be expressed in\nbytes, kilobytes with the <b>k</b> suffix, or megabytes with\nthe <b>m</b> suffix. For example,\n<b>--limit-rate=20k</b> will limit the\nretrieval rate to 20KB/s. This is useful when, for whatever\nreason, you don&rsquo;t want Wget to consume the entire\navailable bandwidth.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This option\nallows the use of decimal numbers, usually in conjunction\nwith power suffixes; for example,\n<b>--limit-rate=2.5k</b> is a legal\nvalue.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that Wget\nimplements the limiting by sleeping the appropriate amount\nof time after a network read that took less time than\nspecified by the rate. Eventually this strategy causes the\n<small>TCP</small> transfer to slow down to approximately\nthe specified rate. However, it may take some time for this\nbalance to be achieved, so don&rsquo;t be surprised if\nlimiting the rate doesn&rsquo;t work well with very small\nfiles.</p>\n\n<p style=\"margin-left:11%;\"><b>-w</b> <i>seconds</i>\n<b><br>\n--wait=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">Wait the specified number of\nseconds between the retrievals. Use of this option is\nrecommended, as it lightens the server load by making the\nrequests less frequent. Instead of in seconds, the time can\nbe specified in minutes using the <tt>&quot;m&quot;</tt>\nsuffix, in hours using <tt>&quot;h&quot;</tt> suffix, or in\ndays using <tt>&quot;d&quot;</tt> suffix.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Specifying a\nlarge value for this option is useful if the network or the\ndestination host is down, so that Wget can wait long enough\nto reasonably expect the network error to be fixed before\nthe retry. The waiting interval specified by this function\nis influenced by\n<tt>&quot;--random-wait&quot;</tt>, which\nsee.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--waitretry=</b><i>seconds</i></p>\n\n<p style=\"margin-left:17%;\">If you don&rsquo;t want Wget to\nwait between <i>every</i> retrieval, but only between\nretries of failed downloads, you can use this option. Wget\nwill use <i>linear backoff</i>, waiting 1 second after the\nfirst failure on a given file, then waiting 2 seconds after\nthe second failure on that file, up to the maximum number of\n<i>seconds</i> you specify.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default,\nWget will assume a value of 10 seconds.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--random-wait</b></p>\n\n<p style=\"margin-left:17%;\">Some web sites may perform log\nanalysis to identify retrieval programs such as Wget by\nlooking for statistically significant similarities in the\ntime between requests. This option causes the time between\nrequests to vary between 0.5 and 1.5 * <i>wait</i> seconds,\nwhere <i>wait</i> was specified using the\n<b>--wait</b> option, in order to mask\nWget&rsquo;s presence from such analysis.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">A 2001 article\nin a publication devoted to development on a popular\nconsumer platform provided code to perform this analysis on\nthe fly. Its author suggested blocking at the class C\naddress level to ensure automated retrieval programs were\nblocked despite changing DHCP-supplied addresses.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<b>--random-wait</b> option was inspired\nby this ill-advised recommendation to block many unrelated\nusers from a web site due to the actions of one.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-proxy</b></p>\n\n<p style=\"margin-left:17%;\">Don&rsquo;t use proxies, even\nif the appropriate <tt>*_proxy</tt> environment variable is\ndefined.</p>\n\n<p style=\"margin-left:11%;\"><b>-Q</b> <i>quota</i>\n<b><br>\n--quota=</b><i>quota</i></p>\n\n<p style=\"margin-left:17%;\">Specify download quota for\nautomatic retrievals. The value can be specified in bytes\n(default), kilobytes (with <b>k</b> suffix), or megabytes\n(with <b>m</b> suffix).</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that quota\nwill never affect downloading a single file. So if you\nspecify <b>wget -Q10k\nhttps://example.com/ls-lR.gz</b>, all of the\n<i>ls-lR.gz</i> will be downloaded. The same goes even\nwhen several URLs are specified on the command-line.\nHowever, quota is respected when retrieving either\nrecursively, or from an input file. Thus you may safely type\n<b>wget -Q2m -i\nsites</b>---download will be aborted when\nthe quota is exceeded.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Setting quota\nto 0 or to <b>inf</b> unlimits the download quota.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-dns-cache</b></p>\n\n<p style=\"margin-left:17%;\">Turn off caching of\n<small>DNS</small> lookups. Normally, Wget remembers the\n<small>IP</small> addresses it looked up from\n<small>DNS</small> so it doesn&rsquo;t have to repeatedly\ncontact the <small>DNS</small> server for the same\n(typically small) set of hosts it retrieves from. This cache\nexists in memory only; a new Wget run will contact\n<small>DNS</small> again.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">However, it has\nbeen reported that in some situations it is not desirable to\ncache host names, even for the duration of a short-running\napplication like Wget. With this option Wget issues a new\n<small>DNS</small> lookup (more precisely, a new call to\n<tt>&quot;gethostbyname&quot;</tt> or\n<tt>&quot;getaddrinfo&quot;</tt>) each time it makes a new\nconnection. Please note that this option will <i>not</i>\naffect caching that might be performed by the resolving\nlibrary or by an external caching layer, such as\n<small>NSCD.</small></p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you\ndon&rsquo;t understand exactly what this option does, you\nprobably won&rsquo;t need it.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--restrict-file-names=</b><i>modes</i></p>\n\n<p style=\"margin-left:17%;\">Change which characters found\nin remote URLs must be escaped during generation of local\nfilenames. Characters that are <i>restricted</i> by this\noption are escaped, i.e. replaced with <b>%HH</b>, where\n<b><small>HH</small></b> is the hexadecimal number that\ncorresponds to the restricted character. This option may\nalso be used to force all alphabetical cases to be either\nlower- or uppercase.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default,\nWget escapes the characters that are not valid or safe as\npart of file names on your operating system, as well as\ncontrol characters that are typically unprintable. This\noption is useful for changing these defaults, perhaps\nbecause you are downloading to a non-native partition, or\nbecause you want to disable escaping of the control\ncharacters, or you want to further restrict characters to\nonly those in the <small>ASCII</small> range of values.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<i>modes</i> are a comma-separated set of text values. The\nacceptable values are <b>unix</b>, <b>windows</b>,\n<b>nocontrol</b>, <b>ascii</b>, <b>lowercase</b>, and\n<b>uppercase</b>. The values <b>unix</b> and <b>windows</b>\nare mutually exclusive (one will override the other), as are\n<b>lowercase</b> and <b>uppercase</b>. Those last are\nspecial cases, as they do not change the set of characters\nthat would be escaped, but rather force local file paths to\nbe converted either to lower- or uppercase.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When\n&quot;unix&quot; is specified, Wget escapes the character\n<b>/</b> and the control characters in the ranges\n0--31 and 128--159. This is the\ndefault on Unix-like operating systems.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When\n&quot;windows&quot; is given, Wget escapes the characters\n<b>\\</b>, <b>|</b>, <b>/</b>, <b>:</b>, <b>?</b>,\n<b>&quot;</b>, <b>*</b>, <b>&lt;</b>, <b>&gt;</b>, and the\ncontrol characters in the ranges 0--31 and\n128--159. In addition to this, Wget in Windows\nmode uses <b>+</b> instead of <b>:</b> to separate host and\nport in local file names, and uses <b>@</b> instead of\n<b>?</b> to separate the query portion of the file name from\nthe rest. Therefore, a <small>URL</small> that would be\nsaved as <b>www.xemacs.org:4300/search.pl?input=blah</b> in\nUnix mode would be saved as\n<b>www.xemacs.org+4300/search.pl@input=blah</b> in Windows\nmode. This mode is the default on Windows.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you specify\n<b>nocontrol</b>, then the escaping of the control\ncharacters is also switched off. This option may make sense\nwhen you are downloading URLs whose names contain\n<small>UTF-8</small> characters, on a system which can\nsave and display filenames in <small>UTF-8</small>\n(some possible byte values used in\n<small>UTF-8</small> byte sequences fall in the range\nof values designated by Wget as &quot;controls&quot;).</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<b>ascii</b> mode is used to specify that any bytes whose\nvalues are outside the range of <small>ASCII</small>\ncharacters (that is, greater than 127) shall be escaped.\nThis can be useful when saving filenames whose encoding does\nnot match the one used locally.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-4</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--inet4-only</b></p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-6</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--inet6-only</b></p>\n\n<p style=\"margin-left:17%;\">Force connecting to IPv4 or\nIPv6 addresses. With <b>--inet4-only</b>\nor <b>-4</b>, Wget will only connect to IPv4 hosts,\nignoring <small>AAAA</small> records in <small>DNS,</small>\nand refusing to connect to IPv6 addresses specified in URLs.\nConversely, with <b>--inet6-only</b> or\n<b>-6</b>, Wget will only connect to IPv6 hosts and\nignore A records and IPv4 addresses.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Neither options\nshould be needed normally. By default, an IPv6-aware\nWget will use the address family specified by the\nhost&rsquo;s <small>DNS</small> record. If the\n<small>DNS</small> responds with both IPv4 and IPv6\naddresses, Wget will try them in sequence until it finds one\nit can connect to. (Also see\n<tt>&quot;--prefer-family&quot;</tt>\noption described below.)</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">These options\ncan be used to deliberately force the use of IPv4 or IPv6\naddress families on dual family systems, usually to aid\ndebugging or to deal with broken network configuration. Only\none of <b>--inet6-only</b> and\n<b>--inet4-only</b> may be specified at\nthe same time. Neither option is available in Wget compiled\nwithout IPv6 support.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--prefer-family=none/IPv4/IPv6</b></p>\n\n<p style=\"margin-left:17%;\">When given a choice of several\naddresses, connect to the addresses with specified address\nfamily first. The address order returned by\n<small>DNS</small> is used without change by default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This avoids\nspurious errors and connect attempts when accessing hosts\nthat resolve to both IPv6 and IPv4 addresses from IPv4\nnetworks. For example, <b>www.kame.net</b> resolves to\n<b>2001:200:0:8002:203:47ff:fea5:3085</b> and to\n<b>203.178.141.194</b>. When the preferred family is\n<tt>&quot;IPv4&quot;</tt>, the IPv4 address is used first;\nwhen the preferred family is <tt>&quot;IPv6&quot;</tt>, the\nIPv6 address is used first; if the specified value is\n<tt>&quot;none&quot;</tt>, the address order returned by\n<small>DNS</small> is used without change.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Unlike\n<b>-4</b> and <b>-6</b>, this option\ndoesn&rsquo;t inhibit access to any address family, it only\nchanges the <i>order</i> in which the addresses are\naccessed. Also note that the reordering performed by this\noption is <i>stable</i>---it doesn&rsquo;t\naffect order of addresses of the same family. That is, the\nrelative order of all IPv4 addresses and of all IPv6\naddresses remains intact in all cases.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--retry-connrefused</b></p>\n\n<p style=\"margin-left:17%;\">Consider &quot;connection\nrefused&quot; a transient error and try again. Normally Wget\ngives up on a <small>URL</small> when it is unable to\nconnect to the site because failure to connect is taken as a\nsign that the server is not running at all and that retries\nwould not help. This option is for mirroring unreliable\nsites whose servers tend to disappear for short periods of\ntime.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--user=</b><i>user</i>\n<b><br>\n--password=</b><i>password</i></p>\n\n<p style=\"margin-left:17%;\">Specify the username\n<i>user</i> and password <i>password</i> for both\n<small>FTP</small> and <small>HTTP</small> file retrieval.\nThese parameters can be overridden using the\n<b>--ftp-user</b> and\n<b>--ftp-password</b> options for\n<small>FTP</small> connections and the\n<b>--http-user</b> and\n<b>--http-password</b> options for\n<small>HTTP</small> connections.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ask-password</b></p>\n\n<p style=\"margin-left:17%;\">Prompt for a password for each\nconnection established. Cannot be specified when\n<b>--password</b> is being used, because they\nare mutually exclusive.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--use-askpass=</b><i>command</i></p>\n\n<p style=\"margin-left:17%;\">Prompt for a user and password\nusing the specified command. If no command is specified then\nthe command in the environment variable\n<small>WGET_ASKPASS</small> is used. If\n<small>WGET_ASKPASS</small> is not set then the command in\nthe environment variable <small>SSH_ASKPASS</small> is\nused.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You can set the\ndefault command for use-askpass in the <i>.wgetrc</i>. That\nsetting may be overridden from the command line.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-iri</b></p>\n\n<p style=\"margin-left:17%;\">Turn off internationalized\n<small>URI</small> ( <small>IRI</small> ) support. Use\n<b>--iri</b> to turn it on. <small>IRI</small>\nsupport is activated by default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You can set the\ndefault state of <small>IRI</small> support using the\n<tt>&quot;iri&quot;</tt> command in <i>.wgetrc</i>. That\nsetting may be overridden from the command line.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--local-encoding=</b><i>encoding</i></p>\n\n<p style=\"margin-left:17%;\">Force Wget to use\n<i>encoding</i> as the default system encoding. That affects\nhow Wget converts URLs specified as arguments from locale to\n<small>UTF-8</small> for <small>IRI</small>\nsupport.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Wget use the\nfunction <tt>&quot;nl_langinfo()&quot;</tt> and then the\n<tt>&quot;CHARSET&quot;</tt> environment variable to get the\nlocale. If it fails, <small>ASCII</small> is used.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You can set the\ndefault local encoding using the\n<tt>&quot;local_encoding&quot;</tt> command in\n<i>.wgetrc</i>. That setting may be overridden from the\ncommand line.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--remote-encoding=</b><i>encoding</i></p>\n\n<p style=\"margin-left:17%;\">Force Wget to use\n<i>encoding</i> as the default remote server encoding. That\naffects how Wget converts URIs found in files from remote\nencoding to <small>UTF-8</small> during a recursive\nfetch. This options is only useful for <small>IRI</small>\nsupport, for the interpretation of non-ASCII characters.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">For\n<small>HTTP,</small> remote encoding can be found in\n<small>HTTP</small> <tt>&quot;Content-Type&quot;</tt>\nheader and in <small>HTML</small>\n<tt>&quot;Content-Type http-equiv&quot;</tt>\nmeta tag.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You can set the\ndefault encoding using the\n<tt>&quot;remoteencoding&quot;</tt> command in\n<i>.wgetrc</i>. That setting may be overridden from the\ncommand line.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--unlink</b></p>\n\n<p style=\"margin-left:17%;\">Force Wget to unlink file\ninstead of clobbering existing file. This option is useful\nfor downloading to the directory with hardlinks.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Directory\nOptions</b></p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"4%\">\n\n\n<p><b>-nd</b></p></td>\n<td width=\"85%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--no-directories</b></p>\n\n<p style=\"margin-left:17%;\">Do not create a hierarchy of\ndirectories when retrieving recursively. With this option\nturned on, all files will get saved to the current\ndirectory, without clobbering (if a name shows up more than\nonce, the filenames will get extensions <b>.n</b>).</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-x</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--force-directories</b></p>\n\n<p style=\"margin-left:17%;\">The opposite of\n<b>-nd</b>---create a hierarchy of\ndirectories, even if one would not have been created\notherwise. E.g. <b>wget -x\nhttp://fly.srk.fer.hr/robots.txt</b> will save the\ndownloaded file to <i>fly.srk.fer.hr/robots.txt</i>.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"4%\">\n\n\n<p><b>-nH</b></p></td>\n<td width=\"85%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--no-host-directories</b></p>\n\n<p style=\"margin-left:17%;\">Disable generation of\nhost-prefixed directories. By default, invoking Wget with\n<b>-r http://fly.srk.fer.hr/</b> will create a\nstructure of directories beginning with\n<i>fly.srk.fer.hr/</i>. This option disables such\nbehavior.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--protocol-directories</b></p>\n\n<p style=\"margin-left:17%;\">Use the protocol name as a\ndirectory component of local file names. For example, with\nthis option, <b>wget -r http://</b><i>host</i> will\nsave to <b>http/</b><i>host</i><b>/...</b> rather than just\nto <i>host</i><b>/...</b>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--cut-dirs=</b><i>number</i></p>\n\n<p style=\"margin-left:17%;\">Ignore <i>number</i> directory\ncomponents. This is useful for getting a fine-grained\ncontrol over the directory where recursive retrieval will be\nsaved.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Take, for\nexample, the directory at\n<b>ftp://ftp.xemacs.org/pub/xemacs/</b>. If you retrieve it\nwith <b>-r</b>, it will be saved locally under\n<i>ftp.xemacs.org/pub/xemacs/</i>. While the\n<b>-nH</b> option can remove the\n<i>ftp.xemacs.org/</i> part, you are still stuck with\n<i>pub/xemacs</i>. This is where\n<b>--cut-dirs</b> comes in handy; it makes\nWget not &quot;see&quot; <i>number</i> remote directory\ncomponents. Here are several examples of how\n<b>--cut-dirs</b> option works.</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        No options        -&gt; ftp.xemacs.org/pub/xemacs/\n        -nH               -&gt; pub/xemacs/\n        -nH --cut-dirs=1  -&gt; xemacs/\n        -nH --cut-dirs=2  -&gt; .\n        --cut-dirs=1      -&gt; ftp.xemacs.org/xemacs/\n        ...</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you just\nwant to get rid of the directory structure, this option is\nsimilar to a combination of <b>-nd</b> and\n<b>-P</b>. However, unlike <b>-nd</b>,\n<b>--cut-dirs</b> does not lose with\nsubdirectories---for instance, with\n<b>-nH --cut-dirs=1</b>, a\n<i>beta/</i> subdirectory will be placed to\n<i>xemacs/beta</i>, as one would expect.</p>\n\n<p style=\"margin-left:11%;\"><b>-P</b> <i>prefix</i>\n<b><br>\n--directory-prefix=</b><i>prefix</i></p>\n\n<p style=\"margin-left:17%;\">Set directory prefix to\n<i>prefix</i>. The <i>directory prefix</i> is the directory\nwhere all other files and subdirectories will be saved to,\ni.e. the top of the retrieval tree. The default is <b>.</b>\n(the current directory).</p>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b><small>HTTP</small>\nOptions <br>\n--default-page=</b><i>name</i></p>\n\n<p style=\"margin-left:17%;\">Use <i>name</i> as the default\nfile name when it isn&rsquo;t known (i.e., for URLs that end\nin a slash), instead of <i>index.html</i>.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-E</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--adjust-extension</b></p>\n\n<p style=\"margin-left:17%;\">If a file of type\n<b>application/xhtml+xml</b> or <b>text/html</b> is\ndownloaded and the <small>URL</small> does not end with the\nregexp <b>\\.[Hh][Tt][Mm][Ll]?</b>, this option will cause\nthe suffix <b>.html</b> to be appended to the local\nfilename. This is useful, for instance, when you&rsquo;re\nmirroring a remote site that uses <b>.asp</b> pages, but you\nwant the mirrored pages to be viewable on your stock Apache\nserver. Another good use for this is when you&rsquo;re\ndownloading CGI-generated materials. A <small>URL</small>\nlike <b>http://site.com/article.cgi?25</b> will be saved as\n<i>article.cgi?25.html</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that\nfilenames changed in this way will be re-downloaded every\ntime you re-mirror a site, because Wget can&rsquo;t tell\nthat the local <i>X.html</i> file corresponds to remote\n<small>URL</small> <i>X</i> (since it doesn&rsquo;t yet know\nthat the <small>URL</small> produces output of type\n<b>text/html</b> or <b>application/xhtml+xml</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">As of version\n1.12, Wget will also ensure that any downloaded files of\ntype <b>text/css</b> end in the suffix <b>.css</b>, and the\noption was renamed from\n<b>--html-extension</b>, to better reflect\nits new behavior. The old option name is still acceptable,\nbut should now be considered deprecated.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">As of version\n1.19.2, Wget will also ensure that any downloaded files with\na <tt>&quot;Content-Encoding&quot;</tt> of <b>br</b>,\n<b>compress</b>, <b>deflate</b> or <b>gzip</b> end in the\nsuffix <b>.br</b>, <b>.Z</b>, <b>.zlib</b> and <b>.gz</b>\nrespectively.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">At some point\nin the future, this option may well be expanded to include\nsuffixes for other types of content, including content types\nthat are not parsed by Wget.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--http-user=</b><i>user</i>\n<b><br>\n--http-password=</b><i>password</i></p>\n\n<p style=\"margin-left:17%;\">Specify the username\n<i>user</i> and password <i>password</i> on an\n<small>HTTP</small> server. According to the type of the\nchallenge, Wget will encode them using either the\n<tt>&quot;basic&quot;</tt> (insecure), the\n<tt>&quot;digest&quot;</tt>, or the Windows\n<tt>&quot;NTLM&quot;</tt> authentication scheme.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Another way to\nspecify username and password is in the <small>URL</small>\nitself. Either method reveals your password to anyone who\nbothers to run <tt>&quot;ps&quot;</tt>. To prevent the\npasswords from being seen, use the\n<b>--use-askpass</b> or store them in\n<i>.wgetrc</i> or <i>.netrc</i>, and make sure to protect\nthose files from other users with\n<tt>&quot;chmod&quot;</tt>. If the passwords are really\nimportant, do not leave them lying in those files\neither---edit the files and delete them\nafter Wget has started the download.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-http-keep-alive</b></p>\n\n<p style=\"margin-left:17%;\">Turn off the\n&quot;keep-alive&quot; feature for <small>HTTP</small>\ndownloads. Normally, Wget asks the server to keep the\nconnection open so that, when you download more than one\ndocument from the same server, they get transferred over the\nsame <small>TCP</small> connection. This saves time and at\nthe same time reduces the load on the server.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This option is\nuseful when, for some reason, persistent (keep-alive)\nconnections don&rsquo;t work for you, for example due to a\nserver bug or due to the inability of server-side scripts to\ncope with the connections.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-cache</b></p>\n\n<p style=\"margin-left:17%;\">Disable server-side cache. In\nthis case, Wget will send the remote server appropriate\ndirectives (<b>Cache-Control: no-cache</b> and <b>Pragma:\nno-cache</b>) to get the file from the remote service,\nrather than returning the cached version. This is especially\nuseful for retrieving and flushing out-of-date documents on\nproxy servers.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Caching is\nallowed by default.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-cookies</b></p>\n\n<p style=\"margin-left:17%;\">Disable the use of cookies.\nCookies are a mechanism for maintaining server-side state.\nThe server sends the client a cookie using the\n<tt>&quot;Set-Cookie&quot;</tt> header, and the client\nresponds with the same cookie upon further requests. Since\ncookies allow the server owners to keep track of visitors\nand for sites to exchange this information, some consider\nthem a breach of privacy. The default is to use cookies;\nhowever, <i>storing</i> cookies is not on by default.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--load-cookies</b>\n<i>file</i></p>\n\n<p style=\"margin-left:17%;\">Load cookies from <i>file</i>\nbefore the first <small>HTTP</small> retrieval. <i>file</i>\nis a textual file in the format originally used by\nNetscape&rsquo;s <i>cookies.txt</i> file.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You will\ntypically use this option when mirroring sites that require\nthat you be logged in to access some or all of their\ncontent. The login process typically works by the web server\nissuing an <small>HTTP</small> cookie upon receiving and\nverifying your credentials. The cookie is then resent by the\nbrowser when accessing that part of the site, and so proves\nyour identity.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Mirroring such\na site requires Wget to send the same cookies your browser\nsends when communicating with the site. This is achieved by\n<b>--load-cookies</b>---simply\npoint Wget to the location of the <i>cookies.txt</i> file,\nand it will send the same cookies your browser would send in\nthe same situation. Different browsers keep textual cookie\nfiles in different locations: <br>\n&quot;Netscape 4.x.&quot;</p>\n\n<p style=\"margin-left:23%;\">The cookies are in\n<i>~/.netscape/cookies.txt</i>.</p>\n\n<p style=\"margin-left:17%;\">&quot;Mozilla and Netscape\n6.x.&quot;</p>\n\n<p style=\"margin-left:23%;\">Mozilla&rsquo;s cookie file is\nalso named <i>cookies.txt</i>, located somewhere under\n<i>~/.mozilla</i>, in the directory of your profile. The\nfull path usually ends up looking somewhat like\n<i>~/.mozilla/default/some-weird-string/cookies.txt</i>.</p>\n\n<p style=\"margin-left:17%;\">&quot;Internet\nExplorer.&quot;</p>\n\n<p style=\"margin-left:23%;\">You can produce a cookie file\nWget can use by using the File menu, Import and Export,\nExport Cookies. This has been tested with Internet Explorer\n5; it is not guaranteed to work with earlier versions.</p>\n\n<p style=\"margin-left:17%;\">&quot;Other browsers.&quot;</p>\n\n<p style=\"margin-left:23%;\">If you are using a different\nbrowser to create your cookies,\n<b>--load-cookies</b> will only work if\nyou can locate or produce a cookie file in the Netscape\nformat that Wget expects.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you cannot\nuse <b>--load-cookies</b>, there might\nstill be an alternative. If your browser supports a\n&quot;cookie manager&quot;, you can use it to view the\ncookies used when accessing the site you&rsquo;re mirroring.\nWrite down the name and value of the cookie, and manually\ninstruct Wget to send those cookies, bypassing the\n&quot;official&quot; cookie support:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget --no-cookies --header &quot;Cookie: &lt;name&gt;=&lt;value&gt;&quot;</pre>\n\n\n\n<p style=\"margin-left:11%;\"><b>--save-cookies</b>\n<i>file</i></p>\n\n<p style=\"margin-left:17%;\">Save cookies to <i>file</i>\nbefore exiting. This will not save cookies that have expired\nor that have no expiry time (so-called &quot;session\ncookies&quot;), but also see\n<b>--keep-session-cookies</b>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--keep-session-cookies</b></p>\n\n<p style=\"margin-left:17%;\">When specified, causes\n<b>--save-cookies</b> to also save session\ncookies. Session cookies are normally not saved because they\nare meant to be kept in memory and forgotten when you exit\nthe browser. Saving them is useful on sites that require you\nto log in or to visit the home page before you can access\nsome pages. With this option, multiple Wget runs are\nconsidered a single browser session as far as the site is\nconcerned.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Since the\ncookie file format does not normally carry session cookies,\nWget marks them with an expiry timestamp of 0. Wget&rsquo;s\n<b>--load-cookies</b> recognizes those as\nsession cookies, but it might confuse other browsers. Also\nnote that cookies so loaded will be treated as other session\ncookies, which means that if you want\n<b>--save-cookies</b> to preserve them\nagain, you must use\n<b>--keep-session-cookies</b>\nagain.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ignore-length</b></p>\n\n<p style=\"margin-left:17%;\">Unfortunately, some\n<small>HTTP</small> servers ( <small>CGI</small> programs,\nto be more precise) send out bogus\n<tt>&quot;Content-Length&quot;</tt> headers, which\nmakes Wget go wild, as it thinks not all the document was\nretrieved. You can spot this syndrome if Wget retries\ngetting the same document again and again, each time\nclaiming that the (otherwise normal) connection has closed\non the very same byte.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">With this\noption, Wget will ignore the\n<tt>&quot;Content-Length&quot;</tt>\nheader---as if it never existed.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--header=</b><i>header-line</i></p>\n\n<p style=\"margin-left:17%;\">Send <i>header-line</i> along\nwith the rest of the headers in each <small>HTTP</small>\nrequest. The supplied header is sent as-is, which means it\nmust contain name and value separated by colon, and must not\ncontain newlines.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You may define\nmore than one additional header by specifying\n<b>--header</b> more than once.</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget --header='Accept-Charset: iso-8859-2' \\\n             --header='Accept-Language: hr'        \\\n               http://fly.srk.fer.hr/</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">Specification\nof an empty string as the header value will clear all\nprevious user-defined headers.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">As of Wget\n1.10, this option can be used to override headers otherwise\ngenerated automatically. This example instructs Wget to\nconnect to localhost, but to specify <b>foo.bar</b> in the\n<tt>&quot;Host&quot;</tt> header:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget --header=&quot;Host: foo.bar&quot; http://localhost/</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">In versions of\nWget prior to 1.10 such use of <b>--header</b>\ncaused sending of duplicate headers.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--compression=</b><i>type</i></p>\n\n<p style=\"margin-left:17%;\">Choose the type of compression\nto be used. Legal values are <b>auto</b>, <b>gzip</b> and\n<b>none</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If <b>auto</b>\nor <b>gzip</b> are specified, Wget asks the server to\ncompress the file using the gzip compression format. If the\nserver compresses the file and responds with the\n<tt>&quot;Content-Encoding&quot;</tt> header field set\nappropriately, the file will be decompressed\nautomatically.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If <b>none</b>\nis specified, wget will not ask the server to compress the\nfile and will not decompress any server responses. This is\nthe default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Compression\nsupport is currently experimental. In case it is turned on,\nplease report any bugs to\n<tt>&quot;bug-wget@gnu.org&quot;</tt>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--max-redirect=</b><i>number</i></p>\n\n<p style=\"margin-left:17%;\">Specifies the maximum number of\nredirections to follow for a resource. The default is 20,\nwhich is usually far more than necessary. However, on those\noccasions where you want to allow more (or fewer), this is\nthe option to use.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--proxy-user=</b><i>user</i>\n<b><br>\n--proxy-password=</b><i>password</i></p>\n\n<p style=\"margin-left:17%;\">Specify the username\n<i>user</i> and password <i>password</i> for authentication\non a proxy server. Wget will encode them using the\n<tt>&quot;basic&quot;</tt> authentication scheme.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Security\nconsiderations similar to those with\n<b>--http-password</b> pertain here as\nwell.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--referer=</b><i>url</i></p>\n\n<p style=\"margin-left:17%;\">Include &lsquo;Referer:\n<i>url</i>&rsquo; header in <small>HTTP</small> request.\nUseful for retrieving documents with server-side processing\nthat assume they are always being retrieved by interactive\nweb browsers and only come out properly when Referer is set\nto one of the pages that point to them.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--save-headers</b></p>\n\n<p style=\"margin-left:17%;\">Save the headers sent by the\n<small>HTTP</small> server to the file, preceding the actual\ncontents, with an empty line as the separator.</p>\n\n<p style=\"margin-left:11%;\"><b>-U</b>\n<i>agent-string</i> <b><br>\n--user-agent=</b><i>agent-string</i></p>\n\n<p style=\"margin-left:17%;\">Identify as <i>agent-string</i>\nto the <small>HTTP</small> server.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<small>HTTP</small> protocol allows the clients to identify\nthemselves using a <tt>&quot;User-Agent&quot;</tt>\nheader field. This enables distinguishing the\n<small>WWW</small> software, usually for statistical\npurposes or for tracing of protocol violations. Wget\nnormally identifies as <b>Wget/</b><i>version</i>,\n<i>version</i> being the current version number of Wget.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">However, some\nsites have been known to impose the policy of tailoring the\noutput according to the\n<tt>&quot;User-Agent&quot;</tt>-supplied\ninformation. While this is not such a bad idea in theory, it\nhas been abused by servers denying information to clients\nother than (historically) Netscape or, more frequently,\nMicrosoft Internet Explorer. This option allows you to\nchange the <tt>&quot;User-Agent&quot;</tt> line issued\nby Wget. Use of this option is discouraged, unless you\nreally know what you are doing.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Specifying\nempty user agent with\n<b>--user-agent=&quot;&quot;</b> instructs\nWget not to send the <tt>&quot;User-Agent&quot;</tt>\nheader in <small>HTTP</small> requests.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--post-data=</b><i>string</i>\n<b><br>\n--post-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Use <small>POST</small> as the\nmethod for all <small>HTTP</small> requests and send the\nspecified data in the request body.\n<b>--post-data</b> sends <i>string</i> as\ndata, whereas <b>--post-file</b> sends the\ncontents of <i>file</i>. Other than that, they work in\nexactly the same way. In particular, they <i>both</i> expect\ncontent of the form\n<tt>&quot;key1=value1&amp;key2=value2&quot;</tt>, with\npercent-encoding for special characters; the only difference\nis that one expects its content as a command-line parameter\nand the other accepts its content from a file. In\nparticular, <b>--post-file</b> is\n<i>not</i> for transmitting files as form attachments: those\nmust appear as <tt>&quot;key=value&quot;</tt> data (with\nappropriate percent-coding) just like everything else. Wget\ndoes not currently support\n<tt>&quot;multipart/form-data&quot;</tt> for\ntransmitting <small>POST</small> data; only\n<tt>&quot;application/x-www-form-urlencoded&quot;</tt>.\nOnly one of <b>--post-data</b> and\n<b>--post-file</b> should be\nspecified.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Please note\nthat wget does not require the content to be of the form\n<tt>&quot;key1=value1&amp;key2=value2&quot;</tt>, and\nneither does it test for it. Wget will simply transmit\nwhatever data is provided to it. Most servers however expect\nthe <small>POST</small> data to be in the above format when\nprocessing <small>HTML</small> Forms.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When sending a\n<small>POST</small> request using the\n<b>--post-file</b> option, Wget treats the\nfile as a binary file and will send every character in the\n<small>POST</small> request without stripping trailing\nnewline or formfeed characters. Any other control characters\nin the text will also be sent as-is in the\n<small>POST</small> request.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Please be aware\nthat Wget needs to know the size of the <small>POST</small>\ndata in advance. Therefore the argument to\n<tt>&quot;--post-file&quot;</tt> must be a\nregular file; specifying a <small>FIFO</small> or something\nlike <i>/dev/stdin</i> won&rsquo;t work. It&rsquo;s not\nquite clear how to work around this limitation inherent in\n<small>HTTP/1.0.</small> Although <small>HTTP/1.1</small>\nintroduces <i>chunked</i> transfer that doesn&rsquo;t\nrequire knowing the request length in advance, a client\ncan&rsquo;t use chunked unless it knows it&rsquo;s talking\nto an <small>HTTP/1.1</small> server. And it can&rsquo;t\nknow that until it receives a response, which in turn\nrequires the request to have been completed -- a\nchicken-and-egg problem.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note: As of\nversion 1.15 if Wget is redirected after the\n<small>POST</small> request is completed, its behaviour will\ndepend on the response code returned by the server. In case\nof a 301 Moved Permanently, 302 Moved Temporarily or 307\nTemporary Redirect, Wget will, in accordance with\n<small>RFC2616,</small> continue to send a\n<small>POST</small> request. In case a server wants the\nclient to change the Request method upon redirection, it\nshould send a 303 See Other response code.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This example\nshows how to log in to a server using <small>POST</small>\nand then proceed to download the desired pages, presumably\nonly accessible to authorized users:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        # Log in to the server.  This can be done only once.\n        wget --save-cookies cookies.txt \\\n             --post-data 'user=foo&amp;password=bar' \\\n             http://example.com/auth.php\n        # Now grab the page or pages we care about.\n        wget --load-cookies cookies.txt \\\n             -p http://example.com/interesting/article.php</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">If the server\nis using session cookies to track user authentication, the\nabove will not work because\n<b>--save-cookies</b> will not save them\n(and neither will browsers) and the <i>cookies.txt</i> file\nwill be empty. In that case use\n<b>--keep-session-cookies</b> along\nwith <b>--save-cookies</b> to force saving\nof session cookies.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--method=</b><i>HTTP-Method</i></p>\n\n<p style=\"margin-left:17%;\">For the purpose of RESTful\nscripting, Wget allows sending of other <small>HTTP</small>\nMethods without the need to explicitly set them using\n<b>--header=Header-Line</b>. Wget will use\nwhatever string is passed to it after\n<b>--method</b> as the <small>HTTP</small>\nMethod to the server.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--body-data=</b><i>Data-String</i>\n<b><br>\n--body-file=</b><i>Data-File</i></p>\n\n<p style=\"margin-left:17%;\">Must be set when additional\ndata needs to be sent to the server along with the Method\nspecified using <b>--method</b>.\n<b>--body-data</b> sends <i>string</i> as\ndata, whereas <b>--body-file</b> sends the\ncontents of <i>file</i>. Other than that, they work in\nexactly the same way.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Currently,\n<b>--body-file</b> is <i>not</i> for\ntransmitting files as a whole. Wget does not currently\nsupport <tt>&quot;multipart/form-data&quot;</tt> for\ntransmitting data; only\n<tt>&quot;application/x-www-form-urlencoded&quot;</tt>.\nIn the future, this may be changed so that wget sends the\n<b>--body-file</b> as a complete file\ninstead of sending its contents to the server. Please be\naware that Wget needs to know the contents of\n<small>BODY</small> Data in advance, and hence the argument\nto <b>--body-file</b> should be a regular\nfile. See <b>--post-file</b> for a more\ndetailed explanation. Only one of\n<b>--body-data</b> and\n<b>--body-file</b> should be\nspecified.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If Wget is\nredirected after the request is completed, Wget will suspend\nthe current method and send a <small>GET</small> request\ntill the redirection is completed. This is true for all\nredirection response codes except 307 Temporary Redirect\nwhich is used to explicitly specify that the request method\nshould <i>not</i> change. Another exception is when the\nmethod is set to <tt>&quot;POST&quot;</tt>, in which case\nthe redirection rules specified under\n<b>--post-data</b> are followed.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--content-disposition</b></p>\n\n<p style=\"margin-left:17%;\">If this is set to on,\nexperimental (not fully-functional) support for\n<tt>&quot;Content-Disposition&quot;</tt> headers is\nenabled. This can currently result in extra round-trips to\nthe server for a <tt>&quot;HEAD&quot;</tt> request, and is\nknown to suffer from a few bugs, which is why it is not\ncurrently enabled by default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">This option is\nuseful for some file-downloading <small>CGI</small> programs\nthat use <tt>&quot;Content-Disposition&quot;</tt>\nheaders to describe what the name of a downloaded file\nshould be.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When combined\nwith <b>--metalink-over-http</b> and\n<b>--trust-server-names</b>, a\n<b>Content-Type: application/metalink4+xml</b> file is named\nusing the <tt>&quot;Content-Disposition&quot;</tt>\nfilename field, if available.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--content-on-error</b></p>\n\n<p style=\"margin-left:17%;\">If this is set to on, wget will\nnot skip the content when the server responds with a http\nstatus code that indicates error.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--trust-server-names</b></p>\n\n<p style=\"margin-left:17%;\">If this is set, on a redirect,\nthe local file name will be based on the redirection\n<small>URL.</small> By default the local file name is based\non the original <small>URL.</small> When doing recursive\nretrieving this can be helpful because in many web sites\nredirected URLs correspond to an underlying file structure,\nwhile link URLs do not.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--auth-no-challenge</b></p>\n\n<p style=\"margin-left:17%;\">If this option is given, Wget\nwill send Basic <small>HTTP</small> authentication\ninformation (plaintext username and password) for all\nrequests, just like Wget 1.10.2 and prior did by\ndefault.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Use of this\noption is not recommended, and is intended only to support\nsome few obscure servers, which never send\n<small>HTTP</small> authentication challenges, but accept\nunsolicited auth info, say, in addition to form-based\nauthentication.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--retry-on-host-error</b></p>\n\n<p style=\"margin-left:17%;\">Consider host errors, such as\n&quot;Temporary failure in name resolution&quot;, as\nnon-fatal, transient errors.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--retry-on-http-error=</b><i>code[,code,...]</i></p>\n\n<p style=\"margin-left:17%;\">Consider given\n<small>HTTP</small> response codes as non-fatal, transient\nerrors. Supply a comma-separated list of 3-digit\n<small>HTTP</small> response codes as argument. Useful to\nwork around special circumstances where retries are\nrequired, but the server responds with an error code\nnormally not retried by Wget. Such errors might be 503\n(Service Unavailable) and 429 (Too Many Requests). Retries\nenabled by this option are performed subject to the normal\nretry timing and retry count limitations of Wget.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Using this\noption is intended to support special use cases only and is\ngenerally not recommended, as it can force retries even in\ncases where the server is actually trying to decrease its\nload. Please use wisely and only if you know what you are\ndoing.</p>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b><small>HTTPS</small>\n( <small>SSL/TLS</small> ) Options</b> <br>\nTo support encrypted <small>HTTP</small> (\n<small>HTTPS</small> ) downloads, Wget must be compiled with\nan external <small>SSL</small> library. The current default\nis GnuTLS. In addition, Wget also supports\n<small>HSTS</small> ( <small>HTTP</small> Strict Transport\nSecurity). If Wget is compiled without <small>SSL</small>\nsupport, none of these options are available. <b><br>\n--secure-protocol=</b><i>protocol</i></p>\n\n<p style=\"margin-left:17%;\">Choose the secure protocol to\nbe used. Legal values are <b>auto</b>, <b>SSLv2</b>,\n<b>SSLv3</b>, <b>TLSv1</b>, <b>TLSv1_1</b>, <b>TLSv1_2</b>,\n<b>TLSv1_3</b> and <b><small>PFS</small></b> . If\n<b>auto</b> is used, the <small>SSL</small> library is given\nthe liberty of choosing the appropriate protocol\nautomatically, which is achieved by sending a TLSv1\ngreeting. This is the default.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Specifying\n<b>SSLv2</b>, <b>SSLv3</b>, <b>TLSv1</b>, <b>TLSv1_1</b>,\n<b>TLSv1_2</b> or <b>TLSv1_3</b> forces the use of the\ncorresponding protocol. This is useful when talking to old\nand buggy <small>SSL</small> server implementations that\nmake it hard for the underlying <small>SSL</small> library\nto choose the correct protocol version. Fortunately, such\nservers are quite rare.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Specifying\n<b><small>PFS</small></b> enforces the use of the so-called\nPerfect Forward Security cipher suites. In short,\n<small>PFS</small> adds security by creating a one-time key\nfor each <small>SSL</small> connection. It has a bit more\n<small>CPU</small> impact on client and server. We use known\nto be secure ciphers (e.g. no <small>MD4</small> ) and the\n<small>TLS</small> protocol. This mode also explicitly\nexcludes non-PFS key exchange methods, such as\n<small>RSA.</small></p>\n\n\n<p style=\"margin-left:11%;\"><b>--https-only</b></p>\n\n<p style=\"margin-left:17%;\">When in recursive mode, only\n<small>HTTPS</small> links are followed.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ciphers</b></p>\n\n<p style=\"margin-left:17%;\">Set the cipher list string.\nTypically this string sets the cipher suites and other\n<small>SSL/TLS</small> options that the user wish should be\nused, in a set order of preference (GnuTLS calls it\n&rsquo;priority string&rsquo;). This string will be fed\nverbatim to the <small>SSL/TLS</small> engine (OpenSSL or\nGnuTLS) and hence its format and syntax is dependent on\nthat. Wget will not process or manipulate it in any way.\nRefer to the OpenSSL or GnuTLS documentation for more\ninformation.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-check-certificate</b></p>\n\n<p style=\"margin-left:17%;\">Don&rsquo;t check the server\ncertificate against the available certificate authorities.\nAlso don&rsquo;t require the <small>URL</small> host name to\nmatch the common name presented by the certificate.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">As of Wget\n1.10, the default is to verify the server&rsquo;s\ncertificate against the recognized certificate authorities,\nbreaking the <small>SSL</small> handshake and aborting the\ndownload if the verification fails. Although this provides\nmore secure downloads, it does break interoperability with\nsome sites that worked with previous Wget versions,\nparticularly those using self-signed, expired, or otherwise\ninvalid certificates. This option forces an\n&quot;insecure&quot; mode of operation that turns the\ncertificate verification errors into warnings and allows you\nto proceed.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you\nencounter &quot;certificate verification&quot; errors or\nones saying that &quot;common name doesn&rsquo;t match\nrequested host name&quot;, you can use this option to bypass\nthe verification and proceed with the download. <i>Only use\nthis option if you are otherwise convinced of the\nsite&rsquo;s authenticity, or if you really don&rsquo;t care\nabout the validity of its certificate.</i> It is almost\nalways a bad idea not to check the certificates when\ntransmitting confidential or important data. For\nself-signed/internal certificates, you should download\nthe certificate and verify against that instead of forcing\nthis insecure mode. If you are really sure of not desiring\nany certificate verification, you can specify\n--check-certificate=quiet to tell wget to\nnot print any warning about invalid certificates, albeit in\nmost cases this is the wrong thing to do.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--certificate=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Use the client certificate\nstored in <i>file</i>. This is needed for servers that are\nconfigured to require certificates from the clients that\nconnect to them. Normally a certificate is not required and\nthis switch is optional.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--certificate-type=</b><i>type</i></p>\n\n<p style=\"margin-left:17%;\">Specify the type of the client\ncertificate. Legal values are <b><small>PEM</small></b>\n(assumed by default) and <b><small>DER</small></b> , also\nknown as <b><small>ASN1</small></b> .</p>\n\n\n<p style=\"margin-left:11%;\"><b>--private-key=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Read the private key from\n<i>file</i>. This allows you to provide the private key in a\nfile separate from the certificate.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--private-key-type=</b><i>type</i></p>\n\n<p style=\"margin-left:17%;\">Specify the type of the private\nkey. Accepted values are <b><small>PEM</small></b> (the\ndefault) and <b><small>DER</small></b> .</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ca-certificate=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Use <i>file</i> as the file\nwith the bundle of certificate authorities (&quot;\n<small>CA&quot;</small> ) to verify the peers. The\ncertificates must be in <small>PEM</small> format.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Without this\noption Wget looks for <small>CA</small> certificates at the\nsystem-specified locations, chosen at OpenSSL installation\ntime.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ca-directory=</b><i>directory</i></p>\n\n<p style=\"margin-left:17%;\">Specifies directory containing\n<small>CA</small> certificates in <small>PEM</small> format.\nEach file contains one <small>CA</small> certificate, and\nthe file name is based on a hash value derived from the\ncertificate. This is achieved by processing a certificate\ndirectory with the <tt>&quot;c_rehash&quot;</tt> utility\nsupplied with OpenSSL. Using\n<b>--ca-directory</b> is more efficient\nthan <b>--ca-certificate</b> when many\ncertificates are installed because it allows Wget to fetch\ncertificates on demand.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Without this\noption Wget looks for <small>CA</small> certificates at the\nsystem-specified locations, chosen at OpenSSL installation\ntime.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--crl-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Specifies a <small>CRL</small>\nfile in <i>file</i>. This is needed for certificates that\nhave been revocated by the CAs.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--pinnedpubkey=file/hashes</b></p>\n\n<p style=\"margin-left:17%;\">Tells wget to use the specified\npublic key file (or hashes) to verify the peer. This can be\na path to a file which contains a single public key in\n<small>PEM</small> or <small>DER</small> format, or any\nnumber of base64 encoded sha256 hashes preceded by\n&quot;sha256//&quot; and separated by &quot;;&quot;</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When\nnegotiating a <small>TLS</small> or <small>SSL</small>\nconnection, the server sends a certificate indicating its\nidentity. A public key is extracted from this certificate\nand if it does not exactly match the public key(s) provided\nto this option, wget will abort the connection before\nsending or receiving any data.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--random-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">[OpenSSL and LibreSSL only] Use\n<i>file</i> as the source of random data for seeding the\npseudo-random number generator on systems without\n<i>/dev/urandom</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">On such systems\nthe <small>SSL</small> library needs an external source of\nrandomness to initialize. Randomness may be provided by\n<small>EGD</small> (see <b>--egd-file</b>\nbelow) or read from an external source specified by the\nuser. If this option is not specified, Wget looks for random\ndata in <tt>$RANDFILE</tt> or, if that is unset, in\n<i>$HOME/.rnd</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you&rsquo;re\ngetting the &quot;Could not seed OpenSSL <small>PRNG</small>\n; disabling <small>SSL.&quot;</small> error, you should\nprovide random data using some of the methods described\nabove.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--egd-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">[OpenSSL only] Use <i>file</i>\nas the <small>EGD</small> socket. <small>EGD</small> stands\nfor <i>Entropy Gathering Daemon</i>, a user-space program\nthat collects data from various unpredictable system sources\nand makes it available to other programs that might need it.\nEncryption software, such as the <small>SSL</small> library,\nneeds sources of non-repeating randomness to seed the random\nnumber generator used to produce cryptographically strong\nkeys.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">OpenSSL allows\nthe user to specify his own source of entropy using the\n<tt>&quot;RAND_FILE&quot;</tt> environment variable. If this\nvariable is unset, or if the specified file does not produce\nenough randomness, OpenSSL will read random data from\n<small>EGD</small> socket specified using this option.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If this option\nis not specified (and the equivalent startup command is not\nused), <small>EGD</small> is never contacted.\n<small>EGD</small> is not needed on modern Unix systems that\nsupport <i>/dev/urandom</i>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-hsts</b></p>\n\n<p style=\"margin-left:17%;\">Wget supports\n<small>HSTS</small> ( <small>HTTP</small> Strict Transport\nSecurity, <small>RFC 6797</small> ) by default. Use\n<b>--no-hsts</b> to make Wget act as a\nnon-HSTS-compliant <small>UA.</small> As a consequence, Wget\nwould ignore all the\n<tt>&quot;Strict-Transport-Security&quot;</tt>\nheaders, and would not enforce any existing\n<small>HSTS</small> policy.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--hsts-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">By default, Wget stores its\n<small>HSTS</small> database in <i>~/.wget-hsts</i>.\nYou can use <b>--hsts-file</b> to override\nthis. Wget will use the supplied file as the\n<small>HSTS</small> database. Such file must conform to the\ncorrect <small>HSTS</small> database format used by Wget. If\nWget cannot parse the provided file, the behaviour is\nunspecified.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\nWget&rsquo;s <small>HSTS</small> database is a plain text\nfile. Each line contains an <small>HSTS</small> entry (ie. a\nsite that has issued a\n<tt>&quot;Strict-Transport-Security&quot;</tt>\nheader and that therefore has specified a concrete\n<small>HSTS</small> policy to be applied). Lines starting\nwith a dash (<tt>&quot;#&quot;</tt>) are ignored by Wget.\nPlease note that in spite of this convenient\nhuman-readability hand-hacking the <small>HSTS</small>\ndatabase is generally not a good idea.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">An\n<small>HSTS</small> entry line consists of several fields\nseparated by one or more whitespace:</p>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\"><tt>&quot;&lt;hostname&gt;\nSP [&lt;port&gt;] SP &lt;include subdomains&gt; SP\n&lt;created&gt; SP &lt;max-age&gt;&quot;</tt></p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<i>hostname</i> and <i>port</i> fields indicate the hostname\nand port to which the given <small>HSTS</small> policy\napplies. The <i>port</i> field may be zero, and it will, in\nmost of the cases. That means that the port number will not\nbe taken into account when deciding whether such\n<small>HSTS</small> policy should be applied on a given\nrequest (only the hostname will be evaluated). When\n<i>port</i> is different to zero, both the target hostname\nand the port will be evaluated and the <small>HSTS</small>\npolicy will only be applied if both of them match. This\nfeature has been included for testing/development purposes\nonly. The Wget testsuite (in <i>testenv/</i>) creates\n<small>HSTS</small> databases with explicit ports with the\npurpose of ensuring Wget&rsquo;s correct behaviour. Applying\n<small>HSTS</small> policies to ports other than the default\nones is discouraged by <small>RFC 6797</small> (see Appendix\nB &quot;Differences between <small>HSTS</small> Policy and\nSame-Origin Policy&quot;). Thus, this functionality should\nnot be used in production environments and <i>port</i> will\ntypically be zero. The last three fields do what they are\nexpected to. The field <i>include_subdomains</i> can either\nbe <tt>1</tt> or <tt>0</tt> and it signals whether the\nsubdomains of the target domain should be part of the given\n<small>HSTS</small> policy as well. The <i>created</i> and\n<i>max-age</i> fields hold the timestamp values of when such\nentry was created (first seen by Wget) and the HSTS-defined\nvalue &rsquo;max-age&rsquo;, which states how long\nshould that <small>HSTS</small> policy remain active,\nmeasured in seconds elapsed since the timestamp stored in\n<i>created</i>. Once that time has passed, that\n<small>HSTS</small> policy will no longer be valid and will\neventually be removed from the database.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If you supply\nyour own <small>HSTS</small> database via\n<b>--hsts-file</b>, be aware that Wget may\nmodify the provided file if any change occurs between the\n<small>HSTS</small> policies requested by the remote servers\nand those in the file. When Wget exists, it effectively\nupdates the <small>HSTS</small> database by rewriting the\ndatabase file with the new entries.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If the supplied\nfile does not exist, Wget will create one. This file will\ncontain the new <small>HSTS</small> entries. If no\n<small>HSTS</small> entries were generated (no\n<tt>&quot;Strict-Transport-Security&quot;</tt>\nheaders were sent by any of the servers) then no file will\nbe created, not even an empty one. This behaviour applies to\nthe default database file (<i>~/.wget-hsts</i>) as\nwell: it will not be created until some server enforces an\n<small>HSTS</small> policy.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Care is taken\nnot to override possible changes made by other Wget\nprocesses at the same time over the <small>HSTS</small>\ndatabase. Before dumping the updated <small>HSTS</small>\nentries on the file, Wget will re-read it and merge the\nchanges.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Using a custom\n<small>HSTS</small> database and/or modifying an existing\none is discouraged. For more information about the potential\nsecurity threats arose from such practice, see section 14\n&quot;Security Considerations&quot; of <small>RFC\n6797,</small> specially section 14.9 &quot;Creative\nManipulation of <small>HSTS</small> Policy Store&quot;.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-file=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Use <i>file</i> as the\ndestination <small>WARC</small> file.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-header=</b><i>string</i></p>\n\n<p style=\"margin-left:17%;\">Use <i>string</i> into as the\nwarcinfo record.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-max-size=</b><i>size</i></p>\n\n<p style=\"margin-left:17%;\">Set the maximum size of the\n<small>WARC</small> files to <i>size</i>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-cdx</b></p>\n\n<p style=\"margin-left:17%;\">Write <small>CDX</small> index\nfiles.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-dedup=</b><i>file</i></p>\n\n<p style=\"margin-left:17%;\">Do not store records listed in\nthis <small>CDX</small> file.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-warc-compression</b></p>\n\n<p style=\"margin-left:17%;\">Do not compress\n<small>WARC</small> files with <small>GZIP.</small></p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-warc-digests</b></p>\n\n<p style=\"margin-left:17%;\">Do not calculate\n<small>SHA1</small> digests.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-warc-keep-log</b></p>\n\n<p style=\"margin-left:17%;\">Do not store the log file in a\n<small>WARC</small> record.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--warc-tempdir=</b><i>dir</i></p>\n\n<p style=\"margin-left:17%;\">Specify the location for\ntemporary files created by the <small>WARC</small>\nwriter.</p>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b><small>FTP</small>\nOptions <br>\n--ftp-user=</b><i>user</i> <b><br>\n--ftp-password=</b><i>password</i></p>\n\n<p style=\"margin-left:17%;\">Specify the username\n<i>user</i> and password <i>password</i> on an\n<small>FTP</small> server. Without this, or the\ncorresponding startup option, the password defaults to\n<b>-wget@</b>, normally used for anonymous\n<small>FTP.</small></p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Another way to\nspecify username and password is in the <small>URL</small>\nitself. Either method reveals your password to anyone who\nbothers to run <tt>&quot;ps&quot;</tt>. To prevent the\npasswords from being seen, store them in <i>.wgetrc</i> or\n<i>.netrc</i>, and make sure to protect those files from\nother users with <tt>&quot;chmod&quot;</tt>. If the\npasswords are really important, do not leave them lying in\nthose files either---edit the files and\ndelete them after Wget has started the download.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-remove-listing</b></p>\n\n<p style=\"margin-left:17%;\">Don&rsquo;t remove the\ntemporary <i>.listing</i> files generated by\n<small>FTP</small> retrievals. Normally, these files contain\nthe raw directory listings received from <small>FTP</small>\nservers. Not removing them can be useful for debugging\npurposes, or when you want to be able to easily check on the\ncontents of remote server directories (e.g. to verify that a\nmirror you&rsquo;re running is complete).</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that even\nthough Wget writes to a known filename for this file, this\nis not a security hole in the scenario of a user making\n<i>.listing</i> a symbolic link to <i>/etc/passwd</i> or\nsomething and asking <tt>&quot;root&quot;</tt> to run Wget\nin his or her directory. Depending on the options used,\neither Wget will refuse to write to <i>.listing</i>, making\nthe globbing/recursion/time-stamping operation fail,\nor the symbolic link will be deleted and replaced with the\nactual <i>.listing</i> file, or the listing will be written\nto a <i>.listing.number</i> file.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Even though\nthis situation isn&rsquo;t a problem, though,\n<tt>&quot;root&quot;</tt> should never run Wget in a\nnon-trusted user&rsquo;s directory. A user could do\nsomething as simple as linking <i>index.html</i> to\n<i>/etc/passwd</i> and asking <tt>&quot;root&quot;</tt> to\nrun Wget with <b>-N</b> or <b>-r</b> so the file\nwill be overwritten.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-glob</b></p>\n\n<p style=\"margin-left:17%;\">Turn off <small>FTP</small>\nglobbing. Globbing refers to the use of shell-like special\ncharacters (<i>wildcards</i>), like <b>*</b>, <b>?</b>,\n<b>[</b> and <b>]</b> to retrieve more than one file from\nthe same directory at once, like:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget ftp://gnjilux.srk.fer.hr/*.msg</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">By default,\nglobbing will be turned on if the <small>URL</small>\ncontains a globbing character. This option may be used to\nturn globbing on or off permanently.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">You may have to\nquote the <small>URL</small> to protect it from being\nexpanded by your shell. Globbing makes Wget look for a\ndirectory listing, which is system-specific. This is why it\ncurrently works only with Unix <small>FTP</small> servers\n(and the ones emulating Unix <tt>&quot;ls&quot;</tt>\noutput).</p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-passive-ftp</b></p>\n\n<p style=\"margin-left:17%;\">Disable the use of the\n<i>passive</i> <small>FTP</small> transfer mode. Passive\n<small>FTP</small> mandates that the client connect to the\nserver to establish the data connection rather than the\nother way around.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If the machine\nis connected to the Internet directly, both passive and\nactive <small>FTP</small> should work equally well. Behind\nmost firewall and <small>NAT</small> configurations passive\n<small>FTP</small> has a better chance of working. However,\nin some rare firewall configurations, active\n<small>FTP</small> actually works when passive\n<small>FTP</small> doesn&rsquo;t. If you suspect this to be\nthe case, use this option, or set\n<tt>&quot;passive_ftp=off&quot;</tt> in your init file.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--preserve-permissions</b></p>\n\n<p style=\"margin-left:17%;\">Preserve remote file\npermissions instead of permissions set by umask.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--retr-symlinks</b></p>\n\n<p style=\"margin-left:17%;\">By default, when retrieving\n<small>FTP</small> directories recursively and a symbolic\nlink is encountered, the symbolic link is traversed and the\npointed-to files are retrieved. Currently, Wget does not\ntraverse symbolic links to directories to download them\nrecursively, though this feature may be added in the\nfuture.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">When\n<b>--retr-symlinks=no</b> is specified,\nthe linked-to file is not downloaded. Instead, a matching\nsymbolic link is created on the local filesystem. The\npointed-to file will not be retrieved unless this recursive\nretrieval would have encountered it separately and\ndownloaded it anyway. This option poses a security risk\nwhere a malicious <small>FTP</small> Server may cause Wget\nto write to files outside of the intended directories\nthrough a specially crafted .LISTING file.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that when\nretrieving a file (not a directory) because it was specified\non the command-line, rather than because it was recursed to,\nthis option has no effect. Symbolic links are always\ntraversed in this case.</p>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b><small>FTPS</small>\nOptions <br>\n--ftps-implicit</b></p>\n\n<p style=\"margin-left:17%;\">This option tells Wget to use\n<small>FTPS</small> implicitly. Implicit <small>FTPS</small>\nconsists of initializing <small>SSL/TLS</small> from the\nvery beginning of the control connection. This option does\nnot send an <tt>&quot;AUTH TLS&quot;</tt> command: it\nassumes the server speaks <small>FTPS</small> and directly\nstarts an <small>SSL/TLS</small> connection. If the attempt\nis successful, the session continues just like regular\n<small>FTPS</small> (<tt>&quot;PBSZ&quot;</tt> and\n<tt>&quot;PROT&quot;</tt> are sent, etc.). Implicit\n<small>FTPS</small> is no longer a requirement for\n<small>FTPS</small> implementations, and thus many servers\nmay not support it. If\n<b>--ftps-implicit</b> is passed and no\nexplicit port number specified, the default port for\nimplicit <small>FTPS, 990,</small> will be used, instead of\nthe default port for the &quot;normal&quot; (explicit)\n<small>FTPS</small> which is the same as that of <small>FTP,\n21.</small></p>\n\n\n<p style=\"margin-left:11%;\"><b>--no-ftps-resume-ssl</b></p>\n\n<p style=\"margin-left:17%;\">Do not resume the\n<small>SSL/TLS</small> session in the data channel. When\nstarting a data connection, Wget tries to resume the\n<small>SSL/TLS</small> session previously started in the\ncontrol connection. <small>SSL/TLS</small> session\nresumption avoids performing an entirely new handshake by\nreusing the <small>SSL/TLS</small> parameters of a previous\nsession. Typically, the <small>FTPS</small> servers want it\nthat way, so Wget does this by default. Under rare\ncircumstances however, one might want to start an entirely\nnew <small>SSL/TLS</small> session in every data connection.\nThis is what\n<b>--no-ftps-resume-ssl</b> is\nfor.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ftps-clear-data-connection</b></p>\n\n<p style=\"margin-left:17%;\">All the data connections will\nbe in plain text. Only the control connection will be under\n<small>SSL/TLS.</small> Wget will send a <tt>&quot;PROT\nC&quot;</tt> command to achieve this, which must be approved\nby the server.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ftps-fallback-to-ftp</b></p>\n\n<p style=\"margin-left:17%;\">Fall back to <small>FTP</small>\nif <small>FTPS</small> is not supported by the target\nserver. For security reasons, this option is not asserted by\ndefault. The default behaviour is to exit with an error. If\na server does not successfully reply to the initial\n<tt>&quot;AUTH TLS&quot;</tt> command, or in the case of\nimplicit <small>FTPS,</small> if the initial\n<small>SSL/TLS</small> connection attempt is rejected, it is\nconsidered that such server does not support\n<small>FTPS.</small></p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Recursive\nRetrieval Options</b></p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-r</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--recursive</b></p>\n\n<p style=\"margin-left:17%;\">Turn on recursive retrieving.\nThe default maximum depth is 5.</p>\n\n<p style=\"margin-left:11%;\"><b>-l</b> <i>depth</i>\n<b><br>\n--level=</b><i>depth</i></p>\n\n<p style=\"margin-left:17%;\">Specify recursion maximum depth\nlevel <i>depth</i>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--delete-after</b></p>\n\n<p style=\"margin-left:17%;\">This option tells Wget to\ndelete every single file it downloads, <i>after</i> having\ndone so. It is useful for pre-fetching popular pages through\na proxy, e.g.:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -r -nd --delete-after http://whatever.com/~popular/page/</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">The\n<b>-r</b> option is to retrieve recursively, and\n<b>-nd</b> to not create directories.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that\n<b>--delete-after</b> deletes files on the\nlocal machine. It does not issue the\n<b><small>DELE</small></b> command to remote\n<small>FTP</small> sites, for instance. Also note that when\n<b>--delete-after</b> is specified,\n<b>--convert-links</b> is ignored, so\n<b>.orig</b> files are simply not created in the first\nplace.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-k</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--convert-links</b></p>\n\n<p style=\"margin-left:17%;\">After the download is complete,\nconvert the links in the document to make them suitable for\nlocal viewing. This affects not only the visible hyperlinks,\nbut any part of the document that links to external content,\nsuch as embedded images, links to style sheets, hyperlinks\nto non-HTML content, etc.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Each link will\nbe changed in one of the two ways:</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"17%\"></td>\n<td width=\"1%\">\n\n\n<p>&bull;</p></td>\n<td width=\"5%\"></td>\n<td width=\"77%\">\n\n\n<p>The links to files that have been downloaded by Wget\nwill be changed to refer to the file they point to as a\nrelative link.</p></td></tr>\n</table>\n\n<p style=\"margin-left:23%; margin-top: 1em\">Example: if the\ndownloaded file <i>/foo/doc.html</i> links to\n<i>/bar/img.gif</i>, also downloaded, then the link in\n<i>doc.html</i> will be modified to point to\n<b>../bar/img.gif</b>. This kind of transformation works\nreliably for arbitrary combinations of directories.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"17%\"></td>\n<td width=\"1%\">\n\n\n<p style=\"margin-top: 1em\">&bull;</p></td>\n<td width=\"5%\"></td>\n<td width=\"77%\">\n\n\n<p style=\"margin-top: 1em\">The links to files that have not\nbeen downloaded by Wget will be changed to include host name\nand absolute path of the location they point to.</p></td></tr>\n</table>\n\n<p style=\"margin-left:23%; margin-top: 1em\">Example: if the\ndownloaded file <i>/foo/doc.html</i> links to\n<i>/bar/img.gif</i> (or to <i>../bar/img.gif</i>), then the\nlink in <i>doc.html</i> will be modified to point to\n<i>http://hostname/bar/img.gif</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Because of\nthis, local browsing works reliably: if a linked file was\ndownloaded, the link will refer to its local name; if it was\nnot downloaded, the link will refer to its full Internet\naddress rather than presenting a broken link. The fact that\nthe former links are converted to relative links ensures\nthat you can move the downloaded hierarchy to another\ndirectory.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that only\nat the end of the download can Wget know which links have\nbeen downloaded. Because of that, the work done by\n<b>-k</b> will be performed at the end of all the\ndownloads.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--convert-file-only</b></p>\n\n<p style=\"margin-left:17%;\">This option converts only the\nfilename part of the URLs, leaving the rest of the URLs\nuntouched. This filename part is sometimes referred to as\nthe &quot;basename&quot;, although we avoid that term here\nin order not to cause confusion.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">It works\nparticularly well in conjunction with\n<b>--adjust-extension</b>, although this\ncoupling is not enforced. It proves useful to populate\nInternet caches with files downloaded from different\nhosts.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Example: if\nsome link points to <i>//foo.com/bar.cgi?xyz</i> with\n<b>--adjust-extension</b> asserted and its\nlocal destination is intended to be\n<i>./foo.com/bar.cgi?xyz.css</i>, then the link would be\nconverted to <i>//foo.com/bar.cgi?xyz.css</i>. Note that\nonly the filename part has been modified. The rest of the\n<small>URL</small> has been left untouched, including the\nnet path (<tt>&quot;//&quot;</tt>) which would otherwise be\nprocessed by Wget and converted to the effective scheme (ie.\n<tt>&quot;http://&quot;</tt>).</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-K</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--backup-converted</b></p>\n\n<p style=\"margin-left:17%;\">When converting a file, back up\nthe original version with a <b>.orig</b> suffix. Affects the\nbehavior of <b>-N</b>.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-m</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--mirror</b></p>\n\n<p style=\"margin-left:17%;\">Turn on options suitable for\nmirroring. This option turns on recursion and time-stamping,\nsets infinite recursion depth and keeps <small>FTP</small>\ndirectory listings. It is currently equivalent to\n<b>-r -N -l inf\n--no-remove-listing</b>.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-p</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--page-requisites</b></p>\n\n<p style=\"margin-left:17%;\">This option causes Wget to\ndownload all the files that are necessary to properly\ndisplay a given <small>HTML</small> page. This includes such\nthings as inlined images, sounds, and referenced\nstylesheets.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Ordinarily,\nwhen downloading a single <small>HTML</small> page, any\nrequisite documents that may be needed to display it\nproperly are not downloaded. Using <b>-r</b> together\nwith <b>-l</b> can help, but since Wget does not\nordinarily distinguish between external and inlined\ndocuments, one is generally left with &quot;leaf\ndocuments&quot; that are missing their requisites.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">For instance,\nsay document <i>1.html</i> contains an\n<tt>&quot;&lt;IMG&gt;&quot;</tt> tag referencing\n<i>1.gif</i> and an <tt>&quot;&lt;A&gt;&quot;</tt> tag\npointing to external document <i>2.html</i>. Say that\n<i>2.html</i> is similar but that its image is <i>2.gif</i>\nand it links to <i>3.html</i>. Say this continues up to some\narbitrarily high number.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If one executes\nthe command:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -r -l 2 http://&lt;site&gt;/1.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">then\n<i>1.html</i>, <i>1.gif</i>, <i>2.html</i>, <i>2.gif</i>,\nand <i>3.html</i> will be downloaded. As you can see,\n<i>3.html</i> is without its requisite <i>3.gif</i> because\nWget is simply counting the number of hops (up to 2) away\nfrom <i>1.html</i> in order to determine where to stop the\nrecursion. However, with this command:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -r -l 2 -p http://&lt;site&gt;/1.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">all the above\nfiles <i>and 3.html</i>&rsquo;s requisite <i>3.gif</i> will\nbe downloaded. Similarly,</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -r -l 1 -p http://&lt;site&gt;/1.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">will cause\n<i>1.html</i>, <i>1.gif</i>, <i>2.html</i>, and <i>2.gif</i>\nto be downloaded. One might think that:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -r -l 0 -p http://&lt;site&gt;/1.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">would download\njust <i>1.html</i> and <i>1.gif</i>, but unfortunately this\nis not the case, because <b>-l 0</b> is equivalent to\n<b>-l inf</b>---that is, infinite\nrecursion. To download a single <small>HTML</small> page (or\na handful of them, all specified on the command-line or in a\n<b>-i</b> <small>URL</small> input file) and its (or\ntheir) requisites, simply leave off <b>-r</b> and\n<b>-l</b>:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -p http://&lt;site&gt;/1.html</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note that Wget\nwill behave as if <b>-r</b> had been specified, but\nonly that single page and its requisites will be downloaded.\nLinks from that page to external documents will not be\nfollowed. Actually, to download a single page and all its\nrequisites (even if they exist on separate websites), and\nmake sure the lot displays properly locally, this author\nlikes to use a few options in addition to\n<b>-p</b>:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget -E -H -k -K -p http://&lt;site&gt;/&lt;document&gt;</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">To finish off\nthis topic, it&rsquo;s worth knowing that Wget&rsquo;s idea\nof an external document link is any <small>URL</small>\nspecified in an <tt>&quot;&lt;A&gt;&quot;</tt> tag, an\n<tt>&quot;&lt;AREA&gt;&quot;</tt> tag, or a\n<tt>&quot;&lt;LINK&gt;&quot;</tt> tag other than\n<tt>&quot;&lt;LINK\nREL=&quot;stylesheet&quot;&gt;&quot;</tt>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--strict-comments</b></p>\n\n<p style=\"margin-left:17%;\">Turn on strict parsing of\n<small>HTML</small> comments. The default is to terminate\ncomments at the first occurrence of\n<b>--&gt;</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">According to\nspecifications, <small>HTML</small> comments are expressed\nas <small>SGML</small> <i>declarations</i>. Declaration is\nspecial markup that begins with <b>&lt;!</b> and ends with\n<b>&gt;</b>, such as <b>&lt;!DOCTYPE ...&gt;</b>, that may\ncontain comments between a pair of <b>--</b>\ndelimiters. <small>HTML</small> comments are &quot;empty\ndeclarations&quot;, <small>SGML</small> declarations without\nany non-comment text. Therefore,\n<b>&lt;!--foo--&gt;</b> is a valid\ncomment, and so is <b>&lt;!--one--\n--two--&gt;</b>, but\n<b>&lt;!--1--2--&gt;</b>\nis not.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">On the other\nhand, most <small>HTML</small> writers don&rsquo;t perceive\ncomments as anything other than text delimited with\n<b>&lt;!--</b> and <b>--&gt;</b>,\nwhich is not quite the same. For example, something like\n<b>&lt;!------------&gt;</b>\nworks as a valid comment as long as the number of dashes is\na multiple of four (!). If not, the comment technically\nlasts until the next <b>--</b>, which may be at\nthe other end of the document. Because of this, many popular\nbrowsers completely ignore the specification and implement\nwhat users have come to expect: comments delimited with\n<b>&lt;!--</b> and\n<b>--&gt;</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Until version\n1.9, Wget interpreted comments strictly, which resulted in\nmissing links in many web pages that displayed fine in\nbrowsers, but had the misfortune of containing non-compliant\ncomments. Beginning with version 1.9, Wget has joined the\nranks of clients that implements &quot;naive&quot; comments,\nterminating each comment at the first occurrence of\n<b>--&gt;</b>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">If, for\nwhatever reason, you want strict comment parsing, use this\noption to turn it on.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Recursive\nAccept/Reject Options <br>\n-A</b> <i>acclist</i> <b>--accept</b>\n<i>acclist</i> <b><br>\n-R</b> <i>rejlist</i> <b>--reject</b>\n<i>rejlist</i></p>\n\n<p style=\"margin-left:17%;\">Specify comma-separated lists\nof file name suffixes or patterns to accept or reject. Note\nthat if any of the wildcard characters, <b>*</b>, <b>?</b>,\n<b>[</b> or <b>]</b>, appear in an element of <i>acclist</i>\nor <i>rejlist</i>, it will be treated as a pattern, rather\nthan a suffix. In this case, you have to enclose the pattern\ninto quotes to prevent your shell from expanding it, like in\n<b>-A &quot;*.mp3&quot;</b> or <b>-A\n&rsquo;*.mp3&rsquo;</b>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--accept-regex</b>\n<i>urlregex</i> <b><br>\n--reject-regex</b> <i>urlregex</i></p>\n\n<p style=\"margin-left:17%;\">Specify a regular expression to\naccept or reject the complete <small>URL.</small></p>\n\n\n<p style=\"margin-left:11%;\"><b>--regex-type</b>\n<i>regextype</i></p>\n\n<p style=\"margin-left:17%;\">Specify the regular expression\ntype. Possible types are <b>posix</b> or <b>pcre</b>. Note\nthat to be able to use <b>pcre</b> type, wget has to be\ncompiled with libpcre support.</p>\n\n<p style=\"margin-left:11%;\"><b>-D</b>\n<i>domain-list</i> <b><br>\n--domains=</b><i>domain-list</i></p>\n\n<p style=\"margin-left:17%;\">Set domains to be followed.\n<i>domain-list</i> is a comma-separated list of domains.\nNote that it does <i>not</i> turn on <b>-H</b>.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--exclude-domains</b>\n<i>domain-list</i></p>\n\n<p style=\"margin-left:17%;\">Specify the domains that are\n<i>not</i> to be followed.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--follow-ftp</b></p>\n\n<p style=\"margin-left:17%;\">Follow <small>FTP</small> links\nfrom <small>HTML</small> documents. Without this option,\nWget will ignore all the <small>FTP</small> links.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--follow-tags=</b><i>list</i></p>\n\n<p style=\"margin-left:17%;\">Wget has an internal table of\n<small>HTML</small> tag / attribute pairs that it considers\nwhen looking for linked documents during a recursive\nretrieval. If a user wants only a subset of those tags to be\nconsidered, however, he or she should be specify such tags\nin a comma-separated <i>list</i> with this option.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ignore-tags=</b><i>list</i></p>\n\n<p style=\"margin-left:17%;\">This is the opposite of the\n<b>--follow-tags</b> option. To skip\ncertain <small>HTML</small> tags when recursively looking\nfor documents to download, specify them in a comma-separated\n<i>list</i>.</p>\n\n<p style=\"margin-left:17%; margin-top: 1em\">In the past,\nthis option was the best bet for downloading a single page\nand its requisites, using a command-line like:</p>\n\n<pre style=\"margin-left:17%; margin-top: 1em\">        wget --ignore-tags=a,area -H -k -K -r http://&lt;site&gt;/&lt;document&gt;</pre>\n\n\n<p style=\"margin-left:17%; margin-top: 1em\">However, the\nauthor of this option came across a page with tags like\n<tt>&quot;&lt;LINK REL=&quot;home&quot;\nHREF=&quot;/&quot;&gt;&quot;</tt> and came to the\nrealization that specifying tags to ignore was not enough.\nOne can&rsquo;t just tell Wget to ignore\n<tt>&quot;&lt;LINK&gt;&quot;</tt>, because then stylesheets\nwill not be downloaded. Now the best bet for downloading a\nsingle page and its requisites is the dedicated\n<b>--page-requisites</b> option.</p>\n\n\n<p style=\"margin-left:11%;\"><b>--ignore-case</b></p>\n\n<p style=\"margin-left:17%;\">Ignore case when matching files\nand directories. This influences the behavior of -R,\n-A, -I, and -X options, as well as\nglobbing implemented when downloading from\n<small>FTP</small> sites. For example, with this option,\n<b>-A &quot;*.txt&quot;</b> will match\n<b>file1.txt</b>, but also <b>file2.TXT</b>,\n<b>file3.TxT</b>, and so on. The quotes in the example are\nto prevent the shell from expanding the pattern.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-H</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--span-hosts</b></p>\n\n<p style=\"margin-left:17%;\">Enable spanning across hosts\nwhen doing recursive retrieving.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p><b>-L</b></p></td>\n<td width=\"86%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--relative</b></p>\n\n<p style=\"margin-left:17%;\">Follow relative links only.\nUseful for retrieving a specific home page without any\ndistractions, not even those from the same hosts.</p>\n\n<p style=\"margin-left:11%;\"><b>-I</b> <i>list</i>\n<b><br>\n--include-directories=</b><i>list</i></p>\n\n<p style=\"margin-left:17%;\">Specify a comma-separated list\nof directories you wish to follow when downloading. Elements\nof <i>list</i> may contain wildcards.</p>\n\n<p style=\"margin-left:11%;\"><b>-X</b> <i>list</i>\n<b><br>\n--exclude-directories=</b><i>list</i></p>\n\n<p style=\"margin-left:17%;\">Specify a comma-separated list\nof directories you wish to exclude from download. Elements\nof <i>list</i> may contain wildcards.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"4%\">\n\n\n<p><b>-np</b></p></td>\n<td width=\"85%\">\n</td></tr>\n</table>\n\n\n<p style=\"margin-left:11%;\"><b>--no-parent</b></p>\n\n<p style=\"margin-left:17%;\">Do not ever ascend to the\nparent directory when retrieving recursively. This is a\nuseful option, since it guarantees that only the files\n<i>below</i> a certain hierarchy will be downloaded.</p>\n\n<h2>ENVIRONMENT\n<a name=\"ENVIRONMENT\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget supports\nproxies for both <small>HTTP</small> and <small>FTP</small>\nretrievals. The standard way to specify proxy location,\nwhich Wget recognizes, is using the following environment\nvariables: <b><br>\nhttp_proxy <br>\nhttps_proxy</b></p>\n\n<p style=\"margin-left:17%;\">If set, the <b>http_proxy</b>\nand <b>https_proxy</b> variables should contain the URLs of\nthe proxies for <small>HTTP</small> and <small>HTTPS</small>\nconnections respectively.</p>\n\n<p style=\"margin-left:11%;\"><b>ftp_proxy</b></p>\n\n<p style=\"margin-left:17%;\">This variable should contain\nthe <small>URL</small> of the proxy for <small>FTP</small>\nconnections. It is quite common that <b>http_proxy</b> and\n<b>ftp_proxy</b> are set to the same <small>URL.</small></p>\n\n<p style=\"margin-left:11%;\"><b>no_proxy</b></p>\n\n<p style=\"margin-left:17%;\">This variable should contain a\ncomma-separated list of domain extensions proxy should\n<i>not</i> be used for. For instance, if the value of\n<b>no_proxy</b> is <b>.mit.edu</b>, proxy will not be used\nto retrieve documents from <small>MIT.</small></p>\n\n<h2>EXIT STATUS\n<a name=\"EXIT STATUS\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Wget may return\none of several error codes if it encounters problems.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>0</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>No problems occurred.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>1</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Generic error code.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>2</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Parse error---for instance, when\nparsing command-line options, the <b>.wgetrc</b> or\n<b>.netrc</b>...</p> </td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>3</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>File I/O error.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>4</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Network failure.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>5</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p><small>SSL</small> verification failure.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>6</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Username/password authentication failure.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>7</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Protocol errors.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"1%\">\n\n\n<p>8</p></td>\n<td width=\"5%\"></td>\n<td width=\"83%\">\n\n\n<p>Server issued an error response.</p></td></tr>\n</table>\n\n<p style=\"margin-left:11%; margin-top: 1em\">With the\nexceptions of 0 and 1, the lower-numbered exit codes take\nprecedence over higher-numbered ones, when multiple types of\nerrors are encountered.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">In versions of\nWget prior to 1.12, Wget&rsquo;s exit status tended to be\nunhelpful and inconsistent. Recursive downloads would\nvirtually always return 0 (success), regardless of any\nissues encountered, and non-recursive fetches only returned\nthe status corresponding to the most recently-attempted\ndownload.</p>\n\n<h2>FILES\n<a name=\"FILES\"></a>\n</h2>\n\n\n\n<p style=\"margin-left:11%; margin-top: 1em\"><b>/usr/local/etc/wgetrc</b></p>\n\n<p style=\"margin-left:17%;\">Default location of the\n<i>global</i> startup file.</p>\n\n<p style=\"margin-left:11%;\"><b>.wgetrc</b></p>\n\n<p style=\"margin-left:17%;\">User startup file.</p>\n\n<h2>BUGS\n<a name=\"BUGS\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">You are welcome\nto submit bug reports via the <small>GNU</small> Wget bug\ntracker (see\n&lt;<b>https://savannah.gnu.org/bugs/?func=additem&amp;group=wget</b>&gt;)\nor to our mailing list\n&lt;<b>bug-wget@gnu.org</b>&gt;.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Visit\n&lt;<b>https://lists.gnu.org/mailman/listinfo/bug-wget</b>&gt;\nto get more info (how to subscribe, list archives, ...).</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Before actually\nsubmitting a bug report, please try to follow a few simple\nguidelines.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p>1.</p></td>\n<td width=\"3%\"></td>\n<td width=\"83%\">\n\n\n<p>Please try to ascertain that the behavior you see really\nis a bug. If Wget crashes, it&rsquo;s a bug. If Wget does\nnot behave as documented, it&rsquo;s a bug. If things work\nstrange, but you are not sure about the way they are\nsupposed to work, it might well be a bug, but you might want\nto double-check the documentation and the mailing lists.</p></td></tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p>2.</p></td>\n<td width=\"3%\"></td>\n<td width=\"83%\">\n\n\n<p>Try to repeat the bug in as simple circumstances as\npossible. E.g. if Wget crashes while downloading <b>wget\n-rl0 -kKE -t5 --no-proxy\nhttp://example.com -o /tmp/log</b>, you should try to\nsee if the crash is repeatable, and if will occur with a\nsimpler set of options. You might even try to start the\ndownload at the page where the crash occurred to see if that\npage somehow triggered the crash.</p></td></tr>\n</table>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Also, while I\nwill probably be interested to know the contents of your\n<i>.wgetrc</i> file, just dumping it into the debug message\nis probably a bad idea. Instead, you should first try to see\nif the bug repeats with <i>.wgetrc</i> moved out of the way.\nOnly if it turns out that <i>.wgetrc</i> settings affect the\nbug, mail me the relevant parts of the file.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p style=\"margin-top: 1em\">3.</p></td>\n<td width=\"3%\"></td>\n<td width=\"83%\">\n\n\n<p style=\"margin-top: 1em\">Please start Wget with\n<b>-d</b> option and send us the resulting output (or\nrelevant parts thereof). If Wget was compiled without debug\nsupport, recompile it---it is <i>much</i>\neasier to trace bugs with debug support on.</p></td></tr>\n</table>\n\n<p style=\"margin-left:17%; margin-top: 1em\">Note: please\nmake sure to remove any potentially sensitive information\nfrom the debug log before sending it to the bug address. The\n<tt>&quot;-d&quot;</tt> won&rsquo;t go out of its way\nto collect sensitive information, but the log <i>will</i>\ncontain a fairly complete transcript of Wget&rsquo;s\ncommunication with the server, which may include passwords\nand pieces of downloaded data. Since the bug address is\npublicly archived, you may assume that all bug reports are\nvisible to the public.</p>\n\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\"\n       cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"></td>\n<td width=\"3%\">\n\n\n<p style=\"margin-top: 1em\">4.</p></td>\n<td width=\"3%\"></td>\n<td width=\"83%\">\n\n\n<p style=\"margin-top: 1em\">If Wget has crashed, try to run\nit in a debugger, e.g. <tt>&quot;gdb `which wget`\ncore&quot;</tt> and type <tt>&quot;where&quot;</tt> to get\nthe backtrace. This may not work if the system administrator\nhas disabled core files, but it is safe to try.</p></td></tr>\n</table>\n\n<h2>SEE ALSO\n<a name=\"SEE ALSO\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">This is\n<b>not</b> the complete manual for <small>GNU</small> Wget.\nFor more complete information, including more detailed\nexplanations of some of the options, and a number of\ncommands available for use with <i>.wgetrc</i> files and the\n<b>-e</b> option, see the <small>GNU</small> Info\nentry for <i>wget</i>.</p>\n\n<h2>AUTHOR\n<a name=\"AUTHOR\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Originally\nwritten by Hrvoje Nik&Aring;&iexcl;i&Auml;\n&lt;hniksic@xemacs.org&gt;.</p>\n\n<h2>COPYRIGHT\n<a name=\"COPYRIGHT\"></a>\n</h2>\n\n\n<p style=\"margin-left:11%; margin-top: 1em\">Copyright (c)\n1996-2011, 2015, 2018-2019 Free Software\nFoundation, Inc.</p>\n\n<p style=\"margin-left:11%; margin-top: 1em\">Permission is\ngranted to copy, distribute and/or modify this document\nunder the terms of the <small>GNU</small> Free Documentation\nLicense, Version 1.3 or any later version published by the\nFree Software Foundation; with no Invariant Sections, with\nno Front-Cover Texts, and with no Back-Cover Texts. A copy\nof the license is included in the section entitled &quot;\n<small>GNU</small> Free Documentation License&quot;.</p>\n<hr>\n</body>\n</html>\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "### VERSION INFO\nset(OpenPose_VERSION_MAJOR 1)\nset(OpenPose_VERSION_MINOR 7)\nset(OpenPose_VERSION_PATCH 0)\nset(OpenPose_VERSION ${OpenPose_VERSION_MAJOR}.${OpenPose_VERSION_MINOR}.${OpenPose_VERSION_PATCH})\n\n\n### OS-DEPENDENT FLAGS\nset(CMAKE_MACOSX_RPATH 1)\n\n\n### CMAKE HEADERS\n# Ubuntu 18 default. After 3.8, no need for find_CUDA\n# https://cmake.org/cmake/help/v3.10/module/FindCUDA.html\n# https://cmake.org/cmake/help/v3.10/command/project.html\n# https://devblogs.nvidia.com/building-cuda-applications-cmake/\nif (${CMAKE_VERSION} VERSION_GREATER 3.9.0)\n  cmake_policy(SET CMP0048 NEW)\n  project(OpenPose VERSION ${OpenPose_VERSION})\n  # # Not tested\n  # cmake_policy(SET CMP0048 NEW)\n  # set(CUDACXX /usr/local/cuda/bin/nvcc)\n  # project(OpenPose VERSION ${OpenPose_VERSION} LANGUAGES CXX CUDA)\n  # set(AUTO_FOUND_CUDA TRUE)\n  # # else\n  # set(AUTO_FOUND_CUDA FALSE)\n# Ubuntu 16 default\nelseif (${CMAKE_VERSION} VERSION_GREATER 3.0.0)\n  cmake_policy(SET CMP0048 NEW)\n  project(OpenPose VERSION ${OpenPose_VERSION})\nelse (${CMAKE_VERSION} VERSION_GREATER 3.9.0)\n  project(OpenPose)\nendif (${CMAKE_VERSION} VERSION_GREATER 3.9.0)\ncmake_minimum_required(VERSION 3.0 FATAL_ERROR) # required by cmake eigen finder to find locally installed versions (e.g., CUDA 9.2 support was added in eigen 3.3.5)\n# cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR) # min. cmake version recommended by Caffe\n\n\n### Extra functionality\ninclude(cmake/Utils.cmake)\nif (NOT WIN32 AND NOT UNIX AND NOT APPLE)\n  message(FATAL_ERROR \"Unsupported operating system. Only Windows, Mac and Unix systems supported.\")\nendif (NOT WIN32 AND NOT UNIX AND NOT APPLE)\n\n\n### CMAKE_BUILD_TYPE\n# Default: Release\n# Bug fixed: By default, it uses something different to Release, that provokes OpenPose to be about 15% slower than\n# it should be.\n# Is CMAKE_BUILD_TYPE \"Debug\" or \"MinSizeRel\" or \"RelWithDebInfo\"?\nset(CMAKE_BUILD_TYPE_KNOWN FALSE)\nif (${CMAKE_BUILD_TYPE} MATCHES \"Debug\")\n  set(CMAKE_BUILD_TYPE_KNOWN TRUE)\nendif (${CMAKE_BUILD_TYPE} MATCHES \"Debug\")\nif (${CMAKE_BUILD_TYPE} MATCHES \"MinSizeRel\")\n  set(CMAKE_BUILD_TYPE_KNOWN TRUE)\nendif (${CMAKE_BUILD_TYPE} MATCHES \"MinSizeRel\")\nif (${CMAKE_BUILD_TYPE} MATCHES \"RelWithDebInfo\")\n  set(CMAKE_BUILD_TYPE_KNOWN TRUE)\nendif (${CMAKE_BUILD_TYPE} MATCHES \"RelWithDebInfo\")\n# Assign proper CMAKE_BUILD_TYPE\nif (${CMAKE_BUILD_TYPE_KNOWN})\n  set(CMAKE_BUILD_TYPE \"Release\" CACHE STRING \"Choose the type of build.\")\nelse (${CMAKE_BUILD_TYPE_KNOWN})\n  set(CMAKE_BUILD_TYPE \"Release\" CACHE STRING \"Choose the type of build.\" FORCE)\nendif (${CMAKE_BUILD_TYPE_KNOWN})\nset_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS \"Release\" \"Debug\" \"MinSizeRel\" \"RelWithDebInfo\")\n\n\n### FLAGS\nif (WIN32)\n  # TODO -- Makeshift solution -- This prevents rerunning build again\n  # https://gitlab.kitware.com/cmake/cmake/issues/16783\n  set(CMAKE_SUPPRESS_REGENERATION ON)\n\n  string (REPLACE \"/D_WINDOWS\" \"\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\n  string (REPLACE \"/DWIN32\" \"\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\n\n  # /GL option causes the code to crash -- fix this\n  # sdl flags causes error -- error : unknown attribute \\\"guard\\\"\n\n  # https://stackoverflow.com/questions/43697154/detect-current-cmake-version-using-cmake\n  message(STATUS \"CMAKE_VERSION = ${CMAKE_VERSION}\")\n  # Remove \"minSizeRel\" and \"relWithDebInfo\"\n  if (${CMAKE_VERSION} VERSION_LESS \"3.14.0\")\n    set(CMAKE_CONFIGURATION_TYPES Release Debug CACHE TYPE INTERNAL FORCE)\n  else (${CMAKE_VERSION} VERSION_LESS \"3.14.0\")\n    # But the above line gives warning on CMake >= 3.14, alternative\n    set(CMAKE_CONFIGURATION_TYPES Release Debug CACHE STRING \"\" FORCE)\n  endif (${CMAKE_VERSION} VERSION_LESS \"3.14.0\")\n\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /MP\")\n  string(REPLACE \"/W3\" \"/W4\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\n  string(REPLACE \"/GR\" \"\" CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}\")\n\n  string(REPLACE \"/O2\" \"/Ox\" CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE}\")\n  string(REPLACE \"/Ob2\" \"\" CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE}\")\n  set(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE} /Ot /Oi /Gy /Z7\")\n\n  set(CMAKE_SHARED_LINKER_FLAGS_RELEASE \"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG:incremental /OPT:REF /OPT:ICF\")\nelseif (UNIX)\n  # Turn on C++11\n  add_definitions(-std=c++11)\n  set(CMAKE_CXX_FLAGS_RELEASE \"-O3\")\nelseif (APPLE)\n  # Turn on C++11\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++11\")\n  set(CMAKE_CXX_FLAGS_RELEASE \"-O3\")\nendif (WIN32)\n\n# C++ additional flags\nif (CMAKE_COMPILER_IS_GNUCXX)\n  message(STATUS \"GCC detected, adding compile flags\")\n  # set(OP_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fopenmp -Wpedantic -Wall -Wextra -Wfatal-errors\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fopenmp\")\n  set(OP_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wpedantic -Wall -Wextra -Wfatal-errors\")\n  # set(CUDA_NVCC_FLAGS \"${CUDA_NVCC_FLAGS} -Wpedantic -Wall -Wextra -Wfatal-errors\")\nendif (CMAKE_COMPILER_IS_GNUCXX)\n\n# Select the Enhanced Instruction Set\nset(INSTRUCTION_SET NONE CACHE STRING \"Enable Enhanced Instruction Set\")\nset_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE AVX2)\nif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n  add_definitions(\"-DWITH_AVX\")\nendif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n# Windows\nif (WIN32)\n  # Suboptions for Enhanced Instruction Set\n  if (${INSTRUCTION_SET} MATCHES \"AVX2\")\n    add_definitions(\"/arch:AVX2\")\n  endif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n# Ubuntu\nelse (WIN32) # if (CMAKE_COMPILER_IS_GNUCXX)\n  if (${INSTRUCTION_SET} MATCHES \"AVX2\")\n    set(SIMD_FLAGS \"${SIMD_FLAGS} -mavx -march=native\")\n  endif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n  message(STATUS \"GCC detected, adding compile flags\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${SIMD_FLAGS}\")\nendif (WIN32)\n# if (CMAKE_COMPILER_IS_GNUCXX)\n#   set_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE SSE4 AVX)\n#   if (${INSTRUCTION_SET} MATCHES \"SSE4\")\n#     add_definitions(\"-DWITH_SSE4\")\n#     set(SIMD_FLAGS \"${SIMD_FLAGS} -msse4.1\")\n#   endif (${INSTRUCTION_SET} MATCHES \"SSE4\")\n#   if (${INSTRUCTION_SET} MATCHES \"AVX2\")\n#     add_definitions(\"-DWITH_AVX\")\n#     set(SIMD_FLAGS \"${SIMD_FLAGS} -mavx -march=native\")\n#   endif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n#   message(STATUS \"GCC detected, adding compile flags\")\n#   set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${SIMD_FLAGS}\")\n# endif (CMAKE_COMPILER_IS_GNUCXX)\n# if (WIN32)\n#   # set_property(CACHE INSTRUCTION_SET PROPERTY STRINGS NONE SSE SSE2 AVX AVX2 IA32)\n#   # Suboptions for Enhanced Instruction Set\n#   if (${INSTRUCTION_SET} MATCHES \"SSE\")\n#     add_definitions(\"/arch:SSE\")\n#   elseif (${INSTRUCTION_SET} MATCHES \"SSE2\")\n#     add_definitions(\"/arch:SSE2\")\n#   elseif (${INSTRUCTION_SET} MATCHES \"AVX\")\n#     add_definitions(\"/arch:AVX\")\n#   elseif (${INSTRUCTION_SET} MATCHES \"AVX2\")\n#     add_definitions(\"/arch:AVX2\")\n#   elseif (${INSTRUCTION_SET} MATCHES \"IA32\")\n#     add_definitions(\"/arch:IA32\")\n#   endif (${INSTRUCTION_SET} MATCHES \"SSE\")\n# endif (WIN32)\n\n\n### PROJECT OPTIONS\n# Select the DL Framework\nset(DL_FRAMEWORK CAFFE CACHE STRING \"Select Deep Learning Framework.\")\nif (WIN32)\n  set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE)\nelse (WIN32)\n  set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE NV_CAFFE)\n  # set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE NV_CAFFE PYTORCH TENSORFLOW)\nendif (WIN32)\n\n# Suboptions for Caffe DL Framework\ninclude(CMakeDependentOption)\nif (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n  CMAKE_DEPENDENT_OPTION(BUILD_CAFFE \"Build Caffe as part of OpenPose.\" ON\n    \"DL_FRAMEWORK\" ON)\n  # OpenPose flags\n  add_definitions(-DUSE_CAFFE)\n  # Nvidia NVCaffe\n  if (${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n      MESSAGE(STATUS \"Using NVIDIA NVCaffe\")\n      add_definitions(-DNV_CAFFE)\n  endif (${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\nendif (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n\n# Set the acceleration library\nif (APPLE)\n  set(GPU_MODE CPU_ONLY CACHE STRING \"Select the acceleration GPU library or CPU otherwise.\")\nelse (APPLE)\n  set(GPU_MODE CUDA CACHE STRING \"Select the acceleration GPU library or CPU otherwise.\")\nendif (APPLE)\n# Display proper options to user\n# if (CUDA_FOUND AND OpenCL_FOUND)\n#   set_property(CACHE GPU_MODE PROPERTY STRINGS CUDA OPENCL CPU_ONLY)\n# elseif (CUDA_FOUND)\n#   set_property(CACHE GPU_MODE PROPERTY STRINGS CUDA CPU_ONLY)\n# elseif (OpenCL_FOUND)\n#   set_property(CACHE GPU_MODE PROPERTY STRINGS OPENCL CPU_ONLY)\n# else ()\n#   set_property(CACHE GPU_MODE PROPERTY STRINGS CPU_ONLY)\n# endif (CUDA_FOUND AND OpenCL_FOUND)\nset_property(CACHE GPU_MODE PROPERTY STRINGS CUDA OPENCL CPU_ONLY)\n\n# Look for CUDA\nset(CUDA_FOUND FALSE)\nif (${GPU_MODE} MATCHES \"CUDA\")\n  find_package(CUDA)\nendif (${GPU_MODE} MATCHES \"CUDA\")\n# Look for OpenCL\nset(OpenCL_FOUND FALSE)\nset(CUDA_VERSION_MAJOR 0)\nif (${GPU_MODE} MATCHES \"OPENCL\")\n  find_package(OpenCL)\nendif (${GPU_MODE} MATCHES \"OPENCL\")\n\n# Code to avoid crash at compiling time if OpenCL is not found\nif (NOT OpenCL_FOUND)\n  set(OpenCL_LIBRARIES \"\")\nendif (NOT OpenCL_FOUND)\n# Required for OpenCL in Nvidia graphic cards\nif (CUDA_FOUND AND OpenCL_FOUND AND ${CUDA_VERSION_MAJOR} LESS 9)\n  add_definitions(-DLOWER_CL_VERSION)\nendif (CUDA_FOUND AND OpenCL_FOUND AND ${CUDA_VERSION_MAJOR} LESS 9)\n# Handle desired GPU mode option\nif (${GPU_MODE} MATCHES \"CUDA\")\n  # OpenPose flags\n  add_definitions(-DUSE_CUDA)\n  message(STATUS \"Building with CUDA.\")\nelseif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n  add_definitions(-DUSE_CPU_ONLY)\n  message(STATUS \"Building CPU Only.\")\n  # OpenPose flag for Caffe\n  add_definitions(-DCPU_ONLY)\nelseif (${GPU_MODE} MATCHES \"OPENCL\")\n  # OpenPose flag for Caffe\n  add_definitions(-DUSE_OPENCL)\n  add_definitions(-DUSE_GREENTEA)\n  message(STATUS \"Building with OpenCL.\")\nendif (${GPU_MODE} MATCHES \"CUDA\")\n\n# Intel branch with MKL Support\nif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n  if (UNIX AND NOT APPLE)\n    OPTION(USE_MKL \"Use MKL Intel Branch.\" OFF)\n  endif (UNIX AND NOT APPLE)\nendif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n\nif (${USE_MKL})\n  # OpenPose flags\n  add_definitions(-DUSE_MKL)\n  message(STATUS \"Building with MKL support.\")\nendif (${USE_MKL})\n\n# Set/disable profiler\nif (PROFILER_ENABLED)\n  add_definitions(-DPROFILER_ENABLED)\nendif (PROFILER_ENABLED)\n\n# Suboptions for GPU architectures\nif (${GPU_MODE} MATCHES \"CUDA\")\n  set(CUDA_ARCH Auto CACHE STRING \"Select target NVIDIA GPU architecture.\")\n  set_property(CACHE CUDA_ARCH PROPERTY STRINGS Auto All Manual)\nendif (${GPU_MODE} MATCHES \"CUDA\")\n\n# Suboptions for acceleration library\nif (${GPU_MODE} MATCHES \"CUDA\")\n  option(USE_CUDNN \"Build OpenPose with cuDNN library support.\" ON)\nendif (${GPU_MODE} MATCHES \"CUDA\")\n\n# Suboptions for OpenPose 3D Reconstruction module and demo\noption(WITH_3D_RENDERER \"Add OpenPose 3D renderer module (it requires FreeGLUT library).\" OFF)\nif (UNIX AND NOT APPLE)\n  option(WITH_CERES \"Add Ceres support for advanced 3-D reconstruction.\" OFF)\nendif (UNIX AND NOT APPLE)\noption(WITH_FLIR_CAMERA \"Add FLIR (formerly Point Grey) camera code (requires Spinnaker SDK already installed).\" OFF)\n# option(WITH_3D_ADAM_MODEL \"Add 3-D Adam model (requires OpenGL, Ceres, Eigen, OpenMP, FreeImage, GLEW, and IGL already installed).\" OFF)\n\n# Faster GUI rendering\n# Note: It seems to work by default in Windows and Ubuntu, but not in Mac nor Android.\n# More info: https://stackoverflow.com/questions/21129683/does-opengl-display-image-faster-than-opencv?answertab=active#tab-top\noption(WITH_OPENCV_WITH_OPENGL \"Much faster GUI display, but you must also enable OpenGL support in OpenCV by configuring OpenCV using CMake with WITH_OPENGL=ON flag.\" OFF)\n\n# Set the acceleration library\nif (WIN32 OR APPLE)\n  set(WITH_EIGEN NONE CACHE STRING \"Select the Eigen mode: NONE if not required, AUTOBUILD to let OpenPose download it, or FIND to let CMake find it (e.g., if you installed it manually).\")\nelseif (UNIX AND NOT APPLE)\n  set(WITH_EIGEN NONE CACHE STRING \"Select the Eigen mode: NONE if not required, AUTOBUILD to let OpenPose download it, or FIND to let CMake find it (e.g., if you installed it manually or used `sudo apt-get install libeigen3-dev`).\")\nendif (WIN32 OR APPLE)\nset_property(CACHE WITH_EIGEN PROPERTY STRINGS NONE AUTOBUILD FIND)\n\n# # Suboptions for OpenPose tracking\n# if (UNIX AND NOT APPLE)\n#   option(WITH_TRACKING \"Add OpenPose 3D tracking module (it requires OpenCV with CUDA support).\" OFF)\n# endif (UNIX AND NOT APPLE)\n\n# Download the models\noption(DOWNLOAD_BODY_25_MODEL \"Download body 25-keypoint (body COCO and 6-keypoint foot) model.\" ON)\noption(DOWNLOAD_BODY_COCO_MODEL \"Download body 18-keypoint COCO model.\" OFF)\noption(DOWNLOAD_BODY_MPI_MODEL \"Download body 15-keypoint MPI model.\" OFF)\noption(DOWNLOAD_FACE_MODEL \"Download face model.\" ON)\noption(DOWNLOAD_HAND_MODEL \"Download hand model.\" ON)\n\n# Asio\n# option(USE_ASIO \"Include Asio header-only library.\" OFF)\n\n# More options\noption(BUILD_EXAMPLES \"Build OpenPose examples.\" ON)\noption(BUILD_DOCS \"Build OpenPose documentation.\" OFF)\noption(BUILD_PYTHON \"Build OpenPose python.\" OFF)\nif (WIN32)\n  option(BUILD_BIN_FOLDER \"Copy all required 3rd-party DLL files into {build_directory}/bin. Disable to save some memory.\" ON)\nendif (WIN32)\n\n# Unity\noption(BUILD_UNITY_SUPPORT \"Build OpenPose as a Unity plugin.\" OFF)\n\n# Build as shared library\noption(BUILD_SHARED_LIBS \"Build as shared lib.\" ON)\n\n# Speed profiler\noption(PROFILER_ENABLED \"If enabled, OpenPose will be able to print out speed information at runtime.\" OFF)\n\n# Threads - Pthread\nif (${GPU_MODE} MATCHES \"OPENCL\" OR (UNIX OR APPLE))\n  unset(CMAKE_THREAD_LIBS_INIT CACHE)\n  find_package(Threads)\nendif (${GPU_MODE} MATCHES \"OPENCL\" OR (UNIX OR APPLE))\n\n# Caffe OpenCL Boost Issue\nif (APPLE)\n  if (${GPU_MODE} MATCHES \"OPENCL\" OR BUILD_PYTHON)\n    unset(Boost_SYSTEM_LIBRARY CACHE)\n    find_package(Boost COMPONENTS system REQUIRED)\n  else ()\n    set(Boost_SYSTEM_LIBRARY \"\")\n  endif ()\nendif (APPLE)\n\nset(DOWNLOAD_SERVER \"http://vcl.snu.ac.kr/OpenPose/\" CACHE STRING \"Server from which the models and 3rdparty libraries will be downloaded from.\")\nmark_as_advanced(DOWNLOAD_SERVER)\n\n### FIND REQUIRED PACKAGES\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules\")\n\nif (${GPU_MODE} MATCHES \"CUDA\")\n  find_package(CUDA)\nendif (${GPU_MODE} MATCHES \"CUDA\")\n\n# Adding 3D\nif (WITH_OPENCV_WITH_OPENGL)\n  # OpenPose flags\n  add_definitions(-DUSE_OPENCV_WITH_OPENGL)\nendif (WITH_OPENCV_WITH_OPENGL)\nif (WITH_3D_RENDERER)\n  # OpenPose flags\n  add_definitions(-DUSE_3D_RENDERER)\nendif (WITH_3D_RENDERER)\nif (WITH_CERES)\n  add_definitions(-DUSE_CERES)\nendif (WITH_CERES)\nif (WITH_FLIR_CAMERA)\n  # OpenPose flags\n  add_definitions(-DUSE_FLIR_CAMERA)\nendif (WITH_FLIR_CAMERA)\nif (WITH_3D_ADAM_MODEL)\n  # OpenPose flags\n  add_definitions(-DUSE_3D_ADAM_MODEL)\nendif (WITH_3D_ADAM_MODEL)\n\n# Adding tracking\nif (WITH_TRACKING)\n  # OpenPose flags\n  add_definitions(-DUSE_TRACKING)\nendif (WITH_TRACKING)\n\n# Unity\nif (BUILD_UNITY_SUPPORT)\n  # OpenPose flags\n  add_definitions(-DUSE_UNITY_SUPPORT)\nendif (BUILD_UNITY_SUPPORT)\n\n# Calibration\n# No Eigen\nif (${WITH_EIGEN} MATCHES \"NONE\")\n  if (WITH_CERES)\n    message(FATAL_ERROR \"Eigen is required (enable `WITH_EIGEN`) if CERES is enabled.\")\n  endif (WITH_CERES)\n# If Eigen used\nelse (${WITH_EIGEN} MATCHES \"NONE\")\n  # OpenPose flags\n  add_definitions(-DUSE_EIGEN)\n  # OpenPose download/builds Eigen\n  if (${WITH_EIGEN} MATCHES \"AUTOBUILD\")\n    # Download it\n    set(OP_URL \"${DOWNLOAD_SERVER}3rdparty/\")\n    set(FIND_LIB_PREFIX ${CMAKE_SOURCE_DIR}/3rdparty/)\n    download_zip(\"eigen_2020_11_18.zip\" ${OP_URL} ${FIND_LIB_PREFIX} 57672715C62C1A795300FE1AE4D2687E)\n    # Set path\n    set(EIGEN3_INCLUDE_DIRS \"3rdparty/eigen/include/\")\n  # Leave to CMake to find it\n  elseif (${WITH_EIGEN} MATCHES \"FIND\")\n    # Eigen\n    # # Option a) apt-get\n    # find_package(PkgConfig)\n    # pkg_check_modules(EIGEN3 REQUIRED eigen3)\n    # # Option b) Find it (including apt-get)\n    if (CUDA_VERSION_STRING STRGREATER \"9.0\")\n      find_package(Eigen3 3.3.5 REQUIRED NO_MODULE)\n    else (CUDA_VERSION_STRING STRGREATER \"9.0\")\n      find_package(Eigen3 3 REQUIRED NO_MODULE)\n    endif (CUDA_VERSION_STRING STRGREATER \"9.0\")\n  endif (${WITH_EIGEN} MATCHES \"AUTOBUILD\")\nendif (${WITH_EIGEN} MATCHES \"NONE\")\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    include(cmake/Cuda.cmake)\n    find_package(CuDNN)\n  endif (${GPU_MODE} MATCHES \"CUDA\")\n  find_package(GFlags) # For Caffe and OpenPose\n  find_package(Glog) # For Caffe\n  find_package(Protobuf REQUIRED) # For Caffe\n\n  if (OpenCV_CONFIG_FILE)\n    include (${OpenCV_CONFIG_FILE})\n  # Allow explicitly setting the OpenCV includes and libs\n  elseif (OpenCV_INCLUDE_DIRS AND OpenCV_LIBS)\n    set(OpenCV_FOUND 1)\n  elseif (OpenCV_INCLUDE_DIRS AND OpenCV_LIBS_DIR)\n    file(GLOB_RECURSE OpenCV_LIBS \"${OpenCV_LIBS_DIR}*.so\")\n    set(OpenCV_FOUND 1)\n  else (OpenCV_CONFIG_FILE)\n    find_package(OpenCV)\n  endif (OpenCV_CONFIG_FILE)\n\n  # 3D\n  if (WITH_3D_RENDERER)\n    # OpenGL\n    find_package(OpenGL REQUIRED)\n    # GLUT\n    find_package(GLUT REQUIRED)\n    # OpenGL\n    find_package(OpenGL REQUIRED)\n  endif (WITH_3D_RENDERER)\n  if (WITH_CERES)\n    # Eigen + Ceres\n    find_package(Ceres REQUIRED COMPONENTS SuiteSparse)\n  endif (WITH_CERES)\n  if (WITH_FLIR_CAMERA)\n    # Spinnaker\n    find_package(Spinnaker)\n    if (NOT SPINNAKER_FOUND)\n      message(FATAL_ERROR \"Spinnaker not found. Either turn off the `WITH_FLIR_CAMERA` option or specify the path to\n        the Spinnaker includes and libs.\")\n    endif (NOT SPINNAKER_FOUND)\n  endif (WITH_FLIR_CAMERA)\n  if (WITH_3D_ADAM_MODEL)\n    if (NOT WITH_3D_RENDERER)\n      message(FATAL_ERROR \"WITH_3D_RENDERER is required if WITH_3D_ADAM_MODEL is enabled.\")\n    endif (NOT WITH_3D_RENDERER)\n    # Eigen\n    # # Option a) apt-get\n    # find_package(PkgConfig)\n    # pkg_check_modules(EIGEN3 REQUIRED eigen3)\n    # # Option b) Find it (including apt-get)\n    if (CUDA_VERSION_STRING STRGREATER \"9.0\")\n      find_package(Eigen3 3.3.5 REQUIRED NO_MODULE)\n    else (CUDA_VERSION_STRING STRGREATER \"9.0\")\n      find_package(Eigen3 3 REQUIRED NO_MODULE)\n    endif (CUDA_VERSION_STRING STRGREATER \"9.0\")\n    # Others: sudo apt-get install libglm-dev\n    # http://ceres-solver.org\n    find_package(Ceres REQUIRED COMPONENTS SuiteSparse)\n    # sudo apt-get install libglew-dev\n    find_package(GLEW REQUIRED)\n    # find_package(GLUT REQUIRED) # TODO: Duplicated of WITH_3D_RENDERER, clean somehow (like Eigen)\n    # git clone --recursive https://github.com/libigl/libigl.git\n    # No installation, it's header only\n    # TODO: It's header only (as Eigen), do AUTOBUILD option too to download it\n    find_package(LIBIGL REQUIRED)\n    find_package(OpenMP REQUIRED)\n    # Only adam/renderer::Renderer::IdleSaveImage() uses it. Make dependency optional in hand_model\n    # FIND_LIBRARY(FREE_IMAGE_LIBRARY NAMES libfreeimage.so)\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}\")\n    set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}\")\n  endif (WITH_3D_ADAM_MODEL)\n\n  # OpenMP\n  if (${GPU_MODE} MATCHES \"CPU_ONLY\")\n    find_package(OpenMP)\n    if (OPENMP_FOUND)\n      set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}\")\n      set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}\")\n      set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}\")\n    endif (OPENMP_FOUND)\n  endif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    # Set CUDA Flags\n    set(CUDA_NVCC_FLAGS \"${CUDA_NVCC_FLAGS} -std=c++14\") # Thrust library requires C++14 for CUDA >= 11\n    set(CUDA_NVCC_FLAGS_DEBUG \"${CUDA_NVCC_FLAGS_DEBUG} -D_DEBUG -g\")\n\n    if (NOT CUDA_FOUND)\n      message(STATUS \"CUDA not found.\")\n      execute_process(COMMAND cat install_cuda.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/scripts/ubuntu)\n      message(FATAL_ERROR \"Install CUDA using the above commands.\")\n    endif (NOT CUDA_FOUND)\n\n    if (USE_CUDNN AND NOT CUDNN_FOUND)\n      message(STATUS \"cuDNN not found.\")\n      execute_process(COMMAND cat install_cudnn_up_to_Ubuntu16.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/scripts/ubuntu)\n      message(FATAL_ERROR \"Install cuDNN using the above commands. or turn off cuDNN by setting USE_CUDNN to OFF.\")\n    endif (USE_CUDNN AND NOT CUDNN_FOUND)\n  endif (${GPU_MODE} MATCHES \"CUDA\")\n\n  if (NOT GLOG_FOUND)\n    message(FATAL_ERROR \"Glog not found. Install Glog from the command line using the command(s) -\\\n      sudo apt-get install libgoogle-glog-dev\")\n  endif (NOT GLOG_FOUND)\n\n  if (NOT GFLAGS_FOUND)\n    message(FATAL_ERROR \"GFlags not found. Install GFlags from the command line using the command(s) --\\\n      sudo apt-get install libgflags-dev\")\n  endif (NOT GFLAGS_FOUND)\n\n  if (NOT OpenCV_FOUND)\n    message(FATAL_ERROR \"OpenCV not found. Install OpenCV from the command line using the command(s) --\\\n      sudo apt-get install libopencv-dev\")\n  endif (NOT OpenCV_FOUND)\n\nendif (UNIX OR APPLE)\n\nif (WIN32)\n\n  if (\"${CMAKE_VERSION}\" VERSION_GREATER 3.6.3)\n    set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OpenPoseDemo)\n  endif (\"${CMAKE_VERSION}\" VERSION_GREATER 3.6.3)\n\n  set_property(GLOBAL PROPERTY USE_FOLDERS ON)\n  set(FIND_LIB_PREFIX ${CMAKE_SOURCE_DIR}/3rdparty/windows)\n\n  # Download Windows 3rd party\n  message(STATUS \"Downloading windows dependencies...\")\n  set(OP_WIN_URL \"${DOWNLOAD_SERVER}3rdparty/windows\")\n  set(OP_WIN_DIR \"${CMAKE_SOURCE_DIR}/3rdparty/windows\")\n\n  # Download required zip files\n  download_zip(\"opencv_450_v15_2020_11_18.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} AFB1BD1A160C43CF5FB856C8BB4FC483)\n  download_zip(\"caffe3rdparty_16_2020_11_14.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 83C17DC4473985B6AB3A29FD9AB93409)\n  if (${GPU_MODE} MATCHES \"OPENCL\")\n    download_zip(\"caffe_opencl_2018_02_13.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 3ac3e1acf5ee6a4e57920be73053067a)\n  elseif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n    download_zip(\"caffe_cpu_2018_05_27.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 87E8401B6DFBAC5B8E909DD20E3B3390)\n  else (${GPU_MODE} MATCHES \"OPENCL\")\n    # download_zip(\"caffe_2019_03_12.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 859a592310f0928fd4f40da1456a217f)\n    # download_zip(\"caffe_15_2020_04_05.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} cd4ec4d709a70c94aa6b151d2d040300)\n    download_zip(\"caffe_16_2020_11_14.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} 33030DBEC9911533566E239199BB4716)\n  endif (${GPU_MODE} MATCHES \"OPENCL\")\n  if (WITH_3D_RENDERER)\n    download_zip(\"freeglut_2018_01_14.zip\" ${OP_WIN_URL} ${FIND_LIB_PREFIX} BB182187285E06880F0EDE3A39530091)\n  endif (WITH_3D_RENDERER)\n  message(STATUS \"Windows dependencies downloaded.\")\n\n  set(OPENCV_VS_VERSION \"15\")\n  find_library(OpenCV_LIBS_RELEASE opencv_world450 HINTS ${FIND_LIB_PREFIX}/opencv/x64/vc${OPENCV_VS_VERSION}/lib)\n  find_library(OpenCV_LIBS_DEBUG opencv_world450d HINTS ${FIND_LIB_PREFIX}/opencv/x64/vc${OPENCV_VS_VERSION}/lib)\n  find_library(GFLAGS_LIBRARY_RELEASE gflags HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(GFLAGS_LIBRARY_DEBUG gflagsd HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(GLOG_LIBRARY_RELEASE glog HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(GLOG_LIBRARY_DEBUG glogd HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n\n  # If OpenPose builds it\n  if (BUILD_CAFFE)\n    unset(Caffe_INCLUDE_DIRS CACHE)\n    unset(Caffe_LIB_RELEASE CACHE)\n    unset(Caffe_Proto_LIB_RELEASE CACHE)\n  endif (BUILD_CAFFE)\n  # OpenCL\n  if (${GPU_MODE} MATCHES \"OPENCL\")\n    set(VCXPROJ_FILE_GPU_MODE \"_CL\")\n    find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib)\n    find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib)\n    find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib)\n    find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe_opencl/lib)\n  # CPU & CUDA\n  else (${GPU_MODE} MATCHES \"OPENCL\")\n    # CPU\n    if (${GPU_MODE} MATCHES \"CPU_ONLY\")\n      set(VCXPROJ_FILE_GPU_MODE \"_CPU\")\n      find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib)\n      find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib)\n      find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib)\n      find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe_cpu/lib)\n    # CUDA\n    else (${GPU_MODE} MATCHES \"CPU_ONLY\")\n      set(VCXPROJ_FILE_GPU_MODE \"\")\n      find_library(Caffe_LIB_RELEASE caffe HINTS ${FIND_LIB_PREFIX}/caffe/lib)\n      find_library(Caffe_Proto_LIB_RELEASE caffeproto HINTS ${FIND_LIB_PREFIX}/caffe/lib)\n      find_library(Caffe_LIB_DEBUG caffe-d HINTS ${FIND_LIB_PREFIX}/caffe/lib)\n      find_library(Caffe_Proto_LIB_DEBUG caffeproto-d HINTS ${FIND_LIB_PREFIX}/caffe/lib)\n    endif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n  endif (${GPU_MODE} MATCHES \"OPENCL\")\n  # Boost DepCopy over required DLL\n  find_library(BOOST_SYSTEM_LIB_RELEASE boost_system-vc142-mt-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(BOOST_SYSTEM_LIB_DEBUG boost_system-vc142-mt-gd-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(BOOST_FILESYSTEM_LIB_RELEASE boost_filesystem-vc142-mt-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  find_library(BOOST_FILESYSTEM_LIB_DEBUG boost_filesystem-vc142-mt-gd-x64-1_74 HINTS ${FIND_LIB_PREFIX}/caffe3rdparty/lib)\n  # message(STATUS \"\\${BOOST_SYSTEM_LIB_RELEASE} = ${BOOST_SYSTEM_LIB_RELEASE}\")\n  # message(STATUS \"\\${BOOST_SYSTEM_LIB_DEBUG} = ${BOOST_SYSTEM_LIB_DEBUG}\")\n  # message(STATUS \"\\${BOOST_FILESYSTEM_LIB_RELEASE} = ${BOOST_FILESYSTEM_LIB_RELEASE}\")\n  # message(STATUS \"\\${BOOST_FILESYSTEM_LIB_DEBUG} = ${BOOST_FILESYSTEM_LIB_DEBUG}\")\n  if (WITH_3D_RENDERER)\n    find_library(GLUT_LIBRARY freeglut HINTS ${FIND_LIB_PREFIX}/freeglut/lib)\n    message(STATUS \"\\${GLUT_LIBRARY} = ${GLUT_LIBRARY}\")\n  endif (WITH_3D_RENDERER)\n  if (WITH_FLIR_CAMERA)\n    find_library(SPINNAKER_LIB spinnaker_v140 HINTS ${FIND_LIB_PREFIX}/spinnaker/lib)\n  endif (WITH_FLIR_CAMERA)\n  set(Caffe_LIBS_RELEASE \"${Caffe_LIB_RELEASE};${Caffe_Proto_LIB_RELEASE}\")\n  set(Caffe_LIBS_DEBUG \"${Caffe_LIB_DEBUG};${Caffe_Proto_LIB_DEBUG}\")\n  set(OpenCV_INCLUDE_DIRS \"3rdparty/windows/opencv/include\")\n  # OpenCL\n  if (${GPU_MODE} MATCHES \"OPENCL\")\n    unset(Caffe_INCLUDE_DIRS CACHE)\n    set(Caffe_INCLUDE_DIRS \"3rdparty/windows/caffe_opencl/include;3rdparty/windows/caffe_opencl/include2\" CACHE FILEPATH \"Caffe_INCLUDE_DIRS\")\n  # CUDA and CPU\n  else (${GPU_MODE} MATCHES \"OPENCL\")\n    # CPU\n    if (${GPU_MODE} MATCHES \"CPU_ONLY\")\n      set(Caffe_INCLUDE_DIRS \"3rdparty/windows/caffe_cpu/include;3rdparty/windows/caffe_cpu/include2\" CACHE FILEPATH \"Caffe_INCLUDE_DIRS\")\n    # CUDA\n    else (${GPU_MODE} MATCHES \"CPU_ONLY\")\n      set(Caffe_INCLUDE_DIRS \"3rdparty/windows/caffe/include;3rdparty/windows/caffe/include2\" CACHE FILEPATH \"Caffe_INCLUDE_DIRS\")\n    endif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n  endif (${GPU_MODE} MATCHES \"OPENCL\")\n  # set(Boost_INCLUDE_DIRS \"3rdparty/windows/caffe3rdparty/include/boost-1_61\") # Added in WINDOWS_INCLUDE_DIRS\n  set(WINDOWS_INCLUDE_DIRS \"3rdparty/windows/caffe3rdparty/include\")\n  if (WITH_3D_RENDERER)\n    set(GLUT_INCLUDE_DIRS \"3rdparty/windows/freeglut/include\")\n  endif (WITH_3D_RENDERER)\n  if (WITH_FLIR_CAMERA)\n    set(SPINNAKER_INCLUDE_DIRS \"3rdparty/windows/spinnaker/include\")\n  endif (WITH_FLIR_CAMERA)\n  set(Caffe_FOUND 1)\n\n  # Build DLL Must be on if Build Python is on\n  if (BUILD_PYTHON)\n    if (NOT BUILD_BIN_FOLDER)\n      message(FATAL_ERROR \"BUILD_BIN_FOLDER must be turned on to as well to build python library\")\n    endif (NOT BUILD_BIN_FOLDER)\n  endif (BUILD_PYTHON)\n\n  # Auto copy DLLs\n  if (BUILD_BIN_FOLDER)\n    # Copy DLLs into same folder\n    set(BIN_FOLDER ${CMAKE_BINARY_DIR}/bin)\n    file(MAKE_DIRECTORY ${BIN_FOLDER})\n    # Locate and copy DLLs\n    # Caffe DLLs\n    if (${GPU_MODE} MATCHES \"CUDA\")\n      file(GLOB CAFFE_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe/bin/*.dll\")\n    elseif (${GPU_MODE} MATCHES \"OPENCL\")\n      file(GLOB CAFFE_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe_opencl/bin/*.dll\")\n    elseif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n      file(GLOB CAFFE_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe_cpu/bin/*.dll\")\n    endif ()\n    file(COPY ${CAFFE_DLL} DESTINATION ${BIN_FOLDER})\n    # Caffe 3rd-party DLLs\n    file(GLOB CAFFE_3RD_PARTY_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/caffe3rdparty/lib/*.dll\")\n    file(COPY ${CAFFE_3RD_PARTY_DLL} DESTINATION ${BIN_FOLDER})\n    # OpenCV DLLs\n    file(GLOB OPENCV_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/opencv/x64/vc${OPENCV_VS_VERSION}/bin/*.dll\")\n    file(COPY ${OPENCV_DLL} DESTINATION ${BIN_FOLDER})\n    # GLUT DLLs\n    if (WITH_3D_RENDERER OR WITH_3D_ADAM_MODEL)\n      file(GLOB GLUT_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/freeglut/bin/*.dll\")\n      file(COPY ${GLUT_DLL} DESTINATION ${BIN_FOLDER})\n    endif (WITH_3D_RENDERER OR WITH_3D_ADAM_MODEL)\n    # Spinnaker DLLs and other files\n    if (WITH_FLIR_CAMERA)\n      file(GLOB SPINNAKER_DLL \"${CMAKE_SOURCE_DIR}/3rdparty/windows/spinnaker/bin/*\")\n      file(COPY ${SPINNAKER_DLL} DESTINATION ${BIN_FOLDER})\n    endif (WITH_FLIR_CAMERA)\n  endif (BUILD_BIN_FOLDER)\n\nendif (WIN32)\n\n\n### CAFFE/NVCAFFE in Ubuntu\nif (UNIX OR APPLE)\n  if (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n    # Check if the user specified caffe paths\n    if (Caffe_INCLUDE_DIRS AND Caffe_LIBS AND NOT BUILD_CAFFE)\n      message(STATUS \"\\${Caffe_INCLUDE_DIRS} set by the user to \" ${Caffe_INCLUDE_DIRS})\n      message(STATUS \"\\${Caffe_LIBS} set by the user to \" ${Caffe_LIBS})\n      set(Caffe_FOUND 1)\n    endif (Caffe_INCLUDE_DIRS AND Caffe_LIBS AND NOT BUILD_CAFFE)\n\n    # Else build from scratch\n    if (BUILD_CAFFE)\n\n      # Download Caffe\n      message(STATUS \"Caffe will be downloaded from source now. NOTE: This process might take several minutes depending\n        on your internet connection.\")\n\n      # Check if pulled\n      file(GLOB CAFFE_DIR_VALID ${CMAKE_SOURCE_DIR}/3rdparty/caffe/*)\n      list(LENGTH CAFFE_DIR_VALID CAFFE_DIR_VALID_LENGTH)\n      if (CAFFE_DIR_VALID_LENGTH EQUAL 0)\n        execute_process(COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n        # execute_process(COMMAND git submodule update --init --recursive --remote) # This would initialize them all\n      else (CAFFE_DIR_VALID_LENGTH EQUAL 0)\n        message(STATUS \"Caffe has already been downloaded.\")\n      endif (CAFFE_DIR_VALID_LENGTH EQUAL 0)\n\n      # Build Process\n      set(CAFFE_CPU_ONLY OFF)\n      if (${GPU_MODE} MATCHES \"CUDA\")\n        # execute_process(COMMAND git checkout master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n        execute_process(COMMAND git checkout 1807aad WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n      elseif (${GPU_MODE} MATCHES \"CPU_ONLY\")\n        if (USE_MKL)\n          #execute_process(COMMAND git checkout intel WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n          execute_process(COMMAND git checkout b6712ce WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n          execute_process(COMMAND sh prepare_mkl.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe/external/mkl\n              OUTPUT_VARIABLE rv)\n          set( MLIST ${rv} )\n          separate_arguments(MLIST)\n          list(GET MLIST 0 MKL_PATH)\n          message(STATUS ${MKL_PATH})\n          file(GLOB MKL_SO\n            \"${MKL_PATH}lib/*\"\n            )\n          file(COPY ${MKL_SO} DESTINATION ${CMAKE_BINARY_DIR}/caffe)\n\n          # New MLSL Lib\n          #execute_process(COMMAND sh prepare_mlsl.sh WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe/external/mlsl\n          #    OUTPUT_VARIABLE rv)\n          #set( MLIST ${rv} )\n          #separate_arguments(MLIST)\n          #list(GET MLIST 0 MLSL_PATH)\n          #message(STATUS ${MLSL_PATH})\n          #file(GLOB MLSL_SO\n          #  \"${MLSL_PATH}/intel64/lib/*\"\n          #  )\n          #file(COPY ${MLSL_SO} DESTINATION ${CMAKE_BINARY_DIR}/caffe)\n\n          set(MKL_LIBS\n            #\"${CMAKE_BINARY_DIR}/caffe/libmlsl.so\"\n            \"${CMAKE_BINARY_DIR}/caffe/libiomp5.so\"\n            \"${CMAKE_BINARY_DIR}/caffe/libmklml_intel.so\"\n            \"${CMAKE_BINARY_DIR}/caffe/lib/libmkldnn.so\"\n            )\n        else (USE_MKL)\n          # execute_process(COMMAND git checkout master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n          execute_process(COMMAND git checkout 1807aad WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n        endif (USE_MKL)\n        set(CAFFE_CPU_ONLY ON)\n        set(USE_CUDNN OFF)\n      elseif (${GPU_MODE} MATCHES \"OPENCL\")\n        execute_process(COMMAND git checkout fe2a1102 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n        set(USE_CUDNN OFF)\n      endif (${GPU_MODE} MATCHES \"CUDA\")\n\n      # Build Caffe\n      message(STATUS \"Caffe will be built from source now.\")\n      find_package(Caffe)\n      include(ExternalProject)\n      set(CAFFE_PREFIX caffe)\n      set(CAFFE_URL ${CMAKE_SOURCE_DIR}/3rdparty/caffe)\n\n      # One for Intel Branch and one for Master\n      if (USE_MKL)\n        ExternalProject_Add(openpose_lib\n          SOURCE_DIR ${CAFFE_URL}\n          PREFIX ${CAFFE_PREFIX}\n          CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>\n          -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}\n          -DMKLDNN_INSTALL_DIR:PATH=<INSTALL_DIR>\n          -DUSE_MKL2017_AS_DEFAULT_ENGINE=${CAFFE_CPU_ONLY}\n          -DUSE_CUDNN=${USE_CUDNN}\n          -DCUDA_ARCH_NAME=${CUDA_ARCH}\n          -DCUDA_ARCH_BIN=${CUDA_ARCH_BIN}\n          -DCUDA_ARCH_PTX=${CUDA_ARCH_PTX}\n          -DCPU_ONLY=${CAFFE_CPU_ONLY}\n          -DCMAKE_BUILD_TYPE=Release\n          -DBUILD_docs=OFF\n          -DBUILD_python=OFF\n          -DBUILD_python_layer=OFF\n          -DUSE_LEVELDB=OFF\n          -DUSE_LMDB=OFF\n          -DUSE_OPENCV=OFF)\n          # -DOpenCV_DIR=${OpenCV_DIR})\n      else (USE_MKL)\n        ExternalProject_Add(openpose_lib\n          SOURCE_DIR ${CAFFE_URL}\n          PREFIX ${CAFFE_PREFIX}\n          CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>\n          -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}\n          -DUSE_CUDNN=${USE_CUDNN}\n          -DCUDA_ARCH_NAME=${CUDA_ARCH}\n          -DCUDA_ARCH_BIN=${CUDA_ARCH_BIN}\n          -DCUDA_ARCH_PTX=${CUDA_ARCH_PTX}\n          -DCPU_ONLY=${CAFFE_CPU_ONLY}\n          -DCMAKE_BUILD_TYPE=Release\n          -DBUILD_docs=OFF\n          -DBUILD_python=OFF\n          -DBUILD_python_layer=OFF\n          -DUSE_LEVELDB=OFF\n          -DUSE_LMDB=OFF\n          -DUSE_OPENCV=OFF)\n          # -DOpenCV_DIR=${OpenCV_DIR})\n      endif (USE_MKL)\n\n      ExternalProject_Get_Property(openpose_lib install_dir)\n\n      if (NOT Caffe_FOUND)\n        add_custom_command(TARGET openpose_lib\n            POST_BUILD\n            COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}\n            COMMAND $(MAKE)\n            WORKING_DIRECTORY ${CMAKE_BINARY_DIR}\n            COMMENT \"Rerunning cmake after building Caffe submodule\")\n      endif (NOT Caffe_FOUND)\n\n    endif (BUILD_CAFFE)\n\n    if (NOT Caffe_FOUND AND NOT BUILD_CAFFE)\n      message(FATAL_ERROR \"Caffe not found. Either turn on the BUILD_CAFFE option or specify the path of Caffe includes\n        and libs using -DCaffe_INCLUDE_DIRS and -DCaffe_LIBS.\")\n    endif (NOT Caffe_FOUND AND NOT BUILD_CAFFE)\n  endif (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\nendif (UNIX OR APPLE)\n\n### PROJECT INCLUDES\n# Specify the include directories\ninclude_directories(\n  include\n  ${Protobuf_INCLUDE_DIRS}\n  ${GFLAGS_INCLUDE_DIR}\n  ${GLOG_INCLUDE_DIR}\n  ${OpenCV_INCLUDE_DIRS})\n\nif (USE_ASIO)\n  include_directories(${CMAKE_SOURCE_DIR}/3rdparty/asio/include/)\n  # OpenPose flags\n  add_definitions(-DUSE_ASIO)\n  # Tell Asio it is not using Boost\n  add_definitions(-DASIO_STANDALONE)\nendif (USE_ASIO)\n\n# Calibration\nif (NOT ${WITH_EIGEN} MATCHES \"NONE\")\n  include_directories(${EIGEN3_INCLUDE_DIRS})\n  if (${WITH_EIGEN} MATCHES \"FIND\")\n    set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} Eigen3::Eigen)\n  endif (${WITH_EIGEN} MATCHES \"FIND\")\nendif (NOT ${WITH_EIGEN} MATCHES \"NONE\")\n\nif (APPLE)\n  include_directories(\"/usr/local/opt/openblas/include\")\nendif (APPLE)\n\nif (USE_MKL)\n include_directories(\"${MKL_PATH}/include/\")\nendif (USE_MKL)\n\nif (Caffe_FOUND)\n  include_directories(${Caffe_INCLUDE_DIRS})\nendif (Caffe_FOUND)\n\nif (${GPU_MODE} MATCHES \"CUDA\")\n  include_directories(${CUDA_INCLUDE_DIRS})\nelseif (${GPU_MODE} MATCHES \"OPENCL\")\n  include_directories(${OpenCL_INCLUDE_DIRS})\nendif (${GPU_MODE} MATCHES \"CUDA\")\n# 3D\nif (WITH_3D_RENDERER)\n  include_directories(${GLUT_INCLUDE_DIRS})\nendif (WITH_3D_RENDERER)\nif (WITH_CERES)\n  include_directories(${CERES_INCLUDE_DIRS})\nendif (WITH_CERES)\nif (WITH_FLIR_CAMERA)\n  include_directories(SYSTEM ${SPINNAKER_INCLUDE_DIRS}) # To remove its warnings, equiv. to -isystem\nendif (WITH_FLIR_CAMERA)\nif (WITH_3D_ADAM_MODEL)\n                                    include_directories(include/adam) # TODO: TEMPORARY - TO BE REMOVED IN THE FUTURE\n  include_directories(${CERES_INCLUDE_DIRS})\n  include_directories(${EIGEN3_INCLUDE_DIRS})\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} Eigen3::Eigen)\n  include_directories(${IGL_INCLUDE_DIRS})\n  include_directories(${LIBIGL_INCLUDE_DIRS})\n  include_directories(${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS})\nendif (WITH_3D_ADAM_MODEL)\n# Windows includes\nif (WIN32)\n  include_directories(${WINDOWS_INCLUDE_DIRS})\nendif (WIN32)\n\n\n### COLLECT ALL 3RD-PARTY LIBRARIES TO BE LINKED AGAINST\nif (UNIX OR APPLE)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${OpenCV_LIBS} ${GLOG_LIBRARY})\nelseif (WIN32)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries}\n      debug ${OpenCV_LIBS_DEBUG} optimized ${OpenCV_LIBS_RELEASE}\n      debug ${GFLAGS_LIBRARY_DEBUG} optimized ${GFLAGS_LIBRARY_RELEASE}\n      debug ${GLOG_LIBRARY_DEBUG} optimized ${GLOG_LIBRARY_RELEASE})\nendif (UNIX OR APPLE)\n# G Flags (for demos)\nif (UNIX OR APPLE)\n  set(examples_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${GFLAGS_LIBRARY})\nendif (UNIX OR APPLE)\n# Deep net Framework\nif (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n  if (UNIX OR APPLE)\n    set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${Caffe_LIBS})\n  elseif (WIN32)\n    set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries}\n      debug ${Caffe_LIBS_DEBUG} optimized ${Caffe_LIBS_RELEASE})\n  endif (UNIX OR APPLE)\nendif (${DL_FRAMEWORK} MATCHES \"CAFFE\" OR ${DL_FRAMEWORK} MATCHES \"NV_CAFFE\")\n# CPU vs. GPU\nif (USE_MKL)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${MKL_LIBS})\nendif (USE_MKL)\nif (${GPU_MODE} MATCHES \"OPENCL\")\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${CMAKE_THREAD_LIBS_INIT} ${OpenCL_LIBRARIES})\nendif (${GPU_MODE} MATCHES \"OPENCL\")\n# Boost\nif (WIN32)\n    if (${GPU_MODE} MATCHES \"CPU_ONLY\" OR ${GPU_MODE} MATCHES \"OPENCL\" OR BUILD_PYTHON)\n    set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries}\n        debug ${BOOST_SYSTEM_LIB_RELEASE} optimized ${BOOST_SYSTEM_LIB_RELEASE})\n        set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries}\n        debug ${BOOST_FILESYSTEM_LIB_RELEASE} optimized ${BOOST_FILESYSTEM_LIB_RELEASE})\n    endif ()\nendif (WIN32)\n# 3-D\nif (WITH_3D_ADAM_MODEL)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries}\n      ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${GLEW_LIBRARY} ${FREE_IMAGE_LIBRARY})\nendif (WITH_3D_ADAM_MODEL)\nif (WITH_3D_RENDERER)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${GLUT_LIBRARY} ${OPENGL_LIBRARIES})\nendif (WITH_3D_RENDERER)\nif (WITH_CERES)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${CERES_LIBRARIES})\nendif (WITH_CERES)\nif (WITH_FLIR_CAMERA)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} ${SPINNAKER_LIB})\nendif (WITH_FLIR_CAMERA)\n# Pthread\nif (UNIX OR APPLE)\n  set(OpenPose_3rdparty_libraries ${OpenPose_3rdparty_libraries} pthread)\nendif (UNIX OR APPLE)\n\n\n\n### ADD SUBDIRECTORIES\nif (Caffe_FOUND)\n  add_subdirectory(src)\n  if (BUILD_EXAMPLES)\n    add_subdirectory(examples)\n  endif (BUILD_EXAMPLES)\nendif (Caffe_FOUND)\n\n\n### DOWNLOAD MODELS\n# Download the models if flag is set\nmessage(STATUS \"Download the models.\")\n\n# URL to the models\nset(OPENPOSE_URL \"${DOWNLOAD_SERVER}models/\")\n\ndownload_model(\"BODY_25\" ${DOWNLOAD_BODY_25_MODEL} pose/body_25/pose_iter_584000.caffemodel\n  78287B57CF85FA89C03F1393D368E5B7) # Body (BODY_25)\ndownload_model(\"body (COCO)\" ${DOWNLOAD_BODY_COCO_MODEL} pose/coco/pose_iter_440000.caffemodel\n  5156d31f670511fce9b4e28b403f2939) # Body (COCO)\ndownload_model(\"body (MPI)\" ${DOWNLOAD_BODY_MPI_MODEL} pose/mpi/pose_iter_160000.caffemodel\n  2ca0990c7562bd7ae03f3f54afa96e00) # Body (MPI)\ndownload_model(\"face\" ${DOWNLOAD_FACE_MODEL} face/pose_iter_116000.caffemodel\n  e747180d728fa4e4418c465828384333) # Face\ndownload_model(\"hand\" ${DOWNLOAD_HAND_MODEL} hand/pose_iter_102000.caffemodel\n  a82cfc3fea7c62f159e11bd3674c1531) # Hand\n\nmessage(STATUS \"Models Downloaded.\")\n\n\n### PYTHON\nif (BUILD_PYTHON)\n  if (WIN32)\n    execute_process(COMMAND cmd /c cd ${CMAKE_SOURCE_DIR} & git submodule update --init 3rdparty/pybind11/)\n    add_subdirectory(3rdparty/pybind11)\n    add_subdirectory(python)\n  elseif (UNIX OR APPLE)\n    if (Caffe_FOUND)\n      execute_process(COMMAND git submodule update --init ${CMAKE_SOURCE_DIR}/3rdparty/pybind11/)\n      # execute_process(COMMAND git submodule update --init --recursive --remote) # This would initialize them all\n      add_subdirectory(3rdparty/pybind11)\n      add_subdirectory(python)\n    endif (Caffe_FOUND)\n  else (WIN32)\n    message(FATAL_ERROR \"Unknown OS.\")\n  endif (WIN32)\nendif (BUILD_PYTHON)\n\n\n### GENERATE DOCUMENTATION\nif (UNIX OR APPLE)\n\n  if (BUILD_DOCS)\n    find_package(Doxygen)\n    if (DOXYGEN_FOUND)\n      # Set input and output files\n      set(DOXYGEN_FILE ${CMAKE_SOURCE_DIR}/.doc_autogeneration.doxygen)\n\n      # Custom target to build the documentation\n      add_custom_target(doc_doxygen ALL\n        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_FILE}\n        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/doc\n        COMMENT \"Generating API documentation with Doxygen\"\n        VERBATIM)\n    else (DOXYGEN_FOUND)\n      message(FATAL_ERROR \"Doxygen needs to be installed to generate the doxygen documentation.\")\n    endif (DOXYGEN_FOUND)\n  endif (BUILD_DOCS)\n\nendif (UNIX OR APPLE)\n\n\n### INSTALL\nif (UNIX OR APPLE)\n  if (Caffe_FOUND)\n    # Install the headers\n    install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/openpose DESTINATION include)\n    install(EXPORT OpenPose DESTINATION lib/OpenPose)\n    if (BUILD_CAFFE)\n      install(DIRECTORY ${CMAKE_BINARY_DIR}/caffe/include/caffe DESTINATION include)\n      install(DIRECTORY ${CMAKE_BINARY_DIR}/caffe/lib/ DESTINATION lib)\n    endif (BUILD_CAFFE)\n\n    # Compute installation prefix relative to this file\n    configure_file(\n      ${CMAKE_SOURCE_DIR}/cmake/OpenPoseConfig.cmake.in\n      ${CMAKE_BINARY_DIR}/cmake/OpenPoseConfig.cmake @ONLY)\n\n    install(FILES ${CMAKE_BINARY_DIR}/cmake/OpenPoseConfig.cmake\n      DESTINATION lib/OpenPose)\n\n    # Uninstall target\n    configure_file(\n      \"${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in\"\n      \"${CMAKE_BINARY_DIR}/cmake_uninstall.cmake\"\n      IMMEDIATE @ONLY)\n\n    add_custom_target(uninstall\n        COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)\n  endif (Caffe_FOUND)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "LICENSE",
    "content": "OPENPOSE: MULTIPERSON KEYPOINT DETECTION\nSOFTWARE LICENSE AGREEMENT\nACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY\n\nBY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT.  IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE.\n\nThis is a license agreement (\"Agreement\") between your academic institution or non-profit organization or self (called \"Licensee\" or \"You\" in this Agreement) and Carnegie Mellon University (called \"Licensor\" in this Agreement).  All rights not specifically granted to you in this Agreement are reserved for Licensor. \n\nRESERVATION OF OWNERSHIP AND GRANT OF LICENSE: \nLicensor retains exclusive ownership of any copy of the Software (as defined below) licensed under this Agreement and hereby grants to Licensee a personal, non-exclusive, \nnon-transferable license to use the Software for noncommercial research purposes, without the right to sublicense, pursuant to the terms and conditions of this Agreement.  As used in this Agreement, the term \"Software\" means (i) the actual copy of all or any portion of code for program routines made accessible to Licensee by Licensor pursuant to this Agreement, inclusive of backups, updates, and/or merged copies permitted hereunder or subsequently supplied by Licensor,  including all or any file structures, programming instructions, user interfaces and screen formats and sequences as well as any and all documentation and instructions related to it, and (ii) all or any derivatives and/or modifications created or made by You to any of the items specified in (i).\n\nCONFIDENTIALITY: Licensee acknowledges that the Software is proprietary to Licensor, and as such, Licensee agrees to receive all such materials in confidence and use the Software only in accordance with the terms of this Agreement.  Licensee agrees to use reasonable effort to protect the Software from unauthorized use, reproduction, distribution, or publication.\n\nCOPYRIGHT: The Software is owned by Licensor and is protected by United \nStates copyright laws and applicable international treaties and/or conventions.\n\nPERMITTED USES:  The Software may be used for your own noncommercial internal research purposes. You understand and agree that Licensor is not obligated to implement any suggestions and/or feedback you might provide regarding the Software, but to the extent Licensor does so, you are not entitled to any compensation related thereto.\n\nDERIVATIVES: You may create derivatives of or make modifications to the Software, however, You agree that all and any such derivatives and modifications will be owned by Licensor and become a part of the Software licensed to You under this Agreement.  You may only use such derivatives and modifications for your own noncommercial internal research purposes, and you may not otherwise use, distribute or copy such derivatives and modifications in violation of this Agreement.\n\nBACKUPS:  If Licensee is an organization, it may make that number of copies of the Software necessary for internal noncommercial use at a single site within its organization provided that all information appearing in or on the original labels, including the copyright and trademark notices are copied onto the labels of the copies.\n\nUSES NOT PERMITTED:  You may not distribute, copy or use the Software except as explicitly permitted herein. Licensee has not been granted any trademark license as part of this Agreement and may not use the name or mark “OpenPose\", \"Carnegie Mellon\" or any renditions thereof without the prior written permission of Licensor.\n\nYou may not sell, rent, lease, sublicense, lend, time-share or transfer, in whole or in part, or provide third parties access to prior or present versions (or any parts thereof) of the Software.\n\nASSIGNMENT: You may not assign this Agreement or your rights hereunder without the prior written consent of Licensor. Any attempted assignment without such consent shall be null and void.\n\nTERM: The term of the license granted by this Agreement is from Licensee's acceptance of this Agreement by downloading the Software or by using the Software until terminated as provided below.\n\nThe Agreement automatically terminates without notice if you fail to comply with any provision of this Agreement.  Licensee may terminate this Agreement by ceasing using the Software.  Upon any termination of this Agreement, Licensee will delete any and all copies of the Software. You agree that all provisions which operate to protect the proprietary rights of Licensor shall remain in force should breach occur and that the obligation of confidentiality described in this Agreement is binding in perpetuity and, as such, survives the term of the Agreement.\n\nFEE: Provided Licensee abides completely by the terms and conditions of this Agreement, there is no fee due to Licensor for Licensee's use of the Software in accordance with this Agreement.\n\nDISCLAIMER OF WARRANTIES:  THE SOFTWARE IS PROVIDED \"AS-IS\" WITHOUT WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE OR OF NON-INFRINGEMENT.  LICENSEE BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND RELATED MATERIALS.\n\nSUPPORT AND MAINTENANCE: No Software support or training by the Licensor is provided as part of this Agreement.  \n\nEXCLUSIVE REMEDY AND LIMITATION OF LIABILITY: To the maximum extent permitted under applicable law, Licensor shall not be liable for direct, indirect, special, incidental, or consequential damages or lost profits related to Licensee's use of and/or inability to use the Software, even if Licensor is advised of the possibility of such damage.\n\nEXPORT REGULATION: Licensee agrees to comply with any and all applicable \nU.S. export control laws, regulations, and/or other laws related to embargoes and sanction programs administered by the Office of Foreign Assets Control.\n\nSEVERABILITY: If any provision(s) of this Agreement shall be held to be invalid, illegal, or unenforceable by a court or other tribunal of competent jurisdiction, the validity, legality and enforceability of the remaining provisions shall not in any way be affected or impaired thereby.\n\nNO IMPLIED WAIVERS: No failure or delay by Licensor in enforcing any right or remedy under this Agreement shall be construed as a waiver of any future or other exercise of such right or remedy by Licensor.\n\nGOVERNING LAW: This Agreement shall be construed and enforced in accordance with the laws of the Commonwealth of Pennsylvania without reference to conflict of laws principles.  You consent to the personal jurisdiction of the courts of this County and waive their rights to venue outside of Allegheny County, Pennsylvania.\n\nENTIRE AGREEMENT AND AMENDMENTS: This Agreement constitutes the sole and entire agreement between Licensee and Licensor as to the matter set forth herein and supersedes any previous agreements, understandings, and arrangements between the parties relating hereto.\n\n\n\n************************************************************************\n\nTHIRD-PARTY SOFTWARE NOTICES AND INFORMATION\n\nThis project incorporates material from the project(s) listed below (collectively, \"Third Party Code\").  This Third Party Code is licensed to you under their original license terms set forth below.  We reserves all other rights not expressly granted, whether by implication, estoppel or otherwise.\n \n1.\tCaffe, version 1.0.0, (https://github.com/BVLC/caffe/)\n\nCOPYRIGHT\n\nAll contributions by the University of California:\nCopyright (c) 2014-2017 The Regents of the University of California (Regents)\nAll rights reserved.\n\nAll other contributions:\nCopyright (c) 2014-2017, the respective contributors\nAll rights reserved.\n\nCaffe uses a shared copyright model: each contributor holds copyright over\ntheir contributions to Caffe. The project versioning records all such\ncontribution and copyright details. If a contributor wants to further mark\ntheir specific copyright on a particular contribution, they should indicate\ntheir copyright solely in the commit message of the change when it is\ncommitted.\n\nLICENSE\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met: \n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer. \n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution. \n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nCONTRIBUTION AGREEMENT\n\nBy contributing to the BVLC/caffe repository through pull-request, comment,\nor otherwise, the contributor releases their content to the\nlicense and copyright terms herein.\n\n************END OF THIRD-PARTY SOFTWARE NOTICES AND INFORMATION**********\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n    <img src=\".github/Logo_main_black.png\" width=\"300\">\n</div>\n\n-----------------\n\n| **Build Type**   |`Linux`           |`MacOS`           |`Windows`         |\n| :---:            | :---:            | :---:            | :---:            |\n| **Build Status** | [![Status](https://github.com/CMU-Perceptual-Computing-Lab/openpose/workflows/CI/badge.svg)](https://github.com/CMU-Perceptual-Computing-Lab/openpose/actions) | [![Status](https://github.com/CMU-Perceptual-Computing-Lab/openpose/workflows/CI/badge.svg)](https://github.com/CMU-Perceptual-Computing-Lab/openpose/actions) | [![Status](https://ci.appveyor.com/api/projects/status/5leescxxdwen77kg/branch/master?svg=true)](https://ci.appveyor.com/project/gineshidalgo99/openpose/branch/master) |\n\n[**OpenPose**](https://github.com/CMU-Perceptual-Computing-Lab/openpose) has represented the **first real-time multi-person system to jointly detect human body, hand, facial, and foot keypoints (in total 135 keypoints) on single images**.\n\nIt is **authored by** [**Ginés Hidalgo**](https://www.gineshidalgo.com), [**Zhe Cao**](https://people.eecs.berkeley.edu/~zhecao), [**Tomas Simon**](http://www.cs.cmu.edu/~tsimon), [**Shih-En Wei**](https://scholar.google.com/citations?user=sFQD3k4AAAAJ&hl=en), [**Yaadhav Raaj**](https://www.raaj.tech), [**Hanbyul Joo**](https://jhugestar.github.io), **and** [**Yaser Sheikh**](http://www.cs.cmu.edu/~yaser). It is **maintained by** [**Ginés Hidalgo**](https://www.gineshidalgo.com) **and** [**Yaadhav Raaj**](https://www.raaj.tech). OpenPose would not be possible without the [**CMU Panoptic Studio dataset**](http://domedb.perception.cs.cmu.edu). We would also like to thank all the people who [have helped OpenPose in any way](doc/09_authors_and_contributors.md).\n\n\n\n<p align=\"center\">\n    <img src=\".github/media/pose_face_hands.gif\" width=\"480\">\n    <br>\n    <sup>Authors <a href=\"https://www.gineshidalgo.com\" target=\"_blank\">Ginés Hidalgo</a> (left) and <a href=\"https://jhugestar.github.io\" target=\"_blank\">Hanbyul Joo</a> (right) in front of the <a href=\"http://domedb.perception.cs.cmu.edu\" target=\"_blank\">CMU Panoptic Studio</a></sup>\n</p>\n\n\n\n## Contents\n1. [Results](#results)\n2. [Features](#features)\n3. [Related Work](#related-work)\n4. [Installation](#installation)\n5. [Quick Start Overview](#quick-start-overview)\n6. [Send Us Feedback!](#send-us-feedback)\n7. [Citation](#citation)\n8. [License](#license)\n\n\n\n## Results\n### Whole-body (Body, Foot, Face, and Hands) 2D Pose Estimation\n<p align=\"center\">\n    <img src=\".github/media/dance_foot.gif\" width=\"300\">\n    <img src=\".github/media/pose_face.gif\" width=\"300\">\n    <img src=\".github/media/pose_hands.gif\" width=\"300\">\n    <br>\n    <sup>Testing OpenPose: (Left) <a href=\"https://www.youtube.com/watch?v=2DiQUX11YaY\" target=\"_blank\"><i>Crazy Uptown Funk flashmob in Sydney</i></a> video sequence. (Center and right) Authors <a href=\"https://www.gineshidalgo.com\" target=\"_blank\">Ginés Hidalgo</a> and <a href=\"http://www.cs.cmu.edu/~tsimon\" target=\"_blank\">Tomas Simon</a> testing face and hands</sup>\n</p>\n\n### Whole-body 3D Pose Reconstruction and Estimation\n<p align=\"center\">\n    <img src=\".github/media/openpose3d.gif\" width=\"360\">\n    <br>\n    <sup><a href=\"https://ziutinyat.github.io/\" target=\"_blank\">Tianyi Zhao</a> testing the OpenPose 3D Module</a></sup>\n</p>\n\n### Unity Plugin\n<p align=\"center\">\n    <img src=\".github/media/unity_main.png\" width=\"300\">\n    <img src=\".github/media/unity_body_foot.png\" width=\"300\">\n    <img src=\".github/media/unity_hand_face.png\" width=\"300\">\n    <br>\n    <sup><a href=\"https://ziutinyat.github.io/\" target=\"_blank\">Tianyi Zhao</a> and <a href=\"https://www.gineshidalgo.com\" target=\"_blank\">Ginés Hidalgo</a> testing the <a href=\"https://github.com/CMU-Perceptual-Computing-Lab/openpose_unity_plugin\" target=\"_blank\">OpenPose Unity Plugin</a></sup>\n</p>\n\n### Runtime Analysis\nWe show an inference time comparison between the 3 available pose estimation libraries (same hardware and conditions): OpenPose, Alpha-Pose (fast Pytorch version), and Mask R-CNN. The OpenPose runtime is constant, while the runtime of Alpha-Pose and Mask R-CNN grow linearly with the number of people. More details [**here**](https://arxiv.org/abs/1812.08008).\n\n<p align=\"center\">\n    <img src=\".github/media/openpose_vs_competition.png\" width=\"360\">\n</p>\n\n\n\n## Features\n**Main Functionality**:\n- **2D real-time multi-person keypoint detection**:\n    - 15, 18 or **25-keypoint body/foot keypoint estimation**, including **6 foot keypoints**. **Runtime invariant to number of detected people**.\n    - **2x21-keypoint hand keypoint estimation**. **Runtime depends on number of detected people**. See [**OpenPose Training**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train) for a runtime invariant alternative.\n    - **70-keypoint face keypoint estimation**. **Runtime depends on number of detected people**. See [**OpenPose Training**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train) for a runtime invariant alternative.\n- [**3D real-time single-person keypoint detection**](doc/advanced/3d_reconstruction_module.md):\n    - 3D triangulation from multiple single views.\n    - Synchronization of Flir cameras handled.\n    - Compatible with Flir/Point Grey cameras.\n- [**Calibration toolbox**](doc/advanced/calibration_module.md): Estimation of distortion, intrinsic, and extrinsic camera parameters.\n- **Single-person tracking** for further speedup or visual smoothing.\n\n**Input**: Image, video, webcam, Flir/Point Grey, IP camera, and support to add your own custom input source (e.g., depth camera).\n\n**Output**: Basic image + keypoint display/saving (PNG, JPG, AVI, ...), keypoint saving (JSON, XML, YML, ...), keypoints as array class, and support to add your own custom output code (e.g., some fancy UI).\n\n**OS**: Ubuntu (20, 18, 16, 14), Windows (10, 8), Mac OSX, Nvidia TX2.\n\n**Hardware compatibility**: CUDA (Nvidia GPU), OpenCL (AMD GPU), and non-GPU (CPU-only) versions.\n\n**Usage Alternatives**:\n- [**Command-line demo**](doc/01_demo.md) for built-in functionality.\n- [**C++ API**](doc/04_cpp_api.md/) and [**Python API**](doc/03_python_api.md) for custom functionality. E.g., adding your custom inputs, pre-processing, post-posprocessing, and output steps.\n\nFor further details, check the [major released features](doc/07_major_released_features.md) and [release notes](doc/08_release_notes.md) docs.\n\n\n\n## Related Work\n- [**OpenPose training code**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train)\n- [**OpenPose foot dataset**](https://cmu-perceptual-computing-lab.github.io/foot_keypoint_dataset/)\n- [**OpenPose Unity Plugin**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_unity_plugin)\n- OpenPose papers published in **IEEE TPAMI and CVPR**. Cite them in your publications if OpenPose helps your research! (Links and more details in the [Citation](#citation) section below).\n\n\n\n## Installation\nIf you want to use OpenPose without installing or writing any code, simply [download and use the latest Windows portable version of OpenPose](doc/installation/0_index.md#windows-portable-demo)!\n\nOtherwise, you could [build OpenPose from source](doc/installation/0_index.md#compiling-and-running-openpose-from-source). See the [installation doc](doc/installation/0_index.md) for all the alternatives.\n\n\n\n## Quick Start Overview\nSimply use the OpenPose Demo from your favorite command-line tool (e.g., Windows PowerShell or Ubuntu Terminal). E.g., this example runs OpenPose on your webcam and displays the body keypoints:\n```\n# Ubuntu\n./build/examples/openpose/openpose.bin\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples\\media\\video.avi\n```\n\nYou can also add any of the available flags in any order. E.g., the following example runs on a video (`--video {PATH}`), enables face (`--face`) and hands (`--hand`), and saves the output keypoints on JSON files on disk (`--write_json {PATH}`).\n```\n# Ubuntu\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --face --hand --write_json output_json_folder/\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples\\media\\video.avi --face --hand --write_json output_json_folder/\n```\n\nOptionally, you can also extend OpenPose's functionality from its Python and C++ APIs. After [installing](doc/installation/0_index.md) OpenPose, check its [official doc](doc/00_index.md) for a quick overview of all the alternatives and tutorials.\n\n\n\n## Send Us Feedback!\nOur library is open source for research purposes, and we want to improve it! So let us know (create a new GitHub issue or pull request, email us, etc.) if you...\n1. Find/fix any bug (in functionality or speed) or know how to speed up or improve any part of OpenPose.\n2. Want to add/show some cool functionality/demo/project made on top of OpenPose. We can add your project link to our [Community-based Projects](doc/10_community_projects.md) section or even integrate it with OpenPose!\n\n\n\n## Citation\nPlease cite these papers in your publications if OpenPose helps your research. All of OpenPose is based on [OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1812.08008), while the hand and face detectors also use [Hand Keypoint Detection in Single Images using Multiview Bootstrapping](https://arxiv.org/abs/1704.07809) (the face detector was trained using the same procedure as the hand detector).\n\n    @article{8765346,\n      author = {Z. {Cao} and G. {Hidalgo Martinez} and T. {Simon} and S. {Wei} and Y. A. {Sheikh}},\n      journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence},\n      title = {OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields},\n      year = {2019}\n    }\n\n    @inproceedings{simon2017hand,\n      author = {Tomas Simon and Hanbyul Joo and Iain Matthews and Yaser Sheikh},\n      booktitle = {CVPR},\n      title = {Hand Keypoint Detection in Single Images using Multiview Bootstrapping},\n      year = {2017}\n    }\n\n    @inproceedings{cao2017realtime,\n      author = {Zhe Cao and Tomas Simon and Shih-En Wei and Yaser Sheikh},\n      booktitle = {CVPR},\n      title = {Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields},\n      year = {2017}\n    }\n\n    @inproceedings{wei2016cpm,\n      author = {Shih-En Wei and Varun Ramakrishna and Takeo Kanade and Yaser Sheikh},\n      booktitle = {CVPR},\n      title = {Convolutional pose machines},\n      year = {2016}\n    }\n\nPaper links:\n- OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields:\n    - [IEEE TPAMI](https://ieeexplore.ieee.org/document/8765346)\n    - [ArXiv](https://arxiv.org/abs/1812.08008)\n- [Hand Keypoint Detection in Single Images using Multiview Bootstrapping](https://arxiv.org/abs/1704.07809)\n- [Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1611.08050)\n- [Convolutional Pose Machines](https://arxiv.org/abs/1602.00134)\n\n\n\n## License\nOpenPose is freely available for free non-commercial use, and may be redistributed under these conditions. Please, see the [license](./LICENSE) for further details. Interested in a commercial license? Check this [FlintBox link](https://cmu.flintbox.com/#technologies/b820c21d-8443-4aa2-a49f-8919d93a8740). For commercial queries, use the `Contact` section from the [FlintBox link](https://cmu.flintbox.com/#technologies/b820c21d-8443-4aa2-a49f-8919d93a8740) and also send a copy of that message to [Yaser Sheikh](mailto:yaser@cs.cmu.edu).\n"
  },
  {
    "path": "appveyor.yml",
    "content": "image: Visual Studio 2019\nclone_folder: c:\\openpose\n\nbuild_script:\n    - mkdir build\n    - cd build\n    - cmake -DGPU_MODE=CPU_ONLY -G \"Visual Studio 16 2019\" -A x64 ..\n    - cmake --build . --config \"Release\"\n\nafter_build:\n    - ps: cd ..\n    - ps: mkdir artifacts\n    - ps: mkdir artifacts/bin\n    - ps: mkdir artifacts/examples\n    - ps: mkdir artifacts/examples/media\n    - ps: mkdir artifacts/include\n    - ps: mkdir artifacts/lib\n    - ps: Get-ChildItem -Path build/x64/Release/*.exe -Recurse -File | Copy-Item -Destination artifacts/bin\n    - ps: Get-ChildItem -Path build/x64/Release/*.dll -Recurse -File | Copy-Item -Destination artifacts/bin\n    - ps: Get-ChildItem -Path build/bin/*.dll -Recurse -File | Copy-Item -Destination artifacts/bin\n    - ps: Get-ChildItem -Path examples/media/* -Recurse -File | Copy-Item -Destination artifacts/examples/media\n    - ps: Copy-Item include/openpose -Recurse -Destination artifacts/include/\n    - ps: Copy-Item 3rdparty/windows/opencv/include/opencv2 -Recurse -Destination artifacts/include/\n    - ps: Get-ChildItem -Path build/*.lib -Recurse -File | Copy-Item -Destination artifacts/lib\n    - ps: Get-ChildItem -Path 3rdparty/*.lib -Recurse -File | Copy-Item -Destination artifacts/lib\n    - ps: Copy-Item models -Recurse -Destination artifacts/\n    - ps: cd artifacts\n    # - ps: 7z a ..\\openpose.zip . # `artifacts` disabled\n    - ps: cd ..\n    # Test\n    - ps: .\\artifacts\\bin\\OpenPoseDemo.exe --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n\n# `artifacts` disabled because of the AppVeyor crash: \"Maximum allowed artifact storage size of 50000 Mb will be exceeded.\"\n# artifacts:\n#     - path: openpose.zip\n#       name: OpenPose\n"
  },
  {
    "path": "cmake/Cuda.cmake",
    "content": "# Copied from Caffe\n\n# More info on available architectures vs. CUDA version:\n# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/\n\nif (CPU_ONLY)\n  return()\nendif ()\n\n################################################################################################\n# Remove duplicates from list(s)\n# Usage:\n#   op_list_unique(<list_variable> [<list_variable>] [...])\nmacro(op_list_unique)\n  foreach(__lst ${ARGN})\n    if (${__lst})\n      list(REMOVE_DUPLICATES ${__lst})\n    endif ()\n  endforeach()\nendmacro()\n\n# This list will be used for CUDA_ARCH = All option\n# Fermi (3.2 <= CUDA <= 8)\n# set(FERMI \"20 21(20)\")\n# Kepler (CUDA >= 5)\nset(KEPLER \"35 37\") # set(KEPLER \"30 35 37\") # This crashes with CUDA 10\n# Maxwell (CUDA >= 6)\nset(MAXWELL \"50 52 53\")\n# Pascal (CUDA >= 8)\nset(PASCAL \"60 61 62\")\n# Volta (CUDA >= 9)\nset(VOLTA \"70 72\") # set(VOLTA \"70 71 72\") # This crashes with CUDA 10\n# Turing (CUDA >= 10)\nset(TURING \"75\")\n# Ampere (CUDA >= 11)\nset(AMPERE \"80 86\")\nif (UNIX AND NOT APPLE)\n  set(Caffe_known_gpu_archs \"${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING} ${AMPERE}\")\n  # set(Caffe_known_gpu_archs \"${FERMI} ${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING}\")\n  # set(Caffe_known_gpu_archs \"20 21(20) 30 35 50 52 60 61\")\nelseif (WIN32)\n  set(Caffe_known_gpu_archs \"${KEPLER} ${MAXWELL} ${PASCAL} ${VOLTA} ${TURING} ${AMPERE}\")\nendif ()\n\n\n################################################################################################\n# A function for automatic detection of GPUs installed  (if autodetection is enabled)\n# Usage:\n#   op_detect_installed_gpus(out_variable)\nfunction(op_detect_installed_gpus out_variable)\n  if (NOT CUDA_gpu_detect_output)\n    set(__cufile ${PROJECT_BINARY_DIR}/detect_cuda_archs.cu)\n\n    file(WRITE ${__cufile} \"\"\n      \"#include <cstdio>\\n\"\n      \"int main()\\n\"\n      \"{\\n\"\n      \"  int count = 0;\\n\"\n      \"  if (cudaSuccess != cudaGetDeviceCount(&count)) return -1;\\n\"\n      \"  if (count == 0) return -1;\\n\"\n      \"  for (int device = 0; device < count; ++device)\\n\"\n      \"  {\\n\"\n      \"    cudaDeviceProp prop;\\n\"\n      \"    if (cudaSuccess == cudaGetDeviceProperties(&prop, device))\\n\"\n      \"      std::printf(\\\"%d.%d \\\", prop.major, prop.minor);\\n\"\n      \"  }\\n\"\n      \"  return 0;\\n\"\n      \"}\\n\")\n\n    execute_process(COMMAND \"${CUDA_NVCC_EXECUTABLE}\" \"--run\" \"${__cufile}\"\n                    WORKING_DIRECTORY \"${PROJECT_BINARY_DIR}/CMakeFiles/\"\n                    RESULT_VARIABLE __nvcc_res OUTPUT_VARIABLE __nvcc_out\n                    ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)\n\n    if (__nvcc_res EQUAL 0)\n      if (NOT WIN32)\n        string(REPLACE \"2.1\" \"2.1(2.0)\" __nvcc_out \"${__nvcc_out}\")\n      endif (NOT WIN32)\n      set(CUDA_gpu_detect_output ${__nvcc_out} CACHE INTERNAL \"Returned GPU architectures from op_detect_gpus tool\" FORCE)\n    endif ()\n  endif ()\n\n  if (NOT CUDA_gpu_detect_output)\n    message(STATUS \"Automatic GPU detection failed. Building for all known architectures.\")\n    set(${out_variable} ${Caffe_known_gpu_archs} PARENT_SCOPE)\n  else ()\n    set(${out_variable} ${CUDA_gpu_detect_output} PARENT_SCOPE)\n  endif ()\nendfunction()\n\n\n################################################################################################\n# Function for selecting GPU arch flags for nvcc based on CUDA_ARCH\n# Usage:\n#   op_select_nvcc_arch_flags(out_variable)\nfunction(op_select_nvcc_arch_flags out_variable)\n  # List of arch names\n  set(__archs_names \"Kepler (CUDA >= 5)\" \"Maxwell (CUDA >= 6)\" \"Pascal (CUDA >= 8)\" \"Volta (CUDA >= 9)\" \"Turing (CUDA >= 10)\" \"All\" \"Manual\")\n  # set(__archs_names \"Fermi (3.2 <= CUDA <= 8)\" \"Kepler (CUDA >= 5)\" \"Maxwell (CUDA >= 6)\" \"Pascal (CUDA >= 8)\" \"Volta (CUDA >= 9)\" \"Turing (CUDA >= 10)\" \"All\" \"Manual\")\n  set(__archs_name_default \"All\")\n  if (NOT CMAKE_CROSSCOMPILING)\n    list(APPEND __archs_names \"Auto\")\n    set(__archs_name_default \"Auto\")\n  endif ()\n\n  # set CUDA_ARCH strings (so it will be seen as dropbox in CMake-Gui)\n  # set(CUDA_ARCH ${__archs_name_default} CACHE STRING \"Select target NVIDIA GPU architecture.\")\n  # set_property( CACHE CUDA_ARCH PROPERTY STRINGS \"\" ${__archs_names} )\n  # mark_as_advanced(CUDA_ARCH)\n\n  # verify CUDA_ARCH value\n  if (NOT \";${__archs_names};\" MATCHES \";${CUDA_ARCH};\")\n    string(REPLACE \";\" \", \" __archs_names \"${__archs_names}\")\n    message(FATAL_ERROR \"Only ${__archs_names} architecture names are supported.\")\n  endif ()\n\n  if (${CUDA_ARCH} STREQUAL \"Manual\")\n    set(CUDA_ARCH_BIN ${Caffe_known_gpu_archs} CACHE STRING \"Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported\")\n    set(CUDA_ARCH_PTX \"50\"                     CACHE STRING \"Specify 'virtual' PTX architectures to build PTX intermediate code for\")\n    # mark_as_advanced(CUDA_ARCH_BIN CUDA_ARCH_PTX)\n  else ()\n    unset(CUDA_ARCH_BIN CACHE)\n    unset(CUDA_ARCH_PTX CACHE)\n  endif ()\n\n  if (${CUDA_ARCH} STREQUAL \"Fermi (3.2 <= CUDA <= 8)\" AND NOT WIN32)\n    set(__cuda_arch_bin ${FERMI})\n  elseif (${CUDA_ARCH} STREQUAL \"Kepler (CUDA >= 5)\")\n    set(__cuda_arch_bin ${KEPLER})\n  elseif (${CUDA_ARCH} STREQUAL \"Maxwell (CUDA >= 6)\")\n    set(__cuda_arch_bin ${MAXWELL})\n  elseif (${CUDA_ARCH} STREQUAL \"Pascal (CUDA >= 8)\")\n    set(__cuda_arch_bin ${PASCAL})\n  elseif (${CUDA_ARCH} STREQUAL \"Volta (CUDA >= 9)\")\n    set(__cuda_arch_bin ${VOLTA})\n  elseif (${CUDA_ARCH} STREQUAL \"Turing (CUDA >= 10)\")\n    set(__cuda_arch_bin ${TURING})\n  elseif (${CUDA_ARCH} STREQUAL \"All\")\n    set(__cuda_arch_bin ${Caffe_known_gpu_archs})\n  elseif (${CUDA_ARCH} STREQUAL \"Auto\")\n    op_detect_installed_gpus(__cuda_arch_bin)\n  else ()  # (${CUDA_ARCH} STREQUAL \"Manual\")\n    set(__cuda_arch_bin ${CUDA_ARCH_BIN})\n  endif ()\n\n  # remove dots and convert to lists\n  string(REGEX REPLACE \"\\\\.\" \"\" __cuda_arch_bin \"${__cuda_arch_bin}\")\n  string(REGEX REPLACE \"\\\\.\" \"\" __cuda_arch_ptx \"${CUDA_ARCH_PTX}\")\n  string(REGEX MATCHALL \"[0-9()]+\" __cuda_arch_bin \"${__cuda_arch_bin}\")\n  string(REGEX MATCHALL \"[0-9]+\"   __cuda_arch_ptx \"${__cuda_arch_ptx}\")\n  op_list_unique(__cuda_arch_bin __cuda_arch_ptx)\n\n  set(__nvcc_flags \"\")\n  set(__nvcc_archs_readable \"\")\n\n  # Tell NVCC to add binaries for the specified GPUs\n  foreach(__arch ${__cuda_arch_bin})\n    if (__arch MATCHES \"([0-9]+)\\\\(([0-9]+)\\\\)\")\n      # User explicitly specified PTX for the concrete BIN\n      list(APPEND __nvcc_flags -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1})\n      list(APPEND __nvcc_archs_readable sm_${CMAKE_MATCH_1})\n    else ()\n      # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN\n      list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=sm_${__arch})\n      list(APPEND __nvcc_archs_readable sm_${__arch})\n    endif ()\n  endforeach()\n\n  # Tell NVCC to add PTX intermediate code for the specified architectures\n  foreach(__arch ${__cuda_arch_ptx})\n    list(APPEND __nvcc_flags -gencode arch=compute_${__arch},code=compute_${__arch})\n    list(APPEND __nvcc_archs_readable compute_${__arch})\n  endforeach()\n\n  string(REPLACE \";\" \" \" __nvcc_archs_readable \"${__nvcc_archs_readable}\")\n  set(${out_variable}          ${__nvcc_flags}          PARENT_SCOPE)\n  set(${out_variable}_readable ${__nvcc_archs_readable} PARENT_SCOPE)\nendfunction()\n\n################################################################################################\n# Short command for cuda compilation\n# Usage:\n#   op_cuda_compile(<objlist_variable> <cuda_files>)\nmacro(op_cuda_compile objlist_variable)\n  foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)\n    set(${var}_backup_in_cuda_compile_ \"${${var}}\")\n\n    # we remove /EHa as it generates warnings under windows\n    string(REPLACE \"/EHa\" \"\" ${var} \"${${var}}\")\n\n  endforeach()\n\n  if (UNIX OR APPLE)\n    list(APPEND CUDA_NVCC_FLAGS -Xcompiler -fPIC)\n  endif ()\n\n  if (APPLE)\n    list(APPEND CUDA_NVCC_FLAGS -Xcompiler -Wno-unused-function)\n  endif ()\n\n  cuda_compile(cuda_objcs ${ARGN})\n\n  foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG)\n    set(${var} \"${${var}_backup_in_cuda_compile_}\")\n    unset(${var}_backup_in_cuda_compile_)\n  endforeach()\n\n  set(${objlist_variable} ${cuda_objcs})\nendmacro()\n\n################################################################################################\n# Short command for cuDNN detection. Believe it soon will be a part of CUDA toolkit distribution.\n# That's why not FindcuDNN.cmake file, but just the macro\n# Usage:\n#   detect_cuDNN()\nfunction(detect_cuDNN)\n  set(CUDNN_ROOT \"\" CACHE PATH \"CUDNN root folder\")\n\n  find_path(CUDNN_INCLUDE cudnn.h\n            PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDA_TOOLKIT_INCLUDE}\n            DOC \"Path to cuDNN include directory.\" )\n\n  # dynamic libs have different suffix in mac and linux\n  if (APPLE)\n    set(CUDNN_LIB_NAME \"libcudnn.dylib\")\n  else ()\n    set(CUDNN_LIB_NAME \"libcudnn.so\")\n  endif ()\n\n  get_filename_component(__libpath_hist ${CUDA_CUDART_LIBRARY} PATH)\n  find_library(CUDNN_LIBRARY NAMES ${CUDNN_LIB_NAME}\n   PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDNN_INCLUDE} ${__libpath_hist} ${__libpath_hist}/../lib\n   DOC \"Path to cuDNN library.\")\n  \n  if (CUDNN_INCLUDE AND CUDNN_LIBRARY)\n    set(HAVE_CUDNN  TRUE PARENT_SCOPE)\n    set(CUDNN_FOUND TRUE PARENT_SCOPE)\n\n    if(EXISTS \"${CUDNN_INCLUDE}/cudnn_version.h\")\n        file(READ ${CUDNN_INCLUDE}/cudnn_version.h CUDNN_VERSION_FILE_CONTENTS)\n    else()\n        file(READ ${CUDNN_INCLUDE}/cudnn.h CUDNN_VERSION_FILE_CONTENTS)\n    endif()\n\n    # cuDNN v3 and beyond\n    string(REGEX MATCH \"define CUDNN_MAJOR * +([0-9]+)\"\n           CUDNN_VERSION_MAJOR \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_MAJOR * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_MAJOR \"${CUDNN_VERSION_MAJOR}\")\n    string(REGEX MATCH \"define CUDNN_MINOR * +([0-9]+)\"\n           CUDNN_VERSION_MINOR \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_MINOR * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_MINOR \"${CUDNN_VERSION_MINOR}\")\n    string(REGEX MATCH \"define CUDNN_PATCHLEVEL * +([0-9]+)\"\n           CUDNN_VERSION_PATCH \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_PATCHLEVEL * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_PATCH \"${CUDNN_VERSION_PATCH}\")\n\n    if (NOT CUDNN_VERSION_MAJOR)\n      set(CUDNN_VERSION \"???\")\n    else ()\n      set(CUDNN_VERSION \"${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}\")\n    endif ()\n\n    message(STATUS \"Found cuDNN: ver. ${CUDNN_VERSION} found (include: ${CUDNN_INCLUDE}, library: ${CUDNN_LIBRARY})\")\n\n    string(COMPARE LESS \"${CUDNN_VERSION_MAJOR}\" 3 cuDNNVersionIncompatible)\n    if (cuDNNVersionIncompatible)\n      message(FATAL_ERROR \"cuDNN version >3 is required.\")\n    endif ()\n\n    set(CUDNN_VERSION \"${CUDNN_VERSION}\" PARENT_SCOPE)\n    mark_as_advanced(CUDNN_INCLUDE CUDNN_LIBRARY CUDNN_ROOT)\n\n  endif ()\nendfunction()\n\n################################################################################################\n###  Non macro section\n################################################################################################\n\nfind_package(CUDA 5.5 QUIET)\nfind_cuda_helper_libs(curand)  # cmake 2.8.7 compartibility which doesn't search for curand\n\nif (NOT CUDA_FOUND)\n  return()\nendif ()\n\nset(HAVE_CUDA TRUE)\nmessage(STATUS \"CUDA detected: \" ${CUDA_VERSION})\nlist(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDA_INCLUDE_DIRS})\nlist(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDA_CUDART_LIBRARY}\n                                     ${CUDA_curand_LIBRARY} ${CUDA_CUBLAS_LIBRARIES})\n\n# cudnn detection\nif (USE_CUDNN)\n  detect_cuDNN()\n  if (HAVE_CUDNN)\n    list(APPEND Caffe_DEFINITIONS PUBLIC -DUSE_CUDNN)\n    list(APPEND Caffe_INCLUDE_DIRS PUBLIC ${CUDNN_INCLUDE})\n    list(APPEND Caffe_LINKER_LIBS PUBLIC ${CUDNN_LIBRARY})\n  endif ()\nendif ()\n\n# setting nvcc arch flags\nop_select_nvcc_arch_flags(NVCC_FLAGS_EXTRA)\nlist(APPEND CUDA_NVCC_FLAGS ${NVCC_FLAGS_EXTRA})\nmessage(STATUS \"Added CUDA NVCC flags for: ${NVCC_FLAGS_EXTRA_readable}\")\n\n# Boost 1.55 workaround, see https://svn.boost.org/trac/boost/ticket/9392 or\n# https://github.com/ComputationalRadiationPhysics/picongpu/blob/master/src/picongpu/CMakeLists.txt\nif (Boost_VERSION EQUAL 105500)\n  message(STATUS \"Cuda + Boost 1.55: Applying noinline work around\")\n  # avoid warning for CMake >= 2.8.12\n  set(CUDA_NVCC_FLAGS \"${CUDA_NVCC_FLAGS} \\\"-DBOOST_NOINLINE=__attribute__((noinline))\\\" \")\nendif ()\n\n# disable some nvcc diagnostic that apears in boost, glog, glags, opencv, etc.\nforeach(diag cc_clobber_ignored integer_sign_change useless_using_declaration set_but_not_used)\n  list(APPEND CUDA_NVCC_FLAGS -Xcudafe --diag_suppress=${diag})\nendforeach()\n\n# setting default testing device\nif (NOT CUDA_TEST_DEVICE)\n  set(CUDA_TEST_DEVICE -1)\nendif ()\n\nmark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD)\nmark_as_advanced(CUDA_SDK_ROOT_DIR CUDA_SEPARABLE_COMPILATION)\n\n# Handle clang/libc++ issue\nif (APPLE)\n  op_detect_darwin_version(OSX_VERSION)\n\n  # OSX 10.9 and higher uses clang/libc++ by default which is incompatible with old CUDA toolkits\n  if (OSX_VERSION VERSION_GREATER 10.8)\n    # enabled by default if and only if CUDA version is less than 7.0\n    op_option(USE_libstdcpp \"Use libstdc++ instead of libc++\" (CUDA_VERSION VERSION_LESS 7.0))\n  endif ()\nendif ()\n"
  },
  {
    "path": "cmake/Modules/FindCaffe.cmake",
    "content": "# Copied from\n# https://raw.githubusercontent.com/opencv/opencv_contrib/master/modules/cnn_3dobj/FindCaffe.cmake\n\nunset(Caffe_FOUND)\nunset(Caffe_INCLUDE_DIRS)\nunset(Caffe_LIBS)\n\nfind_path(Caffe_INCLUDE_DIRS NAMES\n    caffe/caffe.hpp\n    caffe/common.hpp\n    caffe/net.hpp\n    caffe/proto/caffe.pb.h\n    caffe/util/io.hpp\n    HINTS\n    ${CMAKE_BINARY_DIR}/caffe/include\n    NO_DEFAULT_PATH)\n    \n\nfind_library(Caffe_LIBS NAMES caffe\n    HINTS\n    ${CMAKE_BINARY_DIR}/caffe/lib\n    ${CMAKE_BINARY_DIR}/caffe/lib/x86_64-linux-gnu\n    NO_DEFAULT_PATH)\n\nif (Caffe_LIBS AND Caffe_INCLUDE_DIRS)\n  set(Caffe_FOUND 1)\nendif (Caffe_LIBS AND Caffe_INCLUDE_DIRS)\n"
  },
  {
    "path": "cmake/Modules/FindCuDNN.cmake",
    "content": "set(CUDNN_ROOT \"\" CACHE PATH \"CUDNN root folder\")\nset(CUDNN_LIB_NAME \"libcudnn.so\")\n\nfind_path(CUDNN_INCLUDE cudnn.h\n    PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDA_TOOLKIT_INCLUDE}\n    DOC \"Path to cuDNN include directory.\" )\n\nget_filename_component(__libpath_hist ${CUDA_CUDART_LIBRARY} PATH)\nfind_library(CUDNN_LIBRARY NAMES ${CUDNN_LIB_NAME}\n    PATHS ${CUDNN_ROOT} $ENV{CUDNN_ROOT} ${CUDNN_INCLUDE} ${__libpath_hist} ${__libpath_hist}/../lib\n    DOC \"Path to cuDNN library.\")\n\nif(CUDNN_INCLUDE AND CUDNN_LIBRARY)\n    set(HAVE_CUDNN  TRUE)\n    set(CUDNN_FOUND TRUE)\n\n    if(EXISTS \"${CUDNN_INCLUDE}/cudnn_version.h\")\n        file(READ ${CUDNN_INCLUDE}/cudnn_version.h CUDNN_VERSION_FILE_CONTENTS)\n    else()\n        file(READ ${CUDNN_INCLUDE}/cudnn.h CUDNN_VERSION_FILE_CONTENTS)\n    endif()\n\n    # cuDNN v3 and beyond\n    string(REGEX MATCH \"define CUDNN_MAJOR * +([0-9]+)\"\n           CUDNN_VERSION_MAJOR \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_MAJOR * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_MAJOR \"${CUDNN_VERSION_MAJOR}\")\n    string(REGEX MATCH \"define CUDNN_MINOR * +([0-9]+)\"\n           CUDNN_VERSION_MINOR \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_MINOR * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_MINOR \"${CUDNN_VERSION_MINOR}\")\n    string(REGEX MATCH \"define CUDNN_PATCHLEVEL * +([0-9]+)\"\n           CUDNN_VERSION_PATCH \"${CUDNN_VERSION_FILE_CONTENTS}\")\n    string(REGEX REPLACE \"define CUDNN_PATCHLEVEL * +([0-9]+)\" \"\\\\1\"\n           CUDNN_VERSION_PATCH \"${CUDNN_VERSION_PATCH}\")\n\n    if (NOT CUDNN_VERSION_MAJOR)\n      set(CUDNN_VERSION \"???\")\n    else ()\n      set(CUDNN_VERSION \"${CUDNN_VERSION_MAJOR}.${CUDNN_VERSION_MINOR}.${CUDNN_VERSION_PATCH}\")\n    endif()\n\n    message(STATUS \"Found cuDNN: ver. ${CUDNN_VERSION} found (include: ${CUDNN_INCLUDE}, library: ${CUDNN_LIBRARY})\")\n\n    string(COMPARE LESS \"${CUDNN_VERSION_MAJOR}\" 3 cuDNNVersionIncompatible)\n    if(cuDNNVersionIncompatible)\n      message(FATAL_ERROR \"cuDNN version >3 is required.\")\n    endif()\n\n    set(CUDNN_VERSION \"${CUDNN_VERSION}\")\n    mark_as_advanced(CUDNN_INCLUDE CUDNN_LIBRARY CUDNN_ROOT)\nelse(CUDNN_INCLUDE AND CUDNN_LIBRARY)\n    message(STATUS \"cuDNN not found\")\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGFlags.cmake",
    "content": "# - Try to find GFLAGS\n#\n# The following variables are optionally searched for defaults\n#  GFLAGS_ROOT_DIR:            Base directory where all GFLAGS components are found\n#\n# The following are set after configuration is done:\n#  GFLAGS_FOUND\n#  GFLAGS_INCLUDE_DIRS\n#  GFLAGS_LIBRARIES\n#  GFLAGS_LIBRARYRARY_DIRS\n\ninclude(FindPackageHandleStandardArgs)\n\nset(GFLAGS_ROOT_DIR \"\" CACHE PATH \"Folder contains Gflags\")\n\n# We are testing only a couple of files in the include directories\nif(WIN32)\n    find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h\n        PATHS ${GFLAGS_ROOT_DIR}/src/windows)\nelse()\n    find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h\n        PATHS ${GFLAGS_ROOT_DIR})\nendif()\n\nif(MSVC)\n    find_library(GFLAGS_LIBRARY_RELEASE\n        NAMES libgflags\n        PATHS ${GFLAGS_ROOT_DIR}\n        PATH_SUFFIXES Release)\n\n    find_library(GFLAGS_LIBRARY_DEBUG\n        NAMES libgflags-debug\n        PATHS ${GFLAGS_ROOT_DIR}\n        PATH_SUFFIXES Debug)\n\n    set(GFLAGS_LIBRARY optimized ${GFLAGS_LIBRARY_RELEASE} debug ${GFLAGS_LIBRARY_DEBUG})\nelse()\n    find_library(GFLAGS_LIBRARY gflags)\nendif()\n\nfind_package_handle_standard_args(GFlags DEFAULT_MSG GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)\n\n\nif(GFLAGS_FOUND)\n    set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})\n    set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY})\n    message(STATUS \"Found gflags  (include: ${GFLAGS_INCLUDE_DIR}, library: ${GFLAGS_LIBRARY})\")\n    mark_as_advanced(GFLAGS_LIBRARY_DEBUG GFLAGS_LIBRARY_RELEASE\n                     GFLAGS_LIBRARY GFLAGS_INCLUDE_DIR GFLAGS_ROOT_DIR)\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindGlog.cmake",
    "content": "# - Try to find Glog\n#\n# The following variables are optionally searched for defaults\n#  GLOG_ROOT_DIR:            Base directory where all GLOG components are found\n#\n# The following are set after configuration is done:\n#  GLOG_FOUND\n#  GLOG_INCLUDE_DIRS\n#  GLOG_LIBRARIES\n#  GLOG_LIBRARYRARY_DIRS\n\ninclude(FindPackageHandleStandardArgs)\n\nset(GLOG_ROOT_DIR \"\" CACHE PATH \"Folder contains Google glog\")\n\nif (WIN32)\n    find_path(GLOG_INCLUDE_DIR glog/logging.h\n        PATHS ${GLOG_ROOT_DIR}/src/windows)\nelse ()\n    find_path(GLOG_INCLUDE_DIR glog/logging.h\n        PATHS ${GLOG_ROOT_DIR})\nendif()\n\nif (MSVC)\n    find_library(GLOG_LIBRARY_RELEASE libglog_static\n        PATHS ${GLOG_ROOT_DIR}\n        PATH_SUFFIXES Release)\n\n    find_library(GLOG_LIBRARY_DEBUG libglog_static\n        PATHS ${GLOG_ROOT_DIR}\n        PATH_SUFFIXES Debug)\n\n    set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG})\nelse ()\n    find_library(GLOG_LIBRARY glog\n        PATHS ${GLOG_ROOT_DIR}\n        PATH_SUFFIXES lib lib64)\nendif()\n\nfind_package_handle_standard_args(Glog DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY)\n\nif(GLOG_FOUND)\n  set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})\n  set(GLOG_LIBRARIES ${GLOG_LIBRARY})\n  message(STATUS \"Found glog    (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})\")\n  mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG\n                                 GLOG_LIBRARY GLOG_INCLUDE_DIR)\nendif()\n"
  },
  {
    "path": "cmake/Modules/FindLIBIGL.cmake",
    "content": "# Copied from:\n# https://github.com/libigl/libigl-examples/blob/master/cmake/FindLIBIGL.cmake\n\n# - Try to find the LIBIGL library\n# Once done this will define\n#\n#  LIBIGL_FOUND - system has LIBIGL\n#  LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory\n#  LIBIGL_INCLUDE_DIRS - LIBIGL include directories\n#  LIBIGL_SOURCES - the LIBIGL source files\nif(NOT LIBIGL_FOUND)\n\nFIND_PATH(LIBIGL_INCLUDE_DIR igl/readOBJ.h\n   ${PROJECT_SOURCE_DIR}/../../include\n   ${PROJECT_SOURCE_DIR}/../include\n   ${PROJECT_SOURCE_DIR}/include\n   ${PROJECT_SOURCE_DIR}/../libigl/include\n   ${PROJECT_SOURCE_DIR}/../../libigl/include\n   $ENV{LIBIGL}/include\n   $ENV{LIBIGLROOT}/include\n   $ENV{LIBIGL_ROOT}/include\n   $ENV{LIBIGL_DIR}/include\n   $ENV{LIBIGL_DIR}/inc\n   /usr/include\n   /usr/local/include\n   /usr/local/igl/libigl/include\n)\n\n\nif(LIBIGL_INCLUDE_DIR)\n   set(LIBIGL_FOUND TRUE)\n   set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIR}  ${LIBIGL_INCLUDE_DIR}/../external/Singular_Value_Decomposition)\n   #set(LIBIGL_SOURCES\n   #   ${LIBIGL_INCLUDE_DIR}/igl/viewer/Viewer.cpp\n   #)\nendif(LIBIGL_INCLUDE_DIR)\n\nif(LIBIGL_USE_STATIC_LIBRARY)\n  add_definitions(-DIGL_STATIC_LIBRARY)\n  set(LIBIGL_LIB_DIRS\n   ${CMAKE_BINARY_DIR}/\n   ${PROJECT_SOURCE_DIR}/../../lib\n   ${PROJECT_SOURCE_DIR}/../lib\n   ${PROJECT_SOURCE_DIR}/lib\n   ${PROJECT_SOURCE_DIR}/../../libigl/lib\n   ${PROJECT_SOURCE_DIR}/../libigl/lib\n   $ENV{LIBIGL}/lib\n   $ENV{LIBIGLROOT}/lib\n   $ENV{LIBIGL_ROOT}/lib\n   $ENV{LIBIGL_DIR}/lib\n   /usr/lib\n   /usr/local/lib)\n  FIND_LIBRARY( LIBIGL_LIBRARY NAMES igl PATHS ${LIBIGL_LIB_DIRS})\n\n  # try to find pre-requisites\n  find_package(CORK QUIET)\n  find_package(CGAL QUIET)\n  find_package(EMBREE QUIET)\n  find_package(LIBCOMISO QUIET)\n  find_package(MATLAB QUIET)\n  find_package(MOSEK QUIET)\n  find_package(TETGEN QUIET)\n  find_package(TINYXML2 QUIET)\n  find_package(TRIANGLE QUIET)\n\n  # Main library must be found\n  if(NOT LIBIGL_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libigl\")\n  endif(NOT LIBIGL_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGL_LIBRARY})\n\n  FIND_LIBRARY( LIBIGLANTTWEAKBAR_LIBRARY NAMES iglanttweakbar PATHS ${LIBIGL_LIB_DIRS})\n  if(NOT LIBIGLANTTWEAKBAR_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libiglanttweakbar\")\n  endif(NOT LIBIGLANTTWEAKBAR_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLANTTWEAKBAR_LIBRARY})\n\n  # libiglbbw will work with/without mosek\n  FIND_LIBRARY( LIBIGLBBW_LIBRARY NAMES iglbbw PATHS ${LIBIGL_LIB_DIRS})\n  if(NOT LIBIGLBBW_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libiglbbw\")\n  endif(NOT LIBIGLBBW_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLBBW_LIBRARY})\n\n  if(LIBCOMISO_FOUND)\n    FIND_LIBRARY(LIBIGLCOMISO_LIBRARY NAMES iglcomiso PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLCOMISO_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglcomiso\")\n    endif(NOT LIBIGLCOMISO_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLCOMISO_LIBRARY})\n  endif(LIBCOMISO_FOUND)\n\n  if(CGAL_FOUND)\n\n    FIND_LIBRARY( LIBIGLCGAL_LIBRARY NAMES iglcgal PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLCGAL_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglcgal\")\n    endif(NOT LIBIGLCGAL_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLCGAL_LIBRARY})\n  endif(CGAL_FOUND)\n\n  if(EMBREE_FOUND)\n    FIND_LIBRARY( LIBIGLEMBREE_LIBRARY NAMES iglembree PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLEMBREE_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglembree\")\n    endif(NOT LIBIGLEMBREE_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLEMBREE_LIBRARY})\n  endif(EMBREE_FOUND)\n\n  if(LIM_FOUND)\n    FIND_LIBRARY( LIBIGLLIM_LIBRARY NAMES igllim PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLLIM_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libigllim\")\n    endif(NOT LIBIGLLIM_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLLIM_LIBRARY})\n  endif(LIM_FOUND)\n\n  if(MATLAB_FOUND)\n    FIND_LIBRARY( LIBIGLMATLAB_LIBRARY NAMES iglmatlab PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLMATLAB_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglmatlab\")\n    endif(NOT LIBIGLMATLAB_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLMATLAB_LIBRARY})\n  endif(MATLAB_FOUND)\n\n  # mosek support should be determined before trying to find bbw\n  if(MOSEK_FOUND)\n    FIND_LIBRARY( LIBIGLMOSEK_LIBRARY NAMES iglmosek PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLMOSEK_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglmosek\")\n    endif(NOT LIBIGLMOSEK_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLMOSEK_LIBRARY})\n  endif(MOSEK_FOUND)\n\n  FIND_LIBRARY( LIBIGLOPENGL_LIBRARY NAMES iglopengl PATHS ${LIBIGL_LIB_DIRS})\n  if(NOT LIBIGLOPENGL_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libiglopengl\")\n  endif(NOT LIBIGLOPENGL_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLOPENGL_LIBRARY})\n\n  FIND_LIBRARY( LIBIGLOPENGL2_LIBRARY NAMES iglopengl2 PATHS ${LIBIGL_LIB_DIRS})\n  if(NOT LIBIGLOPENGL2_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libiglopengl2\")\n  endif(NOT LIBIGLOPENGL2_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLOPENGL2_LIBRARY})\n\n  if(TETGEN_FOUND)\n    FIND_LIBRARY( LIBIGLTETGEN_LIBRARY NAMES igltetgen PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLTETGEN_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libigltetgen\")\n    endif(NOT LIBIGLTETGEN_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLTETGEN_LIBRARY})\n  endif(TETGEN_FOUND)\n\n  if(TINYXML2_FOUND)\n    FIND_LIBRARY( LIBIGLXML_LIBRARY NAMES iglxml PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLXML_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libiglxml\")\n    endif(NOT LIBIGLXML_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLXML_LIBRARY})\n  endif(TINYXML2_FOUND)\n\n  if(TRIANGLE_FOUND)\n    FIND_LIBRARY( LIBIGLTRIANGLE_LIBRARY NAMES igltriangle PATHS ${LIBIGL_LIB_DIRS})\n    if(NOT LIBIGLTRIANGLE_LIBRARY)\n      set(LIBIGL_FOUND FALSE)\n      message(FATAL_ERROR \"could NOT find libigltriangle\")\n    endif(NOT LIBIGLTRIANGLE_LIBRARY)\n    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLTRIANGLE_LIBRARY})\n  endif(TRIANGLE_FOUND)\n\n  # libiglviewer is required\n  FIND_LIBRARY( LIBIGLVIEWER_LIBRARY NAMES iglviewer PATHS ${LIBIGL_LIB_DIRS})\n  if(NOT LIBIGLVIEWER_LIBRARY)\n    set(LIBIGL_FOUND FALSE)\n    message(FATAL_ERROR \"could NOT find libiglviewer\")\n  endif(NOT LIBIGLVIEWER_LIBRARY)\n  set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} ${LIBIGLVIEWER_LIBRARY})\n\n  find_package(OpenMP)\n  if (OPENMP_FOUND)\n    set (CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}\")\n    set (CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}\")\n  endif(OPENMP_FOUND)\n\n\nendif(LIBIGL_USE_STATIC_LIBRARY)\n\n\n\nif(LIBIGL_FOUND)\n   if(NOT LIBIGL_FIND_QUIETLY)\n      message(STATUS \"Found LIBIGL: ${LIBIGL_INCLUDE_DIR}\")\n   endif(NOT LIBIGL_FIND_QUIETLY)\nelse(LIBIGL_FOUND)\n   if(LIBIGL_FIND_REQUIRED)\n      message(FATAL_ERROR \"could NOT find LIBIGL\")\n   endif(LIBIGL_FIND_REQUIRED)\nendif(LIBIGL_FOUND)\n\nMARK_AS_ADVANCED(LIBIGL_INCLUDE_DIRS LIBIGL_INCLUDE_DIR LIBIGL_LIBRARIES IGL_VIEWER_SOURCES)\n\nendif(NOT LIBIGL_FOUND)\n"
  },
  {
    "path": "cmake/Modules/FindSpinnaker.cmake",
    "content": "# Based on `FindCaffe.cmake`\n\nunset(SPINNAKER_FOUND)\nunset(SPINNAKER_INCLUDE_DIRS)\nunset(SPINNAKER_LIB)\n\nfind_path(SPINNAKER_INCLUDE_DIRS NAMES\n  Spinnaker.h\n  HINTS\n  /usr/include/spinnaker/\n  /usr/local/include/spinnaker/)\n\nfind_library(SPINNAKER_LIB NAMES Spinnaker\n    HINTS\n    /usr/lib\n    /usr/local/lib)\n\nif (SPINNAKER_INCLUDE_DIRS AND SPINNAKER_LIB)\n  set(SPINNAKER_FOUND 1)\nendif (SPINNAKER_INCLUDE_DIRS AND SPINNAKER_LIB)\n"
  },
  {
    "path": "cmake/OpenPose.vcxproj.user",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n</Project>"
  },
  {
    "path": "cmake/OpenPoseConfig.cmake.in",
    "content": "# Compute and install package configuration and version files\nget_filename_component(_dir \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\nget_filename_component(_prefix \"${_dir}/../..\" ABSOLUTE)\n\n# Import the targets\ninclude(\"${_prefix}/lib/OpenPose/OpenPose.cmake\")\nif (@BUILD_CAFFE@)\n  set(Caffe_INCLUDE_DIRS \"${_prefix}/include/\")\n  # set(Caffe_LIBS \"${_prefix}/lib/libcaffe.so\")\nendif (@BUILD_CAFFE@)\n\n# Report other information\nset(OpenPose_INCLUDE_DIRS \"${_prefix}/include/\")\nset(OpenPose_VERSION_MAJOR @OpenPose_VERSION_MAJOR@)\nset(OpenPose_VERSION_MINOR @OpenPose_VERSION_MINOR@)\nset(OpenPose_VERSION_PATCH @OpenPose_VERSION_PATCH@)\nset(OpenPose_VERSION @OpenPose_VERSION@)\n\n# Check that the user requested components \n# are actually targets that are part of this build\nif (OpenPose_FIND_COMPONENTS)\n  foreach (comp ${OpenPose_FIND_COMPONENTS})\n    if (NOT TARGET ${comp})\n      set (OpenPose_${comp}_FOUND 0)\n      if (OpenPose_FIND_REQUIRED_${comp})\n        message(FATAL_ERROR \"OpenPose ${comp} not available.\")\n      endif (OpenPose_FIND_REQUIRED_${comp})\n    else (NOT TARGET ${comp})\n      set(OpenPose_${comp}_FOUND 1)\n      set(OpenPose_LIBS \"${comp};${OpenPose_LIBS}\")\n    endif (NOT TARGET ${comp})\n  endforeach ()\nelse (OpenPose_FIND_COMPONENTS)\n  set(OpenPose_LIBS \"openpose\")\nendif (OpenPose_FIND_COMPONENTS)\n\nif (OpenPose_INCLUDE_DIRS AND OpenPose_LIBS)\n  set(OpenPose_FOUND 1)\nendif (OpenPose_INCLUDE_DIRS AND OpenPose_LIBS)\n"
  },
  {
    "path": "cmake/OpenPose_CL.vcxproj.user",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe_opencl\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe_opencl\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n</Project>"
  },
  {
    "path": "cmake/OpenPose_CPU.vcxproj.user",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe_cpu\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LocalDebuggerEnvironment>PATH=%PATH%;3rdparty\\windows\\caffe_cpu\\bin\\;3rdparty\\windows\\opencv\\x64\\vc15\\bin;3rdparty\\windows\\freeglut\\bin\\;3rdparty\\windows\\spinnaker\\bin\\</LocalDebuggerEnvironment>\n    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n    <LocalDebuggerWorkingDirectory>..\\..\\..</LocalDebuggerWorkingDirectory>\n  </PropertyGroup>\n\n</Project>"
  },
  {
    "path": "cmake/Utils.cmake",
    "content": "# Function to download models\nfunction (download_model MODEL_NAME MODEL_DOWNLOAD_FLAG MODEL_RELATIVE_PATH CHECKSUM)\n  if (MODEL_DOWNLOAD_FLAG)\n    message(STATUS \"Downloading ${MODEL_NAME} model...\")\n    set(MODEL_FILENAME ${CMAKE_SOURCE_DIR}/models/${MODEL_RELATIVE_PATH})\n    if (NOT EXISTS ${MODEL_FILENAME})\n      message(STATUS \"NOTE: This process might take several minutes depending on your internet connection.\")\n      file(DOWNLOAD ${OPENPOSE_URL}${MODEL_RELATIVE_PATH} ${MODEL_FILENAME}\n          EXPECTED_MD5 ${CHECKSUM}) # SHOW_PROGRESS)\n    else (NOT EXISTS ${MODEL_FILENAME})\n      message(STATUS \"Model already exists.\")\n    endif (NOT EXISTS ${MODEL_FILENAME})\n  else (MODEL_DOWNLOAD_FLAG)\n    message(STATUS \"Not downloading ${MODEL_NAME} model\")\n  endif (MODEL_DOWNLOAD_FLAG)\nendfunction (download_model)\n\n# Function to download zip files, then extracting them and then deleting them\nfunction(download_zip FILE_NAME URL DOWNLOAD_PATH CHECKSUM)\n  set(FULL_FILE_PATH \"${DOWNLOAD_PATH}/${FILE_NAME}\")\n  if (NOT EXISTS ${FULL_FILE_PATH})\n    message(STATUS \"Downloading ${URL}/${FILE_NAME}...\")\n    file(DOWNLOAD \"${URL}/${FILE_NAME}\" \"${DOWNLOAD_PATH}/${FILE_NAME}\"\n        EXPECTED_MD5 ${CHECKSUM})\n    message(STATUS \"Extracting ${FULL_FILE_PATH}...\")\n    execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf ${FILE_NAME} WORKING_DIRECTORY ${DOWNLOAD_PATH})\n    else (NOT EXISTS ${FULL_FILE_PATH})\n      message(STATUS \"${FILE_NAME} already exists.\")\n  endif (NOT EXISTS ${FULL_FILE_PATH})\nendfunction(download_zip)\n\n# Function to prepend filenames with common path\nfunction(prepend var prefix)\n   set(listVar \"\")\n   foreach (f ${ARGN})\n      list(APPEND listVar \"${prefix}/${f}\")\n   endforeach (f)\n   set(${var} \"${listVar}\" PARENT_SCOPE)\nendfunction(prepend)\n\n# Get names of subdirectories in directory\nmacro(subdirlist result curdir)\n  FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)\n  SET(dirlist \"\")\n  foreach (child ${children})\n    if (IS_DIRECTORY ${curdir}/${child} AND NOT ${child} STREQUAL \"CMakeFiles\")\n      list(APPEND dirlist ${child})\n    endif()\n  endforeach ()\n  set(${result} ${dirlist})\nendmacro()"
  },
  {
    "path": "cmake/cmake_uninstall.cmake.in",
    "content": "# Reference -- https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F\nif(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n  message(FATAL_ERROR \"Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\nendif(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\")\n\nfile(READ \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\" files)\nstring(REGEX REPLACE \"\\n\" \";\" files \"${files}\")\nforeach(file ${files})\n  message(STATUS \"Uninstalling $ENV{DESTDIR}${file}\")\n  if(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\n    exec_program(\n      \"@CMAKE_COMMAND@\" ARGS \"-E remove \\\"$ENV{DESTDIR}${file}\\\"\"\n      OUTPUT_VARIABLE rm_out\n      RETURN_VALUE rm_retval\n      )\n    if(NOT \"${rm_retval}\" STREQUAL 0)\n      message(FATAL_ERROR \"Problem when removing $ENV{DESTDIR}${file}\")\n    endif(NOT \"${rm_retval}\" STREQUAL 0)\n  else(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\n    message(STATUS \"File $ENV{DESTDIR}${file} does not exist.\")\n  endif(IS_SYMLINK \"$ENV{DESTDIR}${file}\" OR EXISTS \"$ENV{DESTDIR}${file}\")\nendforeach(file)\n\n"
  },
  {
    "path": "doc/00_index.md",
    "content": "OpenPose Doc\n==========================\n\nThe OpenPose documentation is available in 2 different formats, choose your preferred one!\n- As a traditional website (recommended): [cmu-perceptual-computing-lab.github.io/openpose](https://cmu-perceptual-computing-lab.github.io/openpose).\n- As markdown files: [github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/00_index.md](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/00_index.md).\n\nMost users can simply use the OpenPose Demo without reading any C++/Python code. Users that need to add additional functionality (new inputs, outputs, etc) should check the C++/Python APIs:\n\n- If you face issues with any of these steps, keep in mind to check the [FAQ](installation/05_faq.md) section.\n\n- The first step for any software, [install it](installation/0_index.md)!\n\n- [OpenPose Demo](01_demo.md): Choose your input (e.g., images, video, webcam), set of algorithms (body, hand, face), output (e.g., display, JSON keypoint saving, image+keypoints), and run OpenPose from your terminal or PowerShell!\n    - E.g.: Given an input video (`--video`), extract body (by default), face (`--face`) and hand (`--hand`) keypoints, save the keypoints in a JSON file (`--write_json`), and display (by default) the results in the screen. You can remove any of the flags to remove that particular functionality or add any other.\n```\n# Ubuntu\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --face --hand --write_json output_json_folder/\n\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples\\media\\video.avi --face --hand --write_json output_json_folder/\n```\n\n- [Output information](02_output.md): Learn about the output format, keypoint index ordering, etc.\n\n- [OpenPose Python API](03_python_api.md): Almost all the OpenPose functionality, but in Python! If you want to read a specific input, and/or add your custom post-processing function, and/or implement your own display/saving.\n\n- [OpenPose C++ API](04_cpp_api.md): If you want to read a specific input, and/or add your custom post-processing function, and/or implement your own display/saving.\n\n- [Maximizing OpenPose speed and benchmark](06_maximizing_openpose_speed.md): Check the OpenPose Benchmark as well as some hints to speed up and/or reduce the memory requirements for OpenPose.\n\n- [Calibration toolbox](advanced/calibration_module.md) and [3D OpenPose](advanced/3d_reconstruction_module.md): Calibrate your cameras for 3D OpenPose (or any other stereo vision tasks) and start obtaining 3D keypoints!\n\n- [Standalone face or hand detector](advanced/standalone_face_or_hand_keypoint_detector.md) is useful if you want to do any of the following:\n    - **Face** keypoint detection **without body** keypoint detection: Pros: Speedup and RAM/GPU memory reduction. Cons: Worse accuracy and less detected number of faces).\n    - **Use your own face/hand detector**: You can use the hand and/or face keypoint detectors with your own face or hand detectors, rather than using the body detector. E.g., useful for camera views at which the hands are visible but not the body (OpenPose detector would fail).\n"
  },
  {
    "path": "doc/01_demo.md",
    "content": "OpenPose Doc - Demo\n====================================\n\nForget about the OpenPose code, just download the portable Windows binaries (or compile the code from source) and use the demo by following this tutorial!\n\n## Contents\n1. [Quick Start](#quick-start)\n    1. [Running on Images, Video, or Webcam](#running-on-images-video-or-webcam)\n    2. [Face and Hands](#face-and-hands)\n    3. [Different Outputs (JSON, Images, Video, UI)](#different-outputs-json-images-video-ui)\n    4. [Only Skeleton without Background Image](#only-skeleton-without-background-image)\n    5. [Not Running All GPUs](#not-running-all-gpus)\n    6. [Maximum Accuracy Configuration](#maximum-accuracy-configuration)\n        1. [Additional Model with Maximum Accuracy](#additional-model-with-maximum-accuracy)\n        2. [Additional Model with Lower False Positives](#additional-model-with-lower-false-positives)\n    7. [3-D Reconstruction](#3-d-reconstruction)\n    8. [Tracking](#tracking)\n    9. [Kinect 2.0 as Webcam on Windows 10](#kinect-20-as-webcam-on-windows-10)\n    10. [Main Flags](#main-flags)\n2. [Advanced Quick Start](#advanced-quick-start)\n3. [Bug Solving](#bug-solving)\n    1. [Improving Memory and Speed but Decreasing Accuracy](#improving-memory-and-speed-but-decreasing-accuracy)\n    2. [Mac OSX Additional Step](#mac-osx-additional-step)\n    3. [FAQ](#faq)\n\n\n\n\n\n## Quick Start\nIn Ubuntu, Mac, and other Unix systems, use `Terminal` or `Terminator`. In Windows, the `Windows PowerShell`. Watch any Youtube video tutorial if you are not familiar with these tools. Make sure that you are in the **root directory of the project** when running any command (i.e., in the OpenPose folder, not inside `build/` nor `windows/` nor `bin/`). In addition, `examples/media/video.avi` and `examples/media` exist, so there is no need to change any lines of code.\n\nTest OpenPose by running the following. The expected visual result should look like [doc/02_output.md#ui-and-visual-output](02_output.md#ui-and-visual-output).\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --video examples/media/video.avi\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples/media/video.avi\n```\n\nIf you are only using the OpenPose demo, we highly recommend using [the latest Windows portable version of OpenPose](doc/installation/0_index.md#windows-portable-demo). If you still want to use the demo with Visual Studio, you can copy the `bin/*.dll` files into the final DLL bin location following [doc/installation/0_index.md#windows](installation/0_index.md#windows), or you could also simply modify the default flag values from [include/flags.hpp](../include/flags.hpp). If you have copied the DLLs, you can execute this:\n```\n:: Windows - Library - Assuming you have copied the DLLs following doc/installation/0_index.md#windows\nbuild\\x64\\Release\\OpenPoseDemo.exe --video examples/media/video.avi\n```\n\nIf it worked, continue with the next section. Otherwise:\n- If these failed with an out of memory error, check and follow the section [Improving Memory and Speed but Decreasing Accuracy](#improving-memory-and-speed-but-decreasing-accuracy).\n- If you are using Mac, make sure to check and follow the section [Mac OSX Additional Step](#mac-osx-additional-step).\n- Otherwise, check the section [FAQ](#faq).\n\n\n\n### Running on Images, Video, or Webcam\n- Directory with images (`--image_dir {DIRECTORY_PATH}`):\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --image_dir examples/media/\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --image_dir examples/media/\n```\n- Video (`--video {VIDEO_PATH}`):\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --video examples/media/video.avi\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples/media/video.avi\n```\n- Webcam is applied by default (i.e., if no `--image_dir` or `--video` flags used). Optionally, if you have more than 1 camera, you could use `--camera {CAMERA_NUMBER}` to select the right one:\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin\n./build/examples/openpose/openpose.bin --camera 0\n./build/examples/openpose/openpose.bin --camera 1\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe\nbin\\OpenPoseDemo.exe --camera 0\nbin\\OpenPoseDemo.exe --camera 1\n```\n\n\n\n### Face and Hands\nSimply add `--face` and/or `--hand` to any command:\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --image_dir examples/media/ --face --hand\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --face --hand\n./build/examples/openpose/openpose.bin --face --hand\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --image_dir examples/media/ --face --hand\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --face --hand\nbin\\OpenPoseDemo.exe --face --hand\n```\n\n\n\n## Different Outputs (JSON, Images, Video, UI)\nAll the output options are complementary to each other. E.g., whether you display the images with the skeletons on the UI (or not) is independent on whether you save them on disk (or not).\n\n- Save the skeletons in a set of JSON files with `--write_json {OUTPUT_JSON_PATH}`, see [doc/02_output.md](02_output.md) to understand its format.\n```\n# Ubuntu and Mac (same flags for Windows)\n./build/examples/openpose/openpose.bin --image_dir examples/media/ --write_json output_jsons/\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_json output_jsons/\n./build/examples/openpose/openpose.bin --write_json output_jsons/\n```\n- Save on disk the visual output of OpenPose (the images with the skeletons overlaid) as an output video (`--write_video {OUTPUT_VIDEO_PATH}`) or set of images (`--write_images {OUTPUT_IMAGE_DIRECTORY_PATH}`.:\n```\n# Ubuntu and Mac (same flags for Windows)\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_video output/result.avi\n./build/examples/openpose/openpose.bin --image_dir examples/media/ --write_video output/result.avi\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_images output_images/\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_images output_images/ --write_images_format jpg\n./build/examples/openpose/openpose.bin --image_dir examples/media/ --write_images output_images/\n./build/examples/openpose/openpose.bin --image_dir examples/media/ --write_images output_images/ --write_images_format jpg\n```\n- You can also disable the UI visualization with `--display 0`. However, some kind of output must be generated. I.e., set one out of `--write_json`, `--write_video`, or `--write_images` if `--display 0`.\n```\n# Ubuntu and Mac (same flags for Windows)\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_images output_images/ --display 0\n```\n- To speed up OpenPose even further when using `--display 0`, also add `--render_pose 0` if you are not using `--write_video` or `--write_images` (so OpenPose will not overlay skeletons with the input images).\n```\n# Ubuntu and Mac (same flags for Windows)\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --write_json output_jsons/ --display 0 --render_pose 0\n```\n\n\n\n## Only Skeleton without Background Image\nYou can also visualize/save the skeleton without the original image overlaid or blended by adding `--disable_blending`:\n```\n# Ubuntu and Mac (same flags for Windows)\n# Only body\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --disable_blending\n```\n\n\n\n## Not Running All GPUs\nBy default, OpenPose will use all the GPUs available in your machine. Otherwise, `--num_gpu` sets the number of total GPUs and `--num_gpu_start` the first GPU to use. E.g., `--num_gpu 2 --num_gpu_start 1` will use GPUs ID 1 and 2 while ignore GPU ID 0 (assuming there are at least 3 GPUs):\n```\n:: Windows - Portable Demo (same flags for Ubuntu and Mac)\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --num_gpu 2 --num_gpu_start 1\n```\n\n\n\n### Maximum Accuracy Configuration\nThis command provides the most accurate results we have been able to achieve for body, hand and face keypoint detection.\n```\n# Ubuntu and Mac: Body\n./build/examples/openpose/openpose.bin --net_resolution \"1312x736\" --scale_number 4 --scale_gap 0.25\n# Ubuntu and Mac: Body + Hand + Face\n./build/examples/openpose/openpose.bin --net_resolution \"1312x736\" --scale_number 4 --scale_gap 0.25 --hand --hand_scale_number 6 --hand_scale_range 0.4 --face\n```\n```\n:: Windows - Portable Demo: Body\nbin\\OpenPoseDemo.exe --net_resolution \"1312x736\" --scale_number 4 --scale_gap 0.25\n:: Windows - Portable Demo: Body + Hand + Face\nbin\\OpenPoseDemo.exe --net_resolution \"1312x736\" --scale_number 4 --scale_gap 0.25 --hand --hand_scale_number 6 --hand_scale_range 0.4 --face\n```\n\n- Required:\n    - `BODY_25` (default model). `COCO` is less accurate (but still usable), while `MPI` is not supported (i.e., `MPI` accuracy and speed will drop by using these settings).\n    - Nvidia GPU with at least 16 GB of memory. 8 or 12 GB could work in some subcases detailed here.\n        - `BODY_25` (body + foot, default model): Nvidia GPU with at least about 10.5 GB of memory. E.g., Titan X(P), some Quadro models, P100, V100.\n        - `BODY_25` + face + hands: Nvidia GPU with at least about 16 GB of memory. E.g., V100.\n        - `COCO` Body + face + hands: Nvidia GPU with at least about 6.7 GB of memory. E.g., 2070, 2080.\n    - It won't work on CPU/OpenCL modes, your only option there is to manually crop each person, rescale it, and fed it into the default OpenPose\n- Additional information:\n    - It runs at about 2 FPS on a Titan X for `BODY_25` (1 FPS for COCO).\n    - Increasing `--net_resolution` will highly reduce speed, while it does not guarantee the accuracy to increase. Thus, we recommend only using the exact flags and values detailed here (or alternatively ask the user to make their own accuracy analysis if using other values).\n    - (Not recommended, use at your own risk) You can add `--maximize_positives` to harm the visual/qualitative accuracy, but it increases the accuracy value metric on COCO challenge. It reduces the thresholds to accept a person candidate (i.e., more false and true positives), which maximizes average recall but could harm average precision. Our experience: it looks much worse visually, but improves the challenge accuracy numbers.\n    - If you are operating on Ubuntu, you can check the experimental scripts that we use to test our accuracy (we do not officially support it, i.e., we will not answer questions about it, as well as it might change it continuously), they are placed in `openpose/scripts/tests/`, called `pose_accuracy_coco_test_dev.sh` and `pose_accuracy_coco_val.sh`.\n\n\n#### Additional Model with Maximum Accuracy\nDisclaimer: It is more accurate but also slower, requires more GPU memory, and must use the Nvidia GPU version.\n\nOur paper accuracy numbers do not match the default model numbers. We released our best model at the time but found better ones later.\n\nFor our best model, you can download the `BODY_25B` pre-trained model from the OpenPose training repository: [BODY_25B Model - Option 1 (Maximum Accuracy, Less Speed)](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train/tree/master/experimental_models#body_25b-model---option-1-maximum-accuracy-less-speed).\n\n\n#### Additional Model with Lower False Positives\nDisclaimer: It must use the Nvidia GPU version.\n\nDo you need a model with less false positives but the same runtime performance and GPU requirements? You can download the `BODY_25B` pre-trained model from the OpenPose training repository: [BODY_25B Model - Option 2 (Recommended)](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train/tree/master/experimental_models#body_25b-model---option-2-recommended).\n\n\n\n### 3-D Reconstruction\n1. Real-time demo\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1\n# With face and hands\n./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --face --hand\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1\n:: With face and hands\nbin\\OpenPoseDemo.exe --flir_camera --3d --number_people_max 1 --face --hand\n```\n\n2. Saving 3-D keypoints and video\n```\n# Ubuntu and Mac (same flags for Windows)\n./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --write_json output_folder_path/ --write_video_3d output_folder_path/video_3d.avi\n```\n\n3. Fast stereo camera image saving (without keypoint detection) for later post-processing\n```\n# Ubuntu and Mac (same flags for Windows)\n# Saving video\n# Note: saving in PNG rather than JPG will improve image quality, but slow down FPS (depending on hard disk writing speed and camera number)\n./build/examples/openpose/openpose.bin --flir_camera --num_gpu 0 --write_video output_folder_path/video.avi --write_video_fps 5\n# Saving images\n# Note: saving in PNG rather than JPG will improve image quality, but slow down FPS (depending on hard disk writing speed and camera number)\n./build/examples/openpose/openpose.bin --flir_camera --num_gpu 0 --write_images output_folder_path/ --write_images_format jpg\n```\n\n4. Reading and processing previously saved stereo camera images\n```\n# Ubuntu and Mac (same flags for Windows)\n# Optionally add `--face` and/or `--hand` to include face and/or hands\n# Assuming 3 cameras\n# Note: We highly recommend to reduce `--output_resolution`. E.g., for 3 cameras recording at 1920x1080, the resulting image is (3x1920)x1080, so we recommend e.g. 640x360 (x3 reduction).\n# Video\n./build/examples/openpose/openpose.bin --video output_folder_path/video.avi --3d_views 3 --3d --number_people_max 1 --output_resolution {desired_output_resolution}\n# Images\n./build/examples/openpose/openpose.bin --image_dir output_folder_path/ --3d_views 3 --3d --number_people_max 1 --output_resolution {desired_output_resolution}\n```\n\n5. Reconstruction when the keypoint is visible in at least `x` camera views out of the total `n` cameras\n```\n# Ubuntu and Mac (same flags for Windows)\n# Reconstruction when a keypoint is visible in at least 2 camera views (assuming `n` >= 2)\n./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --3d_min_views 2 --output_resolution {desired_output_resolution}\n# Reconstruction when a keypoint is visible in at least max(2, min(4, n-1)) camera views\n./build/examples/openpose/openpose.bin --flir_camera --3d --number_people_max 1 --output_resolution {desired_output_resolution}\n```\n\n\n\n### Tracking\n1. Runtime huge speed up by reducing the accuracy:\n```\n:: Windows - Portable Demo (same flags for Ubuntu and Mac)\n# Using OpenPose 1 frame, tracking the following e.g., 5 frames\nbin\\OpenPoseDemo.exe --tracking 5 --number_people_max 1\n```\n\n2. Runtime speed up while keeping most of the accuracy:\n```\n:: Windows - Portable Demo (same flags for Ubuntu and Mac)\n# Using OpenPose 1 frame and tracking another frame\nbin\\OpenPoseDemo.exe --tracking 1 --number_people_max 1\n```\n\n3. Visual smoothness:\n```\n:: Windows - Portable Demo (same flags for Ubuntu and Mac)\n# Running both OpenPose and tracking on each frame. Note: There is no speed up/slow down\nbin\\OpenPoseDemo.exe --tracking 0 --number_people_max 1\n```\n\n\n\n## Kinect 2.0 as Webcam on Windows 10\nSince the Windows 10 Anniversary, Kinect 2.0 can be read as a normal webcam. All you need to do is go to `device manager`, expand the `kinect sensor devices` tab, right click and update driver of `WDF kinectSensor Interface`. If you already have another webcam, disconnect it or use `--camera 2`.\n\n\n\n\n\n### Main Flags\nThese are the most common flags, but check [doc/advanced/demo_advanced.md](advanced/demo_advanced.md) for a full list and description of all of them.\n\n- `--face`: Enables face keypoint detection.\n- `--hand`: Enables hand keypoint detection.\n- `--video input.mp4`: Read video `input.mp4`.\n- `--camera 3`: Read webcam number 3.\n- `--image_dir path_with_images/`: Run on the directory `path_with_images/` with images.\n- `--ip_camera http://iris.not.iac.es/axis-cgi/mjpg/video.cgi?resolution=320x240?x.mjpeg`: Run on a streamed IP camera. See examples public IP cameras [here](http://www.webcamxp.com/publicipcams.aspx).\n- `--write_video path.avi`: Save processed images as video.\n- `--write_images folder_path`: Save processed images on a folder.\n- `--write_keypoint path/`: Output JSON, XML or YML files with the people pose data on a folder.\n- `--process_real_time`: For video, it might skip frames to display at real time.\n- `--disable_blending`: If enabled, it will render the results (keypoint skeletons or heatmaps) on a black background, not showing the original image. Related: `part_to_show`, `alpha_pose`, and `alpha_pose`.\n- `--part_to_show`: Prediction channel to visualize.\n- `--display 0`: Display window not opened. Useful for servers and/or to slightly speed up OpenPose.\n- `--num_gpu 2 --num_gpu_start 1`: Parallelize over this number of GPUs starting by the desired device id. By default it uses all the available GPUs.\n- `--model_pose MPI`: Model to use, affects number keypoints, speed and accuracy.\n- `--logging_level 3`: Logging messages threshold, range [0,255]: 0 will output any message & 255 will output none. Current messages in the range [1-4], 1 for low priority messages and 4 for important ones.\n\n\n\n\n\n## Advanced Quick Start\nIn order to learn about many more flags, check [doc/advanced/demo_advanced.md](advanced/demo_advanced.md).\n\n\n\n\n\n## Bug Solving\n### Improving Memory and Speed but Decreasing Accuracy\n**If you have a Nvidia GPU that does not goes out of memory when running, you should skip this step!**\n\n**Use `net_resolution` at your own risk**: If your GPU runs out of memory or you do not have a Nvidia GPU, you can reduce `--net_resolution` to improve the speed and reduce the memory requirements, but it will also highly reduce accuracy! The lower the resolution, the lower accuracy but better speed/memory.\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --net_resolution -1x320\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --net_resolution -1x256\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --net_resolution -1x196\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --net_resolution -1x128\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --net_resolution -1x320\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --net_resolution -1x256\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --net_resolution -1x196\nbin\\OpenPoseDemo.exe --video examples/media/video.avi --net_resolution -1x128\n```\n\nAdditional notes:\n- The default resolution is `-1x368`, any resolution smaller will improve speed.\n- The `-1` means that that the resolution will be adapted to maintain the aspect ratio of the input source. E.g., `-1x368`, `656x-1`, and `656x368` will result in the same exact resolution for 720p and 1080p input images.\n- For videos, using `-1` is recommended to let OpenPose find the ideal resolution. For a folder of images of different sizes, not adding `-1` and using images with completely different aspect ratios might result in out of memory issues. E.g., if a folder contains 2 images of resolution `100x11040` and `10000x368`. Then, using the default `-1x368` will result in the network output resolutions of `3x368` and `10000x368`, resulting in an obvious out of memory for the `10000x368` image.\n\n\n\n### Mac OSX Additional Step\n**If you are not using Mac, or you are using Mac with `CPU_only`, you can skip this section.**\n\nIf you are using a Mac and selected `OPENCL` support, and it has an AMD graphics card, that means that the machine has 2 GPUs that are not compatible with each other (AMD and Intel). Then, you will have to manually select one of them (the AMD one should be more powerful). To do that, first check which device your Graphics card is set under. Most likely, your AMD device will be device 2.\n```bash\nclinfo\n```\n\nFor any OpenPose command you run, add the following 2 flags to use your AMD card for acceleration (where `num_gpu_start` should be the ID number given above).\n```bash\n./build/examples/openpose/openpose.bin --num_gpu 1 --num_gpu_start 2\n```\n\nIf you only have an integrated Intel Graphics card, then it will most probably be the device 1. Then, always add the following 2 flags to use your AMD card for acceleration.\n```bash\n./build/examples/openpose/openpose.bin --num_gpu 1 --num_gpu_start 1\n```\n\n\n### FAQ\nCheck [doc/05_faq.md](05_faq.md) to see if you can find your error, issue, or concern.\n"
  },
  {
    "path": "doc/02_output.md",
    "content": "OpenPose Doc - Output\n====================================\n\n\n\n## Contents\n1. [UI and Visual Output](#ui-and-visual-output)\n2. [JSON-UI Mapping](#json-ui-mapping)\n    1. [Pose Output Format (BODY_25)](#pose-output-format-body_25)\n    2. [Pose Output Format (COCO)](#pose-output-format-coco)\n    3. [Face Output Format](#face-output-format)\n    4. [Hand Output Format](#hand-output-format)\n3. [JSON Output Format](#output-format)\n4. [Keypoints in C++/Python](#body-keypoints-in-c-python)\n    1. [Keypoint Ordering in C++/Python](#body-keypoint-ordering-in-c-python)\n    2. [Keypoint Format in Datum (Advanced)](#keypoint-format-in-datum-advanced)\n5. [Reading Saved Results](#reading-saved-results)\n6. [Advanced](#advanced)\n    1. [Camera Matrix Output Format](#camera-matrix-output-format)\n    2. [Heatmaps](#heatmaps)\n\n\n\n\n\n## UI and Visual Output\nThe visual GUI should show the original image with the poses blended on it, similarly to the pose of this gif:\n\n<p align=\"center\">\n    <img src=\"../.github/media/shake.gif\" width=\"720\">\n</p>\n\n\n\n\n\n## JSON-UI Mapping\nThe output of the JSON files consist of a set of keypoints, whose ordering is related with the UI output as follows:\n\n### Pose Output Format (BODY_25)\n<p align=\"center\">\n    <img src=\"../.github/media/keypoints_pose_25.png\" width=\"480\">\n</p>\n\n\n\n### Pose Output Format (COCO)\n<p align=\"center\">\n    <img src=\"../.github/media/keypoints_pose_18.png\" width=\"480\">\n</p>\n\n\n\n### Face Output Format\n<p align=\"center\">\n    <img src=\"../.github/media/keypoints_face.png\" width=\"480\">\n</p>\n\n\n\n### Hand Output Format\n<p align=\"center\">\n    <img src=\"../.github/media/keypoints_hand.png\" width=\"480\">\n</p>\n\n\n\n\n\n## JSON Output Format\nThere are 2 alternatives to save the OpenPose output. But both of them follow the keypoint ordering described in the section [Keypoint Ordering in C++/Python](#body-keypoints-in-c-python) section (which you should read next).\n\n1. The `--write_json` flag saves the people pose data into JSON files. Each file represents a frame, it has a `people` array of objects, where each object has:\n    1. `pose_keypoints_2d`: Body part locations (`x`, `y`) and detection confidence (`c`) formatted as `x0,y0,c0,x1,y1,c1,...`. The coordinates `x` and `y` can be normalized to the range [0,1], [-1,1], [0, source size], [0, output size], etc. (see the flag `--keypoint_scale` for more information), while the confidence score (`c`) in the range [0,1]. Additionally, the number of keypoints output in this array will remain consistent between JSON files.\n    2. `face_keypoints_2d`, `hand_left_keypoints_2d`, and `hand_right_keypoints_2d` are analogous to `pose_keypoints_2d` but applied to the face and hand parts.\n    3. `body_keypoints_3d`, `face_keypoints_3d`, `hand_left_keypoints_2d`, and `hand_right_keypoints_2d` are analogous but applied to the 3-D parts. They are empty if `--3d` is not enabled. Their format is `x0,y0,z0,c0,x1,y1,z1,c1,...`, where `c` is 1 or 0 depending on whether the 3-D reconstruction was successful or not.\n    4. `part_candidates` (optional and advanced): The body part candidates before being assembled into people. Empty if `--part_candidates` is not enabled (see that flag for more details).\n```\n{\n    \"version\":1.1,\n    \"people\":[\n        {\n            \"pose_keypoints_2d\":[582.349,507.866,0.845918,746.975,631.307,0.587007,...],\n            \"face_keypoints_2d\":[468.725,715.636,0.189116,554.963,652.863,0.665039,...],\n            \"hand_left_keypoints_2d\":[746.975,631.307,0.587007,615.659,617.567,0.377899,...],\n            \"hand_right_keypoints_2d\":[617.581,472.65,0.797508,0,0,0,723.431,462.783,0.88765,...]\n            \"pose_keypoints_3d\":[582.349,507.866,507.866,0.845918,507.866,746.975,631.307,0.587007,...],\n            \"face_keypoints_3d\":[468.725,715.636,715.636,0.189116,715.636,554.963,652.863,0.665039,...],\n            \"hand_left_keypoints_3d\":[746.975,631.307,631.307,0.587007,631.307,615.659,617.567,0.377899,...],\n            \"hand_right_keypoints_3d\":[617.581,472.65,472.65,0.797508,472.65,0,0,0,723.431,462.783,0.88765,...]\n        }\n    ],\n    // If `--part_candidates` enabled\n    \"part_candidates\":[\n        {\n            \"0\":[296.994,258.976,0.845918,238.996,365.027,0.189116],\n            \"1\":[381.024,321.984,0.587007],\n            \"2\":[313.996,314.97,0.377899],\n            \"3\":[238.996,365.027,0.189116],\n            \"4\":[283.015,332.986,0.665039],\n            \"5\":[457.987,324.003,0.430488,283.015,332.986,0.665039],\n            \"6\":[],\n            \"7\":[],\n            \"8\":[],\n            \"9\":[],\n            \"10\":[],\n            \"11\":[],\n            \"12\":[],\n            \"13\":[],\n            \"14\":[293.001,242.991,0.674305],\n            \"15\":[314.978,241,0.797508],\n            \"16\":[],\n            \"17\":[369.007,235.964,0.88765]\n        }\n    ]\n}\n```\n\n2. (Deprecated) `--write_keypoint` uses the OpenCV `cv::FileStorage` default formats, i.e., JSON (if OpenCV 3 or higher), XML, and YML. It only prints 2D body information (no 3D or face/hands).\n\n(Low level details) If you wanted to change anything in this file format (e.g., the output file name), you could check and/or modify [peopleJsonSaver.cpp](../src/openpose/filestream/peopleJsonSaver.cpp).\n\n\n\n\n## Keypoints in C++/Python\n### Keypoint Ordering in C++/Python\nThe body part mapping order of any body model (e.g., `BODY_25`, `COCO`, `MPI`) can be extracted from the C++ and Python APIs.\n\n- In C++, `getPoseBodyPartMapping(const PoseModel poseModel)` is available in [poseParameters.hpp](../include/openpose/pose/poseParameters.hpp):\n```\n// C++ API call\n#include <openpose/pose/poseParameters.hpp>\nconst auto& poseBodyPartMappingBody25 = getPoseBodyPartMapping(PoseModel::BODY_25);\nconst auto& poseBodyPartMappingCoco = getPoseBodyPartMapping(PoseModel::COCO_18);\nconst auto& poseBodyPartMappingMpi = getPoseBodyPartMapping(PoseModel::MPI_15);\nconst auto& poseBodyPartMappingBody25B = getPoseBodyPartMapping(PoseModel::BODY_25B);\nconst auto& poseBodyPartMappingBody135 = getPoseBodyPartMapping(PoseModel::BODY_135);\n\n// Result for BODY_25 (25 body parts consisting of COCO + foot)\n// const std::map<unsigned int, std::string> POSE_BODY_25_BODY_PARTS {\n//     {0,  \"Nose\"},\n//     {1,  \"Neck\"},\n//     {2,  \"RShoulder\"},\n//     {3,  \"RElbow\"},\n//     {4,  \"RWrist\"},\n//     {5,  \"LShoulder\"},\n//     {6,  \"LElbow\"},\n//     {7,  \"LWrist\"},\n//     {8,  \"MidHip\"},\n//     {9,  \"RHip\"},\n//     {10, \"RKnee\"},\n//     {11, \"RAnkle\"},\n//     {12, \"LHip\"},\n//     {13, \"LKnee\"},\n//     {14, \"LAnkle\"},\n//     {15, \"REye\"},\n//     {16, \"LEye\"},\n//     {17, \"REar\"},\n//     {18, \"LEar\"},\n//     {19, \"LBigToe\"},\n//     {20, \"LSmallToe\"},\n//     {21, \"LHeel\"},\n//     {22, \"RBigToe\"},\n//     {23, \"RSmallToe\"},\n//     {24, \"RHeel\"},\n//     {25, \"Background\"}\n// };\n```\n\n- You can also check them on Python:\n```\nposeModel = op.PoseModel.BODY_25\nprint(op.getPoseBodyPartMapping(poseModel))\nprint(op.getPoseNumberBodyParts(poseModel))\nprint(op.getPosePartPairs(poseModel))\nprint(op.getPoseMapIndex(poseModel))\n```\n\n\n\n### Keypoint Format in Datum (Advanced)\nThis section is only for advance users that plan to use the C++ API. Not needed for the OpenPose demo and/or Python API.\n\nThere are 3 different keypoint `Array<float>` elements in the `Datum` class:\n\n1. Array<float> **poseKeypoints**: In order to access person `person` and body part `part` (where the index matches `POSE_COCO_BODY_PARTS` or `POSE_MPI_BODY_PARTS`), you can simply output:\n```\n    // Common parameters needed\n    const auto numberPeopleDetected = poseKeypoints.getSize(0);\n    const auto numberBodyParts = poseKeypoints.getSize(1);\n    // Easy version\n    const auto x = poseKeypoints[{person, part, 0}];\n    const auto y = poseKeypoints[{person, part, 1}];\n    const auto score = poseKeypoints[{person, part, 2}];\n    // Slightly more efficient version\n    // If you want to access these elements on a huge loop, you can get the index\n    // by your own, but it is usually not faster enough to be worthy\n    const auto baseIndex = poseKeypoints.getSize(2)*(person*numberBodyParts + part);\n    const auto x = poseKeypoints[baseIndex];\n    const auto y = poseKeypoints[baseIndex + 1];\n    const auto score = poseKeypoints[baseIndex + 2];\n```\n2. Array<float> **faceKeypoints**: It is completely analogous to poseKeypoints.\n```\n    // Common parameters needed\n    const auto numberPeopleDetected = faceKeypoints.getSize(0);\n    const auto numberFaceParts = faceKeypoints.getSize(1);\n    // Easy version\n    const auto x = faceKeypoints[{person, part, 0}];\n    const auto y = faceKeypoints[{person, part, 1}];\n    const auto score = faceKeypoints[{person, part, 2}];\n    // Slightly more efficient version\n    const auto baseIndex = faceKeypoints.getSize(2)*(person*numberFaceParts + part);\n    const auto x = faceKeypoints[baseIndex];\n    const auto y = faceKeypoints[baseIndex + 1];\n    const auto score = faceKeypoints[baseIndex + 2];\n```\n3. std::array<Array<float>, 2> **handKeypoints**, where handKeypoints[0] corresponds to the left hand and handKeypoints[1] to the right one. Each handKeypoints[i] is analogous to poseKeypoints and faceKeypoints:\n```\n    // Common parameters needed\n    const auto numberPeopleDetected = handKeypoints[0].getSize(0); // = handKeypoints[1].getSize(0)\n    const auto numberHandParts = handKeypoints[0].getSize(1); // = handKeypoints[1].getSize(1)\n\n    // Easy version\n    // Left Hand\n    const auto xL = handKeypoints[0][{person, part, 0}];\n    const auto yL = handKeypoints[0][{person, part, 1}];\n    const auto scoreL = handKeypoints[0][{person, part, 2}];\n    // Right Hand\n    const auto xR = handKeypoints[1][{person, part, 0}];\n    const auto yR = handKeypoints[1][{person, part, 1}];\n    const auto scoreR = handKeypoints[1][{person, part, 2}];\n\n    // Slightly more efficient version\n    const auto baseIndex = handKeypoints[0].getSize(2)*(person*numberHandParts + part);\n    // Left Hand\n    const auto xL = handKeypoints[0][baseIndex];\n    const auto yL = handKeypoints[0][baseIndex + 1];\n    const auto scoreL = handKeypoints[0][baseIndex + 2];\n    // Right Hand\n    const auto xR = handKeypoints[1][baseIndex];\n    const auto yR = handKeypoints[1][baseIndex + 1];\n    const auto scoreR = handKeypoints[1][baseIndex + 2];\n```\n\n\n\n\n\n## Reading Saved Results\nWe use the standard formats (JSON, PNG, JPG, ...) to save our results, so there are many open-source libraries to read them in most programming languages (especially Python). For C++, you might want to check [include/openpose/filestream/fileStream.hpp](../include/openpose/filestream/fileStream.hpp). In particular, `loadData` (for JSON, XML and YML files) and `loadImage` (for image formats such as PNG or JPG) to load the data into cv::Mat format.\n\n\n\n\n\n## Advanced\n### Camera Matrix Output Format\nIf you need to use the camera calibration or 3D modules, the camera matrix output format is detailed in [doc/advanced/calibration_module.md#camera-matrix-output-format](advanced/calibration_module.md#camera-matrix-output-format).\n\n\n\n### Heatmaps\nIf you need to use heatmaps, check [doc/advanced/heatmap_output.md](advanced/heatmap_output.md).\n"
  },
  {
    "path": "doc/03_python_api.md",
    "content": "OpenPose Doc - Python API\n====================================\n\n## Contents\n1. [Introduction](#introduction)\n2. [Advance Introduction (Optional)](#advance-introduction-optional)\n3. [Compatibility](#compatibility)\n4. [Installation](#installation)\n5. [Testing And Developing](#testing-and-developing)\n6. [Exporting Python OpenPose](#exporting-python-openpose)\n7. [Common Issues](#common-issues)\n\n\n\n## Introduction\nAlmost all the OpenPose functionality, but in Python!\n\nWhen should you look at the [Python](03_python_api.md) or [C++](04_cpp_api.md) APIs? If you want to read a specific input, and/or add your custom post-processing function, and/or implement your own display/saving.\n\nYou should be familiar with the [**OpenPose Demo**](01_demo.md) and the main OpenPose flags before trying to read the C++ or Python API examples. Otherwise, it will be way harder to follow.\n\n\n\n## Advance Introduction (Optional)\nThis module exposes a Python API for OpenPose. It is effectively a wrapper that replicates most of the functionality of the [op::Wrapper class](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/include/openpose/wrapper/wrapper.hpp) and allows you to populate and retrieve data from the [op::Datum class](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/include/openpose/core/datum.hpp) using standard Python and Numpy constructs.\n\nThe Python API is analogous to the C++ function calls. You may find them in [python/openpose/openpose_python.cpp#L194](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/python/openpose/openpose_python.cpp#L194).\n\nThe Python API is rather simple: `op::Array<float>` and `cv::Mat` objects get casted to numpy arrays automatically. Every other data structure based on the standard library is automatically converted into Python objects. For example, an `std::vector<std::vector<float>>` would become `[[item, item], [item, item]]`, etc. We also provide a casting of `op::Rectangle` and `op::Point` which simply expose setter getter for [x, y, width, height], etc.\n\n\n\n\n\n## Compatibility\nThe OpenPose Python module is compatible with both Python 2 and Python 3 (default and recommended). In addition, it will also run in all OpenPose compatible operating systems. It uses [Pybind11](https://github.com/pybind/pybind11) for mapping between C++ and Python datatypes.\n\nTo compile, enable `BUILD_PYTHON` in CMake-gui, or run `cmake -DBUILD_PYTHON=ON ..` from your build directory. In Windows, make sure you compile the whole solution (clicking the green play button does not compile the whole solution!). You can do that by right-click on the OpenPose project solution, and clicking in `Build Solution` (or individually building the PyOpenPose module).\n\nPybind selects the latest version of Python by default (Python 3). To use Python 2, change `PYTHON_EXECUTABLE` and `PYTHON_LIBRARY` flags in CMake-gui to your desired Python version.\n\n```\n# Ubuntu\nPYTHON_EXECUTABLE=/usr/bin/python2.7\nPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7m.so\n```\n\n```\n# Mac OSX\nPYTHON_EXECUTABLE=/usr/local/bin/python2.7\nPYTHON_LIBRARY=/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7m.dylib\n```\n\n```\n:: Windows\nPYTHON_EXECUTABLE=C:/Users/user/AppData/Local/Programs/Python/Python27/python.exe\n```\n\nIf run via the command line, you may need to run cmake twice in order for this change to take effect.\n\n\n\n## Installation\nMake sure you followed the Python steps in [doc/installation/0_index.md#cmake-configuration](installation/0_index.md#cmake-configuration).\n\n\n\n## Testing And Developing\nAll the Python examples from the Tutorial API Python module can be found in `build/examples/tutorial_api_python` in your build folder. Navigate directly to this path to run examples.\n\n```\n# From command line\ncd build/examples/tutorial_api_python\n\n# Python 3 (default version)\npython3 01_body_from_image.py\npython3 02_whole_body_from_image.py\n# python3 [any_other_python_example.py]\n\n# Python 2\npython2 01_body_from_image.py\npython2 02_whole_body_from_image.py\n# python2 [any_other_python_example.py]\n```\n\nFor quick prototyping, you can simply duplicate and rename any of the existing sample files in `build/examples/tutorial_api_python` within that same folder and start building in there. These files are copied from [existing example files](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples/tutorial_api_python) on compiling time. 2 alternatives:\n- You can either duplicate and create your files in [examples/tutorial_api_python/](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples/tutorial_api_python), but you will have to recompile OpenPose every time you make changes to your Python files so they are copied over the `build/` folder.\n- Or you can directly edit them in `build/examples/tutorial_api_python`. This does not require rebuilding, but cleaning OpenPose will remove the whole `build/` folder, so make sure to back your files up!\n\n\n\n## Exporting Python OpenPose\nNote: This step is only required if you are moving the `*.py` files outside their original location, or writing new `*.py` scripts outside `build/examples/tutorial_api_python`.\n\nUbuntu/OSX:\n\n- Option a, installing OpenPose: On an Ubuntu or OSX based system, you could install OpenPose by running `sudo make install`, you could then set the OpenPose path in your python scripts to the OpenPose installation path (default: `/usr/local/python`) and start using OpenPose at any location. Take a look at `build/examples/tutorial_api_python/01_body_from_image.py` for an example.\n- Option b, not installing OpenPose: To move the OpenPose Python API demos to a different folder, ensure that the line `sys.path.append('{OpenPose_path}/python')` is properly set in your `*.py` files, where `{OpenPose_path}` points to your build folder of OpenPose. Take a look at `build/examples/tutorial_api_python/01_body_from_image.py` for an example.\n\nWindows:\n\n- Ensure that the folder  `build/x{86/64}/Release`and `build/bin` are copied along with `build/python` As noted in the example, the path for these can be changed in the following two variables:\n\n  ```\n  sys.path.append(dir_path + '/../../python/openpose/Release);\n  os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../{x86/x64}/Release;' +  dir_path + '/../../bin;'\n  ```\n\n\n\n## Common Issues\n### Do not use PIL\nIn order to read images in Python, make sure to use OpenCV (do not use PIL). We found that feeding a PIL image format to OpenPose results in the input image appearing in grey and duplicated 9 times (so the output skeleton appear 3 times smaller than they should be, and duplicated 9 times).\n\n\n### Cannot Import Name PyOpenPose\nThe error in general is that PyOpenPose cannot be found (an error similar to: `ImportError: cannot import name pyopenpose`). Ensure first that `BUILD_PYTHON` flag is set to ON. If the error persists, check the following:\n\nIn the script you are running, check for the following line, and run the following command in the same location as where the file is\n\n**Ubuntu/OSX:**\n\n`sys.path.append('../../python');`\n\n```\nls ../../python/openpose\n```\n\nCheck the contents of this location. It should contain one of the following files:\n\n```\npyopenpose.cpython-35m-x86_64-linux-gnu.so\npyopenpose.so\n```\n\nIf you do not have any one of those, you may not have compiled openpose successfully, or you may be running the examples, not from the build folder but the source folder. If you have the first one, you have compiled PyOpenPose for Python 3, and have to run the scripts with `python3`, and vice versa for the 2nd one. Follow the testing examples above for exact commands.\n\n**Windows:**\n\nProblem 1: If you are in Windows, and you fail to install the required third party Python libraries, it might print an error similar to: `Exception: Error: OpenPose library could not be found. Did you enable BUILD_PYTHON in CMake and have this Python script in the right folder?`. From GitHub issue #941:\n```\nI had a similar issue with Visual Studio (VS). I am pretty sure that the issue is that while you are compiling OpenPose in VS, it tries to import cv2 (python-opencv) and it fails. So make sure that if you open cmd.exe and run Python, you can actually import cv2 without errors. I could not, but I had cv2 installed in a IPython environment (Anaconda), so I activated that environment, and then ran (change this to adapt it to your VS version and location of OpenPose.sln):\n\nC:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Enterprise\\MSBuild.exe C:\\path\\to\\OpenPose.sln\n```\n\nProblem 2: Python for Openpose needs to be compiled in Release mode for now. This can be done in [Visual Studio](https://cdn.stereolabs.com/docs/getting-started/images/release_mode.png). Once that is done check this line:\n\n`sys.path.append(dir_path + '/../../python/openpose/Release');`\n\n```\ndir ../../python/openpose/Release\n```\n\nCheck the contents of this location. It should contain one of the following files:\n\n```\npyopenpose.cp36-win_amd64.pyd\npyopenpose.pyd\n```\n\nIf such a folder does not exist, you need to compile in Release mode as seen above. If you have the first one, you have compiled PyOpenPose for Python 3, and have to run the scripts with `python3`, and vice versa for the 2nd one. Follow the testing examples above for exact commands. If that still does not work, check this line:\n\n`os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'`\n\n```\ndir ../../x64/Release\ndir ../../bin\n```\n\nEnsure that both of these paths exist, as PyOpenPose needs to reference those libraries. If they don't exist, change the path so that they point to the correct location in your build folder.\n"
  },
  {
    "path": "doc/04_cpp_api.md",
    "content": "OpenPose Doc - C++ API\n====================================\n\n## Contents\n1. [Introduction](#introduction)\n2. [Advance Introduction (Optional)](#advance-introduction-optional)\n3. [Compatibility](#compatibility)\n4. [Installation](#installation)\n5. [Testing And Developing](#testing-and-developing)\n6. [Exporting Python OpenPose](#exporting-python-openpose)\n7. [Common Issues](#common-issues)\n\n\n\n## Introduction\nExtend the OpenPose functionality with all the power and performance of C++!\n\nWhen should you look at the [Python](03_python_api.md) or [C++](04_cpp_api.md) APIs? If you want to read a specific input, and/or add your custom post-processing function, and/or implement your own display/saving.\n\nYou should be familiar with the [**OpenPose Demo**](01_demo.md) and the main OpenPose flags before trying to read the C++ or Python API examples. Otherwise, it will be way harder to follow.\n\n\n## Adding your Custom Code\nOnce you are familiar with the [command line demo](01_demo.md), then you should explore the different C++ examples in the [OpenPose C++ API](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples/tutorial_api_cpp) folder.\n\nFor quick prototyping, you can simply **duplicate and rename any of the existing sample files** from the [OpenPose C++ API](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples/tutorial_api_cpp) folder into the [examples/user_code/](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples/user_code) folder and start building in there. Add the name of your new file(s) into the [CMake file from that folder](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/user_code/CMakeLists.txt), and CMake will automatically compile it together with the whole OpenPose project.\n\nSee [examples/user_code/README.md](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/user_code/README.md) for more details.\n"
  },
  {
    "path": "doc/05_faq.md",
    "content": "OpenPose Doc - Frequently Asked Questions (FAQ)\n============================================\n\n## Contents\n1. [FAQ](#faq)\n    1. [Errors](#errors)\n        1. [Download Server Down](#download-server-down)\n        2. [Out of Memory Error](#out-of-memory-error)\n        3. [Video/Webcam Not Working](#videowebcam-not-working)\n        4. [Cannot Find OpenPose.dll Error](#cannot-find-openposedll-error-windows)\n        5. [Free Invalid Pointer Error](#free-invalid-pointer-error)\n        6. [Source Directory does not Contain CMakeLists.txt (Windows)](#source-directory-does-not-contain-cmakeliststxt-windows)\n        7. [Always Zero People Detected](#always-zero-people-detected)\n        8. [Very Few People Detected](#very-few-people-detected)\n        9. [Check Failed for ReadProtoFromBinaryFile (Failed to Parse NetParameter File)](#check-failed-for-readprotofrombinaryfile-failed-to-parse-netparameter-file)\n        10. [3D OpenPose Returning Wrong Results: 0, NaN, Infinity, etc.](#3d-openpose-returning-wrong-results-0-nan-infinity-etc)\n        11. [Protobuf Clip Param Caffe Error](#protobuf-clip-param-caffe-error)\n        12. [The Human Skeleton Looks like Dotted Lines Rather than Solid Lines](#the-human-skeleton-looks-like-dotted-lines-rather-than-solid-lines)\n        13. [CUDA_cublas_device_LIBRARY Not Found](#cuda_cublas_device_library-not-found)\n        14. [CMake-GUI Error While Getting Default Caffe](#cmake-gui-error-while-getting-default-caffe)\n        15. [Libgomp Out of Memory Error](#libgomp-out-of-memory-error)\n        16. [Runtime Error with Turing GPU (Tesla T4) or Volta GPU](#runtime-error-with-turing-gpu-teslat4-or-volta-gpu)\n        17. [Obscure CMake Error about Caffe or Pybind](#obscure-cmake-error-about-caffe-or-pybind).\n    2. [Speed Performance Issues](#speed-performance-issues)\n        1. [Speed Up, Memory Reduction, and Benchmark](#speed-up-memory-reduction-and-benchmark)\n        2. [How to Measure the Latency Time?](#how-to-measure-the-latency-time)\n        3. [CPU Version Too Slow](#cpu-version-too-slow)\n        4. [Profiling Speed and Estimating FPS without Display](#profiling-speed-and-estimating-fps-without-display)\n        5. [Webcam Slower than Images](#webcam-slower-than-images)\n    3. [Accuracy Issues](#speed-performance-issues)\n        1. [Is Maximum Accuracy Configuration Possible on Lower End GPUs?](#is-maximum-accuracy-configuration-possible-on-lower-end-gpus)\n    4. [Other FAQ](#other-faq)\n        1. [How Should I Link my IP Camera?](#how-should-i-link-my-ip-camera)\n        2. [Difference between BODY_25 vs. COCO vs. MPI](#difference-between-body_25-vs-coco-vs-mpi)\n        3. [Huge RAM Usage](#huge-ram-usage)\n\n\n\n\n\n## FAQ\n### Errors\n#### Download Server Down\n**Q: The download server is down, Download Hash mismatch, Error 502: Bad Gateway, etc. I.e., I cannot download the OpenPose models and/or 3rd party libraries.**\n**A**: The are 2 alternatives. Option 1 (recommended): Download the links from [1602#issuecomment-641653411](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1602#issuecomment-641653411) and download them in the places indicated by [doc/1_prerequisites.md](1_prerequisites.md). Option 2: If you downloaded the models and dependencies to some local server, you could set the advanced CMake property `DOWNLOAD_SERVER` to link OpenPose to your local mirror server instead.\n\n\n\n#### Out of Memory Error\n**Q: Out of memory error** - I get an error similar to: `Check failed: error == cudaSuccess (2 vs. 0)  out of memory`.\n\n**A**: Make sure you have a GPU with at least 4 GB of memory. If your GPU is between 2 and 4 GB, it should be fine for body-only settings, but you can also reduce the `--net_resolution` if it does not fit (check [Speed Up, Memory Reduction, and Benchmark](#speed-up-memory-reduction-and-benchmark) for the consequences of this).\n\n(Only if you are compiling OpenPose by yourself, this does not apply to the portable OpenPose binaries for Windows because they already include cuDNN): If you have a GPU with >= 4 GB of memory, and you still face this error, most probably cuDNN is not installed/enabled. The default Caffe model uses >12 GB of GPU memory, cuDNN reduces it to ~2.2 GB for BODY_25 (default) and ~1.5 GB for COCO (`--model_pose COCO`). Note that you still need at least about 2.2 GB free for the default OpenPose to run. I.e., GPUs with only 2 GB will not fit the default OpenPose, and you will have to either switch to the `COCO` model (slower and less accurate), or reduce the `--net_resolution` (faster speed but also lower accuracy).\n\nAlso, hands and face increases the GPU memory requeriments, and 4 GB GPUs might run a bit short in some cases.\n\n\n\n#### Video/Webcam Not Working\n**Q: Video and/or webcam are not working** - Using a folder with images does work, but the video and/or the webcam do not. Note: often on Windows.\n\n**A**: OpenCV has some issues with some camera drivers and video codecs (specially on Windows). Follow the same steps as the `Webcam is slow` question to test the webcam is working. After re-compiling OpenCV, you can also try this [OpenCV example for video](http://docs.opencv.org/3.0-beta/modules/videoio/doc/reading_and_writing_video.html).\n\n\n\n#### Cannot Find OpenPose.dll Error (Windows)\n**Q: System cannot find the file specified (Openpose.dll) error when trying to release** - Using a folder with images does work, but the video and/or the webcam do not. Note: often on Windows.\n\n**A**: Visual Studio (VS) and the [doc/installation/0_index.md](installation/0_index.md) section is only intended if you plan to modify the OpenPose code or integrate it with another library or project. If you just want to use the OpenPose demo, simply follow [doc/installation/0_index.md#windows-portable-demo](installation/0_index.md#windows-portable-demo) and download the OpenPose binaries in the [Releases](https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases) section.\n\nIf you need to compile it with Visual Studio (VS), then keep reading. In this error, VS is simply saying that there were errors while compiling the OpenPose library. Try compiling only the OpenPose library (not the demo), by right clicking on it, then `Set as StartUp Project`, and finally right click + `Build`. Then, at the bottom left part of VS, press `Error list` and then you should see which errors VS encountered while compiling. In that way, VS gives you the exact error so you can know it and share the exact issue.\n\nIf it didn't have any error, then setting OpenPoseDemo as main project again and F5 (or green play button) should work.\n\nNote: OpenPose library is not an executable, but a library. So instead clicking F5 or the green button instead of `Build` will give you an error similar to `openpose.dll is not a valid Win32 application`.\n\n\n\n#### Free Invalid Pointer Error\n**Q: I am getting an error of the type: munmap_chunk()/free/invalid pointer.**\n\n**A**: In order to run OpenCV 3.X and Caffe simultaneously, [OpenCV must be compiled without `WITH_GTK` and with `WITH_QT` flags](https://github.com/BVLC/caffe/issues/5282#issuecomment-306063718). On Ubuntu 16.04 the qt5 package is \"qt5-default\" and the OpenCV cmake option is WITH_QT.\n\n\n\n#### Source Directory does not Contain CMakeLists.txt (Windows)\n**Q: I am getting an error of the type: `The source directory {path to file} does not contain a CMakeLists.txt file.`.**\n\n**A**: You might not have writing access to that folder. If you are in Windows, you should not try to install it in `Program Files`.\n\n\n\n#### Always Zero People Detected\n**Q: Always 0 people detected and displayed in default video and images.**\n\n**A**: This answer assumes that never a single person is detected. If in your case it works sometimes, then check [Always Zero People Detected](#always-zero-people-detected). This always-0-people problem usually occurs in 2 situations: 1) When you selection `--num_gpu 0`, and 2) when the caffemodel has not been properly downloaded. E.g., if the connection drops when downloading the models.\n\nFor problem 1, setting `--num_gpu 0` means that no processing is done, so you can use this setting e.g., to record webcam. This functionality is kept for back-compatibility. You are most probably trying to run on CPU-only mode, for that, install OpenPose in CPU-only mode following [doc/installation/0_index.md](installation/0_index.md).\n\nFor problem 2, try the following solutions (in this order):\n\n1. Assuming that default OpenPose (i.e., BODY_25 model) failed, try with `--model_pose COCO` and `--model_pose MPII` models. If any of them work, the `caffemodel` files of the other models were corrupted while being downloaded. Otherwise, it will most probably be a Caffe/protobuf issue.\n2. Assuming that the model is corrupted, remove the current models in the model folder, and download them manually from the links in [doc/installation/0_index.md](installation/0_index.md). Alternatively, remove them and re-run Cmake again. If this does not work, try downloading the COCO_25 model from the browser following the download link on this [Dropbox link](https://www.dropbox.com/s/03r8pa8sikrqv62/pose_iter_584000.caffemodel).\n3. If none of the OpenPose models are working, make sure Caffe is working properly and that you can run the Caffe examples with other caffemodel / prototxt files.\n\n\n\n#### Very Few People Detected\n**Q: Low detection rate. It can detect the person on some images (usually higher contrast, with bigger people), but it will fail for most of images with low resolution or small people.**\n\n**A**: Images with low resolution, or with people too tiny will simply not work too well. However, it can be highly improved by using the maximum accuracy configuration detailed in [doc/01_demo.md#maximum-accuracy-configuration](01_demo.md#maximum-accuracy-configuration).\n\n\n\n#### Check Failed for ReadProtoFromBinaryFile (Failed to Parse NetParameter File)\n**Q: I am facing an error similar to:** `Check failed: ReadProtoFromBinaryFile(param_file, param) Failed to parse NetParameter file: models/pose/body_25/pose_iter_584000.caffemodel`\n\n**A**: Same answer than for [Always Zero People Detected](#always-zero-people-detected).\n\n\n\n#### 3D OpenPose Returning Wrong Results: 0, NaN, Infinity, etc.\n**Q: 3D OpenPose is returning wrong results.**\n\n**A**: 99.99% of the cases, this is due to wrong or poor calibration. Repeat the calibration making sure that the final reprojection error is about or less than 0.1 pixels.\n\n\n\n#### Protobuf Clip Param Caffe Error\n**Q: Runtime error similar to:**\n```\n[libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type \"caffe.NetParameter\" because it is missing required fields: layer[0].clip_param.min, layer[0].clip_param.max\nF0821 14:26:29.665053 22812 upgrade_proto.cpp:97] Check failed: ReadProtoFromBinaryFile(param_file, param) Failed to parse NetParameter file: models/pose/body_25/pose_iter_584000.caffemodel\n```\n\n**A**: This error has been solved in the latest OpenPose versions. Completely remove OpenPose and re-download the latest version (just cleaning the compilation or removing the `build/` folder will not work).\n\nIf you wanna use your custom Caffe and it has this error: This error only happens in some Ubuntu machines. Following #787, compile your own Caffe with an older version of it. The hacky (quick but not recommended way) is to follow [#787#issuecomment-415476837](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/787#issuecomment-415476837), the elegant way (compatible with future OpenPose versions) is to build your own Caffe independently, following [doc/installation/0_index.md#custom-caffe-ubuntu-only](installation/0_index.md#custom-caffe-ubuntu-only).\n\n\n\n#### The Human Skeleton Looks like Dotted Lines Rather than Solid Lines\n**Q**: When I use the demo to handle my images，the skeletons are dotted lines. I want to know how to make them to be solid lines.\n\n**A**: The reason is that your input image size is too small. You can either 1) manually rescale your images up or 2) use a bigger `--output_resolution` so OpenPose will resize them up.\n\n\n\n#### CUDA_cublas_device_LIBRARY Not Found\n**Q**: I encounter an error similar to the following:\n```\nCMake Error: The following variables are used in this project, but they are set to NOTFOUND.\nPlease set them or make sure they are set and tested correctly in the CMake files:\nCUDA_cublas_device_LIBRARY (ADVANCED)\n    linked by target \"caffe\" in directory /home/jakebmalis/Documents/openpose/3rdparty/caffe/src/caffe\n```\n\n**A**: Make sure to download and install CMake-GUI following the [doc/1_prerequisites.md](1_prerequisites.md) section. This is a known problem with CMake-GUI versions from 3.8 to 3.11 (unfortunately, default Ubuntu 18 CMake-GUI uses 3.10). You will need a CMake version >= 3.12.\n\n\n\n#### CMake-GUI Error While Getting Default Caffe\n**Q**: It seems to me CMake-gui does not download Caffe at all. I tried to wipe everything and try to install OpenPose again, but received the same mistake. I also tried to see if cmake follows the ifs in the CMakeLists.txt correctly and reaches the branches where he establishes that Caffe needs to be downloaded and it seems to me it does so.\n\n**A**: There are 2 solutions to try. First, if you were using an old OP version and you just updated it, you should simply completely remove that OpenPose folder, and then re-download and re-compile OpenPose. Second, and only if after re-cloning master and running CMake-GUI the `3rdparty/caffe/` folder stays empty, manually trigger the git submodules to update. So the clone step becomes:\n```\ngit clone https://github.com/CMU-Perceptual-Computing-Lab/openpose\ncd openpose\n\ngit submodule init\ngit submodule update\n```\n\n\n\n\n#### Libgomp Out of Memory Error\n**Q**: When I start OpenPose, I receive an error similar to the following: `libgomp: Out of memory allocating 927712937064 bytes`.\n\n**A**: Reinstall and upgrade from scratch CUDA, cuDNN, Python, and OpenCV (GitHub issue #1160).\n\n\n\n\n#### Runtime Error with Turing GPU (Tesla T4) or Volta GPU\n**Q**: When I start OpenPose, I receive a runtime error for new GPU architectures.\n\n**A**: To solve this problem, 1) make sure you are using CUDA 10 or higher, and 2) change line 7 in `{OPENPOSE_PATH}/3rdparty/caffe/cmake/Cuda.cmake`, from `set(Caffe_known_gpu_archs \"30 35 50 52 60 61\")` to `set(Caffe_known_gpu_archs \"30 35 50 52 60 61 75\")`.\n\n\n\n\n#### Obscure CMake Error about Caffe or Pybind\n**Q:** There appear some weird and obscure errors on CMake about Caffe and/or Pybind.\n\n**A**: Check [doc/installation/0_index.md](installation/0_index.md) to run the `git submodule` command, i.e.,\n```\ngit submodule update --init --recursive --remote\n```\n\n\n\n\n\n### Speed Performance Issues\n#### Speed Up, Memory Reduction, and Benchmark\n**Q: Low speed** - OpenPose is quite slow, is it normal? How can I speed it up?\n\n**A**: Check [doc/06_maximizing_openpose_speed.md](06_maximizing_openpose_speed.md) to discover the approximate speed of your graphics card and some speed tips.\n\n\n\n#### How to Measure the Latency Time?\n**Q: How to measure/calculate/estimate the latency/lag time?**\n\n**A**: [Profile](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/06_maximizing_openpose_speed.md#profiling-speed) the OpenPose speed. For 1-GPU or CPU-only systems (use `--disable_multi_thread` for simplicity in multi-GPU systems for latency measurement), the latency will be roughly the sum of all the reported measurements.\n\n\n\n#### CPU Version Too Slow\n**Q: The CPU version is insanely slow compared to the GPU version.**\n\n**A**: Check [doc/06_maximizing_openpose_speed.md#cpu-version](06_maximizing_openpose_speed.md#cpu-version) to discover the approximate speed and some speed tips.\n\n\n\n#### Profiling Speed and Estimating FPS without Display\nCheck the [doc/06_maximizing_openpose_speed.md#profiling-speed](06_maximizing_openpose_speed.md#profiling-speed) section.\n\n\n\n#### Webcam Slower than Images\n**Q: Webcam is slow** - Using a folder with images matches the speed FPS benchmarks, but the webcam has lower FPS. Note: often on Windows.\n\n**A**: OpenCV has some issues with some camera drivers (specially on Windows). The first step should be to compile OpenCV by your own and re-compile OpenPose after that (following the [doc/installation/0_index.md#reinstallation](installation/0_index.md#reinstallation) section). If the speed is still slower, you can better debug it by running a webcam OpenCV example (e.g. [this C++ example](http://answers.opencv.org/question/1/how-can-i-get-frames-from-my-webcam/)). If you are able to get the proper FPS with the OpenCV demo but OpenPose is still low, then let us know!\n\n\n\n\n\n### Accuracy Issues\n#### Is Maximum Accuracy Configuration Possible on Lower End GPUs?\n**Q**: I've read that this command provides the most accurate results possible on Openpose so far: https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/01_demo.md#maximum-accuracy-configuration. However, a 8GB GPU (e.g., 1080 or 2080) will run out of memory, is there any method to achieve the same accuracy on GPU using less memory even if it meant sacrificing speed?\n\n**A**: Unfortunately no, there is no way at the moment. Caffe just takes so much memory doing that. You can try with `--scale_number 3` instead of 4, reducing a bit the `net_resolution` (e.g. `720` vs. `736`) and starting the computer without GUI (which also takes about 1GB of memory just to keep the computer GUI running).\n\n\n\n\n\n### Other FAQ\n#### How Should I Link my IP Camera?\n**Q: How Should I Link my IP Camera with http protocol?**\n\n**A**: Usually with `http://CamIP:PORT_NO./video?x.mjpeg`.\n\n\n\n#### Difference between BODY_25 vs. COCO vs. MPI\nCOCO model will eventually be removed. BODY_25 model is faster, more accurate, and it includes foot keypoints. However, `COCO` requires less memory on GPU (being able to fit into 2GB GPUs with the default settings) and it runs faster on CPU-only mode. `MPI` model is only meant for people requiring the MPI-keypoint structure. It is also slower than BODY_25 and far less accurate.\n\nKey differences:\n- `BODY_25` is the fastest one on the GPU, the most accurate one, and the one with the highest number of keypoints (including foot keypoints!), highly recommended. It also uses the most amount of RAM/GPU memory.\n- `COCO` is faster than `BODY_25` on the CPU but slower on the GPU and less accurate.\n- `MPI` is the fastest on the CPU but the least accurate of all 3.\n\n\n\n#### Huge RAM Usage\n**Q**: During the execution of the demo, the CPU usage oscillates between 50 and 99%, but the RAM is almost at 100%.\n\n**A**: Highly reducing the `--net_resolution` and following the tips in the [Speed Up, Memory Reduction, and Benchmark](#speed-up-memory-reduction-and-benchmark) section are the only way to reduce the RAM usage. Alternatively, you can disable `USE_MKL` in CMake, which will highly reduce the RAM usage of the Caffe version, but it might also reduce the program speed.\n"
  },
  {
    "path": "doc/06_maximizing_openpose_speed.md",
    "content": "OpenPose Doc - Maximizing the OpenPose Speed\n========================================================================================\n\n## Contents\n1. [OpenPose Benchmark](#openpose-benchmark)\n2. [Profiling Speed](#profiling-speed)\n3. [CPU Version](#cpu-version)\n4. [Speed Up Preserving Accuracy](#speed-up-preserving-accuracy)\n5. [Speed Up and Memory Reduction](#speed-up-and-memory-reduction)\n\n\n\n\n\n## OpenPose Benchmark\nCheck the [OpenPose Benchmark](https://docs.google.com/spreadsheets/d/1-DynFGvoScvfWDA1P4jDInCkbD4lg0IKOYbXgEq0sK0/edit#gid=0) to discover the approximate expected speed of your graphics card.\n\n\n\n### CPU Version\nThe CPU version runs at about 0.3 FPS on the COCO model, and at about 0.1 FPS (i.e., about 15 sec / frame) on the default BODY_25 model. Switch to COCO model and/or reduce the `net_resolution` as indicated above. Contradictory fact: BODY_25 model is about 5x slower than COCO on CPU-only version, but it is about 40% faster on GPU version.\n\nOn Ubuntu (for OS versions older than 20), you can also boost CPU-only speed by 2-3x by following [installation/0_index.md#faster-cpu-version-ubuntu-only](installation/0_index.md#faster-cpu-version-ubuntu-only).\n\n\n\n### Profiling Speed\nOpenPose displays the FPS in the basic GUI. However, more complex speed metrics can be obtained from the command line while running OpenPose. In order to obtain those, compile OpenPose with the `PROFILER_ENABLED` flag on CMake-gui. OpenPose will automatically display time measurements for each subthread after processing `F` frames (by default `F = 1000`, but it can be modified with the `--profile_speed` flag, e.g. `--profile_speed 100`).\n\n- Time measurement for 1 graphic card: The FPS will be the slowest time displayed in your terminal command line (as OpenPose is multi-threaded). Times are in milliseconds, so `FPS = 1000/millisecond_measurement`.\n- Time measurement for >1 graphic cards: Assuming `n` graphic cards, you will have to wait up to `n` x `F` frames to visualize each graphic card speed (as the frames are split among them). In addition, the FPS would be: `FPS = minFPS(speed_per_GPU/n, worst_time_measurement_other_than_GPUs)`. For < 4 GPUs, this is usually `FPS = speed_per_GPU/n`.\n\nMake sure that `wPoseExtractor` time is the slowest timing. Otherwise the input producer (video/webcam codecs issues with OpenCV, images too big, etc.) or the GUI display (use OpenGL support as detailed in the next section (`Speed Up Preserving Accuracy`) might not be optimized.\n\n\n\n## Speed Up Preserving Accuracy\nSome speed tips to maximize the OpenPose runtime speed while preserving the accuracy (do not expect miracles, but it might help a bit boosting the framerate):\n\n    1. Enable the `WITH_OPENCV_WITH_OPENGL` flag in CMake to have a much faster GUI display. It reduces the lag and increase the speed of displaying images by telling OpenCV to render the images using OpenGL support. This speeds up display rendering about 3x. E.g., it reduces from about 30 msec to about 3-10 msec the display time for HD resolution images. It requires OpenCV to be compiled with OpenGL support and it provokes a visual aspect-ratio artifact when rendering a folder with images of different resolutions. Note: Default OpenCV in Ubuntu 16 (from apt-get install) does have OpenGL support included. Nevertheless, default one from Ubuntu 18 and the Windows portable binaries do not.\n    2. Change GPU rendering by CPU rendering to get approximately +0.5 FPS (`--render_pose 1`).\n    3. Use cuDNN 5.1 or 7.2 (cuDNN 6 is ~10% slower).\n    4. Use the `BODY_25` model for simultaneously maximum speed and accuracy (both COCO and MPII models are slower and less accurate). But it does increase the GPU memory, so it might go out of memory more easily in low-memory GPUs.\n    5. Enable the AVX flag in CMake-GUI (if your computer supports it).\n\n\n\n## Speed Up and Memory Reduction\nSome speed tips to highly maximize the OpenPose speed, but keep in mind the accuracy trade-off:\n\n    1. Reduce the `--net_resolution` (e.g., to 320x176) (lower accuracy). Note: For maximum accuracy, follow [doc/01_demo.md#maximum-accuracy-configuration](01_demo.md#maximum-accuracy-configuration).\n    2. For face, reduce the `--face_net_resolution`. The resolution 320x320 usually works pretty decently.\n    3. Points 1-2 will also reduce the GPU memory usage (or RAM memory for CPU version).\n    4. Use the `BODY_25` model for maximum speed. Use `MPI_4_layers` model for minimum GPU memory usage (but lower accuracy, speed, and number of parts).\n"
  },
  {
    "path": "doc/07_major_released_features.md",
    "content": "OpenPose Doc - Major Released Features\n====================================\n\n- Nov 2020: [**Python API improved and included on Windows portable binaries**](https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases)!\n- Nov 2020: [Compatibility with Nvidia 30XX cards, CUDA 11, and Ubuntu 20](installation/0_index.md)!\n- Sep 2019: [**Training code released**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_train)!\n- Jan 2019: [**Unity plugin released**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_unity_plugin)!\n- Jan 2019: [**Improved Python API**](doc/03_python_api.md) released! Including body, face, hands, and all the functionality of the C++ API!\n- Dec 2018: [**Foot dataset released**](https://cmu-perceptual-computing-lab.github.io/foot_keypoint_dataset) and [**new paper released**](https://arxiv.org/abs/1812.08008)!\n- Sep 2018: [**Experimental tracker**](01_demo.md#tracking)!\n- Jun 2018: [**Combined body-foot model released! 40% faster and 5% more accurate**](installation/0_index.md)!\n- Jun 2018: [**Python API**](03_python_api.md) released!\n- Jun 2018: [**OpenCL/AMD graphic card version**](installation/0_index.md) released!\n- Jun 2018: [**Calibration toolbox**](advanced/calibration_module.md) released!\n- Jun 2018: [**Mac OSX version (CPU)**](installation/0_index.md) released!\n- Mar 2018: [**CPU version**](installation/0_index.md)!\n- Mar 2018: [**3-D keypoint reconstruction module**](advanced/3d_reconstruction_module.md) (from multiple camera views)!\n- Sep 2017: [**CMake**](installation/0_index.md) installer and **IP camera** support!\n- Jul 2017: [**Windows portable binaries and demo**](https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases)!\n- Jul 2017: **Hands** released!\n- Jun 2017: **Face** released!\n- May 2017: **Windows** version!\n- Apr 2017: **Body** released!\nFor further details, check the [release notes](08_release_notes.md).\n"
  },
  {
    "path": "doc/08_release_notes.md",
    "content": "OpenPose Doc - Release Notes\n====================================\n\n\n\n## OpenPose 1.0.0rc1 (Apr 24, 2017)\n1. Initial version, main functionality:\n    1. Body keypoint detection and rendering in Ubuntu 14 and 16.\n    2. It can read an image directory, video or webcam.\n    3. It can display the results or store them on disk.\n\n\n\n## OpenPose 1.0.0rc2 (May 10, 2017)\n1. Main improvements:\n    1. Rendering max resolution from 720p to >32k images.\n    2. Highly improved documentation.\n2. Functions or parameters renamed:\n    1. Demo renamed from rtpose to openpose.\n3. Main bugs fixed:\n    1. Demo uses exec instead of start, so it works with more OpenCV custom compiled versions.\n\n\n\n## OpenPose 1.0.0rc3 (Jun 8, 2017)\n1. Main improvements:\n    1. Added face keypoint detection.\n    2. Added Windows 10 compatibility.\n    3. Auto-detection of the number of GPUs.\n    4. MPI visualization is more similar to COCO one.\n    5. Rendering max resolution from 720p to >32k images.\n    6. GUI info adder working when the worker TDatum has more than 1 Datum.\n    7. It prints out the error description before throwing the exception (so that it is written on the Windows cmd).\n    8. Highly improved documentation.\n2. Functions or parameters renamed:\n    1. Flag `--write_pose` renamed as `--write_keypoint` and it also applies to face and/or hands.\n    2. Flag `--write_pose_json` renamed as `--write_keypoint_json` and it also applies to face and/or hands.\n    3. Flag `--write_pose_format` renamed as `--write_keypoint_format` and it also applies to face and/or hands.\n    4. PoseSaver and its JSON variant renamed as KeypointSaver.\n    5. PoseJsonCocoSaver renamed as CocoJsonSaver.\n3. Main bugs fixed:\n    1. All visualization functions moved to the same thread, so it works with most OpenCV custom compiled versions.\n    2. Fixed error on debug mode: `Too many resources requested for launch`.\n\n\n\n## OpenPose 1.0.0 (Jul 8, 2017)\n1. Main improvements:\n    1. Added hand keypoint detection.\n    2. Windows branch merged to master branch.\n    3. Face and hands use `Maximum` instead of `Nms`, since there is only 1 person / detection.\n    4. Increased accuracy on multi-scale (added `Datum::scaleRatios` to save the relative scale ratio when multi-scale).\n    5. Increased speed ~5% by adding CPU rendering (but GPU is the default rendering).\n    6. Rendering colors modified, visually better results.\n    7. Rendering threshold for pose, face and hands becomes user-configurable.\n    8. Check() functions give more feedback.\n    9. WCocoJsonSaver finished and removed its 3599-image limit.\n    10. Added `--camera_fps` so generated video (`--write_video`) will use that frame rate.\n    11. Reduced the number of printed information messages. Default logging priority threshold increased to Priority::Max.\n    12. GFlags to OpenPose configuration parameters reader moved from each demo to utilities/flagsToOpenPose.\n    13. Nms classes do not use `numberParts` for `Reshape`, they deduce the value.\n    14. Improved documentation.\n2. Functions or parameters renamed:\n    1. Render flags renamed in the demo in order to incorporate the CPU/GPU rendering.\n    2. Keypoints saved in JSON files (`--write_keypoint_json`) are now saved as `pose_keypoints`, `face_keypoints`, `hand_left_keypoints`, and `hand_right_keypoints`. They all were previously saved as `body_parts`.\n    3. Flag `--num_scales` renamed as `--scale_number`.\n    4. All hand and pose flags renamed such as they start by `--hand_` and `--face_` respectively.\n3. Main bugs fixed:\n    1. Fixed bug in Array::getConstCvMat() if mVolume=0, now returning empty cv::Mat.\n    2. Fixed bug: `--process_real_time` threw error with webcam.\n    3. Fixed bug: Face not working when input and output resolutions are different.\n    4. Fixed some bugs that prevented the debug version to run.\n    5. Face saved in JSON files were called `--body_parts`. Now they are called `--face_keypoints`.\n\n\n\n## OpenPose 1.0.1 (Jul 11, 2017)\n1. Main improvements:\n    1. Windows library turned into DLL dynamic library (i.e., portable).\n    2. Improved documentation.\n2. Functions or parameters renamed:\n    1. `openpose/utilities/macros.hpp` moved to `openpose/utilities/macros.hpp`.\n\n\n\n## OpenPose 1.0.2 (Sep 3, 2017)\n1. Main improvements:\n    1. Added OpenCV 3.3 compatibility.\n    2. Caffe turned into a DLL library.\n    3. OpenPose is now completely portable across Windows 10 computers (with Nvidia graphic card).\n    4. Added OpenPose 1.0.1 portable demo.\n    5. Removed Python and some unnecessary boost dependencies on the VS project.\n    6. Replaced all double quotes by angle brackets in include statements (issue #61).\n    7. Added 3-D reconstruction demo.\n    8. Auto-detection of the camera index.\n    9. Speed up of about 30% in floatPtrToUCharCvMat.\n    10. COCO extractor now extracts image ID from the image name itself (format \"string_%d\"). Before, only working with validation test, now applicable to e.g., test sets.\n    11. Changed display texts, added `OpenPose` name.\n2. Main bugs fixed:\n    1. Pycaffe can now be imported from Python.\n    2. Fixed `Tutorial/Wrapper` VS linking errors.\n\n\n\n## OpenPose 1.1.0 (Sep 19, 2017)\n1. Main improvements:\n    1. Added CMake installer for Ubuntu.\n    2. Added how to use keypoint data in `examples/tutorial_wrapper/`.\n    3. Added flag for warnings of type `-Wsign-compare` and removed in code.\n    4. Slightly improved accuracy by considering ears-shoulder connection (e.g., +0.4 mAP for 1 scale in validation set).\n2. Main bugs fixed:\n    1. Windows version crashing with std::map copy.\n\n\n\n## OpenPose 1.2.0 (Nov 3, 2017)\n1. Main improvements:\n    1. Speed increase when processing images with different aspect ratios. E.g., ~20% increase over 3.7k COCO validation images on 1 scale.\n    2. Huge speed increase and memory reduction when processing multi-scale. E.g., over 3.7k COCO validation images on 4 scales: ~40% (~770 to ~450 sec) speed increase, ~25% memory reduction (from ~8.9 to ~6.7 GB / GPU).\n    3. Slightly increase of accuracy given the fixed mini-bugs.\n    4. Added IP camera support.\n    5. Output images can have the input size, OpenPose able to change its size for each image and not required fixed size anymore.\n        1. FrameDisplayer accepts variable size images by rescaling every time a frame with a bigger width or height is displayed (gui module).\n        2. OpOutputToCvMat & GuiInfoAdder does not require to know the output size at construction time, deduced from each image.\n        3. CvMatToOutput and Renderers allow to keep input resolution as output for images (core module).\n    6. New standalone face keypoint detector based on OpenCV face detector: much faster if body keypoint detection is not required but much less accurate.\n    7. Face and hand keypoint detectors now can return each keypoint heatmap.\n    8. The flag `USE_CUDNN` is no longer required; `USE_CAFFE` and `USE_CUDA` (replacing the old `CPU_ONLY`) are no longer required to use the library, only to build it. In addition, Boost, Caffe, and its dependencies have been removed from the OpenPose header files. Only OpenCV include and lib directories are required when building a project using OpenPose.\n    9. OpenPose successfully compiles if the flags `USE_CAFFE` and/or `USE_CUDA` are not enabled, although it will give an error saying they are required.\n    10. COCO JSON file outputs 0 as score for non-detected keypoints.\n    11. Added example for OpenPose for user asynchronous output and cleaned all `tutorial_wrapper/` examples.\n    12. Added `-1` option for `--net_resolution` in order to auto-select the best possible aspect ratio given the user input.\n    13. Net resolution can be dynamically changed (e.g., for images with different size).\n    14. Added example to add functionality/modules to OpenPose.\n    15. Added `--disable_multi_thread` flag in order to allow debug and/or highly reduce the latency (e.g., when using webcam in real-time).\n    16. Allowed to output images without any rendering.\n2. Functions or parameters renamed:\n    1. OpenPose able to change its size and initial size dynamically:\n        1. Flag `--resolution` renamed as `--output_resolution`.\n        2. FrameDisplayer, GuiInfoAdder and Gui constructors arguments modified (gui module).\n        3. OpOutputToCvMat constructor removed (core module).\n        4. New Renders classes to split GpuRenderers from CpuRenderers.\n        5. Etc.\n    2. OpenPose able to change its net resolution size dynamically:\n        1. Changed several functions on `core/`, `pose/`, `face/`, and `hand/` modules.\n    3. `CPU_ONLY` changed by `USE_CUDA` to keep format.\n3. Main bugs fixed:\n    1. Scaling resize issue fixed: approximately 1-pixel offset due to not considering 0-based indexes.\n    2. Ubuntu installer script now works even if Python pip was not installed previously.\n    3. Flags to set first and last frame as well as jumping frames backward and forward now works on the image directory reader.\n\n\n\n## OpenPose 1.2.1 (Jan 9, 2018)\n1. Main improvements:\n    1. Heatmaps can be saved in floating format.\n    2. More efficient non-processing version (i.e., if all keypoint extractors are disabled, and only image extraction and display/saving operations are performed).\n    3. Heat maps scaling: Added `--heatmaps_scale` to OpenPoseDemo, added option not to scale the heatmaps, and added custom `float` format to save heatmaps in floating format.\n    4. Detector of the number of GPUs also considers the initial GPU index given by the user.\n    5. Added `--write_json` as a new version of `--write_keypoint_json`. It includes the body part candidates (if enabled), as well as any extra information added in the future (e.g., person ID).\n    6. Body part candidates can be retrieved in Datum and saved with `--write_json`.\n2. Functions or parameters renamed:\n    1. `PoseParameters` split into `PoseParameters` and `PoseParametersRender` and const parameters turned into functions for more clarity.\n3. Main bugs fixed:\n    1. Render working on images > 4K (#324).\n    2. Cleaned redundant arguments on `getAverageScore` and `getKeypointsArea`.\n    3. Slight speed up when heatmaps must be returned to the user (not doing a double copy anymore).\n\n\n\n## OpenPose 1.3.0 (Mar 24, 2018)\n1. Main improvements:\n    1. Output of `--write_json` uses less hard disk space (enters and tabs removed).\n    2. Removed Boost dependencies.\n    3. Caffe added as a submodule.\n    4. CMake installer compatible with Windows.\n    5. Added freeglut download script (3-D reconstruction demo for Windows).\n    6. Added Debug version for Windows (CMake).\n    7. Runtime verbose about average speed configurable by user with `PROFILER_ENABLED` option (CMake/Makefile.config) and `--profile_speed` flag.\n    8. Lighter Caffe version compiled by CMake in Ubuntu: disabled Caffe extra support (e.g., OpenCV, Python) and doc.\n    9. Renamed CMake binaries (Ubuntu) to match old Makefile format: `_bin` by `.bin`.\n    10. 3-D reconstruction demo cleaned, implemented in Ubuntu too, and now defined as module of OpenPose rather than just a demo.\n    11. CMake as default installer in documentation.\n    12. Added flag: number_people_max to optionally select the maximum number of people to be detected.\n    13. 3-D reconstruction module forces the user to set `number_people_max 1` to avoid errors (as it assumes only 1 person per image).\n    14. Removed old `windows/` version. CMake is the only Windows version available.\n    15. Camera parameters (flir camera) are read from disk at runtime rather than being compiled.\n    16. 3-D reconstruction module can be implemented with different camera brands or custom image sources.\n    17. Flag `--write_json` includes 3-D keypoints.\n    18. 3-D reconstruction module can be used with images and videos. Flag `--3d_views` added to allow `--image_dir` and `--video` to load stereo images.\n    19. Flag `--camera_resolution` applicable to `--flir_camera`.\n    20. Throwing an error message if requested GPU IDs do not exist (e.g., asking for 2 GPUs starting with ID 1 if there are only 2 GPUs in total).\n    21. VideoSaver (`--write_video`) compatible with multi-camera setting. It will save all the different views concatenated.\n    22. OpenPose small GUI rescale the verbose text to the displayed image, to avoid the text to be either too big or small.\n    23. OpenPose small GUI shows the frame number w.r.t. the original producer, rather than the frame id. E.g., if video is started at frame 30, OpenPose will display 30 rather than 0 in the first frame.\n    24. OpenPose GUI: 'l' and 'k' functionality swapped.\n    25. 3-D reconstruction module: Added flag `--3d_min_views` to select minimum number of cameras required for 3-D reconstruction.\n    26. Flir camera producer `n` times faster for `n` cameras (multi-threaded). If the number of cameras is greater than the number of the computer threads, the speed up might not be exactly `n` times.\n2. Functions or parameters renamed:\n    1. Flag `no_display` renamed as `display`, able to select between `NoDisplay`, `Display2D`, `Display3D`, and `DisplayAll`.\n    2. 3-D reconstruction demo is now inside the OpenPose demo binary.\n    3. Renamed `*_keypoints` by `*_keypoints_2d` to avoid confusion with 3d ones in `--write_json` output file.\n    4. CvMatToOpInput requires PoseModel to know the normalization to be performed.\n    5. Created `net/` module in order to reduce `core/` number of classes and files and for future scalability.\n3. Main bugs fixed:\n    1. Slight speed up (around 1%) for performing the non-maximum suppression stage only in the body part heatmaps channels, and not also in the PAF channels.\n    2. Fixed core-dumped in PoseRenderer with GUI when changed element to be rendered to something else than skeleton.\n    3. 3-D visualizer does not crash on exit anymore.\n    4. Fake pause ('m' key pressed) works again.\n\n\n\n## OpenPose 1.4.0 (Sep 01, 2018)\n1. Main improvements:\n    1. Model BODY_25 released, that includes the 17 COCO keypoints + neck + midhip + 6 foot keypoints. It is also about 3% more accurate and 30% faster than the original `COCO` model.\n    2. New calibration module: Intrinsic and extrinsic camera calibration toolbox based on OpenCV.\n    3. Improvements involving Flir cameras:\n        1. Added software trigger and a dedicated thread to keep reading images so latency is removed and runtime is faster (analogously to webcamReader).\n        2. Undistortion of the images is x3.5 faster per camera, i.e., x3.5 Flir camera producer reading w.r.t previous multi-threaded version, which was x number_cameras faster than the original version.\n        3. Added flag `flir_camera_index` to allow running on all the cameras at once, or only on 1 camera at the time.\n        4. Added flag `frame_keep_distortion` not to undistort the images. E.g., useful when recording images for camera calibration.\n        5. Changed Spinnaker::DEFAULT image extraction mode by Spinnaker::IPP, which does not show a pixelated image while keeping a very similar runtime.\n    4. 3-D reconstruction:\n        1. Added non-linear minimization to further improve 3-D triangulation accuracy by ~5% (Ubuntu only).\n        2. It is only run if reprojection error is more than a minimum threshold (improve speed with already good quality results) and also less than another outlier threshold.\n        3. Outliers are removed from the final result if >= 3 camera views.\n        4. Applied RANSAC if >=4 camera views.\n        5. Latency highly reduced in multi-GPU setting. Each GPU processes a different camera view, instead of a different time-instant sequence.\n    5. CMake: All libraries as a single variable (simpler to add/remove libraries).\n    6. Averaged latency reduced to half.\n    7. 15% speed up for the default CMake version. CMake was not setting `Release` mode by default.\n    8. Light speed up, and body approach much more invariant to number of people. Removed `checkEQ` from tight loop in bodyPartConnectorBase, which took a huge time exponential to the number of people.\n    9. Datum includes extrinsic and intrinsic camera parameters.\n    10. Function `scaleKeypoints(Array<float>& keypoints, const float scale)` also accepts 3D keypoints.\n    11. 3D keypoints and camera parameters in meters (instead of millimeters) in order to reduce numerical errors.\n    12. New `PoseExtractor` class to contain future ID and tracking algorithms as well as the current OpenPose keypoint detection algorithm.\n    13. Added initial alpha versions of the `tracking` and `identification` modules (for now disabled but available in the source code), including `PersonIdExtractor` and `PersonTracker`. `PersonIdExtractor` includes greedy matrix OP-LK matching.\n    14. Added catches to all demos for higher debug information.\n    15. GUI includes the capability of dynamically enabling/disabling the face, hand, and 3-D rendering, as well as more clear visualization for skeleton, background, heatmap addition, and PAF addition channels.\n    16. When GUI changes some parameter from PoseExtractorNet, there is a log to notify the user of the change.\n    17. Deprecated flag `--write_keypoint_json` removed (`--write_json` is the equivalent since version 1.2.1).\n    18. Speed up of cvMatToOpOutput and opOutputToCvMat: Datum::outputData is now H x W x C instead of C x H x W, making it much faster to be copied to/from Datum::cvOutputData.\n    19. Much faster GUI display by adding the `WITH_OPENCV_WITH_OPENGL` flag to tell whether to use OpenGL support for OpenCV.\n    20. Turned sanity check error into warning when using dynamic `net_resolution` for `image_dir` in CPU/OpenCL versions.\n    21. Minimized CPU usage when queues are empty or full, in order to prevent problems such as general computer slow down, overheating, or excessive power usage.\n2. Functions or parameters renamed:\n    1. Removed scale parameter from hand and face rectangle extractor (causing wrong results if custom `--output_resolution`).\n    2. Functions `scaleKeypoints`, other than `scaleKeypoints(Array<float>& keypoints, const float scale)`, renamed as `scaleKeypoints2d`.\n    3. `(W)PoseExtractor` renamed to `(W)PoseExtractorNet` to distinguish from the new `PoseExtractor`. Analogously with `(W)FaceExtractorNet` and `(W)HandExtractorNet`.\n    4. Experimental module removed and internal `tracking` directory moved to main openpose directory.\n    5. Switched GUI shortcuts for the kind of channel to render (skeleton, heatmap, PAF, ...) in order to make it more intuitive: 1 for skeleton, 1 for background heatmap, 2 for adding all heatmaps, 3 for adding all PAFs, and 4 to 0 for the initial heatmaps.\n3. Main bugs fixed:\n    1. Fixed hand and face extraction and rendering scaling issues when `--output_resolution` is not the default one.\n    2. Part candidates (`--part_candidates`) are saved with the same scale than the final keypoints itself.\n    3. Fixed bug in keepTopNPeople.hpp (`--number_people_max`) that provoked core dumped if lots of values equal to the threshold.\n    4. Flir cameras: Cameras sorted by serial number. Video and images recorded from flir cameras were (and are) assigned the camera parameters based on serial number order, so it would fail if the cameras order was not the same as if sorted by serial number.\n    5. CPU version working in non-Nvidia Windows machines.\n\n\n\n## OpenPose 1.5.0 (May 16, 2019)\n1. Main improvements:\n    1. Added initial single-person tracker for further speed up or visual smoothing (`--tracking` flag).\n    2. Speed up of the CUDA functions of OpenPose:\n        1. Greedy body part connector implemented in CUDA: +~30% speedup in Nvidia (CUDA) version with default flags and +~10% in maximum accuracy configuration. In addition, it provides a small 0.5% boost in accuracy (default flags).\n        2. +5-30% additional speedup for the body part connector of point 1.\n        3. About 2-4x speedup for NMS.\n        4. About 2x speedup for image resize and about 2x speedup for multi-scale resize.\n        5. About 25-30% speedup for rendering.\n        6. Reduced latency and increased speed by moving the resize in CvMatToOpOutput and OpOutputToCvMat to CUDA. The linear speedup generalizes better to a higher number of GPUs.\n    3. Unity binding of OpenPose released. OpenPose adds the flag `BUILD_UNITY_SUPPORT` on CMake, which enables special Unity code so it can be built as a Unity plugin.\n    4. If the camera is unplugged, OpenPose GUI and command line will display a warning and try to reconnect it.\n    5. Wrapper classes simplified and renamed. Wrapper renamed as WrapperT, and created Wrapper as the non-templated class equivalent.\n    6. API and examples improved:\n        1. New header file `flags.hpp` that includes all OpenPose flags, removing the need to copy them repeatedly on each OpenPose example file.\n        2. Renamed `tutorial_wrapper` as `tutorial_api_cpp` as well as new examples were added.\n        2. Renamed `tutorial_python` as `tutorial_api_python` as well as new examples were added.\n        3. Renamed `tutorial_thread` as `tutorial_api_thread`, focused on the multi-thread mechanism.\n        4. Removed `tutorial_pose`, the directory `tutorial_api_cpp` includes much cleaner and commented examples.\n        5. Examples do not end in core dumped if an OpenPose exception occurred during initialization, but they are rather closed returning -1. However, it will still result in core dumped if the exception occurs during multithreading execution.\n        6. Added new examples, including examples to extract face and/or hand from images.\n        7. Added `--no_display` flag for the examples that do not use OpenPose output.\n        8. Given that display can be disabled in all examples, they all have been added to the Travis build so they can be tested.\n    7. Added a virtual destructor to almost all classes, so they can be inherited. Exceptions (for performance reasons): Array, Point, Rectangle, CvMatToOpOutput, OpOutputToCvMat.\n    8. Auxiliary classes in errorAndLog turned into namespaces (Profiler must be kept as class to allow static parameters).\n    9. Added flags:\n        1. Added flag `--frame_step` to allow the user to select the step or gap between processed frames. E.g., `--frame_step 5` would read and process frames 0, 5, 10, etc.\n        2. Previously hardcoded `COCO_CHALLENGE` variable turned into a user configurable flag `--maximize_positives`.\n        3. Added flag `--verbose` to plot the progress.\n        4. Added flag `--fps_max` to limit the maximum processing frame rate of OpenPose (useful to display results at a maximum desired speed).\n        5. Added sanit30. Added the flags `--prototxt_path` and `--caffemodel_path` to allow custom ProtoTxt and CaffeModel paths.\n        6. Added the flags `--face_detector` and `--hand_detector`, that enable the user to select the face/hand rectangle detector that is used for the later face/hand keypoint detection. It includes OpenCV (for face), and also allows the user to provide its own input. Flag `--hand_tracking` is removed and integrated into this flag too.\n        y checks to avoid `--frame_last` to be smaller than `--frame_first` or higher than the number of total frames.\n        7. Added the flag `--upsampling_ratio`, which controls the upsampling than OpenPose will perform to the frame before the greedy association parsing algorithm.\n        8. Added the flag `--body` (replacing `--body_disable`), which adds the possibility of disabling the OpenPose pose network but still running the greedy association parsing algorithm (on top of the user heatmaps, see the associated `tutorial_api_cpp` example).\n    10. Array improvements for Pybind11 compatibility:\n        1. Array::getStride() to get step size of each dimension of the array.\n        2. Array::getPybindPtr() to get an editable const pointer.\n        3. Array::pData as binding of spData.\n        4. Array::Array that takes as input a pointer, so it does not re-allocate memory.\n    11. Producer defined inside Wrapper rather than being defined on each example.\n    12. Reduced many Visual Studio warnings (e.g., uncontrolled conversions between types).\n    13. Added new keypoint-related auxiliary functions in `utilities/keypoints.hpp`.\n    14. Function `resizeFixedAspectRatio` can take already allocated memory (e.g., faster if target is an Array<T> object, no intermediate cv::Mat required).\n    15. Added compatibility for OpenCV 4.0, while preserving 2.4.X and 3.X compatibility.\n    16. Improved and added several functions to `utilities/keypoints.hpp` and Array to simplify keypoint post-processing.\n    17. Removed warnings from Spinnaker SDK at compiling time.\n    18. All bash scripts incorporate `#!/bin/bash` to tell the terminal that they are bash scripts.\n    19. Added find_package(Protobuf) to allow specific versions of Protobuf.\n    20. Video saving improvements:\n        1. Video (`--write_video`) can be generated from images (`--image_dir`), as long as they maintain the same resolution.\n        2. Video with the 3D output can be saved with the new `--write_video_3d` flag.\n        3. Added the capability of saving videos in MP4 format (by using the ffmpeg library).\n        4. Added the flag `write_video_with_audio` to enable saving these output MP4 videos with audio.\n    21. Frame undistortion can be applied not only to FLIR cameras, but also to all other input sources (image, webcam, video, etc.).\n    22. Calibration improvements:\n        1. Improved chessboard orientation detection, more robust and less errors.\n        2. Triangulation functions (triangulate and triangulateWithOptimization) public, so calibration can use them for bundle adjustment.\n        3. Added bundle adjustment refinement for camera extrinsic calibration.\n        4. Added `CameraMatrixInitial` field into the XML calibration files to keep the information of the original camera extrinsic parameters when bundle adjustment is run.\n    23. Added Mac OpenCL compatibility.\n    24. Added documentation for Nvidia TX2 with JetPack 3.3.\n    25. Added Travis build check for several configurations: Ubuntu (14/16)/Mac/Windows, CPU/CUDA/OpenCL, with/without Python, and Release/Debug.\n    26. Assigned 755 access to all sh scripts (some of them were only 644).\n    27. Replaced the old Python wrapper for an updated Pybind11 wrapper version, that includes all the functionality of the C++ API.\n    28. Function getFilesOnDirectory() can extra all basic image file types at once without requiring to manually enumerate them.\n    29. Maximum queue size per OpenPose thread is configurable through the Wrapper class.\n    30. Added pre-processing capabilities to Wrapper (WorkerType::PreProcessing), which will be run right after the image has been read.\n    31. Removed boost::shared_ptr and caffe::Blob dependencies from the headers. No 3rdparty dependencies left on headers (except dim3 for CUDA).\n    32. Added Array `poseNetOutput` to Datum so that the user can introduce his custom network output.\n    33. OpenPose will never provoke a core dumped or crash. Exceptions in threads (`errorWorker()` instead of `error()`) lead to stopping the threads and reporting the error from the main thread, while exceptions in destructors (`errorDestructor()` instead of `error()`) are reported with std::cerr but not thrown as std::exceptions.\n    34. When reading a directory of images, they will be sorted in natural order (rather than regular sort).\n    35. Windows updates:\n        1. Upgraded OpenCV version for Windows from 3.1 to 4.0.1, which provides stable 30 FPS for webcams (vs. 10 FPS that OpenCV 3.1 provides by default on Windows).\n        2. Upgrade VS2015 to VS2017, allowing CUDA 10 and 20XX Nvidia cards.\n    36. Output JSON updated to version 1.3, which now includes the person IDs (if any).\n2. Functions or parameters renamed:\n    1. By default, python example `tutorial_developer/python_2_pose_from_heatmaps.py` was using 2 scales starting at -1x736, changed to 1 scale at -1x368.\n    2. WrapperStructPose default parameters changed to match those of the OpenPose demo binary.\n    3. WrapperT.configure() changed from 1 function that requires all arguments to individual functions that take 1 argument each.\n    4. Added `Forward` to all net classes that automatically selects between CUDA, OpenCL, or CPU-only versions depending on the defines.\n    5. Removed old COCO 2014 validation scripts.\n    6. WrapperStructOutput split into WrapperStructOutput and WrapperStructGui.\n    7. Replaced flags:\n        1. Replaced `--camera_fps` flag by `--write_video_fps`, given that it was a confusing name: It did not affect the webcam FPS, but only the FPS of the output video. In addition, the default value changed from 30 to -1.\n        2. Flag `--hand_tracking` is a subcase of `--hand_detector`, so it has been removed and incorporated as `--hand_detector 3`.\n    8. Renamed `--frame_keep_distortion` as `--frame_undistort`, which performs the opposite operation (the default value has been also changed to the opposite).\n    9. Renamed `--camera_parameter_folder` as `--camera_parameter_path` because it could also take a whole XML file path rather than its parent directory.\n    10. Default value of flag `--scale_gap` changed from 0.3 to 0.25.\n    11. Moved most sh scripts into the `scripts/` directory. Only models/getModels.sh and the `*.bat` files are kept under `models/` and `3rdparty/windows`.\n    12. For Python compatibility and scalability increase, template `TDatums` used for `include/openpose/wrapper/wrapper.hpp` has changed from `std::vector<Datum>` to `std::vector<std::shared_ptr<Datum>>`, including the respective changes in all the worker classes. In addition, some template classes have been simplified to only take 1 template parameter for user simplicity.\n    13. Renamed intRound, charRound, etc. by positiveIntRound, positiveCharRound, etc. so that people can realize it is not safe for negative numbers.\n    14. Replaced flag `--write_coco_foot_json` by `--write_coco_json_variants` in order to generalize to any COCO JSON format (i.e., hand, face, etc).\n3. Main bugs fixed:\n    1. CMake-GUI was forced to Release mode, now also allowed Debug modes.\n    2. NMS returns in index 0 the number of found peaks. However, while the number of peaks was truncated to a maximum of 127, this index 0 was saving the real number instead of the truncated one.\n    3. Template functions could not be imported in Windows for projects using the OpenPose library DLL.\n    4. Function `scaleKeypoints2d` was not working if any of the scales was 1 (e.g., fail if scaleX = 1 but scaleY != 1, or if any offset was not 0).\n    5. Fixed bug in `KeepTopNPeople` that could provoke segmentation fault for `number_people_max` > 1.\n    6. Camera parameter reader can now take directory paths even if they are not finished in `/` (e.g., `~/Desktop/` worked but `~/Desktop` did not).\n    7. 3D module: If the image area was smaller than HD resolution image area, the 3D keypoints were not properly estimated.\n    8. OpenCL fixes.\n    9. If manual CUDA architectures are set in CMake, they are also set for Caffe rather than only for OpenPose.\n    10. Fixed flag `--hand_alpha_pose`.\n\n\n\n## OpenPose 1.5.1 (Sep 03, 2019)\n1. Main improvements:\n    1. Highly improved 3D triangulation for >3 cameras by fixing some small bugs.\n    2. Added community-based support for Nvidia NVCaffe.\n    3. Increased accuracy very lightly for CUDA version (about 0.01%) by adapting the threshold in `process()` in `bodyPartConnectorBase.cu` to `defaultNmsThreshold`. This also removes any possibility of future bugs in that function for using a default NMS threshold higher than 0.15 (which was the hard-coded value used previously).\n    4. Increased mAP but reduced mAR (both about 0.01%) as well as reduction of false positives. Step 1: removed legs where only knee/ankle/feet are found. Step 2: If no people are found in an image, `removePeopleBelowThresholdsAndFillFaces` is re-run with `maximizePositives = true`.\n    5. Number of maximum people is not limited by the maximum number of max peaks anymore. However, the number of body part candidates for a specific keypoint (e.g., nose) is still limited to the number of max peaks.\n    6. Added more checks during destructors of CUDA-related functions and safer CUDA frees.\n    7. Improved accuracy of CPU version about 0.2% by following the CUDA/OpenCL approach of assigning the minimum possible PAF score to keypoints that are very close to each other.\n    8. Added Windows auto-testing (AppVeyor).\n2. Functions or parameters renamed:\n    1. `--3d_min_views` default value (-1) no longer means that all camera views are required. Instead, it will be equal to max(2, min(4, #cameras-1)). This should provide a good trade-off between recall and precision.\n3. Main bugs fixed:\n    1. Windows: Added back support for OpenGL and Spinnaker, as well as DLLs for debug compilation.\n    2. `06_face_from_image.cpp`, `07_hand_from_image.cpp`, and `09_keypoints_from_heatmaps` working again, they stopped working in version 1.5.0 with the GPU image resize for the GUI.\n\n\n\n## OpenPose 1.6.0 (Apr 26, 2020)\n1. Main improvements:\n    1. Multi-camera (3D) working on Asynchronous mode.\n        1. Functions `WrapperT::waitAndEmplace()` and `WrapperT::tryEmplace()` improved, allowing multi-camera/3-D (`TDatums` of size > 1).\n        2. Added `createMultiviewTDatum()` to auto-generate a `TDatums` for multi-camera/3-D from a single cv::Mat (that is split) and the desired camera parameter matrices.\n        3. Added `examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.cpp` for a test example.\n    2. Created Matrix as container of cv::Mat, and String as container of std::string.\n    3. After replacing cv::Mat by Matrix, headers do not contain any 3rd-party library includes nor functions. This way, OpenPose can be exported without needing 3rd-party includes nor static library files (e.g., lib files in Windows), allowing people to use their own versions of OpenCV, Eigen, etc. without conflicting with OpenPose. Dynamic library files (e.g., `dll` files in Windows, `so` in Ubuntu) are still required.\n    4. Created the `openpose_private` directory with some internal headers that, if exported with OpenPose, would require including 3rd-party headers and static library files.\n    5. Default OpenCV version for Windows upgraded to version 4.2.0, extracted from their official website: section `Releases`, subsection `OpenCV - 4.2.0`, `Windows` version.\n    6. In all `*.cpp` files, their include of their analog `*.hpp` file has been moved to the first line of those `*.cpp` files to slightly speed up compiling time.\n    7. String is used in `include/openpose/wrapper/` to avoid std::string to cause errors for using different std DLLs.\n    8. Added `ScaleMode::ZeroToOneFixedAspect` and `ScaleMode::PlusMinusOneFixedAspect`. Compared to `ZeroToOne` and `PlusMinusOne`, the new ones also preserve the aspect ratio of each axis.\n    9. Added more verbose to wrapper when it has been configured, showing the values of some of its parameters.\n    10. Removed many Visual Studio (Windows) warnings.\n2. Functions or parameters renamed:\n    1. All headers moved into `openpose_private`, all 3rd-party library calls in headers, and std::string calls in `include/openpose/wrapper/`.\n    2. Renamed `dLog()` as `opLogIfDebug()`, `log()` as `opLog()`, `check()` as `checkBool()`, and also renamed all the `checkX()` functions in `include/openpose/utilities/check.hpp`. This avoids compiling crashes when exporting OpenPose to other projects which contain other 3rd-party libraries that define functions with the same popular names with `#define`.\n3. Main bugs fixed:\n    1. The debug version of OpenPose actually targets debug lib/DLL files of 3rd-party libraries.\n    2. The debug version no longer prints on console a huge log message from Caffe with the network when starting OpenPose (fixed by using the right debug libraries).\n    4. Natural sort now works properly with filenames containing numbers longer than the limit of an int.\n    5. The optionally auto-generated bin directory only contains the required DLLs (depending on the CMake configuration), instead of all of them.\n    6. When WrapperStructFace and WrapperStructHand are not called and configured for Wrapper, setting the body to CPU rendering was not working.\n    7. Skeleton rendering bugs:\n        1. All or some skeletons were not properly displayed or completely missing on images with many people (e.g., videos with about 32 people).\n        2. All or some skeletons were not properly displayed or completely missing on images where the multiplication of people and image resolution was too big (e.g., videos with about 32 people on 4k resolution).\n        3. Flag `output_resolution` was not working with GPU resize, redirected to CPU in those cases.\n\n\n\n## OpenPose 1.7.0 (Nov 15, 2020)\n1. Main improvements:\n    1. Added compatibility with CUDA 11.X and cuDNN 8.X.\n    2. Added compatibility with Ubuntu 20.04.\n    3. Added Asynchronous mode to Python API.\n    4. Added `DOWNLOAD_SERVER` variable to CMake. It specifies the link where the models and 3rd party libraries will be downloaded from.\n    5. Installation documentation highly simplified and improved.\n    6. Removed all compiler warnings for Ubuntu 20.04 (GCC and Clang) as well as some for Windows 10.\n2. Functions or parameters renamed:\n    1. `USE_MKL` disabled by default in Ubuntu. Reason: Not compatible with non-intel CPUs or Ubuntu 20.\n3. Main bugs fixed:\n    1. 90 and 270-degree rotations working again.\n    2. C++ tutorial API demos only try to cv::imshow the image if it is not empty (avoiding the assert that it would trigger otherwise).\n    3. Several typos fixed in the documentation.\n\n\n\n## Current version - Future OpenPose 1.7.1\n1. Main improvements:\n    1. (For images and custom inputs only): Flag `--net_resolution_dynamic` added to avoid out of memory errors in low GPUs (set by default to 1). It also allows maintaining the maximum possible accuracy (for big GPUs), which was the previous default until OpenPose v1.7.0.\n    2. Webcam speed boosted on Windows (by updating OpenCV).\n    3. Third party versions updated:\n        1. OpenCV (Windows): From 4.2 to 4.5.\n        2. Eigen: From 3.3.4 to 3.3.8.\n        3. `wget` (Windows): From 1.19.1 to 1.20.3.\n    4. AppVeyor now tests the actual OpenPoseDemo.exe example (Windows).\n    5. Documentation improvements:\n        1. Highly simplified README.md.\n        2. Highly simplified doc, restructured to improve simplicity and now divided into subdirectories (`advanced`, `deprecated`, `installation`, etc).\n        3. More examples added to the demo quick start documentation.\n    6. Calibration documentation links to the included chessboard pdf.\n    7. Deprecated examples directories `tutorial_add_module` and `tutorial_api_thread` (and renamed as `deprecated`). They still compile, but we no longer support them.\n    8. GitHub Pages autogenerated into [cmu-perceptual-computing-lab.github.io/openpose](https://cmu-perceptual-computing-lab.github.io/openpose) with README.md, doc/ and include/openpose folders.\n2. Functions or parameters renamed:\n    1. Added GitHub Actions (Workspaces) to test Ubuntu and Mac OSX versions (rather than the deprecated Travis). Travis was giving many issues, that were not OpenPose errors, making Travis not usable. Its code has been left for now (but commented out).\n    2. Doc highly reordered and renamed in order to fit the Doxygen and GitHub Markdown styles simultaneously.\n3. Main bugs fixed:\n    1. Eigen working again on Windows.\n    2. OpenPose links to the right OpenCV DLL Files on Windows (it was wrongly linking to v14 rather than v15).\n    3. AppVeyor auto-testing working again by disabling artifacts (Windows).\n    4. All CI tests pass (after switching to GitHub actions).\n\n\n\n## All OpenPose Versions\nDownload and/or check any OpenPose version from [https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases](https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases).\n"
  },
  {
    "path": "doc/09_authors_and_contributors.md",
    "content": "OpenPose Doc - Authors and Contributors\n====================================\n\n\n\n## Authors\nOpenPose is authored by [Ginés Hidalgo](https://www.gineshidalgo.com), [Zhe Cao](https://people.eecs.berkeley.edu/~zhecao), [Tomas Simon](http://www.cs.cmu.edu/~tsimon), [Shih-En Wei](https://scholar.google.com/citations?user=sFQD3k4AAAAJ&hl=en), [Yaadhav Raaj](https://www.raaj.tech), [Hanbyul Joo](https://jhugestar.github.io), and [Yaser Sheikh](http://www.cs.cmu.edu/~yaser). It is maintained by [Ginés Hidalgo](https://www.gineshidalgo.com) and [Yaadhav Raaj](https://www.raaj.tech).\n\nOpenPose would not be possible without the [**CMU Panoptic Studio dataset**](http://domedb.perception.cs.cmu.edu). The body pose estimation work is based on the following and original 2 repositories: [CVPR 2017 repository](https://github.com/ZheC/Multi-Person-Pose-Estimation) and [ECCV 2016 repository](https://github.com/CMU-Perceptual-Computing-Lab/caffe_rtpose).\n\n\n\n## Contributors\nWe would also like to thank the following people, who have contributed to key components of OpenPose:\n1. [Bikramjot Hanzra](https://www.linkedin.com/in/bikz05): Former OpenPose maintainer, CMake (Ubuntu and Windows) version, and initial Travis Build version for Ubuntu.\n2. [Donglai Xiang](https://xiangdonglai.github.io): Camera calibration toolbox improvement, including the implementation of its bundle adjustment algorithm.\n3. [Luis Fernando Fraga](https://github.com/fragalfernando): Implementation of Lukas-Kanade algorithm and person ID extractor.\n4. [Akash Patwal](https://www.linkedin.com/in/akash-patwal-63a12012a): Speedup of the CUDA image resize and visual skeleton rendering, as well as extension that allows OpenPose to speedup linearly to more than 4 GPUs.\n5. [Helen Medina](https://github.com/helen-medina): First Windows version.\n6. [Matthijs van der Burgh](https://github.com/MatthijsBurgh): First GitHub Actions CI version for Ubuntu and Mac, and ported all the deprecated Travis CI tests into the new CI system.\n\nWe would also like to thank all the people who [have helped OpenPose in any way](https://github.com/CMU-Perceptual-Computing-Lab/openpose/graphs/contributors).\n"
  },
  {
    "path": "doc/10_community_projects.md",
    "content": "OpenPose Doc - Community-based Projects\n====================================\n\nHere we expose all projects created with OpenPose by the community and that were shared with us. Do you want to share yours? Simply create a pull request and add to this file your demo and a description of it!\n\n1. [**ROS OpenPose**](https://github.com/ravijo/ros_openpose): ROS wrapper for OpenPose\n2. [**Hand gesture classification application - OpenHand**](https://github.com/ArthurFDLR/OpenHand-App): Third-party application that eases hand keypoints datasets creation and real-time hand gesture classification. You can deploy your own Neural Network classification model on top of OpenPose and play with it in real-time through a GUI!\n3. Integrated to [Huggingface Spaces](https://huggingface.co/spaces) with [Gradio](https://github.com/gradio-app/gradio). See demo: [![Hugging Face Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces/akhaliq/openpose)\n4. [**RealSense2OpenPose3D**](https://github.com/foxtierney/RealSense2OpenPose3D): Use an Intel RealSense RGB-D camera to add depth to OpenPose. Generates JSON files with 3D keypoints.\n\n\nDisclaimer: We do not support any of these projects, we are simply exposing them. GitHub issues or questions about those will result in strict user bans and the posts being deleted.\n"
  },
  {
    "path": "doc/README.md",
    "content": "The OpenPose documentation is available in 2 different formats, choose your preferred one!\n- As a traditional website (recommended): [cmu-perceptual-computing-lab.github.io/openpose](https://cmu-perceptual-computing-lab.github.io/openpose).\n- As markdown files: [github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/doc](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/doc).\n"
  },
  {
    "path": "doc/advanced/3d_reconstruction_module.md",
    "content": "﻿OpenPose Advanced Doc - 3-D Reconstruction Module and Demo\n=============================================\n\n## Contents\n1. [Introduction](#introduction)\n2. [Installation](#installation)\n3. [Non Linear Optimization](#non-linear-optimization)\n4. [Features](#features)\n5. [Required Hardware](#required-hardware)\n6. [Camera Calibration](#camera-calibration)\n7. [Camera Ordering](#camera-ordering)\n8. [Quick Start](#quick-start)\n9. [Expected Visual Results](#expected-visual-results)\n10. [Using a Different Camera Brand](#using-a-different-camera-brand)\n11. [Known Bug](#known-bug)\n\n\n\n## Introduction\nThis module performs 3-D keypoint (body, face, and hand) reconstruction and rendering for 1 person. We will not keep updating it nor solving questions/issues about it at the moment. It requires the user to be familiar with computer vision and camera calibration, including extraction of intrinsic and extrinsic parameters.\n\n\n\n\n## Installation\nCheck [doc/installation/2_additional_settings.md#3d-reconstruction-module](../installation/2_additional_settings.md#3d-reconstruction-module) for installation steps.\n\n\n\n\n## Non Linear Optimization\nIn order to increase the 3-D reconstruction accuracy, OpenPose optionally performs non-linear optimization if Ceres solver support is enabled (only available in Ubuntu for now). To enable it, check [doc/installation/2_additional_settings.md#3d-reconstruction-module](../installation/2_additional_settings.md#3d-reconstruction-module) for more details.\n\n\n\n## Features\n- Auto detection of all FLIR cameras connected to your machine, and image streaming from all of them.\n- Hardware trigger and buffer `NewestFirstOverwrite` modes enabled. Hence, the algorithm will always get the last synchronized frame from each camera, deleting the rest.\n- 3-D reconstruction of body, face, and hands for 1 person.\n- If more than 1 person is detected per camera, the algorithm will just try to match person 0 on each camera, which will potentially correspond to different people in the scene. Thus, the 3-D reconstruction will completely fail.\n- Only points with high threshold with respect to each one of the cameras are reprojected (and later rendered). An alternative for > 4 cameras could potentially do 3-D reprojection and render all points with good views in more than N different cameras (not implemented here).\n- Only Direct linear transformation (DLT) is applied for reconstruction. Non-linear optimization methods (e.g., from Ceres Solver) will potentially improve results (not implemented).\n- Basic OpenGL rendering with the `freeglut` library.\n\n\n\n## Required Hardware\nThis demo assumes n arbitrary stereo cameras from the FLIR company (formerly Point Grey). Ideally any USB-3 FLIR model should work, but we have only used the following specific specifications:\n\n1. Camera details:\n    - Blackfly S Color 1.3 MP USB3 Vision (ON Semi PYTHON 1300)\n    - Model: BFS-U3-13Y3C-C\n    - 1280x1024 resolution and 170 FPS\n    - [https://www.ptgrey.com/blackfly-s-13-mp-color-usb3-vision-on-semi-python1300](https://www.ptgrey.com/blackfly-s-13-mp-color-usb3-vision-on-semi-python1300)\n    - Hardware trigger synchronization required. For this camera model, see `Blackfly S` section in [https://www.ptgrey.com/tan/11052](https://www.ptgrey.com/tan/11052) or [https://www.ptgrey.com/KB/11052](https://www.ptgrey.com/KB/11052).\n    - (Ubuntu-only) Open your USB ports following section `Configuring USBFS` in [http://www.ptgrey.com/KB/10685](http://www.ptgrey.com/KB/10685).\n    - Install the Spinnaker SDK for your operating system: [https://www.ptgrey.com/support/downloads](https://www.ptgrey.com/support/downloads).\n2. Fujinon 3 MP Varifocal Lens (3.8-13mm, 3.4x Zoom) for each camera.\n    - E.g., [https://www.bhphotovideo.com/c/product/736855-REG/Fujinon_DV3_4X3_8SA_1_3_MP_Varifocal_Lens.html](https://www.bhphotovideo.com/c/product/736855-REG/Fujinon_DV3_4X3_8SA_1_3_MP_Varifocal_Lens.html).\n3. 4-Port PCI Express (PCIe) USB 3.0 Card Adapter with 4 dedicated channels.\n    - E.g., the 4 Ext Quad Bus version, PCI Express, from: [https://www.amazon.com/Express-SuperSpeed-Adapter-Dedicated-Channels/dp/B00HJZEA2S/ref=sr_1_1?ie=UTF8&qid=1492197599&sr=8-1&keywords=4%2BPort%2BPCI%2BExpress%2B(PCIe)%2Bdedicated%2Bports&th=1](https://www.amazon.com/Express-SuperSpeed-Adapter-Dedicated-Channels/dp/B00HJZEA2S/ref=sr_1_1?ie=UTF8&qid=1492197599&sr=8-1&keywords=4%2BPort%2BPCI%2BExpress%2B(PCIe)%2Bdedicated%2Bports&th=1).\n    - Alternative: [https://www.startech.com/Cards-Adapters/USB-3.0/Cards/PCI-Express-USB-3-Card-4-Dedicated-Channels-4-Port~PEXUSB3S44V](https://www.startech.com/Cards-Adapters/USB-3.0/Cards/PCI-Express-USB-3-Card-4-Dedicated-Channels-4-Port~PEXUSB3S44V).\n4. USB 3.0 cable for each FLIR camera.\n    - From their official website: [https://www.ptgrey.com/5-meter-type-a-to-micro-b-locking-usb-30-cable](https://www.ptgrey.com/5-meter-type-a-to-micro-b-locking-usb-30-cable).\n\n\n\n## Camera Calibration\nThe user must manually get the intrinsic and extrinsic parameters of the stereo-cameras. Note, we will assume `Flir` cameras, which is specified by default with the flag `--camera_parameter_path \"models/cameraParameters/flir/\"`. Otherwise, change the path to your camera name accordingly.\n\nThere are 2 alternatives to calibrate the cameras:\n1. Using the OpenPose calibration toolbox, [doc/advanced/calibration_module.md](calibration_module.md).\n2. Using your own calibration toolbox (or if you already know the camera parameters of your cameras):\n    1. Create a xml file for each camera named as `models/cameraParameters/flir/{camera_serial_number}.xml`.\n    2. The elements inside each xml file are the extrinsic parameters of the camera (`CameraMatrix`), the intrinsic parameters (`Intrinsics`), and the distortion coefficients (`Distortion`). Copy the format from `models/cameraParameters/flir/17012332.xml.example`. For the extrinsic parameters of the camera, it allows you to set the coordinate origin (so that 3-d keypoints are distances with respect to that origin).\n        - E.g., in order to set the camera 1 as the coordinate center, set its `CameraMatrix` as the identity matrix of size 3x4, and the `CameraMatrix` of the other cameras as the camera extrinsic parameters of from those cameras with respect to the main camera `M_1_i`.\n        - **VERY IMPORTANT: The intrinsic camera matrix should be an upper triangular matrix.**\n    3. The program can use any arbitrary number of cameras. Even if lots of cameras are added in `models/cameraParameters/flir/`, the program will check at runtime which FLIR cameras are detected and simply read those camera parameters. If the file corresponding to any of the cameras detected at runtime is not found, OpenPose will return an error.\n    4. In the example XML, OpenPose uses the 8-distortion-parameter version of OpenCV. The distortion parameters are internally used by the OpenCV function [undistort()](http://docs.opencv.org/3.2.0/da/d54/group__imgproc__transform.html#ga69f2545a8b62a6b0fc2ee060dc30559d) to rectify the images. Therefore, this function can take either 4-, 5- or 8-parameter distortion coefficients (OpenCV 3.X also adds a 12- and 14-parameter alternatives). Therefore, either version (4, 5, 8, 12 or 14) will work in 3D OpenPose.\n\n\n\n## Camera Ordering\nOpenPose will display the cameras sorted by serial number, starting in the left with the image corresponding to the lowest serial number. When the program is run, OpenPose displays the camera serial number associated to each index of each detected camera. If the number of cameras detected is different to the number of actual cameras, make sure the hardware is properly connected and the camera leds are on.\n\n\n\n## Quick Start\nCheck the [doc/01_demo.md#3-d-reconstruction](../01_demo.md#3-d-reconstruction) for basic examples.\n\n\n\n## Expected Visual Results\nThe visual GUI should show 3 screens.\n\n1. The Windows command line or Ubuntu bash terminal.\n2. The different cameras 2-D keypoint estimations.\n3. The final 3-D reconstruction.\n\nIt should be similar to the following image.\n\n<p align=\"center\">\n    <img src=\"../../.github/media/openpose3d.gif\">\n    <br>\n    <sup><a href=\"https://ziutinyat.github.io/\" target=\"_blank\">Tianyi Zhao</a> testing the OpenPose 3D Module</a></sup>\n</p>\n\n\n\n## Using a Different Camera Brand\nYou can copy and modify the OpenPose 3-D demo to use any camera brand by:\n\n1. You can optionally turn off the `WITH_FLIR_CAMERA` while compiling CMake.\n2. Copy `examples/tutorial_api_cpp/14_synchronous_custom_input.cpp` (or `18_synchronous_custom_all_and_datum.cpp`).\n3. Modify `WUserInput` and add your custom code there. Your code should fill `Datum::name`, `Datum::cameraMatrix`, `Datum::cvInputData`, and `Datum::cvOutputData` (fill cvOutputData = cvInputData).\n4. Remove `WUserPostProcessing` and `WUserOutput` (unless you want to have your custom post-processing and/or output).\n\nNote that your custom code should retrieve synchronized images from your cameras or any other source, as well as their intrinsic and extrinsic camera parameters.\n\n\n\n## Known Bug\nFreeGLUT is a quite light library. Due to that, there is a known bug in the 3D module:\n\n1. The window must be closed with the <kbd>Esc</kbd> key. Clicking the close button will cause a core dumped or std::exception error in OpenPose. Reason: There is no way to control the behaviour of the exit button in a FreeGLUT program. Feel free to let us know or create a pull request if you find a workaround applicable to 3-D OpenPose. Another alternative is ussing `--disable_multi_thread` in OpenPose. This would avoid the issue but slow down the program, especially in multi-GPU systems.\n"
  },
  {
    "path": "doc/advanced/calibration_module.md",
    "content": "OpenPose Advanced Doc - Calibration Module and Demo\n=============================================\n\n## Contents\n1. [Introduction](#introduction)\n2. [Example Chessboard](#example-chessboard)\n3. [Installing the Calibration Module](#installing-the-calibration-module)\n4. [Running Calibration](#running-calibration)\n    1. [General Quality Tips](#general-quality-tips)\n    2. [Step 1 - Distortion and Intrinsic Parameter Calibration](#step-1---distortion-and-intrinsic-parameter-calibration)\n    3. [Step 2 - Extrinsic Parameter Calibration](#step-2---extrinsic-parameter-calibration)\n5. [Camera Matrix Output Format](#camera-matrix-output-format)\n6. [Using a Different Camera Brand](#using-a-different-camera-brand)\n7. [Naming Convention for the Output Images](#naming-convention-for-the-output-images)\n\n\n\n## Introduction\nThis experimental module performs camera calibration (distortion, intrinsic, and extrinsic camera parameter extraction). It computes and saves the intrinsics parameters of the input images. It is built on top of OpenCV, but aimed to simplify the process for people with no calibration or computer vision background at all (or for lazy people like myself).\n\nNote: We are not aiming to have the best calibration toolbox, but the simplest one. If very high quality calibration is required, I am sure there must exist many other toolboxs with better extrinsic parameter estimation tools.\n\n**VERY IMPORTANT**: OpenPose requires an upper triangular matrix for the intrinsic camera matrix. If you plan to use your own camera intrinsics, be aware of this.\n\n\n\n## Example Chessboard\n[doc/Chessboard_in_PDF/](Chessboard_in_PDF/) contains a chessboard example that you can use to follow this documentation. You can simply print the PDF version ([doc/Chessboard_in_PDF/pattern.pdf](Chessboard_in_PDF/pattern.pdf)), making your your printer maintains the aspect ratio and, if possible, does not zoom in/out the image. Simply replace the \"127\" used below by the size of each square on your printed chessboard.\n\n\n\n\n## Installing the Calibration Module\nCheck [doc/installation/0_index.md#calibration-module](../installation/0_index.md#calibration-module) for installation steps.\n\n\n\n## Running Calibration\nNote: In order to maximize calibration quality, **do not reuse the same video sequence for both intrinsic and extrinsic parameter estimation**. The intrinsic parameter calibration should be run camera by camera, where each recorded video sequence should be focused in covering all regions of the camera view and repeated from several distances. In the extrinsic sequence, this video sequence should be focused in making sure that the checkboard is visible from at least 2 cameras at the time. So for 3-camera calibration, you would need 1 video sequence per camera as well as a final sequence for the extrinsic parameter calibration.\n\n### General Quality Tips\n1. Keep the same orientation of the chessboard, i.e., do not rotate it more than ~15-30 degrees with respect to its center (i.e., going from a `w` x `h` number of squares to a `h` x `w` one). Our algorithm assumes that the origin is the corner at the top left, so rotating the chessboard will change this origin across frames, resulting in many frames being rejected for the final calibration, i.e., lower calibration accuracy.\n2. Cover several distances, and within each distance, cover all parts of the image view (all corners and center).\n3. Save the images in PNG format (default behavior) in order to improve calibration quality. PNG images are bigger than JPG equivalent, but do not lose information by compression.\n4. Use a chessboard as big as possible, ideally a chessboard with of at least 8x6 squares with a square size of at least 100 millimeters. It will specially affect the extrinsic calibration quality.\n5. Intrinsics: Recommended about 400 image views for high quality calibration. You should get at least 150 images for a good calibration, while no more than 500. The calibration of a camera takes about 3 minutes with about 100 images, about 1.5h with 200 images, and about 9.5h with 450 images. Required RAM memory also grows exponentially.\n6. Extrinsics: Recommended at least 250 images per camera for high quality calibration.\n\n### Step 1 - Distortion and Intrinsic Parameter Calibration\n1. Run OpenPose and save images for your desired camera. Use a grid (chessboard) pattern and move around all the image area. Depending on the images source:\n    1. Webcam calibration: `./build/examples/openpose/openpose.bin --num_gpu 0 --write_images {intrinsic_images_folder_path}`.\n    2. Flir camera calibration: Add the flags `--flir_camera --flir_camera_index 0` (or the desired flir camera index) to the webcam command.\n    3. Calibration from video sequence: Add the flag `--video {video_path}` to the webcam command.\n    4. Any other camera brand: Simply save your images in `{intrinsic_images_folder_path}`, file names are not relevant.\n2. Get familiar with the calibration parameters used in point 3 (i.e., `grid_square_size_mm`, `grid_number_inner_corners`, etc.) by running the `--help` flag:\n```sh\n./build/examples/calibration/calibration.bin --help\n```\n3. Extract and save the intrinsic parameters:\n```sh\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 40.0 --grid_number_inner_corners \"9x5\" --camera_serial_number 18079958 --calibration_image_dir {intrinsic_images_folder_path}\n```\n4. In this case, the intrinsic parameters would have been generated as `{intrinsic_images_folder_path}/18079958.xml`.\n5. Run steps 1-4 for each one of your cameras.\n6. After you calibrate the camera intrinsics, when you run OpenPose with those cameras, you should see the lines in real-life to be (almost) perfect lines in the image. Otherwise, the calibration was not good. Try checking straight patterns such us wall or ceiling edges:\n```sh\n# With distortion (straight lines might not look as straight lines but rather with a more circular shape)\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 0\n# Without distortion (straight lines should look as straight lines)\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 0 --frame_undistort\n```\n\nExamples:\n\n1. Full example for a folder of images, a video, webcam streaming, etc.:\n```sh\n# Ubuntu and Mac\n# Get images for calibration (only if target is not `--image_dir`)\n    # If video\n./build/examples/openpose/openpose.bin --num_gpu 0 --video examples/media/video_chessboard.avi --write_images ~/Desktop/Calib_intrinsics\n    # If webcam\n./build/examples/openpose/openpose.bin --num_gpu 0 --webcam --write_images ~/Desktop/Calib_intrinsics\n# Run calibration\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 30.0 --grid_number_inner_corners \"8x6\" --calibration_image_dir ~/Desktop/Calib_intrinsics/ --camera_parameter_folder models/cameraParameters/ --camera_serial_number frame_intrinsics\n# Output: {OpenPose path}/models/cameraParameters/frame_intrinsics.xml\n# Visualize undistorted images\n./build/examples/openpose/openpose.bin --num_gpu 0 --image_dir ~/Desktop/Calib_intrinsics/ --frame_undistort --camera_parameter_path \"models/cameraParameters/frame_intrinsics.xml\"\n# If video\n./build/examples/openpose/openpose.bin --num_gpu 0 --video examples/media/video_chessboard.avi --frame_undistort --camera_parameter_path \"models/cameraParameters/frame_intrinsics.xml\"\n# If webcam\n./build/examples/openpose/openpose.bin --num_gpu 0 --webcam --frame_undistort --camera_parameter_path \"models/cameraParameters/frame_intrinsics.xml\"\n```\n\n2. Full example for 4-view Flir/Point Grey camera system:\n```sh\n# Ubuntu and Mac\n# Get images for calibration\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 0 --write_images ~/Desktop/intrinsics_0\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 1 --write_images ~/Desktop/intrinsics_1\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 2 --write_images ~/Desktop/intrinsics_2\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --flir_camera_index 3 --write_images ~/Desktop/intrinsics_3\n# Run calibration\n#     - Note: If your computer has enough RAM memory, you can run all of them at the same time in order to speed up the time (they are not internally multi-threaded).\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 127.0 --grid_number_inner_corners \"9x6\" --camera_serial_number 17012332 --calibration_image_dir ~/Desktop/intrinsics_0\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 127.0 --grid_number_inner_corners \"9x6\" --camera_serial_number 17092861 --calibration_image_dir ~/Desktop/intrinsics_1\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 127.0 --grid_number_inner_corners \"9x6\" --camera_serial_number 17092865 --calibration_image_dir ~/Desktop/intrinsics_2\n./build/examples/calibration/calibration.bin --mode 1 --grid_square_size_mm 127.0 --grid_number_inner_corners \"9x6\" --camera_serial_number 18079957 --calibration_image_dir ~/Desktop/intrinsics_3\n# Visualize undistorted images\n#     - Camera parameters will be saved on their respective serial number files, so OpenPose will automatically find them\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --frame_undistort\n```\n\n3. For Windows, simply run `build\\x64\\Release\\calibration.exe` (or the one from the binary portable demo) with the same flags as above.\n\n\n\n### Step 2 - Extrinsic Parameter Calibration\n1. **VERY IMPORTANT NOTE**: If you want to re-run the extrinsic parameter calibration over the same intrinsic XML files (e.g., if you move the camera location, but you know the instrinsics are the same), you must manually re-set to `1 0 0 0  0 1 0 0  0 0 1 0` the camera matrix of each XML file that will be used for `--combine_cam0_extrinsics`.\n2. After intrinsics calibration, save undistorted images for all the camera views:\n```sh\n./build/examples/openpose/openpose.bin --num_gpu 0 --flir_camera --frame_undistort --write_images ~/Desktop/extrinsics\n```\n3. Run the extrinsic calibration tool between each pair of close cameras. In this example:\n\t- We assume camera 0 to the right, 1 in the middle-right, 2 in the middle-left, and 3 in the left.\n\t- We assume camera 1 as the coordinate origin.\n```sh\n# Ubuntu and Mac\n./build/examples/calibration/calibration.bin --mode 2 --grid_square_size_mm 127.0 --grid_number_inner_corners 9x6 --omit_distortion --calibration_image_dir ~/Desktop/extrinsics/ --cam0 1 --cam1 0\n./build/examples/calibration/calibration.bin --mode 2 --grid_square_size_mm 127.0 --grid_number_inner_corners 9x6 --omit_distortion --calibration_image_dir ~/Desktop/extrinsics/ --cam0 1 --cam1 2\n./build/examples/calibration/calibration.bin --mode 2 --grid_square_size_mm 127.0 --grid_number_inner_corners 9x6 --omit_distortion --calibration_image_dir ~/Desktop/extrinsics/ --cam0 1 --cam1 3\n# Potentially more accurate equivalent for the calibration between cameras 1 and 3: If camera 3 and 1 are too far from each other and the calibration chessboard is not visible from both cameras at the same time enough times, the calibration can be run between camera 3 and camera 2, which is closer to 3. In that case, the `combine_cam0_extrinsics` flag is required, which tells the calibration toolbox that cam0 is not the global origin (in this case is camera 1).\n# Note: Wait until calibration of camera index 2 with respect to 1 is completed, as information from camera 2 XML calibration file will be used:\n./build/examples/calibration/calibration.bin --mode 2 --grid_square_size_mm 127.0 --grid_number_inner_corners 9x6 --omit_distortion --calibration_image_dir ~/Desktop/extrinsics/ --cam0 2 --cam1 3 --combine_cam0_extrinsics\n```\n```\n:: Windows\n:: build\\x64\\Release\\calibration.exe with the same flags as above\n```\n4. If you use Ceres solver (`WITH_CERES` flag in CMake), you can improve the calibration results by performing an additional Bundle Adjustment refinement step on top of the previous results. We use camera 0 as the baseline for the internal computation, so try to avoid weird camera configurations in which camera 0 is completely isolated from the other cameras. Ideally, camera 0 should physically be the closest to all other cameras (i.e., the one more centered). But in practice, the accuracy improvement is almost none (as long as it is not too far from the others). To perform this bundle adjustment refinement for the example above, simply run the following line:\n```\n# Ubuntu and Mac\n./build/examples/calibration/calibration.bin --mode 3 --grid_square_size_mm 127.0 --grid_number_inner_corners 9x6 --omit_distortion --calibration_image_dir ~/Desktop/extrinsics/ --number_cameras 4\n```\n```\n:: Windows\n:: Ceres-compatible version not implemented for Windows yet. Make a pull request if you have a working version in Windows.\n```\n5. Hint to verify extrinsic calibration is successful:\n    1. Our final reprojection error (after rescaling) for the bundle adjustment step is usually about 0.1-0.15 pixels.\n    2. Translation vector - Global distance:\n        1. Manually open each one of the generated XML files from the folder indicated by the flag `--camera_parameter_path` (or the default one indicated by the `--help` flag if the former was not used).\n        2. The field `CameraMatrix` is a 3 x 4 matrix (you can see that the subfield `rows` in that file is 3 and `cols` is 4).\n        3. Order the matrix in that 3 x 4 shape (e.g., by copying in a different text file with the shape of 3 rows and 4 columns).\n        4. The 3 first components of the last column of the `CameraMatrix` field define the global `translation` (in meters) with respect to the global origin (in our case camera 1).\n        5. Thus, the distance between that camera and the origin camera 1 should be (approximately) equal to the L2-norm of the `translation` vector.\n    3. Translation vector - Relative x-y-z distances:\n        1. The 3x1 `translation` vector represents the `x`, `y`, and `z` distances to the origin camera, respectively. The camera is looking along the positive `z` axis, the `y` axis is down, and the `x` axis is right. This should match the real distance between both cameras.\n\n\n\n## Camera Matrix Output Format\nYour CameraMatrix will look something like:\n```\n<CameraMatrix type_id=\"opencv-matrix\">\n<rows>3</rows>\n<cols>4</cols>\n<dt>d</dt>\n<data>\n    8.4965260991319647e-01 1.1164693980389649e-01\n    -5.1538859446064478e-01 2.1494190603291283e+00\n    -1.5848315388246692e-01 9.8621217567379460e-01\n    -4.7630184633558698e-02 -4.5237471366168569e-01\n    5.0296474270386005e-01 1.2214952060972525e-01 8.5563190813085876e-01\n    1.1418502919988400e+00</data></CameraMatrix>\n```\nThis is a 3x4 matrix, which represents rotation (R as a 3x3 matrix) and translation (t as a 3x1 matrix) in the following format: [R | t]. They represent the rotation and translation with respect to the world origin. When calibrating with OpenPose, we set one of the cameras as the origin, but this can be easily modified with some manual post-processing.\n\n\n\n## Using a Different Camera Brand\nIf you plan to use the calibration tool without using OpenPose, you can manually save a video sequence of your desired camera into each of the camera image folders (i.e., in the above example, the `~/Desktop/intrinsics_0`, `~/Desktop/intrinsics_1`, etc. folders).\n\nIf you wanna eventually run that camera with OpenPose, check [doc/advanced/3d_reconstruction_module.md#using-a-different-camera-brand](../advanced/3d_reconstruction_module.md#using-a-different-camera-brand).\n\n\n\n## Naming Convention for the Output Images\nThe naming convention for the saved images is the following: `[%12d]_rendered[CAMERA_NUMBER_MINUS_1].png`, where `[CAMERA_NUMBER_MINUS_1]` is nothing for camera 0, `_1` for camera 1, `_2` for camera 2, etc. E.g., for 4 cameras:\n```\n000000000000_rendered.png\n000000000000_rendered_1.png\n000000000000_rendered_2.png\n000000000000_rendered_3.png\n000000000001_rendered.png\n000000000001_rendered_1.png\n000000000001_rendered_2.png\n000000000001_rendered_3.png\n[...]\n```\n\nOpenPose generates them with the base name `[%12d]_rendered`. Ideally, any other base number should work as long as the termination `[CAMERA_NUMBER_MINUS_1]` is kept consistent for all the camera views. E.g., you could call them also as follows (assuming 4 cameras):\n```\na.png, a_1.png, a_2.png, a_3.png,\nb.png, b_1.png, b_2.png, b_3.png,\netc.\n```\n\nAgain, the critical step is to keep the file termination fixed as `_1`, `_2`, etc.\n"
  },
  {
    "path": "doc/advanced/demo_advanced.md",
    "content": "OpenPose Advanced Doc - Demo - Advanced\n====================================\n\nThis document is a more detailed continuation of [doc/01_demo.md](../01_demo.md), and it assumes the user is quite familiar with the OpenPose demo and the contents of [doc/01_demo.md](../01_demo.md).\n\n\n\n## Contents\n1. [More Advanced Common Settings](#more-advanced-common-settings)\n\t1. [Reducing Latency/Lag](#reducing-latencylag)\n\t2. [Advanced Hands](#advanced-hands)\n\t3. [Rendering Face and Hands without Pose](#rendering-face-and-hands-without-pose)\n\t4. [Debugging Information](#debugging-information)\n\t5. [Heat Maps Storing](#heat-maps-storing)\n\t6. [BODY_25 vs. COCO vs. MPI Models](#body-25-vs-coco-vs-mpi-models)\n2. [Help Flag](#help-flag)\n3. [All Flags](#all-flags)\n\n\n\n\n\n## More Advanced Common Settings\n### Reducing Latency/Lag\nIn general, there are 3 ways to reduce the latency (with some drawbacks each one):\n\n- Reducing `--output_resolution`: It will slightly reduce the latency and increase the FPS. But the quality of the displayed image will deteriorate.\n- Reducing `--net_resolution` and/or `--face_net_resolution` and/or `--hand_net_resolution`: It will increase the FPS and reduce the latency. But the accuracy will drop, specially for small people in the image. Note: For maximum accuracy, follow [doc/01_demo.md#maximum-accuracy-configuration](../01_demo.md#maximum-accuracy-configuration).\n- Enabling `--disable_multi_thread`: The latency should be reduced. But the speed will drop to 1-GPU speed (as it will only use 1 GPU). Note that it's practical only for body, if hands and face are also extracted, it's usually not worth it.\n\n\n\n### Advanced Hands\n```\n# Fast method for speed\n./build/examples/openpose/openpose.bin --hand\n# Best results found with 6 scales\n./build/examples/openpose/openpose.bin --hand --hand_scale_number 6 --hand_scale_range 0.4\n# Adding tracking to Webcam (if FPS per GPU > 10 FPS) and Video\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --hand --hand_detector 3\n# Multi-scale + tracking is also possible\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --hand --hand_scale_number 6 --hand_scale_range 0.4 --hand_detector 3\n```\n\n\n\n### Rendering Face and Hands without Pose\n```\n# CPU rendering (faster)\n./build/examples/openpose/openpose.bin --render_pose 0 --face --face_render 1 --hand --hand_render 1\n# GPU rendering\n./build/examples/openpose/openpose.bin --render_pose 0 --face --face_render 2 --hand --hand_render 2\n```\n\n\n\n### Debugging Information\n```\n# Basic information\n./build/examples/openpose/openpose.bin --logging_level 3\n# Showing all messages\n./build/examples/openpose/openpose.bin --logging_level 0\n```\n\n\n\n### Heat Maps Storing\nThe following command will save all the body part heat maps, background heat map and Part Affinity Fields (PAFs) in the folder `output_heatmaps_folder`. It will save them on PNG format. Instead of individually saving each of the 67 heatmaps (18 body parts + background + 2 x 19 PAFs) individually, the library concatenate them vertically into a huge (width x #heatmaps) x (height) matrix. The PAFs channels are multiplied by 2 because there is one heatmpa for the x-coordinates and one for the y-coordinates. The order is body parts + bkg + PAFs. It will follow the sequence on POSE_BODY_PART_MAPPING in [include/openpose/pose/poseParameters.hpp](../../include/openpose/pose/poseParameters.hpp).\n```\n./build/examples/openpose/openpose.bin --video examples/media/video.avi --heatmaps_add_parts --heatmaps_add_bkg --heatmaps_add_PAFs --write_heatmaps output_heatmaps_folder/\n```\n\n\n\n### BODY_25 vs. COCO vs. MPI Models\nThe `BODY_25` model (`--model_pose BODY_25`) includes both body and foot keypoints and it is based in [OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1812.08008). COCO and MPI models are slower, less accurate, and do not contain foot keypoints. They are based in our older paper [Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields](https://arxiv.org/abs/1611.08050). We highly recommend only using the `BODY_25` model.\n\nThere is an exception, for CPU version, the COCO and MPI models seems to be faster. Accuracy is still better for the `BODY_25` model.\n\n\n\n\n\n## Help Flag\nWe recommend following the next section (`All Flags`), which shows all the flags in this document and sorts them by category.\n\nHowever, you could add the flag `--help` at any point to see all the available OpenPose flags. Check only the flags for `examples/openpose/openpose.cpp` itself (i.e., the ones in the section `Flags from examples/openpose/openpose.cpp:`).\n```\n# Ubuntu and Mac\n./build/examples/openpose/openpose.bin --help\n```\n```\n:: Windows - Portable Demo\nbin\\OpenPoseDemo.exe --help\n```\n\n\n\n\n\n## All Flags\nNow that you are more familiar with OpenPose, this is a list with all the available flags. Each one is divided into flag name, default value, and description.\n\n1. Debugging/Other\n- DEFINE_int32(logging_level,             3,              \"The logging level. Integer in the range [0, 255]. 0 will output any opLog() message, while 255 will not output any. Current OpenPose library messages are in the range 0-4: 1 for low priority messages and 4 for important ones.\");\n- DEFINE_bool(disable_multi_thread,       false,          \"It would slightly reduce the frame rate in order to highly reduce the lag. Mainly useful for 1) Cases where it is needed a low latency (e.g., webcam in real-time scenarios with low-range GPU devices); and 2) Debugging OpenPose when it is crashing to locate the error.\");\n- DEFINE_int32(profile_speed,             1000,           \"If PROFILER_ENABLED was set in CMake or Makefile.config files, OpenPose will show some runtime statistics at this frame number.\");\n\n2. Producer\n- DEFINE_int32(camera,                    -1,             \"The camera index for cv::VideoCapture. Integer in the range [0, 9]. Select a negative number (by default), to auto-detect and open the first available camera.\");\n- DEFINE_string(camera_resolution,        \"-1x-1\",        \"Set the camera resolution (either `--camera` or `--flir_camera`). `-1x-1` will use the default 1280x720 for `--camera`, or the maximum flir camera resolution available for `--flir_camera`\");\n- DEFINE_string(video,                    \"\",             \"Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video.\");\n- DEFINE_string(image_dir,                \"\",             \"Process a directory of images. Use `examples/media/` for our default example folder with 20 images. Read all standard formats (jpg, png, bmp, etc.).\");\n- DEFINE_bool(flir_camera,                false,          \"Whether to use FLIR (Point-Grey) stereo camera.\");\n- DEFINE_int32(flir_camera_index,         -1,             \"Select -1 (default) to run on all detected flir cameras at once. Otherwise, select the flir camera index to run, where 0 corresponds to the detected flir camera with the lowest serial number, and `n` to the `n`-th lowest serial number camera.\");\n- DEFINE_string(ip_camera,                \"\",             \"String with the IP camera URL. It supports protocols like RTSP and HTTP.\");\n- DEFINE_uint64(frame_first,              0,              \"Start on desired frame number. Indexes are 0-based, i.e., the first frame has index 0.\");\n- DEFINE_uint64(frame_step,               1,              \"Step or gap between processed frames. E.g., `--frame_step 5` would read and process frames 0, 5, 10, etc..\");\n- DEFINE_uint64(frame_last,               -1,             \"Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g., if set to 10, it will process 11 frames (0-10).\");\n- DEFINE_bool(frame_flip,                 false,          \"Flip/mirror each frame (e.g., for real time webcam demonstrations).\");\n- DEFINE_int32(frame_rotate,              0,              \"Rotate each frame, 4 possible values: 0, 90, 180, 270.\");\n- DEFINE_bool(frames_repeat,              false,          \"Repeat frames when finished.\");\n- DEFINE_bool(process_real_time,          false,          \"Enable to keep the original source frame rate (e.g., for video). If the processing time is too long, it will skip frames. If it is too fast, it will slow it down.\");\n- DEFINE_string(camera_parameter_path,    \"models/cameraParameters/flir\", \"String with the folder where the camera parameters are located. If there is only 1 XML file (for single video, webcam, or images from the same camera), you must specify the whole XML file path (ending in .xml).\");\n- DEFINE_bool(frame_undistort,            false,          \"If false (default), it will not undistort the image, if true, it will undistortionate them based on the camera parameters found in `camera_parameter_path`\");\n\n3. OpenPose\n- DEFINE_string(model_folder,             \"models/\",      \"Folder path (absolute or relative) where the models (pose, face, ...) are located.\");\n- DEFINE_string(prototxt_path,            \"\",             \"The combination `--model_folder` + `--prototxt_path` represents the whole path to the prototxt file. If empty, it will use the default OpenPose ProtoTxt file.\");\n- DEFINE_string(caffemodel_path,          \"\",             \"The combination `--model_folder` + `--caffemodel_path` represents the whole path to the caffemodel file. If empty, it will use the default OpenPose CaffeModel file.\");\n- DEFINE_string(output_resolution,        \"-1x-1\",        \"The image resolution (display and output). Use \\\"-1x-1\\\" to force the program to use the input image resolution.\");\n- DEFINE_int32(num_gpu,                   -1,             \"The number of GPU devices to use. If negative, it will use all the available GPUs in your machine.\");\n- DEFINE_int32(num_gpu_start,             0,              \"GPU device start number.\");\n- DEFINE_int32(keypoint_scale,            0,              \"Scaling of the (x,y) coordinates of the final pose data array, i.e., the scale of the (x,y) coordinates that will be saved with the `write_json` & `write_keypoint` flags. Select `0` to scale it to the original source resolution; `1`to scale it to the net output size (set with `net_resolution`); `2` to scale it to the final output size (set with `resolution`); `3` to scale it in the range [0,1], where (0,0) would be the top-left corner of the image, and (1,1) the bottom-right one; and 4 for range [-1,1], where (-1,-1) would be the top-left corner of the image, and (1,1) the bottom-right one. Non related with `scale_number` and `scale_gap`.\");\n- DEFINE_int32(number_people_max,         -1,             \"This parameter will limit the maximum number of people detected, by keeping the people with top scores. The score is based in person area over the image, body part score, as well as joint score (between each pair of connected body parts). Useful if you know the exact number of people in the scene, so it can remove false positives (if all the people have been detected. However, it might also include false negatives by removing very small or highly occluded people. -1 will keep them all.\");\n- DEFINE_bool(maximize_positives,         false,          \"It reduces the thresholds to accept a person candidate. It highly increases both false and true positives. I.e., it maximizes average recall but could harm average precision.\");\n- DEFINE_double(fps_max,                  -1.,            \"Maximum processing frame rate. By default (-1), OpenPose will process frames as fast as possible. Example usage: If OpenPose is displaying images too quickly, this can reduce the speed so the user can analyze better each frame from the GUI.\");\n\n4. OpenPose Body Pose\n- DEFINE_int32(body,                      1,              \"Select 0 to disable body keypoint detection (e.g., for faster but less accurate face keypoint detection, custom hand detector, etc.), 1 (default) for body keypoint estimation, and 2 to disable its internal body pose estimation network but still still run the greedy association parsing algorithm\");\n- DEFINE_string(model_pose,               \"BODY_25\",      \"Model to be used. E.g., `BODY_25` (fastest for CUDA version, most accurate, and includes foot keypoints), `COCO` (18 keypoints), `MPI` (15 keypoints, least accurate model but fastest on CPU), `MPI_4_layers` (15 keypoints, even faster but less accurate).\");\n- DEFINE_string(net_resolution,           \"-1x368\",       \"Multiples of 16. If it is increased, the accuracy potentially increases. If it is decreased, the speed increases. For maximum speed-accuracy balance, it should keep the closest aspect ratio possible to the images or videos to be processed. Using `-1` in any of the dimensions, OP will choose the optimal aspect ratio depending on the user's input value. E.g., the default `-1x368` is equivalent to `656x368` in 16:9 resolutions, e.g., full HD (1980x1080) and HD (1280x720) resolutions.\");\n- DEFINE_double(net_resolution_dynamic,   1.,             \"This flag only applies to images or custom inputs (not to video or webcam). If it is zero or a negativevalue, it means that using `-1` in `net_resolution` will behave as explained in its description. Otherwise, and to avoid out of memory errors, the `-1` in `net_resolution` will clip to this value times the default 16/9 aspect ratio value (which is 656 width for a 368 height). E.g., `net_resolution_dynamic 10 net_resolution -1x368` will clip to 6560x368 (10 x 656). Recommended 1 for small GPUs (to avoid out of memory errors but maximize speed) and 0 for big GPUs (for maximum accuracy and speed).\");\n- DEFINE_int32(scale_number,              1,              \"Number of scales to average.\");\n- DEFINE_double(scale_gap,                0.25,           \"Scale gap between scales. No effect unless scale_number > 1. Initial scale is always 1. If you want to change the initial scale, you actually want to multiply the `net_resolution` by your desired initial scale.\");\n- DEFINE_double(upsampling_ratio,         0.,             \"Upsampling ratio between the `net_resolution` and the output net results. A value less or equal than 0 (default) will use the network default value (recommended).\");\n\n5. OpenPose Body Pose Heatmaps and Part Candidates\n- DEFINE_bool(heatmaps_add_parts,         false,          \"If true, it will fill op::Datum::poseHeatMaps array with the body part heatmaps, and analogously face & hand heatmaps to op::Datum::faceHeatMaps & op::Datum::handHeatMaps. If more than one `add_heatmaps_X` flag is enabled, it will place then in sequential memory order: body parts + bkg + PAFs. It will follow the order on POSE_BODY_PART_MAPPING in `src/openpose/pose/poseParameters.cpp`. Program speed will considerably decrease. Not required for OpenPose, enable it only if you intend to explicitly use this information later.\");\n- DEFINE_bool(heatmaps_add_bkg,           false,          \"Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to background.\");\n- DEFINE_bool(heatmaps_add_PAFs,          false,          \"Same functionality as `add_heatmaps_parts`, but adding the PAFs.\");\n- DEFINE_int32(heatmaps_scale,            2,              \"Set 0 to scale op::Datum::poseHeatMaps in the range [-1,1], 1 for [0,1]; 2 for integer rounded [0,255]; and 3 for no scaling.\");\n- DEFINE_bool(part_candidates,            false,          \"Also enable `write_json` in order to save this information. If true, it will fill the op::Datum::poseCandidates array with the body part candidates. Candidates refer to all the detected body parts, before being assembled into people. Note that the number of candidates is equal or higher than the number of final body parts (i.e., after being assembled into people). The empty body parts are filled with 0s. Program speed will slightly decrease. Not required for OpenPose, enable it only if you intend to explicitly use this information.\");\n\n6. OpenPose Face\n- DEFINE_bool(face,                       false,          \"Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`. Note that this will considerable slow down the performance and increase the required GPU memory. In addition, the greater number of people on the image, the slower OpenPose will be.\");\n- DEFINE_int32(face_detector,             0,              \"Kind of face rectangle detector. Select 0 (default) to select OpenPose body detector (most accurate one and fastest one if body is enabled), 1 to select OpenCV face detector (not implemented for hands), 2 to indicate that it will be provided by the user, or 3 to also apply hand tracking (only for hand). Hand tracking might improve hand keypoint detection for webcam (if the frame rate is high enough, i.e., >7 FPS per GPU) and video. This is not person ID tracking, it simply looks for hands in positions at which hands were located in previous frames, but it does not guarantee the same person ID among frames.\");\n- DEFINE_string(face_net_resolution,      \"368x368\",      \"Multiples of 16 and squared. Analogous to `net_resolution` but applied to the face keypoint detector. 320x320 usually works fine while giving a substantial speed up when multiple faces on the image.\");\n\n7. OpenPose Hand\n- DEFINE_bool(hand,                       false,          \"Enables hand keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`. Analogously to `--face`, it will also slow down the performance, increase the required GPU memory and its speed depends on the number of people.\");\n- DEFINE_int32(hand_detector,             0,              \"Kind of hand rectangle detector. Analogous to `--face_detector`.\");\n- DEFINE_string(hand_net_resolution,      \"368x368\",      \"Multiples of 16 and squared. Analogous to `net_resolution` but applied to the hand keypoint detector.\");\n- DEFINE_int32(hand_scale_number,         1,              \"Analogous to `scale_number` but applied to the hand keypoint detector. Our best results were found with `hand_scale_number` = 6 and `hand_scale_range` = 0.4.\");\n- DEFINE_double(hand_scale_range,         0.4,            \"Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range between smallest and biggest scale. The scales will be centered in ratio 1. E.g., if scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2.\");\n\n8. OpenPose 3-D Reconstruction\n- DEFINE_bool(3d,                         false,          \"Running OpenPose 3-D reconstruction demo: 1) Reading from a stereo camera system. 2) Performing 3-D reconstruction from the multiple views. 3) Displaying 3-D reconstruction results. Note that it will only display 1 person. If multiple people is present, it will fail.\");\n- DEFINE_int32(3d_min_views,              -1,             \"Minimum number of views required to reconstruct each keypoint. By default (-1), it will require max(2, min(4, #cameras-1)) cameras to see the keypoint in order to reconstruct it.\");\n- DEFINE_int32(3d_views,                  -1,             \"Complementary option for `--image_dir` or `--video`. OpenPose will read as many images per iteration, allowing tasks such as stereo camera processing (`--3d`). Note that `--camera_parameter_path` must be set. OpenPose must find as many `xml` files in the parameter folder as this number indicates.\");\n\n9. Extra algorithms\n- DEFINE_bool(identification,             false,          \"Experimental, not available yet. Whether to enable people identification across frames.\");\n- DEFINE_int32(tracking,                  -1,             \"Experimental, not available yet. Whether to enable people tracking across frames. The value indicates the number of frames where tracking is run between each OpenPose keypoint detection. Select -1 (default) to disable it or 0 to run simultaneously OpenPose keypoint detector and tracking for potentially higher accuracy than only OpenPose.\");\n- DEFINE_int32(ik_threads,                0,              \"Experimental, not available yet. Whether to enable inverse kinematics (IK) from 3-D keypoints to obtain 3-D joint angles. By default (0 threads), it is disabled. Increasing the number of threads will increase the speed but also the global system latency.\");\n\n10. OpenPose Rendering\n- DEFINE_int32(part_to_show,              0,              \"Prediction channel to visualize: 0 (default) for all the body parts, 1 for the background heat map, 2 for the superposition of heatmaps, 3 for the superposition of PAFs, 4-(4+#keypoints) for each body part heat map, the following ones for each body part pair PAF.\");\n- DEFINE_bool(disable_blending,           false,          \"If enabled, it will render the results (keypoint skeletons or heatmaps) on a black background, instead of being rendered into the original image. Related: `part_to_show`, `alpha_pose`, and `alpha_pose`.\");\n\n11. OpenPose Rendering Pose\n- DEFINE_double(render_threshold,         0.05,           \"Only estimated keypoints whose score confidences are higher than this threshold will be rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results. Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong detections).\");\n- DEFINE_int32(render_pose,               -1,             \"Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering (slower but greater functionality, e.g., `alpha_X` flags). If -1, it will pick CPU if CPU_ONLY is enabled, or GPU if CUDA is enabled. If rendering is enabled, it will render both `outputData` and `cvOutputData` with the original image and desired body part to be shown (i.e., keypoints, heat maps or PAFs).\");\n- DEFINE_double(alpha_pose,               0.6,            \"Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it. Only valid for GPU rendering.\");\n- DEFINE_double(alpha_heatmap,            0.7,            \"Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame. Only valid for GPU rendering.\");\n\n12. OpenPose Rendering Face\n- DEFINE_double(face_render_threshold,    0.4,            \"Analogous to `render_threshold`, but applied to the face keypoints.\");\n- DEFINE_int32(face_render,               -1,             \"Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same configuration that `render_pose` is using.\");\n- DEFINE_double(face_alpha_pose,          0.6,            \"Analogous to `alpha_pose` but applied to face.\");\n- DEFINE_double(face_alpha_heatmap,       0.7,            \"Analogous to `alpha_heatmap` but applied to face.\");\n\n13. OpenPose Rendering Hand\n- DEFINE_double(hand_render_threshold,    0.2,            \"Analogous to `render_threshold`, but applied to the hand keypoints.\");\n- DEFINE_int32(hand_render,               -1,             \"Analogous to `render_pose` but applied to the hand. Extra option: -1 to use the same configuration that `render_pose` is using.\");\n- DEFINE_double(hand_alpha_pose,          0.6,            \"Analogous to `alpha_pose` but applied to hand.\");\n- DEFINE_double(hand_alpha_heatmap,       0.7,            \"Analogous to `alpha_heatmap` but applied to hand.\");\n\n14. Display\n- DEFINE_bool(fullscreen,                 false,          \"Run in full-screen mode (press f during runtime to toggle).\");\n- DEFINE_bool(no_gui_verbose,             false,          \"Do not write text on output images on GUI (e.g., number of current frame and people). It does not affect the pose rendering.\");\n- DEFINE_int32(display,                   -1,             \"Display mode: -1 for automatic selection; 0 for no display (useful if there is no X server and/or to slightly speed up the processing if visual output is not required); 2 for 2-D display; 3 for 3-D display (if `--3d` enabled); and 1 for both 2-D and 3-D display.\");\n\n15. Command Line Interface Verbose\n- DEFINE_double(cli_verbose,              -1.f,           \"If -1, it will be disabled (default). If it is a positive integer number, it will print on the command line every `verbose` frames. If number in the range (0,1), it will print the progress every `verbose` times the total of frames.\");\n\n16. Result Saving\n- DEFINE_string(write_images,             \"\",             \"Directory to write rendered frames in `write_images_format` image format.\");\n- DEFINE_string(write_images_format,      \"png\",          \"File extension and format for `write_images`, e.g., png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible extensions.\");\n- DEFINE_string(write_video,              \"\",             \"Full file path to write rendered frames in motion JPEG video format. It might fail if the final path does not finish in `.avi`. It internally uses cv::VideoWriter. Flag `write_video_fps` controls FPS. Alternatively, the video extension can be `.mp4`, resulting in a file with a much smaller size and allowing `--write_video_with_audio`. However, that would require: 1) Ubuntu or Mac system, 2) FFmpeg library installed (`sudo apt-get install ffmpeg`), 3) the creation temporarily of a folder with the same file path than the final video (without the extension) to storage the intermediate frames that will later be used to generate the final MP4 video.\");\n- DEFINE_double(write_video_fps,          -1.,            \"Frame rate for the recorded video. By default, it will try to get the input frames producer frame rate (e.g., input video or webcam frame rate). If the input frames producer does not have a set FPS (e.g., image_dir or webcam if OpenCV not compiled with its support), set this value accordingly (e.g., to the frame rate displayed by the OpenPose GUI).\");\n- DEFINE_bool(write_video_with_audio,     false,          \"If the input is video and the output is so too, it will save the video with audio. It requires the output video file path finishing in `.mp4` format (see `write_video` for details).\");\n- DEFINE_string(write_video_3d,           \"\",             \"Analogous to `--write_video`, but applied to the 3D output.\");\n- DEFINE_string(write_video_adam,         \"\",             \"Experimental, not available yet. Analogous to `--write_video`, but applied to Adam model.\");\n- DEFINE_string(write_json,               \"\",             \"Directory to write OpenPose output in JSON format. It includes body, hand, and face pose keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).\");\n- DEFINE_string(write_coco_json,          \"\",             \"Full file path to write people pose data with JSON COCO validation format. If foot, face, hands, etc. JSON is also desired (`--write_coco_json_variants`), they are saved with different file name suffix.\");\n- DEFINE_int32(write_coco_json_variants,  1,              \"Add 1 for body, add 2 for foot, 4 for face, and/or 8 for hands. Use 0 to use all the possible candidates. E.g., 7 would mean body+foot+face COCO JSON.\");\n- DEFINE_int32(write_coco_json_variant,   0,              \"Currently, this option is experimental and only makes effect on car JSON generation. It selects the COCO variant for cocoJsonSaver.\");\n- DEFINE_string(write_heatmaps,           \"\",             \"Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag must be enabled.\");\n- DEFINE_string(write_heatmaps_format,    \"png\",          \"File extension and format for `write_heatmaps`, analogous to `write_images_format`. For lossless compression, recommended `png` for integer `heatmaps_scale` and `float` for floating values. See `doc/02_output.md` for more details.\");\n- DEFINE_string(write_keypoint,           \"\",             \"(Deprecated, use `write_json`) Directory to write the people pose keypoint data. Set format with `write_keypoint_format`.\");\n- DEFINE_string(write_keypoint_format,    \"yml\",          \"(Deprecated, use `write_json`) File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available for OpenCV < 3.0, use `write_json` instead.\");\n\n17. Result Saving - Extra Algorithms\n- DEFINE_string(write_bvh,                \"\",             \"Experimental, not available yet. E.g., `~/Desktop/mocapResult.bvh`.\");\n\n18. UDP Communication\n- DEFINE_string(udp_host,                 \"\",             \"Experimental, not available yet. IP for UDP communication. E.g., `192.168.0.1`.\");\n- DEFINE_string(udp_port,                 \"8051\",         \"Experimental, not available yet. Port number for UDP communication.\");\n"
  },
  {
    "path": "doc/advanced/deployment.md",
    "content": "OpenPose Advanced Doc - Deploying/Exporting OpenPose to Other Projects\n==========================\n\n## Contents\n1. [Introduction](#introduction)\n2. [Third-Party Libraries](#third-party-libraries)\n3. [Private OpenPose Include Directory](#private-openpose-include-directory)\n4. [Crash and Core Dumped Avoidance](#crash-and-core-dumped-avoidance)\n5. [Deploying OpenPose](#deploying-openpose)\n    1. [Windows](#windows)\n    2. [CMake (Windows, Ubuntu, and Mac)](#cmake-windows-ubuntu-and-mac)\n\n\n\n### Introduction\nStarting in OpenPose 1.6.0 (GitHub code in or after October 2019), OpenPose has considerable refactor its code to get rid of OpenCV in its headers. This makes OpenPose 1.6 headers different to previous versions and a bit harder to use. However, it allows OpenPose to be exported to other projects without requiring any third-party libraries (except in some special cases detailed below). The greatest benefit of this change: if your project already uses OpenCV, and you add your own version of OpenPose, the OpenCV version used in OpenPose and the one used in your project will not interfere with each other anymore, even if they are different versions!\n\n\n\n### Third-Party Libraries\nWhile compiling OpenPose from source, the static library files (`*.a` for Ubuntu, `*.lib` for Windows, etc.) and `include/` directories of all the third-party libraries detailed in [doc/installation/0_index.md](../installation/0_index.md) are required (GFlags, Glog, OpenCV, Caffe, etc.). However, when deploying OpenPose, fewer dependencies are required:\n- GFLags and Glog are required only if the `include/openpose/flags.hpp` file is going to be used (e.g., when intenting to use the command-line interface).\n- OpenCV can be optionally included if your project already uses it (but make sure to use the same binaries and include directory of OpenCV for both OpenPose and your project or weird runtime crashes will occur!). Including OpenCV does not increase the functionality of OpenPose, but it makes it easier to use by adding some functions that directly take cv::Mat matrices as input (rather than raw pointers). However, it is optional starting in OpenPose 1.6.0.\n- Caffe or any other 3rd-party libraries are not required.\n\nThe static library files (`*.a` for Ubuntu, `*.lib` for Windows, etc.) and `include/` directories are the files that must be included in your project settings. However, the runtime library files (`*.so` for Ubuntu, `*.dll` for Windows, etc.), which are always required, must simply be placed together with the final executable or in default system paths. I.e., these files are only used during runtime, so they do not require any configuration in your project settings. E.g., for Windows, you can simply copy the content of the auto-generated `build/bin/` directory into the path where your executable is located.\n\n\n\n### Private OpenPose Include Directory\nInside `include/`, there are 2 directories: `openpose/` and `openpose_private/`. Adding the `include_private` directory will require to include more libraries (e.g., OpenCV and Eigen). This directory exposes some extra functions used internally, but most of the cases this functionality is not required at all, so the `include/` directory should only contain the `openpose/` directory when exported.\n\nWindows-only: In addition, Windows users have to manually add `OP_API` to all the functions/classes from `openpose_private/` that he desires to use and then re-compile OpenPose.\n\n\n\n### Crash and Core Dumped Avoidance\nIf your project already uses OpenCV, and you add your own version of OpenPose, the OpenCV version of OpenPose and the one from your project will not interfere anymore, even if they are different versions. However, you cannot use the OpenCV functions of OpenPose from a different project if that project uses a different versions of OpenCV. Otherwise, very cryptic runtime DLL errors might occur! Make sure you either:\n- Compile OpenPose and your project with the same version of OpenCV.\n- Or if that is not possible (new since OpenPose 1.6.0), use the non-OpenCV analog functions of OpenPose to avoid cryptic DLL runtime crashes.\n\n\n\n## Deploying OpenPose\n### Windows\nFirst of all, make sure to read all the sections above.\n\nSecond, note that the CMake option should also work for Windows. Alternatively, we also show the more Windows-like version in which `*.dll`, `*.lib`, and `include/` files are copied, which might be easier to apply when using the portable binaries.\n\n\n\n### CMake (Windows, Ubuntu, and Mac)\nFirst of all, make sure to read all the sections above.\n\nIf you only intend to use the OpenPose demo, you might skip this step. This step is only recommended if you plan to use the OpenPose API from other projects.\n\nTo install the OpenPose headers and libraries into the system environment path (e.g., `/usr/local/` or `/usr/`), run the following command.\n```\ncd build/\nsudo make install\n```\n\nOnce the installation is completed, you can use OpenPose in your other project using the `find_package` cmake command. Below, is a small example `CMakeLists.txt`. In order to use this script, you also need to copy `FindGFlags.cmake` and `FindGlog.cmake` into your `<project_root_directory>/cmake/Modules/` (create the directory if necessary).\n```\ncmake_minimum_required(VERSION 2.8.7)\n\nadd_definitions(-std=c++11)\n\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules\")\n\nfind_package(GFlags)\nfind_package(Glog)\nfind_package(OpenCV)\nfind_package(OpenPose REQUIRED)\n\ninclude_directories(${OpenPose_INCLUDE_DIRS} ${GFLAGS_INCLUDE_DIR} ${GLOG_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS})\n\nadd_executable(example.bin example.cpp)\n\ntarget_link_libraries(example.bin ${OpenPose_LIBS} ${GFLAGS_LIBRARY} ${GLOG_LIBRARY} ${OpenCV_LIBS})\n```\n\nIf Caffe was built with OpenPose, it will automatically find it. Otherwise, you will need to link Caffe again as shown below (otherwise, you might get an error like `/usr/bin/ld: cannot find -lcaffe`).\n```\nlink_directories(<path_to_caffe_installation>/caffe/build/install/lib)\n```\n"
  },
  {
    "path": "doc/advanced/heatmap_output.md",
    "content": "OpenPose Advanced Doc - Heatmap Output\n====================================\n\n\n\n## Contents\n1. [Keypoints](#keypoints)\n2. [UI and Visual Heatmap Output](#ui-and-visual-heatmap-output)\n3. [Heatmap Ordering](#heatmap-ordering)\n4. [Heatmap Saving in Float Format](#heatmap-saving-in-float-format)\n5. [Heatmap Scaling](#heatmap-scaling)\n\n\n\n\n\n## Keypoints\nCheck [doc/output_keypoints.md](../02_output.md) for the basic output information. This document is for users that want to use the heatmaps.\n\n\n\n\n\n## UI and Visual Heatmap Output\nIf you choose to visualize a body part or a PAF (Part Affinity Field) heat map with the command option `--part_to_show`, the visual GUI should show something similar to one of the following images:\n<p align=\"center\">\n    <img src=\"../.github/media/body_heat_maps.png\" width=\"720\">\n</p>\n\n<p align=\"center\">\n    <img src=\"../.github/media/paf_heat_maps.png\" width=\"720\">\n</p>\n\n\n\n\n\n## Heatmap Ordering\nFor the **heat maps storing format**, instead of saving each of the 67 heatmaps (18 body parts + background + 2 x 19 PAFs) individually, the library concatenates them into a huge (width x #heat maps) x (height) matrix (i.e., concatenated by columns). E.g., columns [0, individual heat map width] contain the first heat map, columns [individual heat map width + 1, 2 * individual heat map width] contain the second heat map, etc. Note that some image viewers are not able to display the resulting images due to the size. However, Chrome and Firefox are able to properly open them.\n\nThe saving order is body parts + background + PAFs. Any of them can be disabled with program flags. If background is disabled, then the final image will be body parts + PAFs. The body parts and background follow the order of `getPoseBodyPartMapping(const PoseModel poseModel)`.\n\nThe PAFs follow the order specified on `getPosePartPairs(const PoseModel poseModel)` together with `getPoseMapIndex(const PoseModel poseModel)`. E.g., assuming COCO (see example code below), the PAF channels in COCO start in 19 (smallest number in `getPoseMapIndex`, equal to #body parts + 1), and end up in 56 (highest one). Then, we can match its value from `getPosePartPairs`. For instance, 19 (x-channel) and 20 (y-channel) in `getPoseMapIndex` correspond to PAF from body part 1 to 8; 21 and 22 correspond to x,y channels in the joint from body part 8 to 9, etc. Note that if the smallest channel is odd (19), then all the x-channels are odd, and all the y-channels even. If the smallest channel is even, then the opposite will happen.\n```\n// C++ API call\n#include <openpose/pose/poseParameters.hpp>\nconst auto& posePartPairsBody25 = getPosePartPairs(PoseModel::BODY_25);\nconst auto& posePartPairsCoco = getPosePartPairs(PoseModel::COCO_18);\nconst auto& posePartPairsMpi = getPosePartPairs(PoseModel::MPI_15);\n\n// getPosePartPairs(PoseModel::BODY_25) result\n// Each index is the key value corresponding to each body part in `getPoseBodyPartMapping`. E.g., 1 for \"Neck\", 2 for \"RShoulder\", etc.\n// 1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18,   14,19,19,20,14,21, 11,22,22,23,11,24\n\n// getPoseMapIndex(PoseModel::BODY_25) result\n// 0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29, 40,41,42,43,44,45, 46,47,48,49,50,51\n```\n\n\n\n## Heatmap Saving in Float Format\nIf you save the heatmaps in floating format by using the flag `--write_heatmaps_format float`, you can later read them in Python with:\n```\n# Load custom float format - Example in Python, assuming a (18 x 300 x 500) size Array\nx = np.fromfile(heatMapFullPath, dtype=np.float32)\nassert x[0] == 3 # First parameter saves the number of dimensions (18x300x500 = 3 dimensions)\nshape_x = x[1:1+int(x[0])]\nassert len(shape_x[0]) == 3 # Number of dimensions\nassert shape_x[0] == 18 # Size of the first dimension\nassert shape_x[1] == 300 # Size of the second dimension\nassert shape_x[2] == 500 # Size of the third dimension\narrayData = x[1+int(round(x[0])):]\n```\n\n\n\n## Heatmap Scaling\nNote that `--net_resolution` sets the size of the network, thus also the size of the output heatmaps. This heatmaps are resized while keeping the aspect ratio. When aspect ratio of the input and network are not the same, padding is added at the bottom and/or right part of the output heatmaps.\n"
  },
  {
    "path": "doc/advanced/standalone_face_or_hand_keypoint_detector.md",
    "content": "OpenPose Advanced Doc - Standalone Face or Hand Keypoint Detector\n====================================\n\nIn case of hand camera views at which the hands are visible but not the rest of the body, or if you do not need the body keypoint detector and want to speed up the process, you can use the OpenPose face or hand keypoint detectors with your own face or hand detectors, rather than using the body keypoint detector as initial detector for those.\n\n\n\n## OpenCV-based Face Keypoint Detector\nNote that this method will be faster than the current system if there is few people in the image, but it is also much less accurate (OpenCV face detector only works with big and frontal faces, while OpenPose works with more scales and face rotations).\n```\n./build/examples/openpose/openpose.bin --body 0 --face --face_detector 1\n```\n\n\n\n## Custom Standalone Face or Hand Keypoint Detector\nCheck the examples in `examples/tutorial_api_cpp/`, in particular [examples/tutorial_api_cpp/06_face_from_image.cpp](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/tutorial_api_cpp/06_face_from_image.cpp) and [examples/tutorial_api_cpp/07_hand_from_image.cpp](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/tutorial_api_cpp/07_hand_from_image.cpp). The provide examples of face and/or hand keypoint detection given a known bounding box or rectangle for the face and/or hand locations. These examples are equivalent to use the following flags:\n```\n# Face\nexamples/tutorial_api_cpp/06_face_from_image.cpp --body 0 --face --face_detector 2\n# Hands\nexamples/tutorial_api_cpp/07_hand_from_image.cpp --body 0 --hand --hand_detector 2\n```\n\nNote: both `FaceExtractor` and `HandExtractor` classes requires as input **squared rectangles**.\n\nAdvance solution: If you wanna use the whole OpenPose framework, you can use the synchronous examples of the `tutorial_api_cpp` folder with the configuration used for [examples/tutorial_api_cpp/06_face_from_image.cpp](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/tutorial_api_cpp/06_face_from_image.cpp) and [examples/tutorial_api_cpp/07_hand_from_image.cpp](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/tutorial_api_cpp/07_hand_from_image.cpp).\n\n\n\n## Cropping the Image for Hand/Face Keypoint Detection\nIf you are using your own hand or face images, you should leave about 10-20% margin between the end of the hand/face and the sides (left, top, right, bottom) of the image. We trained with that configuration, so it should be the ideal one for maximizing detection.\n\nWe did not use any solid-color-based padding, we simply cropped from the whole image. Thus, if you can, use the image rather than adding a color-based padding. Otherwise black padding should work good.\n"
  },
  {
    "path": "doc/installation/0_index.md",
    "content": "OpenPose Doc - Installation\n==========================\n\n## Contents\n1. [Operating Systems, Requirements, and Dependencies](#operating-systems-requirements-and-dependencies)\n2. [Windows Portable Demo](#windows-portable-demo)\n3. [Compiling and Running OpenPose from Source](#compiling-and-running-openpose-from-source)\n    1. [Problems and Errors Installing OpenPose](#problems-and-errors-installing-openpose)\n    2. [Prerequisites](#prerequisites)\n    3. [Clone OpenPose](#clone-openpose)\n    4. [CMake Configuration](#cmake-configuration)\n    5. [Compilation](#compilation)\n    6. [Running OpenPose](#running-openpose)\n    7. [Custom User Code](#custom-user-code)\n4. [Compiling and Running OpenPose from Source on ROS, Docker, and Google Colab - Community-Based Work](#compiling-and-running-openpose-from-source-on-ros-docker-and-google-colab---community-based-work)\n5. [OpenPose Live Demo at Tiyaro - Community-Based Work](#openpose-live-demo-from-tiyaro---community-based-work)\n6. [Uninstalling, Reinstalling, or Updating OpenPose](#uninstalling-reinstalling-or-updating-openpose)\n7. [Additional Settings (Optional)](#additional-settings-optional)\n\n\n\n\n\n## Operating Systems, Requirements, and Dependencies\n- Operating Systems\n    - **Windows 10**.\n    - **Ubuntu 20**.\n    - **Mac OSX** Mavericks and above.\n    - **Ubuntu 14, 16 and 18** as well as **Windows 7 and 8** are no longer officially maintained. However, they should still work (but might require minor changes).\n    - **Nvidia Jetson TX1** (for JetPack 3.1), installation instructions in [doc/installation/jetson_tx/installation_jetson_tx1.md](jetson_tx/installation_jetson_tx1.md).\n    - **Nvidia Jetson TX2** (for JetPack 3.1 or 3.3), installation instructions in [doc/installation/jetson_tx/installation_jetson_tx2_jetpack3.1.md](jetson_tx/installation_jetson_tx2_jetpack3.1.md) and [doc/installation/jetson_tx/installation_jetson_tx2_jetpack3.3.md](jetson_tx/installation_jetson_tx2_jetpack3.3.md) respectively.\n    - OpenPose has also been used on **CentOS** and other **Nvidia Jetson (TK1)** embedded systems. However, we do not officially support them at the moment.\n- **Requirements** for the default configuration\n    - CUDA (Nvidia GPU) version:\n        - NVIDIA graphics card with at least 1.6 GB available (the `nvidia-smi` command checks the available GPU memory in Ubuntu).\n        - At least 2.5 GB of free RAM memory for BODY_25 model or 2 GB for COCO model (assuming cuDNN installed).\n        - Highly recommended: cuDNN.\n    - OpenCL (AMD GPU) version:\n        - Vega series graphics card\n        - At least 2 GB of free RAM memory.\n    - CPU-only (no GPU) version:\n        - Around 8GB of free RAM memory.\n    - Highly recommended: a CPU with at least 8 cores.\n- Advanced tip: You might need more resources with a greater `--net_resolution` and/or `scale_number` or less resources by reducing the net resolution and/or using the MPI and MPI_4 models.\n- **Dependencies**:\n    - OpenCV (all 2.X and 3.X versions are compatible).\n    - Caffe and all its dependencies. Have you ported OpenPose into another DL framework (Tensorflow, Caffe2, Pytorch, ...)?. Email us (gines@alumni.cmu.edu) or feel free to make a pull request if you implemented any of those!\n    - The demo and tutorials additionally use GFlags.\n\n\n\n\n\n## Windows Portable Demo\n**If you just want to use OpenPose** without compiling or writing any code, simply use the latest portable version of OpenPose for Windows.\n1. For maximum speed, you should use OpenPose in a machine with a Nvidia GPU version. If so, you must upgrade your Nvidia drivers to the latest version (in the Nvidia \"GeForce Experience\" software or its [website](https://www.nvidia.com/Download/index.aspx)).\n2. Download the latest OpenPose version from the [Releases](https://github.com/CMU-Perceptual-Computing-Lab/openpose/releases) section.\n3. Follow the `Instructions.txt` file inside the downloaded zip file to download the models required by OpenPose (about 500 Mb).\n4. Then, you can run OpenPose from the PowerShell command-line by following [doc/01_demo.md](../01_demo.md).\n\nNote: If you are using the GPU-accelerated version and are seeing `Cuda check failed (3 vs. 0): initialization error` when running OpenPose, you can fix it by doing one of these:\n- Upgrade your Nvidia drivers. If the error persists, make sure your machine does not contain any CUDA version (or if so, that it's the same than the OpenPose portable demo files). Otherwise, uninstall that CUDA version. If you need to keep that CUDA version installed, follow [Compiling and Running OpenPose from Source](#compiling-and-running-openpose-from-source) for that particular CUDA version instead.\n- Download an older OpenPose version (v1.6.0 does not show this error).\n\n\n\n\n\n## Compiling and Running OpenPose from Source\nThe instructions in the following subsections describe the steps to build OpenPose using CMake-GUI. These instructions are only recommended if you plan to modify the OpenPose code or integrate it with another library or project. You can stop reading this document if you just wanted to run OpenPose on Windows without compiling or modifying any code.\n\n\n\n### Problems and Errors Installing OpenPose\nAny problem installing OpenPose while following this guidelines? Check [doc/05_faq.md](../05_faq.md) and/or check existing GitHub issues. If you don't find your issue, post a new one. We will not respond to duplicated issues, as well as GitHub issues about Caffe, OpenCV or CUDA installation errors, as well as issues that do not fill all the information that the GitHub template asks for.\n\n\n\n### Prerequisites\nMake sure to download and install the [prerequisites for your particular operating system](1_prerequisites.md).\n\n\n\n### Clone OpenPose\nThe first step is to clone the OpenPose repository.\n\n1. Windows: You might use [GitHub Desktop](https://desktop.github.com/) or clone it from Powershell.\n2. Ubuntu, Mac, or Windows Powershell:\n```bash\ngit clone https://github.com/CMU-Perceptual-Computing-Lab/openpose\ncd openpose/\ngit submodule update --init --recursive --remote\n```\n\n\n\n### CMake Configuration\n1. Go to the OpenPose folder and open CMake-GUI from it. On Windows, double click on CMake-gui. On Ubuntu, Mac, or Windows Powershell:\n```\ncd {OpenPose_folder}\nmkdir build/\ncd build/\ncmake-gui ..\n```\n2. Select the OpenPose directory as project source directory, and a non-existing or empty sub-directory (e.g., `build`) where the Makefile files (Ubuntu) or Visual Studio solution (Windows) will be generated. If `build` does not exist, it will ask you whether to create it. Press `Yes`.\n<p align=\"center\">\n    <img src=\"../../.github/media/installation/cmake_im_1.png\" width=\"480\">\n    <img src=\"../../.github/media/installation/cmake_im_1_windows.png\" width=\"480\">\n</p>\n\n3. Press the `Configure` button, keep the generator in `Unix Makefiles` (Ubuntu) or set it to your 64-bit Visual Studio version (Windows), and press `Finish`. Note for Windows users: CMake-GUI has changed their design after version 14. For versions older than 14, you usually select `Visual Studio XX 20XX Win64` as the generator (`X` depends on your VS version), while the `Optional toolset to use` must be empty. However, new CMake versions require you to select only the VS version as the generator, e.g., `Visual Studio 16 2019`, and then you must manually choose `x64` for the `Optional platform for generator`. See the following images as example.\n<p align=\"center\">\n    <img src=\"../../.github/media/installation/cmake_im_2.png\" width=\"240\">\n    <img src=\"../../.github/media/installation/cmake_im_2_windows.png\" width=\"240\">\n    <img src=\"../../.github/media/installation/cmake_im_2_windows_new.png\" width=\"240\">\n</p>\n\n4. Enabling Python (optional step, only apply it if you plan to use the Python API): Enable the `BUILD_PYTHON` flag and click `Configure` again.\n\n5. Set the `GPU_MODE` flag to the proper value and click `Configure` again:\n    1. If your machine has an Nvidia GPU, you should most probably not modify this flag and skip this step. Cases in which you might have to change it:\n        - If you have a Nvidia GPU with 2GB of memory or less: Then you will have to follow some of the tricks in [doc/06_maximizing_openpose_speed.md](../06_maximizing_openpose_speed.md) or change `GPU_MODE` back to `CPU_ONLY`.\n        - If you cannot install CUDA, then you can also set `GPU_MODE` to `CPU_ONLY`.\n    2. Mac OSX and machines with a non-Nvidia GPU (Intel or AMD GPUs): Set the `GPU_MODE` flag to `CPU_ONLY` (easier to install but slower runtime) or `OPENCL` (GPU-accelerated, it is harder to install but provides a faster runtime speed). For more details on OpenCV support, see [doc/1_prerequisites.md](1_prerequisites.md) and [OpenCL Version](#opencl-version).\n    3. If your machine does not have any GPU, set the `GPU_MODE` flag to `CPU_ONLY`.\n\n6. If this step is successful, the `Configuring done` text will appear in the bottom box in the last line. Otherwise, some red text will appear in that same bottom box.\n<p align=\"center\">\n    <img src=\"../../.github/media/installation/cmake_im_3.png\" width=\"480\">\n    <img src=\"../../.github/media/installation/cmake_im_3_windows.png\" width=\"480\">\n</p>\n\n7. Press the `Generate` button and proceed to [Compilation](#compilation). You can now close CMake.\n\nNote: For other optional and custom options (e.g., using your custom Caffe or OpenCV versions), see the [Additional Settings (Optional)](2_additional_settings.md) documentation.\n\n\n\n### Compilation\n#### Ubuntu\nRun the following commands in your terminal.\n```bash\ncd build/\nmake -j`nproc`\n```\n\n#### Mac\nRun the following commands in your terminal:\n```bash\ncd build/\nmake -j`sysctl -n hw.logicalcpu`\n```\nAdvanced tip: Mac provides both `logicalcpu` and `physicalcpu`, but we want the logical number for maximum speed.\n\nIf the default compilation fails with Caffe errors, install Caffe separately and set `BUILD_CAFFE` to false in the CMake config. Steps:\n- Re-create the build folder: `rm -rf build; mkdir build; cd build`.\n- `brew uninstall caffe` to remove the version of Caffe previously installed via cmake.\n- `brew install caffe` to install Caffe separately.\n- Run `cmake-gui` and make the following adjustments to the cmake config:\n    1. `BUILD_CAFFE` set to false.\n    2. `Caffe_INCLUDE_DIRS` set to `/usr/local/include/caffe`.\n    3. `Caffe_LIBS` set to `/usr/local/lib/libcaffe.dylib`.\n    4. Run `Configure` and `Generate` from CMake GUI.\n\nIf you face an OpenCV error during compiling time similar to `fatal error: 'opencv2/highgui/highgui.hpp' file not found`, please apply the following patch (this error has been reported in the latest OSX 10.14):\n```bash\ncd 3rdparty/caffe; git apply ../../scripts/osx/mac_opencl_patch.txt\n```\n\n#### Windows\nIn order to build the project, select and run only one of the 2 following alternatives.\n\n- **CMake-GUI alternative (recommended)**:\n    1. Open the Visual Studio solution (Windows) by clicking in `Open Project` in CMake (or alternatively `build/OpenPose.sln`). Then, set the configuration from `Debug` to `Release`.\n    2. Press <kbd>F7</kbd> (or `Build` menu and click on `Build Solution`).\n    3. **Important for Python version**: Make sure not to skip step 2, it is not enough to click on <kbd>F5</kbd> (Run), you must also `Build Solution` for the Python bindings to be generated.\n    4. After it has compiled, and if you have a webcam, you can press the green triangle icon (alternatively <kbd>F5</kbd>) to run the OpenPose demo with the default settings on the webcam.\n\n- Command-line build alternative (not recommended). NOTE: The command line alternative is not officially supported, but it was added in [GitHub issue #1198](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1198). For any questions or bug report about this command-line version, comment in that GitHub issue.\n    1. Run \"MSVS 2019 Developer Command Console\"\n    ```batch\n    openpose\\mkdir  build\n    cd build\n    cmake .. -G \"Visual Studio 16 2019\" -A x64 -T v142\n    cmake --build . --config Release\n    copy x64\\Release\\*  bin\\\n    ```\n    2. If you want to clean build\n    ```batch\n    cmake --clean-first .\n    cmake --build . --config Release\n    copy x64\\Release\\*  bin\\\n    ```\n\n**NOTE**: To set `GPU_MODE` flag to `CPU_ONLY` when building the tool via cli, append `-D GPU_MODE:STRINGS=CPU_ONLY` to the `cmake` command.\n\n**VERY IMPORTANT NOTE**: In order to use OpenPose outside Visual Studio, and assuming you have not unchecked the `BUILD_BIN_FOLDER` flag in CMake, copy all DLLs from `{build_directory}/bin` into the folder where the generated `openpose.dll` and `*.exe` demos are, e.g., `{build_directory}x64/Release` for the 64-bit release version.\n\nIf you are facing errors with these instructions, these are a set of alternative instructions created by the community:\n- OpenPose for Windows 10, Visual Studio 2019, CMake, and Nvidia GPU: [https://github.com/quickgrid/Build-Guide/blob/master/README.md#windows-10-cmu-openpose-setup-visual-studio-2019-cmake-nvidia-gpu](https://github.com/quickgrid/Build-Guide/blob/master/README.md#windows-10-cmu-openpose-setup-visual-studio-2019-cmake-nvidia-gpu).\n- Video-tutorial: OpenPose + Visual Studio 2017 + CUDA 10.0 + cuDNN 7.5 (no portable demo): [https://youtu.be/QC9GTb6Wsb4](https://youtu.be/QC9GTb6Wsb4). For questions, post in GitHub issue #1426.\n\nWe welcome users to send us their installation videos (e.g., sharing them as GitHub issue or doing a pull request) and we will post them here.\n\n\n\n### Running OpenPose\nCheck OpenPose was properly installed by running any demo example: [doc/01_demo.md](../01_demo.md).\n\n\n\n### Custom User Code\nYou can quickly add your custom code so that quick prototypes can be easily tested without having to create a whole new project just for it. See [examples/user_code/README.md](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/user_code/README.md) for more details.\n\n\n\n## Compiling and Running OpenPose from Source on ROS, Docker, and Google Colab - Community-Based Work\nIf you do not want to use the Windows portable binaries nor compile it from source code, we add links to some community-based work based on OpenPose. Note: We do not support them, and we will remove new GitHub issues opened asking about them as well as block those users from posting again. If you face any issue, comment only in the GitHub issues links especified below, or ask the owner of them.\n\n- ROS examples:\n    - [ROS example 1](https://github.com/ravijo/ros_openpose). For questions and more details, read and post ONLY on [issue thread #891](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/891).\n    - [ROS example 2](https://github.com/firephinx/openpose_ros) (based on a very old OpenPose version). For questions and more details, read and post ONLY on [issue thread #51](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/51).\n\n- Docker Images. For questions and more details, read and post ONLY on [issue thread #347](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/347).\n    - Dockerfile working also with CUDA 10:\n        - Option 1:\n            - 1. If necessary, install the latest version of docker. There are extra steps, but if you are on Ubuntu, the main one is `sudo apt-get install docker-ce`. The other steps can be found [here](https://phoenixnap.com/kb/how-to-install-docker-on-ubuntu-18-04).\n            - 2. `docker pull exsidius/openpose` - [Guide](https://github.com/gormonn/openpose-docker/blob/master/README.md).\n            - 3. [More details here](https://cloud.docker.com/repository/docker/exsidius/openpose/general).\n        - [Link 2](https://github.com/esemeniuc/openpose-docker), it claims to also include Python support. Read and post ONLY on [issue thread #1102](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1102).\n        - [Link 3](https://github.com/ExSidius/openpose-docker/blob/master/Dockerfile).\n        - [Link 4](https://cloud.docker.com/repository/docker/exsidius/openpose/general).\n    - Dockerfile working only with CUDA 8:\n        - [Dockerfile - OpenPose v1.4.0, OpenCV, CUDA 8, CuDNN 5, Python2.7](https://github.com/tlkh/openpose). Read and post ONLY on [issue thread #1102](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1102).\n        - [Dockerfile - OpenPose v1.4.0, OpenCV, CUDA 8, CuDNN 6, Python2.7](https://gist.github.com/moiseevigor/11c02c694fc0c22fccd59521793aeaa6).\n        - [Dockerfile - OpenPose v1.2.1](https://gist.github.com/sberryman/6770363f02336af82cb175a83b79de33).\n\n- Google Colab helper scripts: Script to install OpenPose on Google Colab. Really useful when access to a computer powerful enough to run OpenPose is not possible, so one possible way to use OpenPose is to build it on a GPU-enabled Colab runtime and then run the programs there.\n    - [Google Colab with Openpose 1.7.0](https://colab.research.google.com/github/miu200521358/motion_trace_colab/blob/master/OpenposeDemo.ipynb): For questions and more details, read and post ONLY on [issue thread #949](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/949).\n    - [Google Colab 2/3](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1736#issuecomment-736846794): For questions and more details, read and post ONLY on [issue thread #1736](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1736).\n    - [Google Colab 3/3](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/949#issue-387855863): For questions and more details, read and post ONLY on [issue thread #949](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/949).\n\n\n\n\n\n## OpenPose Live Demo at Tiyaro - Community-Based Work\nYou can find a [Live Demo of the OpenPose API at Tiyaro.ai](https://console.tiyaro.ai/explore/opensource-1-OpenPose/demo). We do not officially support it, but a Tiyaro co-founder added this support in [2129]. Feel free to comment in that post to him if you have questions about it.\n<p align=\"center\"><a href=\"https://console.tiyaro.ai/explore?q=openpose&pub=opensource\"> <img src=\"https://tiyaro-public-docs.s3.us-west-2.amazonaws.com/assets/try_on_tiyaro_badge.svg\"></a></p>\n\n\n\n\n\n## Uninstalling, Reinstalling, or Updating OpenPose\nOpenPose can be easily uninstalled:\n1. (Ubuntu and Mac) If you ran `sudo make install` (which we do not recommend), then run `sudo make uninstall` in `build/`.\n2. Remove the OpenPose folder.\n\nIn order to update it or reinstall it:\n1. Follow the above steps to uninstall it.\n2. Follow the [Compiling and Running OpenPose from Source](#compiling-and-running-openpose-from-source) steps again.\n\n\n\n\n\n## Additional Settings (Optional)\nCheck the [Additional Settings (Optional)](2_additional_settings.md) documentation if you want to:\n1. [Deploy or Export OpenPose to Other Projects](2_additional_settings.md#deploy-or-export-openpose-to-other-projects)\n2. [Maximum Speed](2_additional_settings.md#maximum-speed)\n3. [Faster CPU Version (Ubuntu Only)](2_additional_settings.md#faster-cpu-version-ubuntu-only)\n4. [OpenCL Version](2_additional_settings.md#opencl-version)\n5. [COCO and MPI Models](2_additional_settings.md#coco-and-mpi-models)\n6. [3D Reconstruction Module](2_additional_settings.md#3d-reconstruction-module)\n7. [Calibration Module](2_additional_settings.md#calibration-module)\n8. [Unity Compatible Version](2_additional_settings.md#unity-compatible-version)\n9. [Compile without cuDNN](2_additional_settings.md#compiling-without-cudnn)\n10. [Custom Caffe](2_additional_settings.md#custom-caffe)\n11. [Custom NVIDIA NVCaffe](2_additional_settings.md#custom-nvidia-nvcaffe)\n12. [Custom OpenCV](2_additional_settings.md#custom-opencv)\n13. [Doxygen Documentation Autogeneration (Ubuntu Only)](2_additional_settings.md#doxygen-documentation-autogeneration-ubuntu-only)\n14. [CMake Command Line Configuration (Ubuntu Only)](2_additional_settings.md#cmake-command-line-configuration-ubuntu-only)\n"
  },
  {
    "path": "doc/installation/1_prerequisites.md",
    "content": "OpenPose Doc - Installation - Prerequisites\n==========================\n\n## Contents\n1. [General Tips](#general-tips)\n2. [Ubuntu Prerequisites](#ubuntu-prerequisites)\n3. [Mac OS Prerequisites](#mac-os-prerequisites)\n4. [Windows Prerequisites](#windows-prerequisites)\n\n\n\n## General Tips\nThese tips are **very important** and avoid many bugs:\n- Install the latest CUDA version or make sure your GPU is compatible with the CUDA version you have in your system. E.g., Nvidia 30XX GPUs require at least CUDA 11, others (GTX 20XX, V100, Volta or Turing GPUs) require at least CUDA 10.\n- CMake automatically downloads all the OpenPose models. However, **some firewall or company networks block these downloads**. If so, you might need to download them manually:\n    - [BODY_25 model](http://vcl.snu.ac.kr/OpenPose/models/pose/body_25/pose_iter_584000.caffemodel): download in `models/pose/body_25/`.\n    - [COCO model](http://vcl.snu.ac.kr/OpenPose/models/pose/coco/pose_iter_440000.caffemodel): download in `models/pose/coco/`.\n    - [MPI model](http://vcl.snu.ac.kr/OpenPose/models/pose/mpi/pose_iter_160000.caffemodel): download in `models/pose/mpi/`.\n    - [Face model](http://vcl.snu.ac.kr/OpenPose/models/face/pose_iter_116000.caffemodel): download in `models/face/`.\n    - [Hands model](http://vcl.snu.ac.kr/OpenPose/models/hand/pose_iter_102000.caffemodel): download in `models/hand/`.\n\n\n\n## Ubuntu Prerequisites\n1. **Anaconda should not be installed** on your system **or should be deactivated**. Anaconda includes a Protobuf version that is incompatible with Caffe. Either you uninstall anaconda and install protobuf via apt-get, or you deactivate Conda with the command ```conda deactivate``` (twice if you are not in the base environment).\n\n2. Install **CMake GUI**:\n    - Ubuntu 20: Run the command `sudo apt-get install cmake-qt-gui`.\n    - Ubuntu 18: **Download and compile CMake-gui from source**. The default CMake-gui version (3.10) installed via `sudo apt-get install cmake-qt-gui` provokes some compiling errors. Required CMake version >= 3.12.\n        - Uninstall your current Cmake-gui version by running `sudo apt purge cmake-qt-gui`.\n        - Install OpenSSL for building CMake by running `sudo apt install libssl-dev`.\n        - Run `sudo apt-get install qtbase5-dev`.\n        - Download the `Latest Release` of `CMake Unix/Linux Source` from the [CMake download website](https://cmake.org/download/), called `cmake-X.X.X.tar.gz`.\n        - Unzip it and go inside that folder from the terminal.\n        - Run `./configure --qt-gui`. Make sure no error occurred.\n        - Run ``./bootstrap && make -j`nproc` && sudo make install -j`nproc` ``. Make sure no error occurred.\n        - Assuming your CMake downloaded folder is in {CMAKE_FOLDER_PATH}, every time these instructions mentions `cmake-gui`, you will have to replace that line by `{CMAKE_FOLDER_PATH}/bin/cmake-gui`.\n    - Ubuntu 14 or 16: Run the command `sudo apt-get install cmake-qt-gui`. Note: If you prefer to use CMake through the command line, see [doc/installation/0_index.md#CMake-Command-Line-Configuration-(Ubuntu-Only)](0_index.md#cmake-command-line-configuration-ubuntu-only).\n3. Nvidia GPU version prerequisites:\n    1. **Note: OpenPose has been tested extensively with CUDA 11.7.1 (cuDNN 8.5.0) for Ubuntu 20**. Older OpenPose versions (v1.6.X and v1.5.X) were tested with **CUDA 10.1 (cuDNN 7.5.1) for Ubuntu 18 and CUDA 8.0 (cuDNN 5.1) for Ubuntu 14 and 16**. We highly recommend using those combinations to minimize potential installation issues. Other combinations should also work, but we do not provide any support about installation/compilation issues related to CUDA/cuDNN or their integration with OpenPose. Note: If Secure Boot is enabled (by default it is not), the MOK key installation part might be mandatory. For that, record the public key output path and invoke into `sudo mokutil --import PATH_TO_PUBLIC_KEY` manually if automatic install failed.\n    2. Upgrade your Nvidia drivers to the latest version.\n        - For Ubuntu 20, download ([515.65](https://www.nvidia.com/Download/driverResults.aspx/191961/en-us/))\n    3. **CUDA**: You can simply run `sudo bash ./scripts/ubuntu/install_cuda.sh` if you are not too familiar with CUDA. If you are, then you could also do one of the following instead:\n        - Ubuntu 20 ([**CUDA 11.7.1**](https://developer.nvidia.com/cuda-11-7-1-download-archive)): Download CUDA 11.7.1 from their [official website](https://developer.nvidia.com/cuda-11-7-1-download-archive). Most Ubuntu computers use the `Architecture` named `x86_64`, and we personally recommend the `Installer Type` named `runfile (local)`. Then, follow the Nvidia website installation instructions. When installing, make sure to enable the symbolic link in `usr/local/cuda` to minimize potential future errors. If the (Nvidia) drivers were installed manually, untick the \"install driver\" option.\n        - Ubuntu 18 ([**CUDA 10.1**](https://developer.nvidia.com/cuda-10.1-download-archive-base)): Analog to the instructions for Ubuntu 20, but using CUDA version 10.1.\n        - Ubuntu 14 or 16 ([**CUDA 8**](https://developer.nvidia.com/cuda-80-ga2-download-archive) **or 10**): Run `sudo ./scripts/ubuntu/install_cuda.sh` (if Ubuntu 16 or 14 and for Graphic cards up to 10XX) or alternatively download and install it from their website.\n    4. **cuDNN**:\n        - Download it (usually called `cuDNN Library for Linux (x86_64)`):\n            - Ubuntu 20: [**cuDNN 8.5.0**](https://developer.nvidia.com/cudnn). cuDNN is currently not recommended due to performance degradation issues outlined in [#1864](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1864#issuecomment-774706976).\n            - Ubuntu 18: [**cuDNN 7.5.1**](https://developer.nvidia.com/rdp/cudnn-archive).\n            - Ubuntu 14 or 16 (**cuDNN 5.1 or 7.2**): Run `sudo ./scripts/ubuntu/install_cudnn_up_to_Ubuntu16.sh` (if Ubuntu 16 or 14 and for Graphic cards up to 10XX) or alternatively [download it from their website](https://developer.nvidia.com/rdp/cudnn-archive).\n        - And install it:\n            - In order to manually install it (any version), just unzip it and copy (merge) its contents on the CUDA folder, usually `/usr/local/cuda-{version}/` in Ubuntu and `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v{version}\\` in Windows.\n4. OpenCL / AMD GPU version prerequisites (only if you do not have an Nvidia GPU and want to run on AMD graphic cards):\n    - Ubuntu 20 or 18: Not tested and not officially supported. Try at your own risk. You might want to use the CPU version if no Nvidia GPU is available.\n    - Ubuntu 14 or 16:\n        1. Download 3rd party ROCM driver for Ubuntu from [**AMD - OpenCL**](https://rocm.github.io/ROCmInstall.html).\n        2. Install `sudo apt-get install libviennacl-dev`.\n5. Install **Caffe, OpenCV, and Caffe prerequisites**:\n    - OpenCV must be already installed on your machine. It can be installed with `sudo apt-get install libopencv-dev`. You could also use your own compiled OpenCV version.\n    - Caffe prerequisites: By default, OpenPose uses Caffe under the hood. If you have not used Caffe previously, install its dependencies by running `sudo bash ./scripts/ubuntu/install_deps.sh` after installing your desired CUDA and cuDNN versions.\n    - CMake config generation prerequisites (they might be already installed by default): `sudo apt install protobuf-compiler libgoogle-glog-dev`.\n    - OpenPose make prerequisites (they might be already installed by default): `sudo apt install libboost-all-dev libhdf5-dev libatlas-base-dev`.\n6. Python prerequisites (optional, only if you plan to use the Python API): python-dev, Numpy (for array management), and OpenCV (for image loading).\n```\n# Python 3 (default and recommended)\nsudo apt-get install python3-dev\nsudo pip3 install numpy opencv-python\n\n# Python 2\nsudo apt-get install python-dev\nsudo pip install numpy opencv-python\n```\n\n\n\n## Mac OS Prerequisites\n1. If you don't have `brew`, install it by running `bash scripts/osx/install_brew.sh` on your terminal.\n2. Install **CMake GUI**: Run the command `brew install --cask cmake`.\n3. Install **Caffe, OpenCV, and Caffe prerequisites**: Run `bash scripts/osx/install_deps.sh`.\n\n\n\n## Windows Prerequisites\nNOTE: These instructions are only required when compiling OpenPose from source. If you simply wanna use the OpenPose binaries for Windows, skip this step.\n\n1. Install **CMake GUI**: Download and install the `Latest Release` of CMake `Windows win64-x64 Installer` from the [CMake download website](https://cmake.org/download/), called `cmake-X.X.X-win64-x64.msi`.\n2. Install **Microsoft Visual Studio (VS) 2019 Enterprise**, **Microsoft Visual Studio (VS) 2017 Enterprise** or **VS 2015 Enterprise Update 3**:\n    - **IMPORTANT**: Enable all C++-related flags when selecting the components to install.\n    - Different VS versions:\n        - If **Visual Studio 2019 Community** (or 2017) is desired, we do not officially support it, but it should run similarly to VS 2017/2019 Enterprise.\n3. Nvidia GPU version prerequisites:\n    1. **Note: OpenPose has been tested extensively with CUDA 11.1.1 (cuDNN 8.1.0) for VS2019**. Older OpenPose versions (v1.6.X and v1.5.X) were tested with **CUDA 10.1 (cuDNN 7.5.1) for VS2017 and CUDA 8.0 (cuDNN 5.1) for VS2015**. We highly recommend using those combinations to minimize potential installation issues. Other combinations should also work, but we do not provide any support about installation/compilation issues related to CUDA/cuDNN or their integration with OpenPose.\n    2. Upgrade your Nvidia drivers to the latest version (in the Nvidia \"GeForce Experience\" software or its [website](https://www.nvidia.com/Download/index.aspx)).\n    3. Install one out of [**CUDA 11.1.1**](https://developer.nvidia.com/cuda-11.1.1-download-archive), [**CUDA 10.1**](https://developer.nvidia.com/cuda-10.1-download-archive-base), or [**CUDA 8**](https://developer.nvidia.com/cuda-80-ga2-download-archive):\n        - Install CUDA 11.1.1/10.0/8.0 after Visual Studio 2019/2017/2015 is installed to assure that the CUDA installation will generate all necessary files for VS. If CUDA was installed before installing VS, then re-install CUDA.\n        - **Important installation tips**:\n            - If CMake returns and error message similar to `CUDA_TOOLKIT_ROOT_DIR not found or specified` or any other CUDA component missing, then: 1) Re-install Visual Studio 2015; 2) Reboot your PC; 3) Re-install CUDA (in this order!).\n    4. [**cuDNN 8.1.0**](https://developer.nvidia.com/cudnn), [**cuDNN 7.5.1**](https://developer.nvidia.com/rdp/cudnn-archive), or [**cuDNN 5.1**](https://developer.nvidia.com/rdp/cudnn-archive):\n        - In order to manually install it, just unzip it and copy (merge) the contents on the CUDA folder, usually `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v{version}` in Windows and `/usr/local/cuda-{version}/` in Ubuntu.\n4. AMD GPU version prerequisites (only if you do not have an Nvidia GPU and want to run on AMD graphic cards):\n    1. Download the official AMD drivers for Windows from [**AMD - Windows**](https://support.amd.com/en-us/download).\n    2. The libviennacl package comes packaged inside OpenPose for Windows (i.e., no further action required).\n5. **Caffe, OpenCV, and Caffe prerequisites**:\n    - CMake automatically downloads all the Windows DLLs. Alternatively, you might prefer to download them manually:\n        - Dependencies:\n            - Note: Leave the zip files in `3rdparty/windows/` so that CMake does not try to download them again.\n            - Caffe (if you are not sure which one you need, download the default one):\n                - [CUDA Caffe (Default)](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe_16_2020_11_14.zip): Unzip as `3rdparty/windows/caffe/`.\n                - [CPU Caffe](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe_cpu_2018_05_27.zip): Unzip as `3rdparty/windows/caffe_cpu/`.\n                - [OpenCL Caffe](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe_opencl_2018_02_13.zip): Unzip as `3rdparty/windows/caffe_opencl/`.\n            - [Caffe dependencies](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe3rdparty_16_2020_11_14.zip): Unzip as `3rdparty/windows/caffe3rdparty/`.\n            - [OpenCV 4.2.0](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/opencv_450_v15_2020_11_18.zip): Unzip as `3rdparty/windows/opencv/`.\n7. Python prerequisites (optional, only if you plan to use the Python API): Install any [Python 3.X](https://www.python.org/downloads/windows/) version for Windows, and then:\n```\nsudo pip install numpy opencv-python\n```\n"
  },
  {
    "path": "doc/installation/2_additional_settings.md",
    "content": "OpenPose Doc - Installation - Additional Settings (Optional)\n==========================\n\n## Contents\n1. [Additional Settings (Optional)](#advanced-additional-settings-optional)\n    1. [Deploy or Export OpenPose to Other Projects](#deploy-or-export-openpose-to-other-projects)\n    2. [Maximum Speed](#maximum-speed)\n    3. [Faster CPU Version (Ubuntu Only)](#faster-cpu-version-ubuntu-only)\n    4. [OpenCL Version](#opencl-version)\n    5. [COCO and MPI Models](#coco-and-mpi-models)\n    6. [3D Reconstruction Module](#3d-reconstruction-module)\n    7. [Calibration Module](#calibration-module)\n    8. [Unity Compatible Version](#unity-compatible-version)\n    9. [Compile without cuDNN](#compile-without-cudnn)\n    10. [Custom Caffe](#custom-caffe)\n    11. [Custom NVIDIA NVCaffe](#custom-nvidia-nvcaffe)\n    12. [Custom OpenCV](#custom-opencv)\n    13. [Doxygen Documentation Autogeneration (Ubuntu Only)](#doxygen-documentation-autogeneration-ubuntu-only)\n    14. [CMake Command Line Configuration (Ubuntu Only)](#cmake-command-line-configuration-ubuntu-only)\n\n\n\n\n\n## Additional Settings (Optional)\n### Deploye or Exporte OpenPose to Other Projects\nSee [doc/advanced/deployment.md](../advanced/deployment.md).\n\n\n\n\n\n### Maximum Speed\nCheck the OpenPose Benchmark as well as some hints to speed up and/or reduce the memory requirements to run OpenPose on [doc/06_maximizing_openpose_speed.md](../06_maximizing_openpose_speed.md).\n\n\n\n### Faster CPU Version (Ubuntu Only)\n**NOTE**: The accuracy of the CPU/OpenCL versions is a bit lower than CUDA version, so the results will very slightly vary. In practice, the different is barely noticeable, so you are safe using these.\n\nThis step is only supported for Intel CPUs on Ubuntu versions 16 and 14. It does not compile on Ubuntu 20, and we have not tested it on Ubuntu 18.\n\nAfter setting the `GPU_MODE` flag to `CPU_ONLY` and clicking `Configured`, search for `USE_MKL` and set it to true. Then, click `Configure` again. This way, OpenPose will link against the Intel MKL version (Math Kernel Library) of Caffe. This speeds up CPU version on Ubuntu roughly about 2-3x, making it as fast as the Windows CPU-only version.\n\nThe default CPU version takes about 0.2 images per second on Ubuntu (~50x slower than GPU) while the MKL version provides a roughly 2x speedup at ~0.4 images per second. As of now OpenPose does not support MKL on Windows but will at a later date. Also, MKL version does not support unfixed resolution. So a folder of images of different resolutions requires a fixed net resolution (e.g., `--net_resolution 656x368`).\n\nFor MKL, the user can configure the environmental variables `MKL_NUM_THREADS` and `OMP_NUM_THREADS`. They are set at an optimum parameter level by default (i.e., to the number of threads of the machine). However, they can be tweak by running the following commands into the terminal window, right before running any OpenPose application. Eg:\n\n```bash\n# Optimal number = Number of threads (used by default)\nexport MKL_NUM_THREADS=\"8\"\nexport OMP_NUM_THREADS=\"8\"\n```\n\nIncreasing the number of threads results in a higher RAM memory usage. You can check the [doc/06_maximizing_openpose_speed.md](../06_maximizing_openpose_speed.md) for more information about speed and memory requirements in several CPUs and GPUs.\n\n\n\n### OpenCL Version\n**NOTE**: The accuracy of the CPU/OpenCL versions is a bit lower than CUDA version, so the results will very slightly vary. In practice, the different is not barely noticeable, so you are safe using these.\n\nIf you have an AMD graphics card, you can compile OpenPose with the OpenCL option. To manually select the OpenCL Version, open CMake GUI mentioned above, and set the `GPU_MODE` flag to `OPENCL` (or non-UI CMake with `GPU_MODE=OPENCL`). **Very important:** If you compiled previously the CPU-only or CUDA versions on that same OpenPose folder, you will have to manually delete the `build` directory and run the installation steps from scratch. Otherwise, many weird errors will appear.\n\nThe OpenCL version has been tested on Ubuntu, Windows and OSX. This has been tested only on AMD Vega series and NVIDIA 10 series graphics cards. Please email us if you have issues with other operating systems or graphics cards. Running on OSX on a Mac with an AMD graphics card requires special instructions which can be seen in the section below.\n\nLastly, OpenCL version does not support unfixed `--net_resolution`. So a folder of images of different resolutions with OpenPose, requires the `--net_resolution 656x368` flag for example. This should be fixed by the Caffe author in a future patch.\n\n\n\n### COCO and MPI Models\nBy default, the body `COCO` and `MPI` models are not downloaded (they are slower and less accurate than `BODY_25`, so not useful in most cases!). But you can download them by turning on the `DOWNLOAD_BODY_COCO_MODEL` or `DOWNLOAD_BODY_MPI_MODEL` flags. Check the differences between these models in [doc/05_faq.md#difference-between-body_25-vs-coco-vs-mpi](../05_faq.md#difference-between-body_25-vs-coco-vs-mpi).\n\n\n\n### 3D Reconstruction Module\nYou can include the 3D reconstruction module by:\n\n1. Install the FLIR camera software, Spinnaker SDK. It is a proprietary software, so we cannot provide direct download link. Note: You might skip this step if you intend to use the 3-D OpenPose module with a different camera brand.\n    1. Ubuntu: Get and install the latest Spinnaker SKD version in their default path. OpenPose will automatically find it. Otherwise, set the right path with CMake.\n    2. Windows: Download the latest Spinnaker SKD version from [https://www.ptgrey.com/support/downloads](https://www.ptgrey.com/support/downloads).\n        - Copy `{PointGreyParentDirectory}\\Point Grey Research\\Spinnaker\\bin64\\vs2015\\` as `{OpenPoseDirectory}\\3rdparty\\windows\\spinnaker\\bin\\`. You can remove all the *.exe files.\n        - Copy `{PointGreyParentDirectory}\\Point Grey Research\\Spinnaker\\include\\` as `{OpenPoseDirectory}\\3rdparty\\windows\\spinnaker\\include\\`.\n        - Copy `Spinnaker_v140.lib` and `Spinnakerd_v140.lib` from `{PointGreyParentDirectory}\\Point Grey Research\\Spinnaker\\lib64\\vs2015\\` into `{OpenPoseDirectory}\\3rdparty\\windows\\spinnaker\\lib\\`.\n        - (Optional) Spinnaker SDK overview: [https://www.ptgrey.com/spinnaker-sdk](https://www.ptgrey.com/spinnaker-sdk).\n2. Install the 3D visualizer, FreeGLUT:\n    1. Ubuntu: run `sudo apt-get update && sudo apt-get install build-essential freeglut3 freeglut3-dev libxmu-dev libxi-dev` and reboot your PC.\n    2. Windows:\n        1. It is automatically downloaded by the CMake installer.\n        2. Alternatively, if you prefer to download it yourself, you could either:\n            1. Double click on `3rdparty\\windows\\getFreeglut.bat`.\n            2. Download [this version from our server](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/freeglut_2018_01_14.zip) and unzip it in `{OpenPoseDirectory}\\3rdparty\\windows\\freeglut\\`.\n            3. Download the latest `MSVC Package` from [http://www.transmissionzero.co.uk/software/freeglut-devel/](http://www.transmissionzero.co.uk/software/freeglut-devel/).\n                - Copy `{freeglutParentDirectory}\\freeglut\\bin\\x64\\` as `{OpenPoseDirectory}\\3rdparty\\windows\\freeglut\\bin\\`.\n                - Copy `{freeglutParentDirectory}\\freeglut\\include\\` as `{OpenPoseDirectory}\\3rdparty\\windows\\freeglut\\include\\`.\n                - Copy `{freeglutParentDirectory}\\freeglut\\lib\\x64\\` as `{OpenPoseDirectory}\\3rdparty\\windows\\freeglut\\lib\\`.\n3. Follow the CMake installation steps. In addition, set the `WITH_FLIR_CAMERA` (only if Spinnaker was installed) and `WITH_3D_RENDERER` options.\n4. Increased accuracy with Ceres solver (Ubuntu only): For extra 3-D reconstruction accuracy, run `sudo apt-get install libeigen3-dev`, install [Ceres solver](http://ceres-solver.org/installation.html), and enable `WITH_CERES` in CMake when installing OpenPose. Ceres is harder to install in Windows, so we have not tested it so far in there. Feel free to make a pull request if you do.\n\nAfter installation, check the [doc/advanced/3d_reconstruction_module.md](../advanced/3d_reconstruction_module.md) instructions.\n\n\n\n### Calibration Module\nThe intrinsic camera calibration toolbox is included by default.\n\nTo enable the extrinsic camera parameter estimation toolbox, you must also enable `WITH_EIGEN` in CMake during [CMake Configuration](#cmake-configuration). You can perform any of the 3 following options (but only 1 of them!)\n- Recommended: Simply set the `WITH_EIGEN` flag to `AUTOBUILD`. CMake will automatically download Eigen and configure OpenPose to use it. If you prefer to download it manually (or if your firewall blocks CMake from downloading it):\n    - [Eigen 3.3.8](http://vcl.snu.ac.kr/OpenPose/3rdparty/eigen_2020_11_18.zip): Unzip it as `3rdparty/eigen/`.\n- Advanced (not recommended): If you set `WITH_EIGEN` to `FIND`, you must have Eigen already installed in your system. Note that [Eigen <= 3.3.6 is not supported by CUDA >=9.1](https://bitbucket.org/eigen/eigen/commits/034b6c3e101792a3cc3ccabd9bfaddcabe85bb58?at=default). In order to install it (make sure that Eigen version is compatible with CUDA!):\n    - Run `sudo apt-get install libeigen3-dev` and link CMake to the right CMake.\n- Advanced (not recommended): Or you could also use your own version of Eigen by setting `WITH_EIGEN` to `AUTOBUILD`, click `Configure` to let CMake download the zip file, and replace `3rdparty/eigen/` by your own version.\n\nAfter installation, check the [doc/advanced/calibration_module.md](../advanced/calibration_module.md) instructions.\n\n\n\n### Unity Compatible Version\nCheck [**Unity Plugin**](https://github.com/CMU-Perceptual-Computing-Lab/openpose_unity_plugin).\n\nHowever, the OpenPose Unity version will crash if if faces an error while it is not used inside Unity. Thus, do not use it without Unity. Although this version would work as long as no errors occur.\n\n\n\n### Compile without cuDNN\nThe [cuDNN](https://developer.nvidia.com/cudnn) library is not mandatory, but required for full keypoint detection accuracy. In case your graphics card is not compatible with cuDNN, you can disable it by unchecking `USE_CUDNN` in CMake.\n\nThen, you would have to reduce the `--net_resolution` flag to fit the model into the GPU memory. You can try values like `640x320`, `320x240`, `320x160`, or `160x80` to see your GPU memory capabilities. After finding the maximum approximate resolution that your GPU can handle without throwing an out-of-memory error, adjust the `net_resolution` ratio to your image or video to be processed (see the `--net_resolution` explanation from [doc/advanced/demo_advanced.md](../advanced/demo_advanced.md)), or use `-1` (e.g., `--net_resolution -1x320`).\n\n\n\n### Custom Caffe\nOpenPose uses a [custom fork of Caffe](https://github.com/CMU-Perceptual-Computing-Lab/caffe) (rather than the official Caffe master). Our custom fork is only updated if it works on our machines, but we try to keep it updated with the latest Caffe version. This version works on a newly formatted machine (Ubuntu 16.04 LTS) and in all our machines (CUDA 8 and 10 tested). The default GPU version is the master branch, which it is also compatible with CUDA 10 without changes (official Caffe version might require some changes for it). We also use the OpenCL and CPU tags if their CMake flags are selected. We only modified some Caffe compilation flags and minor details.\n\nAlternatively, you can use your own Caffe distribution on Ubuntu/Mac by 1) disabling `BUILD_CAFFE`, 2) setting `Caffe_INCLUDE_DIRS` to `{CAFFE_PATH}/include/caffe`, and 3) setting `Caffe_LIBS` to `{CAFFE_PATH}/build/lib/libcaffe.so`, as shown in the image below. Note that cuDNN-compatible Caffe version is required in order to get the maximum possible accuracy in OpenPose.\n<p align=\"center\">\n    <img src=\"../../.github/media/installation/cmake_im_5.png\" width=\"480\">\n</p>\n\nFor Windows, simply replace the OpenCV DLLs and include folder for your custom one.\n\n\n\n### Custom NVIDIA NVCaffe\nThis functionality was added by the community, and we do not officially support it. New pull requests with additional functionality or fixing any bug are welcome!\n\nIt has been tested with the official Nvidia Docker image [nvcr.io/nvidia/caffe:18.12-py2](https://ngc.nvidia.com/catalog/containers/nvidia:caffe).\n\nFor questions and issues, please only post on the related [Pull Request #1169](https://github.com/CMU-Perceptual-Computing-Lab/openpose/pull/1169). New GitHub issues about this topic (i.e., outside PR #1169) will be automatically closed with no answer.\n\nWindows support has not been added. Replace `set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE)` by `set_property(CACHE DL_FRAMEWORK PROPERTY STRINGS CAFFE NV_CAFFE)` in `CMakeLists.txt` if you intend to use it for Windows, and feel free to do a pull request of it working!\n\nTo use a NVIDIA's NVCaffe docker image instead of the standard Caffe, set the following CMake flags:\n\n1. Set the `DL_FRAMEWORK` variable to `NV_CAFFE`.\n2. Set the `BUILD_CAFFE` variable to `OFF`.\n3. Set the correct `Caffe_INCLUDE_DIRS` and `Caffe_LIBS` paths following [Custom Caffe](#custom-caffe).\n\nIn addition, [peter-uhrig.de/openpose-with-nvcaffe-in-a-singularity-container-with-support-for-multiple-architectures/](http://peter-uhrig.de/openpose-with-nvcaffe-in-a-singularity-container-with-support-for-multiple-architectures/) contains a detailed step-by-step guide to install a portable container with NVCaffe and support for multiple NVidia cards as well as CPU.\n\n\n\n### Custom OpenCV\nIf you have built OpenCV from source and OpenPose cannot find it automatically, you can set the `OPENCV_DIR` variable to the directory where you build OpenCV (Ubuntu and Mac). For Windows, simply replace the OpenCV DLLs and include folder for your custom one.\n\n\n\n### Doxygen Documentation Autogeneration (Ubuntu Only)\nYou can generate the documentation by setting the `BUILD_DOCS` flag. The documentation will be generated in `doc/doxygen/html/index.html`. You can simply open it with double-click (your default browser should automatically display it).\n\n\n\n### CMake Command Line Configuration (Ubuntu Only)\nNote that this step is unnecessary if you already used the CMake GUI alternative.\n\nCreate a `build` folder in the root OpenPose folder, where you will build the library --\n```bash\ncd openpose\nmkdir build\ncd build\n```\n\nThe next step is to generate the Makefiles. Now there can be multiple scenarios based on what the user already has e.x. Caffe might be already installed and the user might be interested in building OpenPose against that version of Caffe instead of requiring OpenPose to build Caffe from scratch.\n\n#### Scenario 1 - Caffe not installed and OpenCV installed using `apt-get`\nIn the build directory, run the below command --\n```bash\ncmake ..\n```\n\n#### Scenario 2 - Caffe installed and OpenCV build from source\nIn this example, we assume that Caffe and OpenCV are already present. The user needs to supply the paths of the libraries and the include directories to CMake. For OpenCV, specify the include directories and the libraries directory using `OpenCV_INCLUDE_DIRS` and `OpenCV_LIBS_DIR` variables respectively. Alternatively, the user can also specify the path to the `OpenCVConfig.cmake` file by setting the `OpenCV_CONFIG_FILE` variable. For Caffe, specify the include directory and library using the `Caffe_INCLUDE_DIRS` and `Caffe_LIBS` variables. This will be where you installed Caffe. Below is an example of the same.\n```bash\ncmake -DOpenCV_INCLUDE_DIRS=/home/\"${USER}\"/softwares/opencv/build/install/include \\\n  -DOpenCV_LIBS_DIR=/home/\"${USER}\"/softwares/opencv/build/install/lib \\\n  -DCaffe_INCLUDE_DIRS=/home/\"${USER}\"/softwares/caffe/build/install/include \\\n  -DCaffe_LIBS=/home/\"${USER}\"/softwares/caffe/build/install/lib/libcaffe.so -DBUILD_CAFFE=OFF ..\n```\n\n```bash\ncmake -DOpenCV_CONFIG_FILE=/home/\"${USER}\"/softwares/opencv/build/install/share/OpenCV/OpenCVConfig.cmake \\\n  -DCaffe_INCLUDE_DIRS=/home/\"${USER}\"/softwares/caffe/build/install/include \\\n  -DCaffe_LIBS=/home/\"${USER}\"/softwares/caffe/build/install/lib/libcaffe.so -DBUILD_CAFFE=OFF ..\n```\n\n#### Scenario 3 - OpenCV already installed\nIf Caffe is not already present but OpenCV is, then use the below command.\n```bash\ncmake -DOpenCV_INCLUDE_DIRS=/home/\"${USER}\"/softwares/opencv/build/install/include \\\n  -DOpenCV_LIBS_DIR=/home/\"${USER}\"/softwares/opencv/build/install/lib ..\n```\n\n```bash\ncmake -DOpenCV_CONFIG_FILE=/home/\"${USER}\"/softwares/opencv/build/install/share/OpenCV/OpenCVConfig.cmake ..\n```\n\n#### Any Other Scenario\nYou can check the CMake online documentation to check all the options that CMake provides and its analogs to the CMake-gui ones that we show on this document.\n"
  },
  {
    "path": "doc/installation/README.md",
    "content": "The OpenPose documentation is available in 2 different formats, choose your preferred one!\n- As a traditional website (recommended): [cmu-perceptual-computing-lab.github.io/openpose](https://cmu-perceptual-computing-lab.github.io/openpose).\n- As markdown files: [github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/doc/installation](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/doc/installation).\n"
  },
  {
    "path": "doc/installation/deprecated/installation_deprecated.md",
    "content": "OpenPose Doc - Installation (deprecated)\n======================================\n\nNOTE: Do not use this document, see [doc/installation/0_index.md](../0_index.md) instead. This deprecated installation document is kept just for backwards compatibility, but it should not be used.\n\n## Contents\n1. [Operating Systems](#operating-systems)\n2. [Requirements](#requirements)\n3. [Clone OpenPose](#clone-openpose)\n4. [Update OpenPose](#update-openpose)\n5. [Ubuntu](#ubuntu)\n6. [Windows](#windows)\n7. [Doxygen Documentation Autogeneration](#doxygen-documentation-autogeneration)\n8. [Custom Caffe](#custom-caffe)\n9. [Compiling without cuDNN](#compiling-without-cudnn)\n\n\n\n## Operating Systems\nSee [doc/installation/0_index.md#operating-systems](../0_index.md#operating-systems).\n\n\n\n## Requirements\nSee [doc/installation/0_index.md#requirements](../0_index.md#requirements).\n\n\n\n## Clone OpenPose\nSee [doc/installation/0_index.md#clone-openpose](../0_index.md#clone-openpose).\n\n\n\n## Update OpenPose\nSee [doc/installation/0_index.md#update-openpose](../0_index.md#update-openpose).\n\n\n\n## Ubuntu\n### Installation - CMake\nRecommended installation method, it is simpler and offers more customization settings. See [doc/installation/0_index.md](../0_index.md).\n\n\n\n### Prerequisites (Script Compilation or Manual Compilation)\nCUDA, cuDNN, OpenCV and Atlas must be already installed on your machine:\n1. [CUDA](https://developer.nvidia.com/cuda-80-ga2-download-archive) must be installed. You should reboot your machine after installing CUDA.\n2. [cuDNN](https://developer.nvidia.com/cudnn): Once you have downloaded it, just unzip it and copy (merge) the contents on the CUDA folder, e.g., `/usr/local/cuda-8.0/`. Note: We found OpenPose working ~10% faster with cuDNN 5.1 compared to cuDNN 6. Otherwise, check the section [Compiling without cuDNN](#compiling-without-cudnn).\n3. OpenCV can be installed with `apt-get install libopencv-dev`. If you have compiled OpenCV 3 by your own, follow [Manual Compilation](#manual-compilation). After both Makefile.config files have been generated, edit them and uncomment the line `# OPENCV_VERSION := 3`. You might alternatively modify all `Makefile.config.UbuntuXX` files and then run the scripts in step 2.\n4. In addition, OpenCV 3 does not incorporate the `opencv_contrib` module by default. Assuming you have OpenCV 3 compiled with the contrib module and you want to use it, append `opencv_contrib` at the end of the line `LIBRARIES += opencv_core opencv_highgui opencv_imgproc` in the `Makefile` file.\n5. Atlas can be installed with `sudo apt-get install libatlas-base-dev`. Instead of Atlas, you can use OpenBLAS or Intel MKL by modifying the line `BLAS := atlas` in the same way as previously mentioned for the OpenCV version selection.\n\n\n\n### Installation - Script Compilation\nBuild Caffe & the OpenPose library + download the required Caffe models for Ubuntu 14.04 or 16.04 (auto-detected for the script) and CUDA 8:\n```bash\nbash scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh\n```\n**Highly important**: This script only works with CUDA 8 and Ubuntu 14 or 16. Otherwise, see [doc/installation/0_index.md](../0_index.md) or [Installation - Manual Compilation](#installation---manual-compilation).\n\n\n\n### Installation - Manual Compilation\nAlternatively to the script installation, if you want to use CUDA 7, avoid using sh scripts, change some configuration labels (e.g., OpenCV version), etc., then:\n1. Install the [Caffe prerequisites](http://caffe.berkeleyvision.org/installation.html).\n2. Compile Caffe and OpenPose by running these lines:\n    ```\n    ### Install Caffe ###\n    git submodule update --init --recursive --remote\n    cd 3rdparty/caffe/\n    # Select your desired Makefile file (run only one of the next 4 commands)\n    cp Makefile.config.Ubuntu14_cuda7.example Makefile.config # Ubuntu 14, cuda 7\n    cp Makefile.config.Ubuntu14_cuda8.example Makefile.config # Ubuntu 14, cuda 8\n    cp Makefile.config.Ubuntu16_cuda7.example Makefile.config # Ubuntu 16, cuda 7\n    cp Makefile.config.Ubuntu16_cuda8.example Makefile.config # Ubuntu 16, cuda 8\n    # Change any custom flag from the resulting Makefile.config (e.g., OpenCV 3, Atlas/OpenBLAS/MKL, etc.)\n    # Compile Caffe\n    make all -j`nproc` && make distribute -j`nproc`\n\n    ### Install OpenPose ###\n    cd ../../models/\n    bash ./getModels.sh # It just downloads the Caffe trained models\n    cd ..\n    cp scripts/ubuntu/Makefile.example Makefile\n    # Same file cp command as the one used for Caffe\n    cp scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda7.example Makefile.config\n    # Change any custom flag from the resulting Makefile.config (e.g., OpenCV 3, Atlas/OpenBLAS/MKL, etc.)\n    make all -j`nproc`\n    ```\n\n    NOTE: If you want to use your own Caffe distribution, follow the steps on [Custom Caffe](#custom-caffe) section and later re-compile the OpenPose library:\n    ```\n    bash ./install_openpose_if_cuda8.sh\n    ```\n    Note: These steps only need to be performed once. If you are interested in making changes to the OpenPose library, you can simply recompile it with:\n    ```\n    make clean\n    make all -j`nproc`\n    ```\n**Highly important**: There are 2 `Makefile.config.Ubuntu##.example` analogous files, one in the main folder and one in [3rdparty/caffe/](../../../3rdparty/caffe/), corresponding to OpenPose and Caffe configuration files respectively. Any change must be done to both files (e.g., OpenCV 3 flag, Atlab/OpenBLAS/MKL flag, etc.). E.g., for CUDA 8 and Ubuntu16: [3rdparty/caffe/Makefile.config.Ubuntu16_cuda8.example](../../../3rdparty/caffe/Makefile.config.Ubuntu16.example) and [scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example](../../../scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example).\n\n\n\n### Reinstallation\nIf you updated some software that our library or 3rdparty use, or you simply want to reinstall it:\n1. Clean the OpenPose and Caffe compilation folders:\n```\nmake clean && cd 3rdparty/caffe && make clean\n```\n2. Repeat the [Installation](#installation) steps. You do not need to download the models again.\n\n\n\n### Uninstallation\nYou just need to remove the OpenPose folder, by default called `openpose/`. E.g., `rm -rf openpose/`.\n\n\n\n## Windows\n### Installation - Library\n1. Install the pre-requisites:\n    1. **Microsoft Visual Studio (VS) 2015 Enterprise Update 3**.\n        - If **Visual Studio 2017 Community** is desired, we do not officially support it, but it might be compiled by firstly [enabling CUDA 8.0 in VS2017](https://stackoverflow.com/questions/43745099/using-cuda-with-visual-studio-2017?answertab=active#tab-top) or use **VS2017 with CUDA 9** by checking the `.vcxproj` file and changing the necessary paths from CUDA 8 to 9.\n        - VS 2015 Enterprise Update 1 will give some compiler errors and VS 2015 Community has not been tested.\n    2. [**CUDA 8**](https://developer.nvidia.com/cuda-80-ga2-download-archive): Install it on the default location, `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v8.0`. Otherwise, modify the Visual Studio project solution accordingly. Install CUDA 8.0 after Visual Studio 2015 is installed to assure that the CUDA installation will generate all necessary files for VS. If CUDA was already installed, re-install it after installing VS!\n    3. [**cuDNN 5.1**](https://developer.nvidia.com/cudnn): Once you have downloaded it, just unzip it and copy (merge) the contents on the CUDA folder, `C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v8.0`.\n\n#### CMake Installer\nRecommended installation method, it is simpler and offers more customization settings. See [doc/installation/0_index.md](../0_index.md). Note that it is a beta version, post in GitHub any issue you find.\n\n\n#### Deprecated Windows Installer\nNote: This installer will not incorporate any new features, we recommend to use the CMake installer.\n\n1. Download the OpenPose dependencies and models (body, face and hand models) by double-clicking on `{openpose_path}\\windows\\download_3rdparty_and_models.bat`. Alternatively, you might prefer to download them manually:\n    - Models:\n        - [COCO model](http://vcl.snu.ac.kr/OpenPose/models/pose/coco/pose_iter_440000.caffemodel): download in `models/pose/coco/`.\n        - [MPI model](http://vcl.snu.ac.kr/OpenPose/models/pose/mpi/pose_iter_160000.caffemodel): download in `models/pose/mpi/`.\n        - [Face model](http://vcl.snu.ac.kr/OpenPose/models/face/pose_iter_116000.caffemodel): download in `models/face/`.\n        - [Hands model](http://vcl.snu.ac.kr/OpenPose/models/hand/pose_iter_102000.caffemodel): download in `models/hand/`.\n    - Dependencies:\n        - [Caffe](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe_16_2020_11_14.zip): Unzip as `3rdparty/windows/caffe/`.\n        - [Caffe dependencies](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/caffe3rdparty_16_2020_11_14.zip): Unzip as `3rdparty/windows/caffe3rdparty/`.\n        - [OpenCV 4.2.0](http://vcl.snu.ac.kr/OpenPose/3rdparty/windows/opencv_450_v15_2020_11_18.zip): Unzip as `3rdparty/windows/opencv/`.\n2. Open the Visual Studio project sln file by double-cliking on `{openpose_path}\\windows\\OpenPose.sln`.\n3. In order to verify OpenPose is working, try compiling and executing the demo:\n    1. Right click on `OpenPoseDemo` --> `Set as StartUp Project`.\n    2. Change `Debug` by `Release` mode.\n    3. Compile it and run it with <kbd>F5</kbd> or the green play icon.\n4. If you have a webcam connected, OpenPose will automatically start after being compiled.\n5. In order to use the created exe file from the command line (i.e., outside Visual Studio), you have to:\n    1. Copy all the DLLs located on `{openpose_folder}\\3rdparty\\windows\\caffe\\bin\\` on the exe folder: `{openpose_folder}\\windows\\x64\\Release`.\n    2. Copy all the DLLs located on `{openpose_folder}\\3rdparty\\windows\\opencv\\x64\\vc15\\bin\\` on the exe folder: `{openpose_folder}\\windows\\x64\\Release`.\n    3. Open the Windows cmd (Windows button + <kbd>X</kbd>, then <kbd>A</kbd>).\n    4. Go to the OpenPose directory, assuming OpenPose has been downloaded on `C:\\openpose`: `cd C:\\openpose\\`.\n    5. Run the tutorial commands.\n6. Check OpenPose was properly installed by running it on the default images, video or webcam: [doc/01_demo.md](../../01_demo.md).\n\n\n\n### Uninstallation\nYou just need to remove the OpenPose or portable demo folder.\n\n\n\n### Reinstallation\nIf you updated some software that our library or 3rdparty use, or you simply want to reinstall it:\n1. Open the Visual Studio project sln file by double-cliking on `{openpose_path}\\windows\\OpenPose.sln`.\n2. Clean the OpenPose project by right-click on `Solution 'OpenPose'` and `Clean Solution`.\n3. Compile it and run it with <kbd>F5</kbd>  or the green play icon.\n\n\n\n\n\n## Doxygen Documentation Autogeneration\nSee [doc/installation/0_index.md#doxygen-documentation-autogeneration-ubuntu-only](../0_index.md#doxygen-documentation-autogeneration-ubuntu-only).\n\n\n\n\n\n## Custom Caffe\nWe only modified some Caffe compilation flags and minor details. You can use your own Caffe distribution, these are the files we added and modified:\n\n1. Added files: `install_caffe.sh`; as well as `Makefile.config.Ubuntu14.example`, `Makefile.config.Ubuntu16.example`, `Makefile.config.Ubuntu14_cuda_7.example` and `Makefile.config.Ubuntu16_cuda_7.example` (extracted from `Makefile.config.example`). Basically, you must enable cuDNN.\n2. Edited file: Makefile. Search for \"# OpenPose: \" to find the edited code. We basically added the C++11 flag to avoid issues in some old computers.\n3. Optional - deleted Caffe file: `Makefile.config.example`.\n4. In order to link it to OpenPose:\n    1. Run `make all && make distribute` in your Caffe version.\n    2. Open the OpenPose Makefile config file: `./Makefile.config.UbuntuX.example` (where X depends on your OS and CUDA version).\n    3. Modify the Caffe folder directory variable (`CAFFE_DIR`) to your custom Caffe `distribute` folder location in the previous OpenPose Makefile config file.\n\n\n\n\n\n## Compiling without cuDNN\nSee [doc/installation/0_index.md#compiling-without-cudnn](../0_index.md#compiling-without-cudnn).\n"
  },
  {
    "path": "doc/installation/jetson_tx/installation_jetson_tx1.md",
    "content": "OpenPose Doc - Installation on Nvidia Jetson TX1\n====================================\n## Introduction\nWe do not officially support TX1, but thanks to @dreinsdo, we have these instructions about how he made it work in his TX1. We would like to thank @dreinsdo, who added this documentation in [this GitHub issue post](https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1124#issuecomment-474090671). If you face any issue, feel free to post on that issue post.\n\n## Purpose\nThis document describes the full procedure for installing openpose on the Jetson TX1. Other, and less involved, procedures may have been found successful by community members, and we encourage you to share your alternatives.\n\n\n## Preliminary remarks\nThis procedure details moving the Jetson file system to a larger drive, building a custom kernel, building OpenCV from source, and customizing Openpose Makefiles because TX1 eMMC is limited, the onboard camera did not work with Openpose, stock Jetpack 3.1 OpenCV build lacks Openpose dependencies, and Openpose makefiles are not compatible with TX1 CUDA arch, respectively. We used a PS3 Eye camera in place of the onboard camera, and a 120Gb SSD, but most USB webcams and SATA drives should work fine.\n\n\n## Contents\n- [Prep the TX1](#prep-the-tx1)\n- [Build custom kernel](#build-custom-kernel)\n- [Build OpenCV from source](#build-opencv-from-source)\n- [Install Openpose](#install-openpose)\n- [Usage](#usage)\n\n\n## Prep the TX1\n1. Flash Jetson TX1 with [JetPack 3.1](https://developer.nvidia.com/embedded/jetpack) per Jetpack installation guide. Be sure to complete both OS flashing and CUDA / cuDNN installation parts before installation.\n2. Move file system to SATA drive. Follow steps of JetsonHacks article [Install Samsung SSD on NVIDIA Jetson TX1](https://www.jetsonhacks.com/2017/01/28/install-samsung-ssd-on-nvidia-jetson-tx1/).\n\n\n## Build custom kernel\nThis step is required because we were not able to use Openpose with the onboard TX1 camera. The steps are a combination of two JetsonHacks articles [Build Kernel and ttyACM Module – NVIDIA Jetson TX1](https://www.jetsonhacks.com/2017/08/07/build-kernel-ttyacm-module-nvidia-jetson-tx1/) and [Sony PlayStation Eye – NVIDIA Jetson TX1](https://www.jetsonhacks.com/2016/09/29/sony-playstation-eye-nvidia-jetson-tx1/). If you are using a different webcam then include the driver for that webcam in place of the PS3 eye driver in step 3.\n1. Get the install scripts from [JetsonHacks Github](https://github.com/jetsonhacks/buildJetsonTX1Kernel/archive/v1.0-L4T28.1.zip). This link is to the zip of the 'JetPack 3.1' release. If you $git clone$ from the master branch then you will get the most recent kernel build files, which are not compatible with JetPack 3.1.\n2. Unzip the downloaded files, enter the unzipped directory and run script to get kernel sources.\n```\n$ cd buildJetsonTX1Kernel\n$ sudo ./getKernelSources.sh\n```\n3. The script will open the editor for the kernel configuration. Find the driver for your webcam and select with a checkbox (not a dot). Save the configuration and quit the config window.\n4. Make the kernel.\n```\n$ sudo ./makeKernel.sh\n```\n5. Replace the current kernel the newly built kernel image.\n```\n$ sudo cp /usr/src/kernel/kernel-4.4/arch/arm64/boot/Image ($PATH_TO_EMMC)/boot/Image\n```\nReplace $PATH_TO_EMMC with the path to your eMMC. This is required because the Jetson initially boots to eMMC and loads the kernel from their, even with the SATA drive connected.\n\n\n## Build OpenCV from source\nFollow JK Jung's steps from [How to Install OpenCV (3.4.0) on Jetson TX2](https://jkjung-avt.github.io/opencv3-on-tx2/) verbatim, with the following exception: omit installation of Python3 dependencies, i.e. skip the following lines.\n```\n$ sudo apt-get install python3-dev python3-pip python3-tk\n$ sudo pip3 install numpy\n$ sudo pip3 install matplotlib\n```\n\n\n## Install Openpose\nThe following steps detail the modification of three files to install Openpose. Modified versions of the files are attached and may alternatively be used. To use, be sure to rename both makefile configs to `Makefile.config.Ubuntu16_cuda8_JetsonTX2`. \n1. Clone from the master branch.\n```\n$ git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose\n$ cd openpose\n```\n2. Modify makefile config. For the installation procedure we will use the TX2 files for JetPack 3.1. \n```\n$ gedit scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2\n```\nUncomment the opencv line\n```\nOPENCV_VERSION := 3\n```\nReplace all the 'CUDA_ARCH :=' lines with the following\n```\nCUDA_ARCH := -gencode arch=compute_53,code=[sm_53,compute_53]\n```\nAdd CUDNN - not sure if this is necessary, have not retried the install without it.\n```\nUSE_CUDNN := 1\n```\n3. Correct error in install script path.\n```\n$ gedit scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh\n```\nReplace \n```\nexecuteShInItsFolder \"install_openpose_JetsonTX2_JetPack3.1.sh\" \"./scripts/ubuntu/\" \"./\"\n```\nwith\n```\nexecuteShInItsFolder \"./scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh\" \"./\" \"./\"\n```\n4. Start the install process. When you initially call the install script the caffe repo will be cloned and associated files downloaded. As soon as Caffe starts compiling, halt the process and change the makefile config as in step 2.\n```\nbash ./scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh\n```\nOnce caffe begins to compile `CTRL+C`.\n```\n$ gedit 3rdparty/caffe/Makefile.config.Ubuntu16_cuda8_JetsonTX2\n```\nMake the same changes as in step 2. The CUDNN switch should already be on.\n\n5. Restart the installation process.\n```\nbash ./scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh\n```\n\n## Usage\nTo get to decent FPS you need to lower the net resolution:\n```\n./build/examples/openpose/openpose.bin -camera_resolution 640x480 -net_resolution 128x96\n```\n\nTo activate hand or face resolution please complete this command with the following options (warning, both simultaneously will cause out of memory error):\n```\n# Body and face\n./build/examples/openpose/openpose.bin --face -face_net_resolution 256x256\n# Body and hands\n./build/examples/openpose/openpose.bin --hand -hand_net_resolution 256x256\n# All body, face, and hands\n./build/examples/openpose/openpose.bin --face -face_net_resolution 256x256 --hand -hand_net_resolution 256x256\n```\n"
  },
  {
    "path": "doc/installation/jetson_tx/installation_jetson_tx2_jetpack3.1.md",
    "content": "OpenPose Doc - Installation on Nvidia Jetson TX2 JetPack 3.1\n====================================\nNote that OpenPose for Nvidia Jetson TX2 was developed and it is maintained by the community. The OpenPose authors will not be able to provide official support for it.\n\n\n\n## Contents\n1. [Requirements and Dependencies](#requirements-and-dependencies)\n2. [Installation](#installation)\n3. [Usage](#usage)\n\n\n\n## Requirements and Dependencies\nJetson TX2 just flashed with [JetPack 3.1](https://developer.nvidia.com/embedded/jetpack)\n\nNotes:\n\n- Installation is similar to Jetson TX1 and you can follow this [video tutorial](https://www.youtube.com/watch?v=RJkOGMC8IrY).\n- If you are installing from a virtual machine host, installation may need to be done in two steps, please refer to [this solution](https://devtalk.nvidia.com/default/topic/1002081/jetson-tx2/jetpack-3-0-install-with-a-vm/).\n- Be sure to complete both OS flashing and CUDA / cuDNN installation parts before installation.\n\n**Dependencies**:\n\n    - OpenCV (all 2.X and 3.X versions are compatible).\n    - Caffe and all its dependencies.\n    - The demo and tutorials additionally use GFlags.\n\n\n\n## Installation\nUse the following script for installation of both caffe and OpenPose: \n```\nbash ./scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh\n```\n\n\n## Usage\nIt is for now recommended to use an external camera with the demo. To get to decent FPS you need to lower the net resolution:\n```\n./build/examples/openpose/openpose.bin -camera_resolution 640x480 -net_resolution 128x96\n```\n\nTo activate hand or face resolution please complete this command with the following options (warning, both simultaneously will cause out of memory error):\n```\n--hand -hand_net_resolution 256x256\n--face -face_net_resolution 256x256\n```\n"
  },
  {
    "path": "doc/installation/jetson_tx/installation_jetson_tx2_jetpack3.3.md",
    "content": "OpenPose Doc - Installation on Nvidia Jetson TX2 JetPack 3.3\n====================================\nNote that OpenPose for Nvidia Jetson TX2 was developed and it is maintained by the community. The OpenPose authors will not be able to provide official support for it.\n\n\n\n## Contents\n1. [Requirements and Dependencies](#requirements-and-dependencies)\n2. [Installation](#installation)\n3. [Usage](#usage)\n\n\n\n## Requirements and Dependencies\nJetson TX2 just flashed with [JetPack 3.3](https://developer.nvidia.com/embedded/jetpack)\n\nNotes:\n\n- Installation is similar to Jetson TX1 and you can follow this [step by step tutorial](https://docs.nvidia.com/jetson/archives/jetpack-archived/jetpack-33/index.html#jetpack/3.3/install.htm%3FTocPath%3D_____3).\n- If you are installing from a virtual machine host, installation may need to be done in two steps, please refer to [this solution](https://devtalk.nvidia.com/default/topic/1002081/jetson-tx2/jetpack-3-0-install-with-a-vm/).\n- Be sure to complete both OS flashing and CUDA / cuDNN installation parts before installation.\n\n**Dependencies**:\n\n    - OpenCV (3.X versions are compatible).\n    - Caffe and all its dependencies.\n    - The demo and tutorials additionally use GFlags.\n\n\n\n## Installation\nUse the following script for installation of both caffe and OpenPose:\n```\nbash ./scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.3.sh\n```\n\nOptional: If you want to build the Python libraries, then:\n1. Edit the `BUILD_PYTHON` flag on `CMakeLists.txt`:\n\n```option(BUILD_PYTHON \"Build OpenPose python.\" ON)```\n\n2. In both places where this appears, set the flag to ON:\n```\n-DBUILD_python=ON\n-DBUILD_python_layer=ON\n````\n\n3. There are additional flags that need to be set: `PYTHON_EXECUTABLE=/usr/bin/python2.7` and `PYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython2.7.so` for Python 2.7. Therefore, inside build, do:\n\n```cmake -DBUILD_PYTHON=ON -DPYTHON_EXECUTABLE=/usr/bin/python2.7 -DPYTHON_LIBRARY=/usr/lib/aarch64-linux-gnu/libpython2.7.so ..```\n\n4. Now run `make`.  You should see a file called \"pyopenpose.so\" if Python was set to 2.7, in\n`/home/nvidia/openpose/build/python/openpose`. Otherwise, it will be `pyopenpose.cpython-35m-aarch64-linux-gnu`.\n\n5. Finally, run `sudo make install` inside build to copy the files to /usr/local/python and set PYTHONPATH accordingly on .bashrc:\n\n```export PYTHONPATH=\"${PYTHONPATH}:/usr/local/python```\n\n\n\n## Usage\nIt is for now recommended to use an external camera with the demo. To get to decent FPS you need to lower the net resolution:\n```\n./build/examples/openpose/openpose.bin -camera_resolution 640x480 -net_resolution 128x96\n```\n\nTo activate hand or face resolution please complete this command with the following options (warning, both simultaneously will cause out of memory error):\n```\n--hand -hand_net_resolution 256x256\n--face -face_net_resolution 256x256\n```\n"
  },
  {
    "path": "doc/very_advanced/library_structure/0_index.md",
    "content": "OpenPose Very Advanced Doc - Library Structure\n====================================\n\nAs a user, you do not need to know anything about this section! This section is intended for OpenPose internal developers. It is exposed publicly, but you can skip this whole folder if you are just trying to use OpenPose or create new code/demos using OpenPose.\n\nEven if you want to e.g., change internal functions and/or extend the OpenPose functionality, the easiest solution as a user is to follow the [OpenPose C++ API](../../doc/04_cpp_api.md). If the new functionality is cool, make a pull request so we can add it to OpenPose!\n\nIn order to learn the basics about how OpenPose works internally:\n1. See the Doxygen documentation on [http://cmu-perceptual-computing-lab.github.io/openpose](http://cmu-perceptual-computing-lab.github.io/openpose) or build that Doxygen doc from the source code.\n2. Take a look at the [library Quick Start section](../../README.md#quick-start-overview) from the main README (or its Doxygen analog).\n3. OpenPose Overview: Learn the basics about the library source code in [doc/very_advanced/library_structure/1_library_deep_overview.md](1_library_deep_overview.md).\n4. Extending Functionality: Learn how to extend the library in [doc/very_advanced/library_structure/2_library_extend_functionality.md](2_library_extend_functionality.md).\n5. Adding An Extra Module: Learn how to add an extra module in [doc/very_advanced/library_structure/3_library_add_new_module.md](3_library_add_new_module.md).\n"
  },
  {
    "path": "doc/very_advanced/library_structure/1_library_deep_overview.md",
    "content": "OpenPose Very Advanced Doc - Library Structure - Deep Overview\n====================================\n\n\n\nNote: Read [doc/very_advanced/library_structure/0_index.md](0_index.md) before this page.\n\n\n\n## Modules Diagram\n<p align=\"center\">\n    <img src=\"./UML/1_0_0rc3/UML.png\" width=\"720\">\n</p>\n\n\n\n## Debugging C++ Code\n### Finding Segmentation Faults\nThis is the faster method to debug a segmentation fault problem. Usual scenario: You are editing OpenPose source code and suddenly OpenPose returns segmentation fault when executed. In order to find where it occurs:\n\n1. Select one of the 2 options:\n    1. Switch to debug mode.\n    2. Go to `openpose/utilities/errorAndLog.hpp` and modify `dLog`:\n        1. Comment `#ifndef NDEBUG` and its else and endif.\n2. Call OpenPose with `--logging_level 0 --disable_multi_thread`.\n3. At this point you have an idea of in which file class the segmentation fault is coming from. Now you can further isolate the error by iteratively adding the following line all over the code until you find the exact position of the segmentation fault: `opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);`\n4. After you have found the segmentation fault, remember to remove all the extra `opLog()` calls that you temporarily added.\n\n\n\n## Accuracy\n### Checking OpenPose Accuracy Quantitatively\n1. Download OpenPose training code: https://github.com/CMU-Perceptual-Computing-Lab/openpose_train\n2. Download val2017 set from COCO: http://images.cocodataset.org/zips/val2017.zip\n3. Get JSONs in OpenPose: examples/tests/pose_accuracy_coco_val.sh\n4. Get accuracy (Matlab): validation/f_getValidations.m\n\n### Checking Ground-Truth Labels\nFrom the [COCO dataset](http://cocodataset.org/#download):\n1. Download 2014 or 2017 Train/Val annotations.\n2. Download the [COCO API](https://github.com/cocodataset/cocoapi).\n3. With the COCO API (either Python, Matlab, or LUA ones), you can check any image with the image ID (equivalent to the number in the image name).\n\n\n\n## OpenPose Coding Style\n1. Error-prone mistakes:\n    1. Do never use std::mutex.lock and/or std::mutex.unlock. Use std::unique_lock<std::mutex> if unlock required or std::lock_guard<std::mutex> otherwise.\n    2. Do never use the new keyword with std::shared_ptr, but rather: std::make_shared<>.\n2. Naming:\n    1. Class parameters should start with `m`, class pointers with `p`, shared_ptrs with `sp`, unique_ptrs with `up`, static parameters with `s`.\n    2. Function and class parameters coding style is the same other than the previous point.\n    3. Any parameters should not contain special characters, simply letters and numbers (preferred only letters) separated with upper case. E.g., `mThisIsAParameter`, `thisIsAParameter`.\n    4. In addition, the names should be self-explanatory and not abbreviated. Good examples: `counter`, `thisIs`. Bad examples: `ctr`, `var`.\n3. Length:\n    1. Lines should contain up to 120 characters.\n4. Comments:\n    1. Only `//` comments are allowed in the code, `/* */` should not be used.\n    2. There should be a (at least) 1-line comment for each block of code inside each function.\n5. Loops and statements:\n    1. There should be a space between the keyword (`if`, `for`, etc) and the parenthesis, e.g., `if (true)`. Wrong: `if(true)`. Note: So they can be easily located with Ctrl + F.\n    2. Braces should be added in the following line with respect to the loop/statement keyword. See example in point 3.\n    3. 1-line loops/statements should not contain braces. E.g.,\n```\nif (booleanParameter)\n    anotherParameter = 25;\nelse\n{\n    anotherParameter = 2;\n    differentParameter = 3;\n}\n```\n\n6. Includes:\n    1. There cannot be any include to a 3rd party in the headers (other than OpenCV core: `opencv2/core/core.hpp`).\n        1. PImpl idiom can be checked (e.g., in `include/openpose/pose/poseExtractorCaffe.hpp`) for an idea of how to avoid it.\n        2. Otherwise the defining class examples in `include/openpose/core/macros.hpp` (point 1 is highly preferred).\n    2. They should be sorted in this order:\n        1. Std libraries.\n        2. OS libraries.\n        3. 3rd party libraries (e.g., Caffe, OpenCV).\n        4. OpenPose libraries.\n        5. If it is a cpp file, the last one should be its own hpp.\n    3. Inside each of the previous groups, it should be sorted alphabetically.\n7. Functions arguments:\n    1. It should first include the variables to be edited, and secondly the const variables.\n    2. Any variable that is not gonna be modified must be added with `const`.\n8. Pointers:\n    1. Pointers must be avoided if possible.\n    2. If a pointer must be used, std::unique_ptr must be always be used.\n    3. If the pointer must be shared, then std::shared_ptr.\n    4. No `delete` keyword is allowed in OpenPose.\n\n\n\n## Main Modules\nIn order to use and/or slightly extend the OpenPose library, we try to explain the 2 main components on this section. [doc/very_advanced/library_structure/UML](UML/) contains the class diagram of all these modules.\n\n1. The basic module: `core`.\n\n2. The multi-threading module: `thread`.\n\n3. The multi-person keypoint detection module: `pose`.\n\n\n## Basic Module: `core`\n### Array<T> - The OpenPose Basic Raw Data Container\nThis template class implements a multidimensional data array. It is our basic data container, analogous to `cv::Mat` in OpenCV, Tensor in Torch and TensorFlow or Blob in Caffe. It wraps a `cv::Mat` and a `std::shared_ptr`, both of them pointing to the same raw data. I.e. they both share the same memory, so we can read this data in both formats, while there is no performance impact. For instance, `op::Datum` has several `op::Array<float>`, for instance the `op::Datum<float> pose` with the pose data.\n\n#### Construction And Data allocation\nThere are 4 different ways to allocate the memory:\n\n1. The constructor `Array(const std::vector<int>& size)`, which calls `reset(size)`.\n\n2. The constructor `Array(const int size)`, which calls `reset(size)`.\n\n3. The `reset(const std::vector<int>& size)` function: It allocates the memory indicated for size. The allocated memory equals the product of all elements in the size vector. Internally, it is saved as a 1-D std::shared_ptr<T[]>.\n\n4. The `reset(const int size)` function: equivalent for 1-dimension data (i.e., vector).\n\n5. The `setFrom(const cv::Mat& cvMat)` function: It calls `reset()` and copies the data from `cvMat`.\n\n#### Data access\nThe data can be access as a raw pointer, shared pointer or `cv::Mat`. So given your `Array<T>` array:\n\n1. Similar to the std::vector: `array[index]` or `array.at(index)`. If the code is in debug mode, they both has the same functionality. In release mode, the only difference is that the `at` function checks whether the index is within the limits of the data.\n\n2. As `const cv::Mat`: `array.getConstCvMat()`. We do not allow to directly modify the `cv::Mat`, since some operations might change the dimensional size of the data. If you want to do so, you can clone this `cv::Mat`, perform any desired operation, and copy it back to the array class with `setFrom()`.\n\n3. As raw pointer: `T* getPtr()` and `const T* const getConstPtr()`. Similar to std:: and std::shared_ptr::get(). For instance, CUDA code usually requires raw pointers to access its data.\n\n#### Dimensionality Information\nThere are several functions to get information about the allocated data:\n\n1. `bool empty()`: Similar to `cv::Mat::empty()`. It checks whether internal data has been allocated.\n\n2. `std::vector<int> getSize()`: It returns the size of each dimension.\n\n3. `int getSize(const int index)`: It returns the size of the `index` dimension.\n\n4. `size_t getNumberDimensions()`: It returns the number of dimensions (i.e., getSize().size()).\n\n5. `size_t getVolume()`: It returns the total internal number of T objects, i.e., the product of all dimensions size.\n\n\n### Datum - The OpenPose Basic Piece of Information Between Threads\nThe `Datum` class has all the variables that our Workers need to share to each other. The user can inherit from `op::Datum` in order to add extra functionality (e.g., if he want to add new Workers and they require extra information between them). We highly recommend not to modify the `op::Datum` source code. Instead, just inherit it and tell the Workers and `ThreadManager` to use your inherited class. No changes are needed in the OpenPose source code for this task.\n```\nUserDatum : public op::Datum {/* op::Datum + extra variables */}\n\n// Worker and ThreadManager example initialization\nop::WGui<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> userGUI(/* constructor arguments */);\nop::ThreadManager<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> userThreadManager;\n```\n\nSince `UserDatum` inherits from `op::Datum`, all the original OpenPose code will compile and run with your inherited version of `op::Datum`.\n\n\n\n## Multi-Threading Module - `thread`\n### The ThreadManager<T> Template Class\nIt manages and automates the multi-threading configuration and execution. The user just needs to add the desired Worker<T> classes to be executed and the parallelization mode, and this class will take care of it.\n\n#### Constructor\nJust call `op::ThreadManager<TypedefDatumsSP> threadManager`.\n\n#### Adding a Worker Sequence\nThere are 4 ways to add sequence of workers:\n\n1. `void add(const std::vector<std::tuple<unsigned long long, std::vector<TWorker>, unsigned long long, unsigned long long>>& threadWorkerQueues)`.\n\n2. `void add(const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long, unsigned long long>>& threadWorkerQueues)`.\n\n3. `void add(const unsigned long long threadId, const std::vector<TWorker>& tWorkers, const unsigned long long queueInId, const unsigned long long queueOutId)`.\n\n4. `void add(const unsigned long long threadId, const TWorker& tWorker, const unsigned long long queueInId, const unsigned long long queueOutId)`.\n\n#### Threading Configuration Modes\nThere are 3 basic configuration modes: single-threading, multi-threading and smart multi-threading (mix of single- and multi-threading):\n\n1. Single-threading, with 2 variations:\n    1. Just call `threadManager.add(0, std::vector<TypedefWorker> VECTOR_WITH_ALL_WORKERS, 0, 1);`\n    2. Add the workers one by one, but keeping the same threadId:\n    ```\n    auto threadId = 0;\n    auto queueIn = 0;\n    auto queueOut = 0;\n    threadManager.add(threadId, {wDatumProducer, wCvMatToOpInput}, queueIn++, queueOut++);      // Thread 0, queues 0 -> 1\n    threadManager.add(threadId, wPose, queueIn++, queueOut++);                                  // Thread 0, queues 1 -> 2\n    ```\n\n2. Multi-threading: Just increase the thread id for each new sequence:\n    ```\n    auto threadId = 0;\n    auto queueIn = 0;\n    auto queueOut = 0;\n    threadManager.add(threadId++, wDatumProducer, queueIn++, queueOut++);                       // Thread 0, queues 0 -> 1\n    threadManager.add(threadId++, wCvMatToOpInput}, queueIn++, queueOut++);                     // Thread 1, queues 1 -> 2\n    threadManager.add(threadId++, wPose, queueIn++, queueOut++);                                // Thread 2, queues 3 -> 3\n    ```\n\n3. Smart multi-threading: Some classes are much more faster than others (e.g., pose estimation takes ~100 ms while extracting frames from a video only ~10 ms). In addition, any machine has a limited number of threads. Therefore, the library allows the user to merge the faster threads in order to potentially speed up the code. Check the [command line demo](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/examples/openpose/openpose.cpp) too see a more complete example.\n    ```\n    auto threadId = 0;\n    auto queueIn = 0;\n    auto queueOut = 0;\n    threadManager.add(threadId++, {wDatumProducer, wCvMatToOpInput}, queueIn++, queueOut++);    // Thread 0, queues 0 -> 1, 2 workers merged together into 1 thread\n    threadManager.add(threadId++, wPose, queueIn++, queueOut++);                                // Thread 1, queues 1 -> 2, 1 worker\n    ```\n\n#### Thread Id:\nIn order to have X different threads, you just need X different thread ids in the `add()` function. There should not be any missing thread or queue id. I.e., when `start` is called, all the thread ids from 0 to max_thread_id must have been added with the `add()` function, as well as all queue ids from 0 to the maximum queue id introduced.\n\nThe threads will be started following the thread id order (first the lowest id, last the highest one). In practice, thread id ordering might negatively affect the program execution by adding some lag. I.e., if the thread ids are assigned in complete opposite order to the temporal order of the Workers (e.g., first the GUI and lastly the webcam reader), then during the first few iterations the GUI Worker will have an empty queue until all other Workers have processed at least one frame.\n\nWithin each thread, the Workers are executed in the order that they have been added to `ThreadManager` by the `add()` function.\n\n#### Queue Id:\nIn addition, each queue id is forced to be the input and output of at least 1 Worker sequence. Special cases are the queue id 0 (only forced to be input of >= 1 Workers) and max_queue_id (forced to be output of >=1 Workers). This prevent users from accidentally forgetting connecting some queue ids.\n\nRecursive queuing is allowed. E.g., a Worker might work from queue 0 to 1, another one from 1 to 2, and a third one from 2 to 1, creating a recursive queue/threading. However, the index 0 is reserved for the first queue, and the maximum index for the last one.\n\n\n### The Worker<T>  Template Class - The Parent Class of All Workers\nClasses starting by the letter `W` + upper case letter (e.g., `WGui`) directly or indirectly inherit from Worker<T>. They can be directly added to the `ThreadManager` class so they can access and/or modify the data as well as be parallelized automatically.\n\nThe easiest way to create your own Worker is to inherit Worker<T>, and implement the work() function such us it just calls a wrapper to your desired functionality (check the source code of some of our basic Workers). Since the Worker classes are templates, they are always compiled. Therefore, including your desired functionality in a different file will let you compile it only once. Otherwise, it would be compiled any time that any code which uses your worker is compiled.\n\nAll OpenPose Workers are templates, i.e., they are not only limited to work with the default op::Datum. However, if you intend to use some of our Workers, your custom `TDatums` class (the one substituting op::Datum) should implement the same variables and functions that those Workers use. The easiest solution is to inherit from `op::Datum` and extend its functionality.\n\n\n### Creating New Workers\nUsers can directly implement their own `W` from Worker<T> or any other sub-inherited Worker[...]<T> class and add them to `ThreadManager`. For that, they just need to: inherit those classes from...\n\n1. Inherit from `Worker<T>` and implement the functionality `work(T& tDatum)`, i.e., it will use and modify tDatum.\n\n2. Inherit from `WorkerProducer<T>` and implement the functionality `T work()`, i.e., it will create and return tDatum.\n\n3. Inherit from `WorkerConsumer<T>` and implement the functionality `work(const T& tDatum)`, i.e., it will use but will not modify tDatum.\n\nWe suggest users to also start their inherited `Worker<T>` classes with the `W` letter for code clarity, required if they want to send us a pull request.\n\n\n### All Workers Wrap a Non-Worker Class\nAll Workers wrap and call a non-Worker non-template equivalent which actually performs their functionality. E.g., `WPoseExtractor<T>` and `PoseExtractor`. In this way, threading and functionality are completely decoupled. This gives us the best of templates and normal classes:\n\n1. Templates allow us to use different classes, e.g., the user could use his own specific equivalent to `op::Datum`. However, they must be compiled any time that any function that uses them changes.\n\n2. Classes can be compiled only once, and later the algorithm just use them. However, they can only be used with specific arguments. \n\nBy separating functionality and their `Worker<T>` wrappers, we get the good of both points, eliminating the cons. In this way, the user is able to:\n\n1. Change `std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>` for a custom class, implementing his own `Worker` templates, but using the already implemented functionality to create new custom `Worker` templates.\n\n2. Create a `Worker` which wraps several non-`Worker`s classes.\n\n\n\n## Multi-Person Key-Point Detection module - `pose`\nThe human body pose detection is wrapped into the `WPoseExtractor<T>` worker and its equivalent non-template PoseExtractor. In addition, it can be rendered and/or blended into the original frame with `(W)PoseRenderer` class.\n\n### PoseExtractor Class\nCurrently, only `PoseExtractorCaffe` is implemented, which uses the Caffe framework. We might add other famous frameworks later (e.g., Torch or TensorFlow). If you compile our library with any other framework, please email us or make a pull request! We are really interested in adding any other Deep Net framework, and the code is mostly prepared for it. Just create the equivalent `PoseExtractorDesiredFramework` and make the pull request!\n\n#### Constructor\nIn order to be initialized, `PoseExtractorCaffe` has the following constructor and parameters: `PoseExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize, const Point<int>& outputSize, const int scaleNumber, const double scaleGap, const PoseModel poseModel, const std::string& modelsFolder, const int gpuId)`.\n\n1. `netInputSize` is the resolution of the first layer of the deep net. I.e., the frames given to this class must have that size.\n\n2. `netOutputSize` is the resolution of the last layer of the deep net. I.e., the resulting heatmaps will have this size. Currently, it must be set to the same size as `netInputSize`.\n\n3. `outputSize` is the final desired resolution to be used. The human pose keypoint locations will be scaled to this output size. However, the heat-maps will have the `netOutputSize` size due to performance.\n\n4. `scaleNumber` and `scaleGap` specify the multi-scale parameters. Explained in [doc/advanced/demo_advanced.md](../../advanced/demo_advanced.md).\n\n5. `poseModel` specifies the model to load (e.g., COCO or MPI).\n\n6. `modelsFolder` is the resolution of the last layer of the deep net. I.e., the resulting heat-maps will have this size.\n\n7. `gpuId` specifies the GPU where the deep net will run. To parallelize the process along the number of available GPUs, just create the class with the same number of parameters but a different GPU id.\n\n#### Detect Human Pose\nIn order to detect the human pose:\n\n1. First run the deep net over the desired target image, by using `forwardPass(const Array<float>& inputNetData, const Point<int>& inputDataSize)`. `inputNetData` is the input image scaled to `netInputSize`, while `inputDataSize` indicates the original frame resolution before being rescaled to `netInputSize` (this is required given that we resize the images keeping the original aspect ratio).\n\n2. After, you can choose either to get:\n    1. The people pose as a op::Array<float>: `Array<float> getPose()`.\n    2. The scale used (keeping the aspect ratio) to rescale from `netOutputSize` to `outputSize`: `double getScaleNetToOutput()`.\n    3. The people pose as a constant GPU float pointer (not implemented yet): `const float* getPoseGpuConstPtr()`.\n    4. The heatmap data as a constant CPU or GPU float pointer: `const float* getHeatMapCpuConstPtr()` and `const float* getHeatMapGpuConstPtr()`.\n\nDue to performance reasons, we only copy the people pose data given by `getPose()`. However, we do not copy the heatmap and GPU pose values and just give you a raw pointer to them. Hence, you need to manually copy the data if you pretend to use it later, since we reuse that memory on each `forwardPass`.\n\n### PoseRenderer Class\nAfter estimating the pose, you usually desired to visualize it. `PoseRenderer` does this work for you.\n\n#### Constructor\nIn order to be initialized, `PoseRenderer` has the following constructor and parameters: `PoseRenderer(const Point<int>& netOutputSize, const Point<int>& outputSize, const PoseModel poseModel, const std::shared_ptr<PoseExtractor>& poseExtractor, const float alphaKeypoint, const float alphaHeatMap)`.\n\n1. `netOutputSize`, `outputSize` and `poseModel` are the same as the ones used for `PoseExtractorCaffe`.\n\n2. `poseExtractor` is the pose extractor used previously. It is only used for heatmap and PAFs rendering, since the GPU data is not copied to `op::Datum` for performance purposes. If any of the heatmaps are gonna be rendered, `PoseRenderer` must be placed in the same thread as `PoseExtractor`. Otherwise, it will throw a runtime exception.\n\n3. `alphaKeypoint` and `alphaHeatMap` controls the blending coefficient between original frame and rendered pose or heatmap/PAF respectively. A value `alphaKeypoint = 1` will render the pose with no transparency at all, while `alphaKeypoint = 0` will not be visible. In addition, `alphaHeatMap = 1` would only show the heatmap, while `alphaHeatMap = 0` would only show the original frame.\n\n#### Render Human Pose\nIn order to render the detected human pose, run `std::pair<int, std::string> renderPose(Array<float>& outputData, const Array<float>& pose, const double scaleNetToOutput)`.\n\n1. `outputData` is the Array<float> where the original image resized to `outputSize` is located.\n\n2. `pose` is given by `PoseExtractor::getPose()`.\n\n3. `scaleNetToOutput` is given by `PoseExtractor::getScaleNetToOutput()`.\n\n4. The resulting std::pair has the element rendered id, and its name. E.g., <0, \"Nose\"> or <19, \"Part Affinity Fields\">.\n"
  },
  {
    "path": "doc/very_advanced/library_structure/2_library_extend_functionality.md",
    "content": "OpenPose Very Advanced Doc - Library Structure - How to Extend Functionality\n====================================\n\nIf you intend to extend the functionality of our library:\n\n1. Read the [README.md](../../../README.md) page.\n2. Check the basic library overview doc on [doc/very_advanced/library_structure/1_library_deep_overview.md](1_library_deep_overview.md).\n3. Read, understand and play with the basic real time pose demo source code [OpenPose demo](../../doc/01_demo.md) and [C++ API](../../doc/04_cpp_api.md). It includes all the functionality of our library, and it has been properly commented.\n4. Read, understand and play with the other tutorials in [examples/](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/examples). It includes more specific examples.\n5. Check the basic UML diagram on the [doc/very_advanced/library_structure/UML](UML/) to get an idea of each module relations.\n6. Take a look to the stucuture of the already existing modules.\n7. The C++ headers files add documentation in [Doxygen](http://www.doxygen.org/) format. Create this documentation by compiling the [include](https://github.com/CMU-Perceptual-Computing-Lab/openpose/tree/master/include) folder with Doxygen. This documentation is slowly but continuously improved.\n8. You can also take a look to the source code or ask us on GitHub.\n"
  },
  {
    "path": "doc/very_advanced/library_structure/3_library_add_new_module.md",
    "content": "OpenPose Very Advanced Doc - Library Structure - Steps to Add a New Module\n====================================\n\n## Developing Steps\nIn order to add a new module, these are the recommended steps in order to develop it:\n\n1. Create a folder with its name in the `experimental/` module, e.g., `experimental/hair/`.\n2. Implement all the functionality in one `Worker`. I.e., inherit from `Worker` and implement all the functionality on that class (copy the examples from any Worker subclass).\n    1. The first letter of the class name should be `W` (e.g., `WHairExtractor`).\n    2. To initially simplify development:\n        1. Optionally (higher debug info), you might initially create the Worker as a non-templated class, assuming it uses std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> instead of directly using a template class (following the `examples/tutorial_api_cpp` synchronous examples). While developing, templates provide more confusing debugging info. Turn the class into a template after being initially developed.\n        2. Optionally (for development speed), use op::Datum as unique argument of your auxiliary functions within that worker.\n        3. Use the OpenPose Wrapper class in ThreadManagerMode::SingleThread mode (e.g., it allows you to directly use cv::imshow).\n        4. If you are using your own custom Caffe -> initially change the Caffe for your version. It should directly work.\n    3. Copy the design from `pose/WPoseExtractor`.\n3. To test it:\n    1. Add the functionality to `Wrapper`, use the `experimental` namespace for the new Struct (e.g., `experimental::HairStruct`) that the `Wrapper` will use. Do not change any function name from `Wrapper`, just add a new `configure`, with the new `HairStruct` or modify the existing ones without changing their names.\n    2. Add a demo (e.g., `examples/openpose/rthair.cpp`) to test it.\n4. Split the `Worker` into as many Workers as required.\n5. If the Workers need extra data from `Datum`, simply add into `Datum` the new variables required (without removing/modifying any previous variables!).\n6. Read also the release steps before starting this developping phase.\n\n\n\n## Release Steps\nAfter the code is running and ready to be merged, in order to officially release the new module:\n\n1. Move the functionality of each `Worker` class to the non-template class (e.g., `WHairExtractor` to `HairExtractor`). `WHairExtractor` will simply wrap `HairExtractor`. This will reduce compiling time for the user. See examples from other modules.\n2. If you are using a custom Caffe version, move the custom code into the OpenPose library and change back Caffe to the default (most updated) version.\n3. Move the module from `experimental/hair/` to `hair/`.\n4. Remove `experimental` namespaces (e.g., from `Wrapper` and `Hair`) and turn Workers into template classes.\n5. Integrate the new flags to the OpenPose Demo in `examples/openpose/` and optionally add some tutorial examples in `examples/tutorial_api_cpp`.\n"
  },
  {
    "path": "doc/very_advanced/library_structure/UML/1_0_0rc3/UML.mdj",
    "content": "{\n\t\"_type\": \"Project\",\n\t\"_id\": \"AAAAAAFF+h6SjaM2Hec=\",\n\t\"name\": \"Untitled\",\n\t\"ownedElements\": [\n\t\t{\n\t\t\t\"_type\": \"UMLModel\",\n\t\t\t\"_id\": \"AAAAAAFF+qBWK6M3Z8Y=\",\n\t\t\t\"_parent\": {\n\t\t\t\t\"$ref\": \"AAAAAAFF+h6SjaM2Hec=\"\n\t\t\t},\n\t\t\t\"name\": \"Model\",\n\t\t\t\"ownedElements\": [\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbPme936hyNvU=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"Legend\",\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbPmguIqilCQQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbPme936hyNvU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;15;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 953,\n\t\t\t\t\t\t\t\"height\": 146,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Legend:\\n    - The `Module Diagram` section shows the package dependencies.\\n    - The other sections (`core`, `thread`, `pose`, ...) show the file dependencies inside of that module.\\n        - Each file corresponds at most to 1 class, with the same name but initial upper case. Examples:\\n            - File wGui = class WGui.\\n            - File array = class Array.\\n        - If a file name finishes in *.hpp, it means that there is no associated *.cpp.\\n        - If a file name does not finish in *.hpp, there is both *.hpp and *.cpp. In case of CUDA classes, there might be a *.cu file associated too.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbHIJpMS36f7s=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"Module Diagram\",\n\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHCwkb098Gn8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"openpose\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1QElDMPAM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"utilities\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1OMVCzVD0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"profiler\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1MqlCahVc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"debug\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1IyVBoNV4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"producer\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC/EoVNdCyI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1IyVBoNV4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1IyVBoNV4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1KeVCBpLY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"thread\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1G+lBPPsc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"core\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9JuVLempo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1EhVA2eKM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"pose\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9UmlLvhDw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEFiO1Mmm7U=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC1AKlAdhqg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"filestream\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9bqlMAYZQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEF5SVM3f7Q=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC0+ElAE2jQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"gui\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9h+FMRrKY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9pCVMip8Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHC9xUVMzMBc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8kjKBZ98=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlRWuhTb0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wrapper\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHuMZiPmwEI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"3rd party\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHwvmCSZ3oQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cuda\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHvjGSQMEkI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"caffe\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHyaSCVmqsA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"protobuf\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHwh2CR/pHM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"opencv\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHw5mCSz/Mc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cuDNN\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHwWmCRl81Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"boost\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHx6GCUN8a0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"gflags\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUrvNhinY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUrvNicKc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHCwkb098Gn8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Nj5uU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNicKc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2346,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -655,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NkZVw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNicKc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 22,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 919,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"openpose\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NlS6U=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNicKc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2346,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -655,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 153,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from Module Diagram)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NmTvY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNicKc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2346,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -655,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 15,\n\t\t\t\t\t\t\t\t\t\"width\": 929,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Nj5uU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/NkZVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/NlS6U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/NmTvY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 929,\n\t\t\t\t\t\t\t\"height\": 529,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNicKc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NnWbQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 464,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 0: Dependencies: 3rd party. Used by all modules.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NoMHg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 392,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 1 - Dependencies: 3rdparty and module level 0.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Np+jI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 314,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 2 - Dependencies: 3rdparty and modules levels 0-1.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NqRgQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 3 - Dependencies: 3rdparty and modules levels 0-2.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Nr9tQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 168,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 4 - Dependencies: 3rdparty and modules levels 0-3.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NscFI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1QElDMPAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Ntn3M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/NscFI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1QElDMPAM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Nucfo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Ntn3M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2642,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -943,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/NvTn4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Ntn3M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 221,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 494,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"utilities\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Nwj4g=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Ntn3M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2642,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -943,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/Nx7CI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Ntn3M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 221,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 510,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\t\t\"top\": 487,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Nucfo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/NvTn4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Nwj4g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Nx7CI=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\"top\": 472,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 41,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/Ntn3M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/N+ggs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1IyVBoNV4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/N/MAo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N+ggs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1IyVBoNV4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OA+l0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N/MAo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -791,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OBZuM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N/MAo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 397,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 342,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 65,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"producer\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OC2VA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N/MAo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -791,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OD/AY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N/MAo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -791,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 392,\n\t\t\t\t\t\t\t\t\t\"top\": 335,\n\t\t\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OA+l0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OBZuM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OC2VA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OD/AY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 392,\n\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N/MAo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OEzro=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OFF4k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1KeVCBpLY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OG4lk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OFF4k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2514,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -751,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OHg78=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OFF4k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 221,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 422,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"thread\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OIbfY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OFF4k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2514,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -751,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OJq3A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OFF4k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2514,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -751,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\t\t\"top\": 415,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OG4lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OHg78=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OIbfY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OJq3A=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\"top\": 400,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OFF4k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OK8aY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OLsHs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OK8aY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1G+lBPPsc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUr/OM+rQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OLsHs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2210,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -583,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPONPeY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OLsHs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 125,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 342,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"core\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOO0Zo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OLsHs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2210,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -583,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOPPRQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OLsHs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2210,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -583,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 335,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OM+rQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPONPeY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOO0Zo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOPPRQ=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OLsHs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOQbhs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPORBkQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOQbhs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1EhVA2eKM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOSy7k=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPORBkQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -471,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOTti8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPORBkQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 405,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 262,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"pose\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOUvfE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPORBkQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -471,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOV81o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPORBkQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1658,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -471,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 400,\n\t\t\t\t\t\t\t\t\t\"top\": 255,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOSy7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOTti8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOUvfE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOV81o=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 400,\n\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPORBkQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOWfGA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOXNXg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOWfGA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC1AKlAdhqg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOYm00=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOXNXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2418,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -279,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOZwhY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOXNXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 165,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 198,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"filestream\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOayEU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOXNXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2418,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -279,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPObgW8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOXNXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2418,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -279,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 160,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOYm00=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOZwhY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOayEU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPObgW8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 160,\n\t\t\t\t\t\t\t\"top\": 176,\n\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOXNXg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOcVl8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOdIPQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOcVl8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC0+ElAE2jQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOe1Xk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOdIPQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2330,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -295,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOfGnA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOdIPQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 317,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 198,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"gui\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOgr10=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOdIPQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2330,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -295,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOhEiw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOdIPQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -2330,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -295,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 14,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 26,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOe1Xk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOfGnA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOgr10=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOhEiw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\"top\": 176,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 42,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOdIPQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOiTcA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9JuVLempo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOjpLA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9JuVLempo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 212,\n\t\t\t\t\t\t\t\t\t\"top\": 362,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOk9j0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9JuVLempo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 222,\n\t\t\t\t\t\t\t\t\t\"top\": 350,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOlml0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9JuVLempo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 193,\n\t\t\t\t\t\t\t\t\t\"top\": 385,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOiTcA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OK8aY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"181:362;226:399\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOjpLA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOk9j0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOlml0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOmbEw=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9UmlLvhDw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOnVWY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9UmlLvhDw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 351,\n\t\t\t\t\t\t\t\t\t\"top\": 345,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOorbU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9UmlLvhDw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 361,\n\t\t\t\t\t\t\t\t\t\"top\": 356,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOpZtw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9UmlLvhDw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 332,\n\t\t\t\t\t\t\t\t\t\"top\": 322,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOmbEw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOQbhs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"410:282;275:399\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOnVWY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOorbU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOpZtw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOqgrs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9bqlMAYZQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOrc8c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9bqlMAYZQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 239,\n\t\t\t\t\t\t\t\t\t\"top\": 298,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOsvlQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9bqlMAYZQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 254,\n\t\t\t\t\t\t\t\t\t\"top\": 295,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOtIiQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9bqlMAYZQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 210,\n\t\t\t\t\t\t\t\t\t\"top\": 305,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOqgrs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOWfGA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"205:218;246:399\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOrc8c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOsvlQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOtIiQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOuAzE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9h+FMRrKY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOvsmc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9h+FMRrKY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\t\t\"top\": 307,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOw+Ho=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9h+FMRrKY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 326,\n\t\t\t\t\t\t\t\t\t\"top\": 313,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOxu4Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9h+FMRrKY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 285,\n\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOuAzE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOcVl8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"338:218;260:399\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOvsmc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOw+Ho=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOxu4Y=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOybk4=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9pCVMip8Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPOzed0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9pCVMip8Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 399,\n\t\t\t\t\t\t\t\t\t\"top\": 209,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO02ZY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9pCVMip8Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 197,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO1u2A=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9pCVMip8Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 382,\n\t\t\t\t\t\t\t\t\t\"top\": 234,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOybk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOQbhs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOcVl8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"377:218;406:239\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOzed0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO02ZY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO1u2A=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO2dBI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9xUVMzMBc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO38z4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9xUVMzMBc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 259,\n\t\t\t\t\t\t\t\t\t\"top\": 273,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO4Lhs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9xUVMzMBc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 268,\n\t\t\t\t\t\t\t\t\t\"top\": 285,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO5LWQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC9xUVMzMBc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\"top\": 250,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO2dBI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OK8aY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOcVl8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"318:218;183:319\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO38z4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO4Lhs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO5LWQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO6JZ0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC/EoVNdCyI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO7SWM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC/EoVNdCyI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 345,\n\t\t\t\t\t\t\t\t\t\"top\": 387,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO8xqA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC/EoVNdCyI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 351,\n\t\t\t\t\t\t\t\t\t\"top\": 401,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO9aFc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHC/EoVNdCyI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 332,\n\t\t\t\t\t\t\t\t\t\"top\": 360,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO6JZ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OEzro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/N+ggs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"391:357;288:403\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO7SWM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO8xqA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO9aFc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO+la0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEFiO1Mmm7U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPO/B0Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEFiO1Mmm7U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 299,\n\t\t\t\t\t\t\t\t\t\"top\": 307,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPPASZk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEFiO1Mmm7U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 303,\n\t\t\t\t\t\t\t\t\t\"top\": 321,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPPBLAU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEFiO1Mmm7U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 290,\n\t\t\t\t\t\t\t\t\t\"top\": 278,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO+la0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OK8aY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOQbhs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"399:270;192:329\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPO/B0Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPASZk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPBLAU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsPPCzDA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEF5SVM3f7Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPD+nk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEF5SVM3f7Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 191,\n\t\t\t\t\t\t\t\t\t\"top\": 266,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPE0kU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEF5SVM3f7Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 205,\n\t\t\t\t\t\t\t\t\t\"top\": 270,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPFtGE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEF5SVM3f7Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 162,\n\t\t\t\t\t\t\t\t\t\"top\": 257,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPPCzDA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUr/OK8aY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsPOWfGA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"193:218;162:319\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPD+nk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPE0kU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPFtGE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPGj1A=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPH+hM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHuMZiPmwEI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPIFPA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPH+hM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -666,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -719,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPJR8A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPH+hM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 566,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 919,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"3rd party\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPKNZk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPH+hM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -666,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -719,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 138,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from Module Diagram)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPL+9g=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPH+hM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -666,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -719,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 559,\n\t\t\t\t\t\t\t\t\t\"width\": 929,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPIFPA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPJR8A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPKNZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPL+9g=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 544,\n\t\t\t\t\t\t\t\"width\": 929,\n\t\t\t\t\t\t\t\"height\": 137,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPH+hM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPMbkI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwvmCSZ3oQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPNVvA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPMbkI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwvmCSZ3oQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPOGE4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPNVvA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1090,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -711,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPPcuM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPNVvA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 317,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cuda\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPQ2Ls=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPNVvA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1090,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -711,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPRYg8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPNVvA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1090,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -711,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPOGE4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPPcuM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPQ2Ls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPRYg8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPNVvA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPSO0Y=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHvjGSQMEkI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPTSG0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPSO0Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHvjGSQMEkI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPU3Dk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPTSG0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -450,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -663,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPVgvE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPTSG0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 197,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"caffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPWMbs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPTSG0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -450,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -663,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPX8WI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPTSG0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -450,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -663,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPU3Dk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPVgvE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPWMbs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPX8WI=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPTSG0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPYA9k=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHyaSCVmqsA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPZIz8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPYA9k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHyaSCVmqsA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPa/tE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPZIz8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 790,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -599,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPb9+I=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPZIz8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 789,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"protobuf\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPcku0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPZIz8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 790,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -599,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPdi1E=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPZIz8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 790,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -599,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPa/tE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPb9+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPcku0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPdi1E=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPZIz8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPefpk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwh2CR/pHM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPfd60=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPefpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwh2CR/pHM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPgWow=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPfd60=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -154,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -815,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPhHG8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPfd60=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 557,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"opencv\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPiqE0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPfd60=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -154,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -815,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUsfPjufU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPfd60=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -154,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -815,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPgWow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPhHG8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPiqE0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPjufU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPfd60=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PkU3k=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHw5mCSz/Mc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/Plgxg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PkU3k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHw5mCSz/Mc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/Pmtdc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Plgxg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -882,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -647,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PneZM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Plgxg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 437,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cuDNN\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PoOaU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Plgxg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -882,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -647,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PpUVk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Plgxg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -882,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -647,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 432,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Pmtdc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PneZM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PoOaU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PpUVk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 432,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Plgxg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PqP/U=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwWmCRl81Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PrpOs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PqP/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHwWmCRl81Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PsrR8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PrpOs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -946,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -735,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PtUPg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PrpOs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 77,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"boost\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PuQo4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PrpOs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -946,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -735,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/Pv4aA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PrpOs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -946,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -735,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PsrR8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PtUPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PuQo4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Pv4aA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PrpOs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/Pw+qg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHx6GCUN8a0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PxFr0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Pw+qg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHx6GCUN8a0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/PyGPg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PxFr0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 534,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -607,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/Pz/O4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PxFr0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 677,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 630,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 62,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"gflags\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/P0HyY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PxFr0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 534,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -607,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from 3rd party)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIMUs/P1x8s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PxFr0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 534,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -607,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 672,\n\t\t\t\t\t\t\t\t\t\"top\": 623,\n\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PyGPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/Pz/O4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/P0HyY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/P1x8s=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUsfPGj1A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 672,\n\t\t\t\t\t\t\t\"top\": 608,\n\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\"height\": 40,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUs/PxFr0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8kzKDNC4=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8kzKEic8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKDNC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8kzKFLv4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKEic8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8kzKGkIg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKEic8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 85,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 55,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8lDKH5PM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKEic8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 131,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8lDKI2u8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKEic8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKFLv4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKGkIg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8lDKH5PM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8lDKI2u8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8lDKJ50I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKDNC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 73,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8lDKKEdY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKDNC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 83,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8lDKLYr0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKDNC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": -48,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIP8mzKMq20=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKDNC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kjKBZ98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": -48,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8kzKEic8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8lDKJ50I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8lDKKEdY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8lDKLYr0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIP8mzKMq20=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHIRn9/P2rQY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 104,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 5: wrapper class with all the functionality. It uses all the modules 0-4.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSGuji3g=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSGukExY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWulXrQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGukExY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1176,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1760,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWumtzk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGukExY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 245,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 111,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 53,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wrapper\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWun3C8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGukExY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1176,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1760,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 93,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from openpose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWuoSU0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGukExY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1176,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1760,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\"top\": 104,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWulXrQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWumtzk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWun3C8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWuoSU0=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWupEuk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\"top\": 129,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSWuqwDQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\"top\": 139,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSmurltM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -784,\n\t\t\t\t\t\t\t\t\t\"top\": -1176,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+qlSmusnEM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGuji3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlRWuhTb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -784,\n\t\t\t\t\t\t\t\t\t\"top\": -1176,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIMUrvNhinY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\"top\": 104,\n\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSGukExY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWupEuk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSWuqwDQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSmurltM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbS+qlSmusnEM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbS+r/4tDnklI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebd8ff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 720,\n\t\t\t\t\t\t\t\"top\": 40,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"Level 6: headers.hpp imports all the modules at once.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiF4LK7RRW2E=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8fff8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 464,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"- utilities: Auxiliary functions for other modules\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiF4s3LRSU4k=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#d8ffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 392,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"- thread: Multi-threading module\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiF/73LRUffM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ebffd8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"- producer: Read image, video and webcam\\n- core: Array<T> and Datum\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiGAXrLRVx9c=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#fff5d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"- pose: 18-body-part detection and rendering\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiGNx27RYcY0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffe2d8\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 168,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"- filestream: save/load JSON, XML, PNG, JPG, ...\\n- gui: basic display & GUI\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLNoteView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbiGPEPLRZM9o=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHIJpMS36f7s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffd8eb\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;14;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\"top\": 104,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 57,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"text\": \"-wrapper: Simple wrapper to use all the modules functionality at once.\",\n\t\t\t\t\t\t\t\"wordWrap\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbHDVYsl1GUQo=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"core\",\n\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRV10zeE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"core\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuEyuaf0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cvMatToOpInput\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsY50/Dn0U=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAGM/iNg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAGNAOCM=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAGNBxzI=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZg0xc7rw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"array\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aP2L8JeY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aP2L9MGo=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aP2L+yLs=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKEyF0Kw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"opOutputToCvMat\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsF9k+yn0o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oTmOR1lk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oTmOSFbA=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oTmOToto=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihJ0zX3Z4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"datum\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsuEE/UdvU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2E0AXIA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaE0pq8s=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"net.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDtbT0/lk08=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirkU2kyDg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wCvMatToOpInput.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuCwE/2Ynw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1guFCC148=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk17ze0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wOpOutputToCvMat.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuNM1AH+0I=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1bSVBx/jk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiopk1SCJU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"netCaffe\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96yU8KINY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wCvMatToOpOutput.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy/3vlDB8o0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBlhVWNQPg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z90+8J3g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cvMatToOpOutput\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzA9yVTEB3o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZvVUdaeg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZvlUe8Yg=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZvlUfUq8=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFygkJZojX8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"keypoint\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG2xPqfYUnM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzuq7pEyw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzuq7qC10=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzuq7rWko=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHTOrmNRog=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFydM5Y/IIc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wKeypointScaler.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG7TsKoYdWk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCAcq2WsUE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmChw66cxFQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGCTLdfN0I=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMAre7gzc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"KeypointScaler\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHlSrnppV8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FZeOtro=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"resizeAndMergeCaffe\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnvtqGnGyg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QWc3M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QXMuA=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QYUYc=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc1D+I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"resizeAndMergeBase\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rZe3LU0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"nmsBase\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95Zfg+a8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"nmsCaffe\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnq5qGWd3A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8ArOmRco=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8ArOnTL8=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8ArOo1Sw=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+OFAk314=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"thread\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5SVA/xUk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OFAk314=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRV12Zhg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRl13Jpo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV10zeE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRl14eP0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl13Jpo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -544,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1088,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRl15u8g=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl13Jpo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 22,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 1039,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"core\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRl16500=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl13Jpo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -544,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1088,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDZmRl17nWY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl13Jpo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -544,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1088,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 15,\n\t\t\t\t\t\t\t\t\t\"width\": 1049,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl14eP0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl15u8g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl16500=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl17nWY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 1049,\n\t\t\t\t\t\t\t\"height\": 385,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRl13Jpo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuEywuH8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUyx4n8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUyyAac=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyx4n8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUyzj9c=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyx4n8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 141,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 103,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cvMatToOpInput\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy0qBs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyx4n8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy1JOI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyx4n8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyyAac=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyzj9c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy0qBs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy1JOI=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy21oI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy3NHk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy4iPk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -488,\n\t\t\t\t\t\t\t\t\t\"top\": -112,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDieuUy5BxE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEyuaf0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -488,\n\t\t\t\t\t\t\t\t\t\"top\": -112,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUyx4n8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy21oI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy3NHk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy4iPk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuUy5BxE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhUxetSs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhUxfOxM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhkxgx90=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxfOxM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -72,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhkxhaA4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxfOxM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 177,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 335,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 33,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhkxiEYA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxfOxM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -72,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZhkxj9yU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxfOxM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -72,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 172,\n\t\t\t\t\t\t\t\t\t\"top\": 328,\n\t\t\t\t\t\t\t\t\t\"width\": 43,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhkxgx90=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhkxhaA4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhkxiEYA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhkxj9yU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZh0xkaJs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 172,\n\t\t\t\t\t\t\t\t\t\"top\": 353,\n\t\t\t\t\t\t\t\t\t\"width\": 43,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZh0xlbxo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 172,\n\t\t\t\t\t\t\t\t\t\"top\": 363,\n\t\t\t\t\t\t\t\t\t\"width\": 43,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZh0xmLAU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -16,\n\t\t\t\t\t\t\t\t\t\"top\": 96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiZh0xn+lg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZg0xc7rw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -16,\n\t\t\t\t\t\t\t\t\t\"top\": 96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 172,\n\t\t\t\t\t\t\t\"top\": 328,\n\t\t\t\t\t\t\t\"width\": 43,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxfOxM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZh0xkaJs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZh0xlbxo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZh0xmLAU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZh0xn+lg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyHyzc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyIdSc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyJ/hY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyIdSc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyKDo8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyIdSc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 413,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"opOutputToCvMat\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyLjA8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyIdSc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyMxOw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyIdSc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyJ/hY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyKDo8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyLjA8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyMxOw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKUyNxgg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKkyO4dA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKkyPh60=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 96,\n\t\t\t\t\t\t\t\t\t\"top\": -8,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDibKkyQKLA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKEyF0Kw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 96,\n\t\t\t\t\t\t\t\t\t\"top\": -8,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyIdSc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyNxgg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKkyO4dA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKkyPh60=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKkyQKLA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihJ0zZY0c=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihJ0zaYS0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzbLug=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zaYS0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -160,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzc38c=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zaYS0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 45,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 40,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"datum\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzdARw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zaYS0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -160,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzel+A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zaYS0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -160,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzbLug=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzc38c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzdARw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzel+A=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzfi5Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzgh5Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzh3Hg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -40,\n\t\t\t\t\t\t\t\t\t\"top\": -216,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDihKEzilqs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zX3Z4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -40,\n\t\t\t\t\t\t\t\t\t\"top\": -216,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zaYS0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzfi5Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzgh5Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzh3Hg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihKEzilqs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2E0CgSQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2E0DEAQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2E0ELdY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0DEAQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2E0FdSw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0DEAQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 37,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 55,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0GZnY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0DEAQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0Hlz8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0DEAQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0ELdY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0FdSw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0GZnY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0Hlz8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0ILuo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 73,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0J3QU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 83,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0KmNg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -376,\n\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDij2U0LuVc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0CgSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0AXIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -376,\n\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2E0DEAQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0ILuo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0J3QU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0KmNg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDij2U0LuVc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaE0rwcY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0sE3k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0t3oE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0sE3k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -376,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0uurU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0sE3k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 709,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 48,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"net.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0vVmg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0sE3k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -376,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0wj6Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0sE3k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -376,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0t3oE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0uurU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0vVmg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0wj6Y=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0xOds=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0yVCE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU0z76k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": -296,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDilaU00ZOQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0pq8s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": -296,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0sE3k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0xOds=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0yVCE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU0z76k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaU00ZOQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirkk2m0MU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirk02nxGo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirk02ovaA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02nxGo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -880,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1056,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirk02pCGs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02nxGo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 85,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wCvMatToOpInput.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirk02qGJk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02nxGo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -880,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1056,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirk02r7TE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02nxGo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -880,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1056,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02ovaA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02pCGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02qGJk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02r7TE=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirlE2s50s=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirlE2tHG0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirlE2uEW4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -408,\n\t\t\t\t\t\t\t\t\t\"top\": -664,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDirlE2vAOw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkU2kyDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -408,\n\t\t\t\t\t\t\t\t\t\"top\": -664,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirk02nxGo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirlE2s50s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirlE2tHG0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirlE2uEW4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirlE2vAOw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk19SxU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk1+iJ8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk1/nA0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1+iJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2Anbo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1+iJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 461,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wOpOutputToCvMat.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2Bq8Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1+iJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2CoFU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1+iJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1/nA0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2Anbo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2Bq8Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2CoFU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2DqeA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2E9Q4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2FQ7E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": -544,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiqGk2GRHw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk17ze0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": -544,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk1+iJ8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2DqeA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2E9Q4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2FQ7E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk2GRHw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01U6Vo=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01VWR0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01WoLQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01VWR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 952,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -520,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01Xbzs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01VWR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 597,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 335,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 53,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"netCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01Yhy4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01VWR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 952,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -520,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01ZY+o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01VWR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 952,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -520,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 592,\n\t\t\t\t\t\t\t\t\t\"top\": 328,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01WoLQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01Xbzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01Yhy4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01ZY+o=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01a9Os=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 592,\n\t\t\t\t\t\t\t\t\t\"top\": 353,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01bf8Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 592,\n\t\t\t\t\t\t\t\t\t\"top\": 363,\n\t\t\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01cTKQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\t\t\"top\": -304,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDiop01dImQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiopk1SCJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 512,\n\t\t\t\t\t\t\t\t\t\"top\": -304,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 592,\n\t\t\t\t\t\t\t\"top\": 328,\n\t\t\t\t\t\t\t\"width\": 63,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01VWR0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01a9Os=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01bf8Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01cTKQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01dImQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsF+E+0IHQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF9k+yn0o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsF+U+1AxU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF9k+yn0o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 316,\n\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsF+U+2iho=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF9k+yn0o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 321,\n\t\t\t\t\t\t\t\t\t\"top\": 326,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsF+U+3Rm0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF9k+yn0o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 305,\n\t\t\t\t\t\t\t\t\t\"top\": 285,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+E+0IHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"408:269;215:342\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+U+1AxU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+U+2iho=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsF+U+3Rm0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsY50/FZCs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/Dn0U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsY50/GyI4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/Dn0U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 206,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsY6E/HUK0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/Dn0U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 221,\n\t\t\t\t\t\t\t\t\t\"top\": 290,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsY6E/InH8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/Dn0U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 177,\n\t\t\t\t\t\t\t\t\t\"top\": 292,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/FZCs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"192:269;193:327\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY50/GyI4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY6E/HUK0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsY6E/InH8=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsuEE/WjyQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/UdvU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsuEE/X1Q0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/UdvU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 139,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsuEE/Y1Ns=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/UdvU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 148,\n\t\t\t\t\t\t\t\t\t\"top\": 269,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDsuEE/ZYnk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/UdvU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 304,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/WjyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"90:267;171:332\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/X1Q0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/Y1Ns=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDsuEE/ZYnk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDtbT0/neoM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/lk08=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDtbUE/o34k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/lk08=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 687,\n\t\t\t\t\t\t\t\t\t\"top\": 302,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDtbUE/pYaA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/lk08=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 697,\n\t\t\t\t\t\t\t\t\t\"top\": 313,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDtbUE/qu1g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/lk08=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 666,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbT0/neoM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiop01U6Vo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDilaE0rwcY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"708:269;647:327\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbUE/o34k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbUE/pYaA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDtbUE/qu1g=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuCwE/467Q=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/2Ynw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuCwE/55C8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/2Ynw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 188,\n\t\t\t\t\t\t\t\t\t\"top\": 179,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuCwE/6p04=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/2Ynw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 202,\n\t\t\t\t\t\t\t\t\t\"top\": 174,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuCwE/7Wx0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/2Ynw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 159,\n\t\t\t\t\t\t\t\t\t\"top\": 188,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/467Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"163:157;185:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/55C8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/6p04=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuCwE/7Wx0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuNM1AJHN4=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AH+0I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuNM1AKOa8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AH+0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 515,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuNM1ALy8I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AH+0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 528,\n\t\t\t\t\t\t\t\t\t\"top\": 199,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDuNM1AM+V0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AH+0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 490,\n\t\t\t\t\t\t\t\t\t\"top\": 176,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AJHN4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"523:157;483:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AKOa8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1ALy8I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDuNM1AM+V0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+OlAmHDg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OFAk314=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+OlAnueI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAmHDg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OFAk314=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+O1AopIA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAnueI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+O1ApQPQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAnueI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1061,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 158,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 214,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"thread\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+O1Aqy0E=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAnueI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDy+O1ArFV0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAnueI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1056,\n\t\t\t\t\t\t\t\t\t\"top\": 151,\n\t\t\t\t\t\t\t\t\t\"width\": 224,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+O1AopIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+O1ApQPQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+O1Aqy0E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+O1ArFV0=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1056,\n\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\"width\": 224,\n\t\t\t\t\t\t\t\"height\": 192,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAnueI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5SlBBwM0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5SlBCE+o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5SlBD9Ps=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBCE+o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5SlBEOL4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBCE+o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1133,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 223,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5S1BFQMY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBCE+o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5S1BGbrU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBCE+o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 216,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBD9Ps=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBEOL4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5S1BFQMY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5S1BGbrU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5S1BH96Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 241,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5S1BIenk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 251,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5S1BJ2DU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHDz5TFBKy7Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SVA/xUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 312,\n\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDy+OlAmHDg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\"top\": 216,\n\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBCE+o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5S1BH96Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5S1BIenk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5S1BJ2DU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5TFBKy7Q=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1bSVBzYVw=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBx/jk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1bSlB0IJU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBx/jk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 875,\n\t\t\t\t\t\t\t\t\t\"top\": 168,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1bSlB1bWI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBx/jk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 877,\n\t\t\t\t\t\t\t\t\t\"top\": 153,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1bSlB2Idg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBx/jk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 870,\n\t\t\t\t\t\t\t\t\t\"top\": 197,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSVBzYVw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"620:148;1127:231\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSlB0IJU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSlB1bWI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1bSlB2Idg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1guFCE2Yw=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCC148=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1guFCFR5o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCC148=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 681,\n\t\t\t\t\t\t\t\t\t\"top\": 167,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1guFCGjKM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCC148=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 683,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD1guFCHciE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCC148=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\"top\": 196,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCE2Yw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"234:142;1127:234\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCFR5o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCGjKM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD1guFCHciE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMA6RU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMBi/k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 304,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMCOL0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 111,\n\t\t\t\t\t\t\t\t\t\"top\": 316,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMDXzQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L8JeY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 139,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMEeGM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L9MGo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 141,\n\t\t\t\t\t\t\t\t\t\"top\": 321,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMFpa4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L9MGo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 131,\n\t\t\t\t\t\t\t\t\t\"top\": 330,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMGLZY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L9MGo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 161,\n\t\t\t\t\t\t\t\t\t\"top\": 302,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMHovc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L+yLs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 100,\n\t\t\t\t\t\t\t\t\t\"top\": 288,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMIhes=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L+yLs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 94,\n\t\t\t\t\t\t\t\t\t\"top\": 300,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMJmHw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L+yLs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 114,\n\t\t\t\t\t\t\t\t\t\"top\": 264,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMKZUM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L9MGo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE9aQGMLTyY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMA6RU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aP2L+yLs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDihJ0zZY0c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"171:332;90:267\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMBi/k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMCOL0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMDXzQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMEeGM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMFpa4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMGLZY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMHovc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMIhes=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMJmHw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMKZUM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE9aQGMLTyY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAGNDahQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAGNExz8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 159,\n\t\t\t\t\t\t\t\t\t\"top\": 188,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNFH+s=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 145,\n\t\t\t\t\t\t\t\t\t\"top\": 193,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNGyik=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGM/iNg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 188,\n\t\t\t\t\t\t\t\t\t\"top\": 179,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNHfSU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNAOCM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 162,\n\t\t\t\t\t\t\t\t\t\"top\": 197,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNIKXo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNAOCM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 149,\n\t\t\t\t\t\t\t\t\t\"top\": 199,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNJIV8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNAOCM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 190,\n\t\t\t\t\t\t\t\t\t\"top\": 192,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNKRUY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNBxzI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 156,\n\t\t\t\t\t\t\t\t\t\"top\": 180,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNL9es=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNBxzI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 145,\n\t\t\t\t\t\t\t\t\t\"top\": 186,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNMMXI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNBxzI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 181,\n\t\t\t\t\t\t\t\t\t\"top\": 167,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNNM7M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNAOCM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+jAWNOzLY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNDahQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNBxzI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDirkk2m0MU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDieuEywuH8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"185:223;163:157\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAGNExz8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNFH+s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNGyik=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNHfSU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNIKXo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNJIV8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNKRUY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNL9es=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNMMXI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNNM7M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+jAWNOzLY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OV5Y8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OWNVs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 490,\n\t\t\t\t\t\t\t\t\t\"top\": 176,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OXAgk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 477,\n\t\t\t\t\t\t\t\t\t\"top\": 168,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OYZSI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOR1lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 515,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OZSuw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOSFbA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 483,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OaNrg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOSFbA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 473,\n\t\t\t\t\t\t\t\t\t\"top\": 178,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2Ob3sk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOSFbA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 504,\n\t\t\t\t\t\t\t\t\t\"top\": 204,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OcHzI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOToto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 496,\n\t\t\t\t\t\t\t\t\t\"top\": 165,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OdTXY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOToto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 484,\n\t\t\t\t\t\t\t\t\t\"top\": 160,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OeuLo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOToto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 522,\n\t\t\t\t\t\t\t\t\t\"top\": 175,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2Ofd6E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOSFbA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 56,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE+oT2OglUk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OV5Y8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oTmOToto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 56,\n\t\t\t\t\t\t\t\t\t\"top\": -160,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiqGk19SxU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDibKUyHyzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"483:223;523:157\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OWNVs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OXAgk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OYZSI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OZSuw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OaNrg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2Ob3sk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OcHzI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OdTXY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OeuLo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2Ofd6E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE+oT2OglUk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96y08MtFk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96y08NDGA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96y08Ovl8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08NDGA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1440,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8PpTs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08NDGA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 285,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wCvMatToOpOutput.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8QxXQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08NDGA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1440,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8RNX4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08NDGA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1440,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08Ovl8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8PpTs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8QxXQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8RNX4=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8SzTI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8TyS4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zE8Ue9Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 160,\n\t\t\t\t\t\t\t\t\t\"top\": -952,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy96zU8Vo8I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96yU8KINY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 160,\n\t\t\t\t\t\t\t\t\t\"top\": -952,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08NDGA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8SzTI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8TyS4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zE8Ue9Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96zU8Vo8I=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+E++48k=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+E+/R2U=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+E/Akt4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E+/R2U=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1104,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/BhKc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E+/R2U=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 113,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cvMatToOpOutput\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/CePI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E+/R2U=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1104,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/D7rQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E+/R2U=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1104,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 267,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E/Akt4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/BhKc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/CePI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/D7rQ=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/EQwQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 267,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/F0J8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 267,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+U/Gicg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": -696,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy+z+k/HtIM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z90+8J3g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": -696,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 267,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 123,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E+/R2U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/EQwQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/F0J8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+U/Gicg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+k/HtIM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy/3wFDDdXc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3vlDB8o0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy/3wFDEI0k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3vlDB8o0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 786,\n\t\t\t\t\t\t\t\t\t\"top\": 168,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy/3wVDFC/c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3vlDB8o0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 788,\n\t\t\t\t\t\t\t\t\t\"top\": 153,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJy/3wVDGAZc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3vlDB8o0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 783,\n\t\t\t\t\t\t\t\t\t\"top\": 197,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDDdXc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"444:145;1127:233\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wFDEI0k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wVDFC/c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy/3wVDGAZc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzA9ylTGfXg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9yVTEB3o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzA9ylTHaIE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9yVTEB3o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 265,\n\t\t\t\t\t\t\t\t\t\"top\": 306,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzA9ylTIxfQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9yVTEB3o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 274,\n\t\t\t\t\t\t\t\t\t\"top\": 318,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzA9ylTJn4c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9yVTEB3o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 246,\n\t\t\t\t\t\t\t\t\t\"top\": 283,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTGfXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"298:269;215:333\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTHaIE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTIxfQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzA9ylTJn4c=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZv1UhDK0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUiIBM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 329,\n\t\t\t\t\t\t\t\t\t\"top\": 179,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUjBKk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 315,\n\t\t\t\t\t\t\t\t\t\"top\": 175,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUkz6o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvVUdaeg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 358,\n\t\t\t\t\t\t\t\t\t\"top\": 188,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUlOmk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUe8Yg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 327,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUmyEA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUe8Yg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 315,\n\t\t\t\t\t\t\t\t\t\"top\": 181,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwFUnLD4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUe8Yg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 353,\n\t\t\t\t\t\t\t\t\t\"top\": 199,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwVUo980=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUfUq8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 332,\n\t\t\t\t\t\t\t\t\t\"top\": 171,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwVUpNeE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUfUq8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 318,\n\t\t\t\t\t\t\t\t\t\"top\": 170,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwVUqh5U=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUfUq8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 360,\n\t\t\t\t\t\t\t\t\t\"top\": 175,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwVUrdwY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUe8Yg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -200,\n\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBZwVUswRk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZv1UhDK0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZvlUfUq8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -200,\n\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"335:223;354:157\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUiIBM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUjBKk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUkz6o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUlOmk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUmyEA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwFUnLD4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwVUo980=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwVUpNeE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwVUqh5U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwVUrdwY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBZwVUswRk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBlhlWP66A=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhVWNQPg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBlhlWQX4Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhVWNQPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 358,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBlh1WR+JM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhVWNQPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 372,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbJzBlh1WSPXw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhVWNQPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 329,\n\t\t\t\t\t\t\t\t\t\"top\": 180,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWP66A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy+z+E++48k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJy96y08MtFk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"354:157;335:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlhlWQX4Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlh1WR+JM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbJzBlh1WSPXw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJHsH0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJICKQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJJUsI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJICKQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJKJ6A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJICKQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 589,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 95,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"keypoint\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJLRSs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJICKQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJMgkY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJICKQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJJUsI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJKJ6A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJLRSs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJMgkY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJNNiA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJO5do=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJPX8g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 55,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJQRfY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFygkJZojX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 55,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJICKQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJNNiA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJO5do=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJPX8g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJQRfY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRXI9LpI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnI+ZCw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnI/wCA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI+ZCw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -393,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJAiyQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI+ZCw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 629,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 47,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wKeypointScaler.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJBRoY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI+ZCw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -393,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJCTKk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI+ZCw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -393,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -720,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 624,\n\t\t\t\t\t\t\t\t\t\"top\": 40,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI/wCA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJAiyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJBRoY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJCTKk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJDZXo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 624,\n\t\t\t\t\t\t\t\t\t\"top\": 65,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJE1zw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 624,\n\t\t\t\t\t\t\t\t\t\"top\": 75,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJFglw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -512,\n\t\t\t\t\t\t\t\t\t\"top\": -352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmAJRnJGOdA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFydM5Y/IIc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -512,\n\t\t\t\t\t\t\t\t\t\"top\": -352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 624,\n\t\t\t\t\t\t\t\"top\": 40,\n\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnI+ZCw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJDZXo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJE1zw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJFglw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJGOdA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmChxK6eW+I=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChw66cxFQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmChxK6fTdo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChw66cxFQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 93,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmChxK6gzzk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChw66cxFQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 719,\n\t\t\t\t\t\t\t\t\t\"top\": 94,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmChxK6hc8c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChw66cxFQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 675,\n\t\t\t\t\t\t\t\t\t\"top\": 90,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6eW+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"692:85;689:111\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6fTdo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6gzzk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmChxK6hc8c=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67t9JE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67uJrI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 675,\n\t\t\t\t\t\t\t\t\t\"top\": 89,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67vBEE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 660,\n\t\t\t\t\t\t\t\t\t\"top\": 87,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67w4/c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7pEyw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 94,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67xOsw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7qC10=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 677,\n\t\t\t\t\t\t\t\t\t\"top\": 77,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67ywaI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7qC10=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 664,\n\t\t\t\t\t\t\t\t\t\"top\": 73,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu67zeRc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7qC10=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 703,\n\t\t\t\t\t\t\t\t\t\"top\": 84,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu670zaM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7rWko=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 674,\n\t\t\t\t\t\t\t\t\t\"top\": 103,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu671S/8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7rWko=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 660,\n\t\t\t\t\t\t\t\t\t\"top\": 103,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu672y4Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7rWko=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 701,\n\t\t\t\t\t\t\t\t\t\"top\": 101,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu673kUw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7qC10=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmCzu674KBs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67t9JE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzuq7rWko=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"689:111;692:85\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67uJrI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67vBEE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67w4/c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67xOsw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67ywaI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu67zeRc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu670zaM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu671S/8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu672y4Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu673kUw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmCzu674KBs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGCTLdh840=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdfN0I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGCTLdit18=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdfN0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 947,\n\t\t\t\t\t\t\t\t\t\"top\": 133,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGCTLdjLNU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdfN0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 952,\n\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGCTLdkDU4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdfN0I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 936,\n\t\t\t\t\t\t\t\t\t\"top\": 162,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdh840=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDz5SlBBwM0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRXI9LpI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"758:85;1127:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdit18=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdjLNU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGCTLdkDU4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7e9i94=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7e+LJ8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7e/HJU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e+LJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -912,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7fAk0s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e+LJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 637,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 97,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"KeypointScaler\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7fBEo0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e+LJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -912,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7fCY4Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e+LJ8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -912,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 107,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e/HJU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7fAk0s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7fBEo0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7fCY4Y=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMA7fD4Kc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 107,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMBLfEln4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 107,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMBLfFS1E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -544,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmGMBLfGbb0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMAre7gzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -544,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 107,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e+LJ8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7fD4Kc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMBLfEln4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMBLfFS1E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMBLfGbb0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHTO7mP7ns=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTOrmNRog=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHTO7mQybE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTOrmNRog=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 402,\n\t\t\t\t\t\t\t\t\t\"top\": 309,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHTO7mR4d8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTOrmNRog=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 405,\n\t\t\t\t\t\t\t\t\t\"top\": 324,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHTO7mSadU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTOrmNRog=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 395,\n\t\t\t\t\t\t\t\t\t\"top\": 280,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mP7ns=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDiZhUxetSs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"583:258;215:345\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mQybE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mR4d8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHTO7mSadU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHlS7nr418=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlSrnppV8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHlS7nsyVQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlSrnppV8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 673,\n\t\t\t\t\t\t\t\t\t\"top\": 189,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHlS7nthXg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlSrnppV8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 687,\n\t\t\t\t\t\t\t\t\t\"top\": 195,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbgmHlS7nuOWI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlSrnppV8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 646,\n\t\t\t\t\t\t\t\t\t\"top\": 178,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nr418=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmAJRnJHsH0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmGMA7e9i94=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"675:157;646:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nsyVQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nthXg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbgmHlS7nuOWI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpHypfaIQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpHypgncQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 831,\n\t\t\t\t\t\t\t\t\t\"top\": 183,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICphrpM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 846,\n\t\t\t\t\t\t\t\t\t\"top\": 183,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICpieS0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 802,\n\t\t\t\t\t\t\t\t\t\"top\": 184,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypfaIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"818:157;817:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpHypgncQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICphrpM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpieS0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICpj6qk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICpknBE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 965,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICplHfg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 979,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpICpmMPg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 936,\n\t\t\t\t\t\t\t\t\t\"top\": 180,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpj6qk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"961:157;942:223\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpknBE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICplHfg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpICpmMPg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqVrfU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqWYto=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqXk7s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqWYto=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqYB1s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqWYto=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 901,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"resizeAndMergeCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqZjxQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqWYto=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqagFY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqWYto=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 896,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqXk7s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqYB1s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqZjxQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqagFY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqb7PE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 896,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqc8EI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 896,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqdXCo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -83,\n\t\t\t\t\t\t\t\t\t\"top\": -262,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqeBic=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqVrfU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -83,\n\t\t\t\t\t\t\t\t\t\"top\": -262,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 896,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqWYto=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqb7PE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqc8EI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqdXCo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqeBic=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqLa4s=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqMNYQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqNlfI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqMNYQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 266,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -548,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqOlaY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqMNYQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 869,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 134,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"resizeAndMergeBase\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqPOFg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqMNYQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 266,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -548,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqQtYk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqMNYQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 266,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -548,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 864,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqNlfI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqOlaY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqPOFg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqQtYk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqR/mc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 864,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqSyAs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 864,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqT4zI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 45,\n\t\t\t\t\t\t\t\t\t\"top\": -126,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqUlZc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqLa4s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 45,\n\t\t\t\t\t\t\t\t\t\"top\": -126,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 864,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqMNYQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqR/mc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqSyAs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqT4zI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqUlZc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqfnt8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqgjTg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqh4GQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqgjTg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 710,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqiL28=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqgjTg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 789,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 57,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"nmsBase\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqjAKI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqgjTg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 710,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqkUKE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqgjTg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 710,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -796,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqh4GQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqiL28=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqjAKI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqkUKE=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISql4lg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqmmdg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 259,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqnqpM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 333,\n\t\t\t\t\t\t\t\t\t\"top\": -246,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqouF8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqfnt8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 333,\n\t\t\t\t\t\t\t\t\t\"top\": -246,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqgjTg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISql4lg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqmmdg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqnqpM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqouF8=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqprwk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDVYsl1GUQo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqqVXg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpISqrj5w=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqqVXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -62,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1068,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqsXfc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqqVXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 789,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 119,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 59,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"nmsCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqtLX0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqqVXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -62,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1068,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiquJUA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqqVXg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -62,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1068,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqrj5w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqsXfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqtLX0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiquJUA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqv2Bo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 137,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqwekI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 147,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqxRAs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -191,\n\t\t\t\t\t\t\t\t\t\"top\": -390,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswhpIiqyBM8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqprwk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -191,\n\t\t\t\t\t\t\t\t\t\"top\": -390,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDZmRV12Zhg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\"top\": 112,\n\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpISqqVXg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqv2Bo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqwekI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqxRAs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswhpIiqyBM8=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbHDfDwV2pYSY=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"thread\",\n\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57HVDkPq4=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"thread\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ6VPEs5k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"subThreadQueueIn.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFI5mYsLlc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLbJGbpfa4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRirmuODQA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5j1YD/pE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"queueBase.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx71Vfqh4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"subThreadQueueOut.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFE3zmYKLpE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLOrmbH+pY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQoAmmeBgE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQoAmmfe+4=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQoAmmeBgE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQoAmmgGEA=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQoAmmeBgE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQ49moO8PE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3l1XaxjA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"subThreadQueueInOut.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFEy7mX58e8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLVg2bYTxg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRdk2tBzNI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwNlU2kqs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"thread.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYjaXcfD9g=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYjaXcgThA=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFYjaXcfD9g=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYjaXchb0I=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFYjaXcfD9g=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntp1UNMvk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"threadManager.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFZBb3gOsOg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFZIR3hqvUU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFamNXplyYs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFa6TnqjrOU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFhC54f7Eks=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWI6/o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wQueueOrderer.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE4Su2KpLQ0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2B1WxudQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"workerProducer.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXDcXLPDXQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk31Rp4JU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr11TkZW0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"workerConsumer.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXJlnMNtRc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnea1PuhXg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnoz1S7CCo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"subThreadNoQueue.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFAV2Ybm/c=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLJUWa2aeA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngX1QXn1w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"priorityQueue.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEpxVVYxfn0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnin1RAI/M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"queue.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEp0tlZCQMA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeVmiogQE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeVmipwtU=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeVmiqFCU=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjrWgc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjsEHI=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjtdWU=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnLmk9eHc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2k+i+w=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2k/CCk=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYzxnePusI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYzxneQJ4U=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFYzxnePusI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFYzxneR2vE=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFYzxnePusI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm51SSihM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"subThread.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57H1DmLb0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57IFDnHUM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57HVDkPq4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57IFDolHM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDnHUM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57IFDpiQ4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDnHUM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 22,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 1223,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"thread\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57IFDqf98=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDnHUM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHD57IFDr61c=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDnHUM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 15,\n\t\t\t\t\t\t\t\t\t\"width\": 1233,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDolHM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDpiQ4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDqf98=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDr61c=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 1233,\n\t\t\t\t\t\t\t\"height\": 600,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57IFDnHUM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ6lPGa/A=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PHIaE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PIGAg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PHIaE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PJSpI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PHIaE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 701,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 263,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 149,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"subThreadQueueIn.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PK5W0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PHIaE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PL3X0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PHIaE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 696,\n\t\t\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\t\t\"width\": 159,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PIGAg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PJSpI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PK5W0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PL3X0=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PMz/U=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 696,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 159,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ61PNm/8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 696,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 159,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ7FPOlMo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": -16,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEmZ7FPPBmA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6VPEs5k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": -16,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 696,\n\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\"width\": 159,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PHIaE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PMz/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ61PNm/8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ7FPOlMo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ7FPPBmA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYFcRs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYGUks=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYHgbs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYGUks=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYIm88=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYGUks=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 269,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 519,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 99,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"queueBase.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYJUlI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYGUks=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYKOek=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYGUks=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\t\t\"width\": 109,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYHgbs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYIm88=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYJUlI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYKOek=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYLcbU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 537,\n\t\t\t\t\t\t\t\t\t\"width\": 109,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYMrak=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 547,\n\t\t\t\t\t\t\t\t\t\"width\": 109,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYNKA0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn5kFYOnyE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5j1YD/pE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\"width\": 109,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYGUks=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYLcbU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYMrak=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYNKA0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYOnyE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEpxVlYzHLg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVVYxfn0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEpxV1Y0qkk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVVYxfn0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 298,\n\t\t\t\t\t\t\t\t\t\"top\": 471,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEpxWFY1BUw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVVYxfn0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 310,\n\t\t\t\t\t\t\t\t\t\"top\": 463,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEpxWFY2byQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVVYxfn0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 273,\n\t\t\t\t\t\t\t\t\t\"top\": 488,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxVlYzHLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"269:461;303:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxV1Y0qkk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxWFY1BUw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEpxWFY2byQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEp0tlZEhJY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZCQMA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEp0t1ZFc8g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZCQMA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 351,\n\t\t\t\t\t\t\t\t\t\"top\": 485,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEp0t1ZGmyQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZCQMA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 365,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEp0t1ZHdsc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZCQMA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 324,\n\t\t\t\t\t\t\t\t\t\"top\": 474,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0tlZEhJY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn5kFYFcRs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"348:461;328:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0t1ZFc8g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0t1ZGmyQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEp0t1ZHdsc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVhJLU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FViOPA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVjG1M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FViOPA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVkXX4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FViOPA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1045,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 263,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"subThreadQueueOut.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVlPmI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FViOPA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVmkfo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FViOPA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1040,\n\t\t\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\t\t\"width\": 169,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVjG1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVkXX4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVlPmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVmkfo=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVn774=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1040,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 169,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVoqlE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1040,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 169,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVpV3o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 464,\n\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnx8FVqJm4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx71Vfqh4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 464,\n\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1040,\n\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\"width\": 169,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FViOPA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVn774=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVoqlE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVpV3o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVqJm4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXc1PI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXdXmQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXeV5Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXdXmQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -584,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXfmHw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXdXmQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 861,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 263,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 171,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"subThreadQueueInOut.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXgn7o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXdXmQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -584,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXhlqU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXdXmQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -584,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 856,\n\t\t\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\t\t\"width\": 181,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXeV5Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXfmHw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXgn7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXhlqU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXieGI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 856,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 181,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXjW+w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 856,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 181,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXkHlI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -472,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn3mFXl6aQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3l1XaxjA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -472,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 856,\n\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\"width\": 181,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXdXmQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXieGI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXjW+w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXkHlI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXl6aQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U4NBM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U5jZs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U6tlY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U5jZs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -336,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U7Yoo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U5jZs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 29,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 519,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"thread.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U87ok=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U5jZs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -336,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U9+Bk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U5jZs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -336,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 24,\n\t\t\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U6tlY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U7Yoo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U87ok=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U9+Bk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U+wIk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 24,\n\t\t\t\t\t\t\t\t\t\"top\": 537,\n\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1U/+y4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 24,\n\t\t\t\t\t\t\t\t\t\"top\": 547,\n\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1VAjfs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -576,\n\t\t\t\t\t\t\t\t\t\"top\": -128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnwN1VBjok=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwNlU2kqs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -576,\n\t\t\t\t\t\t\t\t\t\"top\": -128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 24,\n\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U5jZs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U+wIk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U/+y4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1VAjfs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1VBjok=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFUPpoU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFUQ2oI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFURlUA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUQ2oI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -280,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -904,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFUS7Kk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUQ2oI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 301,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 127,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 125,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"threadManager.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFUTm20=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUQ2oI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -280,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -904,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqFUUZGM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUQ2oI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -280,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -904,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 296,\n\t\t\t\t\t\t\t\t\t\"top\": 120,\n\t\t\t\t\t\t\t\t\t\"width\": 135,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFURlUA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUS7Kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUTm20=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUUZGM=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqlUVTFg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 296,\n\t\t\t\t\t\t\t\t\t\"top\": 145,\n\t\t\t\t\t\t\t\t\t\"width\": 135,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqlUWN4Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 296,\n\t\t\t\t\t\t\t\t\t\"top\": 155,\n\t\t\t\t\t\t\t\t\t\"width\": 135,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqlUX0lI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": -368,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEntqlUYdyw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntp1UNMvk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": -368,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 296,\n\t\t\t\t\t\t\t\"top\": 120,\n\t\t\t\t\t\t\t\"width\": 135,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUQ2oI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqlUVTFg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqlUWN4Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqlUX0lI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqlUYdyw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWK4v0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWLNio=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWMI9U=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWLNio=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -712,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWNFTY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWLNio=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 503,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wQueueOrderer.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWOtDo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWLNio=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -712,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWP1A0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWLNio=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 240,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -712,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 498,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWMI9U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWNFTY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWOtDo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWP1A0=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWQxZU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 498,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GFWR50w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 498,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GVWSWMI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\"top\": -352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn0GVWTiAc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWI6/o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\"top\": -352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 498,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWLNio=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWQxZU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWR50w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GVWSWMI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GVWTiAc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFWzvuI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW0eLg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW1Glk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW0eLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW2CBc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW0eLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 797,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"workerProducer.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW3VV8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW0eLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW4UJA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW0eLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 792,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW1Glk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW2CBc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW3VV8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW4UJA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW5KrA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 792,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW6Ky4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 792,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW7VDI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 560,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEn2CFW8SZw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2B1WxudQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 560,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 792,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 140,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW0eLg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW5KrA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW6Ky4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW7VDI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFW8SZw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRra2Q=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRsPH4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRtkJ4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRsPH4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 600,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRu1YU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRsPH4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 573,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 519,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRvSr8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRsPH4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 600,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRwOz4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRsPH4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 600,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 568,\n\t\t\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRtkJ4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRu1YU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRvSr8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRwOz4=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4FRx4zU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 568,\n\t\t\t\t\t\t\t\t\t\"top\": 537,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4VRyDu0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 568,\n\t\t\t\t\t\t\t\t\t\"top\": 547,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4VRzbKA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 448,\n\t\t\t\t\t\t\t\t\t\"top\": 352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnk4VR0dqg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk31Rp4JU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 448,\n\t\t\t\t\t\t\t\t\t\"top\": 352,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 568,\n\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRsPH4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRx4zU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4VRyDu0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4VRzbKA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4VR0dqg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTmbGs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTn6SQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FToEEQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTn6SQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 976,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTp/2Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTn6SQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 645,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"workerConsumer.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTqs5Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTn6SQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 976,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTrzHQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTn6SQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 976,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FToEEQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTp/2Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTqs5Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTrzHQ=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTsHDU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTtxfU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTunBg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnr2FTvKxE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr11TkZW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 640,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTn6SQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTsHDU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTtxfU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTunBg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTvKxE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnea1PwDbU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnea1PxXXU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFPyuC0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PxXXU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -424,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -360,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFPzhOQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PxXXU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 93,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 63,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP0c5s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PxXXU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -424,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -360,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP1jBg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PxXXU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -424,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -360,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 88,\n\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFPyuC0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFPzhOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP0c5s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP1jBg=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP2FfY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 88,\n\t\t\t\t\t\t\t\t\t\"top\": 81,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP3p5w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 88,\n\t\t\t\t\t\t\t\t\t\"top\": 91,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP4q6E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnebFP5BIY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PwDbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PuhXg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -96,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 88,\n\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnea1PxXXU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP2FfY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP3p5w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP4q6E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnebFP5BIY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FS9jUU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FS+VdY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FS/XGs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS+VdY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTAs1k=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS+VdY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1069,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 154,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"subThreadNoQueue.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTBeTM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS+VdY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTCmEM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS+VdY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS/XGs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTAs1k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTBeTM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTCmEM=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTDoM4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTEPZk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTFmZY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEno0FTGJ3w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnoz1S7CCo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 164,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS+VdY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTDoM4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTEPZk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTFmZY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FTGJ3w=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYFQZQQU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYFQapZA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYFQb0p8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQapZA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQcQ5M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQapZA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 197,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 115,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"priorityQueue.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQdTsM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQapZA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQeMPk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQapZA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -608,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 125,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQb0p8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQcQ5M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQdTsM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQeMPk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQfNmY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 125,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQgiTw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 125,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYVQhDzc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -352,\n\t\t\t\t\t\t\t\t\t\"top\": 248,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEngYlQiwAw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQZQQU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngX1QXn1w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -352,\n\t\t\t\t\t\t\t\t\t\"top\": 248,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 125,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYFQapZA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQfNmY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQgiTw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYVQhDzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEngYlQiwAw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRCaRA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRDKv4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFREkic=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRDKv4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRFz50=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRDKv4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 325,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 68,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"queue.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRGIVQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRDKv4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRHzX8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRDKv4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -824,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFREkic=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRFz50=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRGIVQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRHzX8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRI9Fg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 441,\n\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioFRJUvU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 451,\n\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioVRKoaw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -456,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnioVRLRew=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnin1RAI/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -456,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRDKv4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRI9Fg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRJUvU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioVRKoaw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioVRLRew=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSU+Cc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSVyd8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSW87Q=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSVyd8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSXl80=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSVyd8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 973,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 519,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 95,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"subThread.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSYpro=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSVyd8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSZT0o=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSVyd8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 968,\n\t\t\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSW87Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSXl80=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSYpro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSZT0o=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSaFHY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 968,\n\t\t\t\t\t\t\t\t\t\"top\": 537,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6FSbAhI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 968,\n\t\t\t\t\t\t\t\t\t\"top\": 547,\n\t\t\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6VScCD0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHEnm6VSdjck=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm51SSihM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHD57H1DmLb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 968,\n\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\"width\": 105,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSVyd8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSaFHY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSbAhI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6VScCD0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6VSdjck=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE4SvGKriPI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4Su2KpLQ0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE4SvGKsTCg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4Su2KpLQ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 600,\n\t\t\t\t\t\t\t\t\t\"top\": 473,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE4SvWKtAzU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4Su2KpLQ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 614,\n\t\t\t\t\t\t\t\t\t\"top\": 467,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHE4SvWKulD8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4Su2KpLQ0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 573,\n\t\t\t\t\t\t\t\t\t\"top\": 486,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKriPI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn0GFWK4v0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"577:461;598:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvGKsTCg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvWKtAzU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHE4SvWKulD8=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFEy7mX7MZk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX58e8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFEy7mX8Fx0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX58e8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 997,\n\t\t\t\t\t\t\t\t\t\"top\": 395,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFEy7mX9b8A=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX58e8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1011,\n\t\t\t\t\t\t\t\t\t\"top\": 391,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFEy7mX+OoQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX58e8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 968,\n\t\t\t\t\t\t\t\t\t\"top\": 404,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX7MZk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"953:301;1013:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX8Fx0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX9b8A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFEy7mX+OoQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFE3zmYM/sU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYKLpE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFE3zmYNI3c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYKLpE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1085,\n\t\t\t\t\t\t\t\t\t\"top\": 405,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFE3zmYO0Cc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYKLpE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1099,\n\t\t\t\t\t\t\t\t\t\"top\": 411,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFE3zmYPRzo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYKLpE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1058,\n\t\t\t\t\t\t\t\t\t\"top\": 394,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYM/sU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"1115:301;1029:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYNI3c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYO0Cc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFE3zmYPRzo=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFAV2YdE9A=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2Ybm/c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFAV2YeqIY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2Ybm/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1091,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFAV2YftCo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2Ybm/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1100,\n\t\t\t\t\t\t\t\t\t\"top\": 503,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFAWGYgCiQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2Ybm/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1072,\n\t\t\t\t\t\t\t\t\t\"top\": 468,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YdE9A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"1115:461;1050:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YeqIY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAV2YftCo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFAWGYgCiQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFI52YuT1M=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI5mYsLlc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFI52YvCAU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI5mYsLlc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 907,\n\t\t\t\t\t\t\t\t\t\"top\": 389,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFI6GYwrOI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI5mYsLlc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 918,\n\t\t\t\t\t\t\t\t\t\"top\": 379,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFFI6GYx7ZI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI5mYsLlc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 886,\n\t\t\t\t\t\t\t\t\t\"top\": 410,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YuT1M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnm6FSU+Cc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"797:301;998:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI52YvCAU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI6GYwrOI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFFI6GYx7ZI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLJUWa4bg0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa2aeA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLJUWa5U/4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa2aeA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 858,\n\t\t\t\t\t\t\t\t\t\"top\": 497,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLJUWa6X6E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa2aeA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 861,\n\t\t\t\t\t\t\t\t\t\"top\": 512,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLJUWa73h0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa2aeA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 853,\n\t\t\t\t\t\t\t\t\t\"top\": 468,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa4bg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEno0FS9jUU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"1063:453;650:526\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa5U/4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa6X6E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLJUWa73h0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLOrmbJ7YQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbH+pY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLOrmbKScA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbH+pY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 870,\n\t\t\t\t\t\t\t\t\t\"top\": 414,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLOrmbLk18=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbH+pY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 877,\n\t\t\t\t\t\t\t\t\t\"top\": 427,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLOrmbMoOA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbH+pY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 857,\n\t\t\t\t\t\t\t\t\t\"top\": 387,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbJ7YQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"1078:301;650:513\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbKScA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbLk18=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLOrmbMoOA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLVhGbauTg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVg2bYTxg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLVhGbb8tE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVg2bYTxg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 786,\n\t\t\t\t\t\t\t\t\t\"top\": 411,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLVhGbcJHU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVg2bYTxg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 795,\n\t\t\t\t\t\t\t\t\t\"top\": 423,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLVhGbdG/o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVg2bYTxg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 767,\n\t\t\t\t\t\t\t\t\t\"top\": 388,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbauTg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"916:301;638:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbb8tE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbcJHU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLVhGbdG/o=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLbJWbr3kk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJGbpfa4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLbJWbsXj4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJGbpfa4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 703,\n\t\t\t\t\t\t\t\t\t\"top\": 408,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLbJWbt66c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJGbpfa4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 716,\n\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFLbJWbuMUI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJGbpfa4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\"top\": 391,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbr3kk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"760:301;623:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbsXj4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbt66c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFLbJWbuMUI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2isSK8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2itD50=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 550,\n\t\t\t\t\t\t\t\t\t\"top\": 341,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2iuDNY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 545,\n\t\t\t\t\t\t\t\t\t\"top\": 327,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2ivXyI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiogQE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 561,\n\t\t\t\t\t\t\t\t\t\"top\": 370,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2iw0mg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmipwtU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 416,\n\t\t\t\t\t\t\t\t\t\"top\": 393,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2ix8hs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmipwtU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 414,\n\t\t\t\t\t\t\t\t\t\"top\": 380,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2iyWqs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmipwtU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 422,\n\t\t\t\t\t\t\t\t\t\"top\": 420,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2izp58=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiqFCU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 685,\n\t\t\t\t\t\t\t\t\t\"top\": 290,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2i0Kdw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiqFCU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 678,\n\t\t\t\t\t\t\t\t\t\"top\": 278,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2i1pAg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiqFCU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 699,\n\t\t\t\t\t\t\t\t\t\"top\": 314,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeV2i2W/I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmipwtU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQeWGi3mw4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2isSK8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeVmiqFCU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"398:423;715:301\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2itD50=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2iuDNY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2ivXyI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2iw0mg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2ix8hs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2iyWqs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2izp58=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2i0Kdw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2i1pAg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeV2i2W/I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQeWGi3mw4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjvWbM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjw1Zg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 625,\n\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjxmXo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 621,\n\t\t\t\t\t\t\t\t\t\"top\": 329,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjyrR8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjrWgc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 372,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmjzvwU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjsEHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 419,\n\t\t\t\t\t\t\t\t\t\"top\": 399,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj0UHw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjsEHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 417,\n\t\t\t\t\t\t\t\t\t\"top\": 386,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj1uro=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjsEHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 422,\n\t\t\t\t\t\t\t\t\t\"top\": 427,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj2EJw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjtdWU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 831,\n\t\t\t\t\t\t\t\t\t\"top\": 287,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj3IpU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjtdWU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 826,\n\t\t\t\t\t\t\t\t\t\"top\": 275,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj4rc0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjtdWU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 843,\n\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj5wmk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjsEHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQiRmj6dPU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjvWbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjtdWU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"398:427;861:301\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjw1Zg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjxmXo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjyrR8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmjzvwU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj0UHw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj1uro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj2EJw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj3IpU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj4rc0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj5wmk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQiRmj6dPU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lBLAY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lCimE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 714,\n\t\t\t\t\t\t\t\t\t\"top\": 342,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lDmqc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 711,\n\t\t\t\t\t\t\t\t\t\"top\": 327,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lEAh0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnLmk9eHc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 721,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lFCUk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k+i+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 420,\n\t\t\t\t\t\t\t\t\t\"top\": 404,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lGfOA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k+i+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 419,\n\t\t\t\t\t\t\t\t\t\"top\": 390,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lHpLU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k+i+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 421,\n\t\t\t\t\t\t\t\t\t\"top\": 431,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lI9wY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k/CCk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1010,\n\t\t\t\t\t\t\t\t\t\"top\": 280,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lJNEs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k/CCk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1005,\n\t\t\t\t\t\t\t\t\t\"top\": 268,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lK+lA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k/CCk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1020,\n\t\t\t\t\t\t\t\t\t\"top\": 306,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lLMzY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k+i+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQnL2lMrW8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lBLAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2k/CCk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"398:430;1039:296\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lCimE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lDmqc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lEAh0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lFCUk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lGfOA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lHpLU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lI9wY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lJNEs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lK+lA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lLMzY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQnL2lMrW8=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQ49moQuhI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moO8PE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQ49moRiNA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moO8PE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 721,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQ492oSBSk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moO8PE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 724,\n\t\t\t\t\t\t\t\t\t\"top\": 386,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFQ492oTIHc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moO8PE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 714,\n\t\t\t\t\t\t\t\t\t\"top\": 342,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moQuhI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnx8FVhJLU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"1039:296;398:430\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ49moRiNA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ492oSBSk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFQ492oTIHc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRdk2tDT7A=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tBzNI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRdk2tEZ1c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tBzNI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 372,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRdmmtFJVw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tBzNI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 636,\n\t\t\t\t\t\t\t\t\t\"top\": 386,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRdmmtGb3M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tBzNI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 625,\n\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tDT7A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn3mFXc1PI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"861:301;398:427\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdk2tEZ1c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdmmtFJVw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRdmmtGb3M=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRirmuQiiM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuODQA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRirmuRq4o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuODQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 561,\n\t\t\t\t\t\t\t\t\t\"top\": 369,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRirmuStkk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuODQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 566,\n\t\t\t\t\t\t\t\t\t\"top\": 383,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFRirmuT0SQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuODQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 550,\n\t\t\t\t\t\t\t\t\t\"top\": 342,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuQiiM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEmZ6lPGa/A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"715:301;398:423\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuRq4o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuStkk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFRirmuT0SQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXDcnLRtNk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcXLPDXQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXDcnLS7eA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcXLPDXQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 730,\n\t\t\t\t\t\t\t\t\t\"top\": 496,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXDc3LTJYo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcXLPDXQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 735,\n\t\t\t\t\t\t\t\t\t\"top\": 510,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXDc3LUne0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcXLPDXQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 719,\n\t\t\t\t\t\t\t\t\t\"top\": 469,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLRtNk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEn2CFWzvuI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"800:461;650:518\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDcnLS7eA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDc3LTJYo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXDc3LUne0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXJlnMP9g0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMNtRc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXJlnMQeXY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMNtRc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 670,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXJlnMRaxg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMNtRc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\"top\": 502,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFXJlnMSsuU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMNtRc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 649,\n\t\t\t\t\t\t\t\t\t\"top\": 468,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMP9g0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnr2FTmbGs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"687:461;633:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMQeXY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMRaxg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFXJlnMSsuU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFamNnpnLb8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNXplyYs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFamNnpokyE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNXplyYs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 374,\n\t\t\t\t\t\t\t\t\t\"top\": 284,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFamNnpprvg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNXplyYs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 389,\n\t\t\t\t\t\t\t\t\t\"top\": 284,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFamNnpqQBY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNXplyYs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 345,\n\t\t\t\t\t\t\t\t\t\"top\": 283,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpnLb8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnioFRCaRA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"363:165;358:415\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpokyE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpprvg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFamNnpqQBY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFa6T3qlSqA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6TnqjrOU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFa6T3qmXZg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6TnqjrOU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": 341,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFa6T3qnYY8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6TnqjrOU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 236,\n\t\t\t\t\t\t\t\t\t\"top\": 350,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFa6T3qoMuc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6TnqjrOU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 201,\n\t\t\t\t\t\t\t\t\t\"top\": 322,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qlSqA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnwN1U4NBM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"345:165;81:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qmXZg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qnYY8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFa6T3qoMuc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFhC6If9J/c=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDfDwV2pYSY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC54f7Eks=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFhC6If+xmU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC54f7Eks=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 497,\n\t\t\t\t\t\t\t\t\t\"top\": 324,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFhC6If/tiE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC54f7Eks=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 510,\n\t\t\t\t\t\t\t\t\t\"top\": 316,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFhC6IgAHIg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC54f7Eks=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 472,\n\t\t\t\t\t\t\t\t\t\"top\": 339,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If9J/c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEnk4FRra2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHEntqFUPpoU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"377:165;594:511\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If+xmU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6If/tiE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFhC6IgAHIg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbHDdYEV2Qawk=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"pose\",\n\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJJWoCjs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"pose\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDZXtVSk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wPoseExtractorNet.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCH1K22V0Q=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD7mq+0ft0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblZYWiRQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"wPoseRenderer.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHB2E612aDc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD2Aq92KiE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyptZbjGLg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"poseParameters.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGw5J6MXrlI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGw5J6MYVBM=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGw5J6MXrlI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGw5J6MZyXA=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGw5J6MXrlI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjIpa6NmI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"enumClasses.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxZaRGg0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELZhbldE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"renderPose\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB0pgy9QE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"poseExtractorCaffe\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrEq8VKcc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrEq8WF48=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrEq8X3Y0=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLGeneralization\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHGZKrGqXrE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIq0rUjTho=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIvkrWOA8M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHI0w7X5fe0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsO71y8uU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsO71zxWo=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsO710h4k=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHTZc8YMcWg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tZgJmKs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"poseRenderer\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/K7DPvI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/K7EAnY=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/K7FK4E=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHK6E74POAA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHSf7MWSFj4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5ZiEMoA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"poseExtractor\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGqxTKG5wjw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrME6HKk7E=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW9ZXECgk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"bodyPartConnectorBase\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGLjx6FvWeI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGMlpKGFzvA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbZcMIfs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"bodyPartConnectorCaffe\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwQTKLXKW4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwVTKL3GS0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGxt3qOc9Cg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVkrSVUkA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVkrSW4DQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVkrSXJ+E=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJipqEm58o=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"core\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XKFAf+Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"array.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociation\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHKHbh/M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end1\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHKHcSME=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"none\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"end2\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAssociationEnd\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHKHd2lk=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"reference\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"navigable\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"aggregation\": \"composite\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"isReadOnly\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isOrdered\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isUnique\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\"isID\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\t\t\"isDerived\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRoLSckR0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"rectangle.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZKylPT8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"thread\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RJqxmjag=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZKylPT8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJJWqH+E=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJZWrwUc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWoCjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJZWsAEM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWrwUc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJ5WtH/8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWrwUc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 22,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 1023,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"pose\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJ5WuAo4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWrwUc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFxkJ5WvYrw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWrwUc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -400,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 15,\n\t\t\t\t\t\t\t\t\t\"width\": 1033,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWsAEM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJ5WtH/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJ5WuAo4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJ5WvYrw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 1033,\n\t\t\t\t\t\t\t\"height\": 625,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJZWrwUc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW9pXGlaM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW9pXHj64=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW9pXIA24=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXHj64=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 560,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XJedc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXHj64=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 637,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 463,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 153,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"bodyPartConnectorBase\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XKpHI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXHj64=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 560,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XL7o8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXHj64=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 560,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 456,\n\t\t\t\t\t\t\t\t\t\"width\": 163,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXIA24=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XJedc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XKpHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XL7o8=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XMewg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 481,\n\t\t\t\t\t\t\t\t\t\"width\": 163,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XNtN4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 163,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW95XO+CE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 288,\n\t\t\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyW+JXPekA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9ZXECgk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 288,\n\t\t\t\t\t\t\t\t\t\"top\": 48,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\"top\": 456,\n\t\t\t\t\t\t\t\"width\": 163,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXHj64=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XMewg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XNtN4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW95XO+CE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW+JXPekA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpXvuYI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpXwCEs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpXxuhY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXwCEs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 336,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpXySIQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXwCEs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 653,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 127,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wPoseExtractorNet.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpXzeyQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXwCEs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 336,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpX0VSw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXwCEs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 336,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 137,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXxuhY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXySIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXzeyQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpX0VSw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpX1Aso=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 137,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpX2nYg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 137,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpX3s8Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 208,\n\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyaDpX4fmk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDZXtVSk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 208,\n\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 648,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 137,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXwCEs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpX1Aso=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpX2nYg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpX3s8Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpX4fmk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblZYYzdE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblZYZdp4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblZYa+Pg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYZdp4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYbqOk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYZdp4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 378,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 129,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"wPoseRenderer.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYcoGk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYZdp4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYdToA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYZdp4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -504,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 373,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 139,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYa+Pg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYbqOk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYcoGk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYdToA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYeB4w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 373,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 139,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYf788=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 373,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 139,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYgxEE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -232,\n\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyblpYh2tI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYWiRQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -232,\n\t\t\t\t\t\t\t\t\t\"top\": -288,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 373,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 139,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYZdp4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYeB4w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYf788=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYgxEE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblpYh2tI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyptpbluc8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bm7YA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bnhj8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bm7YA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5boQvY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bm7YA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 717,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 567,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 131,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"poseParameters.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bp3gk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bm7YA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bqBOw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bm7YA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -496,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 712,\n\t\t\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\t\t\"width\": 141,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bnhj8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5boQvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bp3gk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bqBOw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bra6Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 712,\n\t\t\t\t\t\t\t\t\t\"top\": 585,\n\t\t\t\t\t\t\t\t\t\"width\": 141,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypt5bsGF8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 712,\n\t\t\t\t\t\t\t\t\t\"top\": 595,\n\t\t\t\t\t\t\t\t\t\"width\": 141,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypuJbtp1Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -504,\n\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFypuJbu7BE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptZbjGLg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -504,\n\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 712,\n\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\"width\": 141,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bm7YA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bra6Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypt5bsGF8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypuJbtp1Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFypuJbu7BE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5a8Kvc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5a9GDw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5a+Amg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a9GDw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5a/XRk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a9GDw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 877,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 567,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 111,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"enumClasses.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bA0nY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a9GDw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bBIDk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a9GDw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 872,\n\t\t\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a+Amg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a/XRk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bA0nY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bBIDk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bC5g8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 872,\n\t\t\t\t\t\t\t\t\t\"top\": 585,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bDMpo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 872,\n\t\t\t\t\t\t\t\t\t\"top\": 595,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bEt24=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyjI5bFW0Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjIpa6NmI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 80,\n\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 872,\n\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a9GDw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bC5g8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bDMpo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bEt24=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5bFW0Q=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxZaTi+g=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxZaUYZM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxZaVJ84=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaUYZM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -936,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -864,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxZaWako=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaUYZM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 77,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 95,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpaXwQE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaUYZM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -936,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -864,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpaYN0M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaUYZM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -936,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -864,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": 88,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaVJ84=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaWako=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpaXwQE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpaYN0M=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpaZ9ug=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": 113,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpaaNVI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": 123,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpabYMc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -496,\n\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyhxpacmW4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaTi+g=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaRGg0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -496,\n\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\"top\": 88,\n\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxZaUYZM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpaZ9ug=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpaaNVI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpabYMc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyhxpacmW4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcOd/U=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcPX8s=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcQXNs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcPX8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 752,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -624,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcRAmU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcPX8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 741,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 367,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 155,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"bodyPartConnectorCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcS4Xg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcPX8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 752,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -624,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcT5Us=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcPX8s=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 752,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -624,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 736,\n\t\t\t\t\t\t\t\t\t\"top\": 360,\n\t\t\t\t\t\t\t\t\t\"width\": 165,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcQXNs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcRAmU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcS4Xg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcT5Us=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcU1BI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 736,\n\t\t\t\t\t\t\t\t\t\"top\": 385,\n\t\t\t\t\t\t\t\t\t\"width\": 165,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcV3u8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 736,\n\t\t\t\t\t\t\t\t\t\"top\": 395,\n\t\t\t\t\t\t\t\t\t\"width\": 165,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytbpcWeGU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 416,\n\t\t\t\t\t\t\t\t\t\"top\": -336,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFytb5cXWA4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbZcMIfs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 416,\n\t\t\t\t\t\t\t\t\t\"top\": -336,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 736,\n\t\t\t\t\t\t\t\"top\": 360,\n\t\t\t\t\t\t\t\"width\": 165,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcPX8s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcU1BI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcV3u8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcWeGU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytb5cXWA4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELphdmCE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELpheFqI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELphfvaU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELpheFqI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELphgEv8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELpheFqI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 525,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 567,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 147,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"renderPose\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzELphhOIY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELpheFqI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzEL5hiHSo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELpheFqI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -984,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\t\t\"width\": 157,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphfvaU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphgEv8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphhOIY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzEL5hiHSo=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzEL5hj/mI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\t\t\"top\": 585,\n\t\t\t\t\t\t\t\t\t\"width\": 157,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzEL5hko7w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\t\t\"top\": 595,\n\t\t\t\t\t\t\t\t\t\"width\": 157,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzEL5hlMOA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -240,\n\t\t\t\t\t\t\t\t\t\"top\": -240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzEL5hmQ8c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELphdmCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELZhbldE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -240,\n\t\t\t\t\t\t\t\t\t\"top\": -240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\"top\": 560,\n\t\t\t\t\t\t\t\"width\": 157,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzELpheFqI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzEL5hj/mI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzEL5hko7w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzEL5hlMOA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzEL5hmQ8c=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB0pg0a44=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB0pg1+dg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g2u1A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg1+dg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1712,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1040,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g3rcg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg1+dg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 133,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 327,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 120,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"poseExtractorCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g4+VU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg1+dg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1712,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1040,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g5atM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg1+dg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1712,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1040,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g2u1A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g3rcg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g4+VU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g5atM=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g6+M8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\"top\": 345,\n\t\t\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g7NxU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\"top\": 355,\n\t\t\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g8emo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -880,\n\t\t\t\t\t\t\t\t\t\"top\": -560,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzB05g9l4g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pgy9QE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -880,\n\t\t\t\t\t\t\t\t\t\"top\": -560,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\"width\": 130,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg1+dg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g6+M8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g7NxU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g8emo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB05g9l4g=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tZgLHvQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tZgM8Sw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tZgN0qE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgM8Sw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1248,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgOw7k=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgM8Sw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 250,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 255,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"poseRenderer\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgP1VA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgM8Sw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1248,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgQIKk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgM8Sw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -1248,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1192,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 245,\n\t\t\t\t\t\t\t\t\t\"top\": 248,\n\t\t\t\t\t\t\t\t\t\"width\": 99,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgN0qE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgOw7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgP1VA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgQIKk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgRD3I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 245,\n\t\t\t\t\t\t\t\t\t\"top\": 273,\n\t\t\t\t\t\t\t\t\t\"width\": 99,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgSS8U=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 245,\n\t\t\t\t\t\t\t\t\t\"top\": 283,\n\t\t\t\t\t\t\t\t\t\"width\": 99,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgT52s=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -632,\n\t\t\t\t\t\t\t\t\t\"top\": -640,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy/tpgUfCU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgJmKs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -632,\n\t\t\t\t\t\t\t\t\t\"top\": -640,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 245,\n\t\t\t\t\t\t\t\"top\": 248,\n\t\t\t\t\t\t\t\"width\": 99,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgM8Sw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgRD3I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgSS8U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgT52s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tpgUfCU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piG7DA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piHWYU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piImrY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piHWYU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -856,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piJse4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piHWYU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 426,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 463,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 87,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"poseExtractor\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piKVAg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piHWYU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -856,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK5piLYAw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piHWYU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -856,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -568,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 421,\n\t\t\t\t\t\t\t\t\t\"top\": 456,\n\t\t\t\t\t\t\t\t\t\"width\": 97,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piImrY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piJse4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piKVAg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piLYAw=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK55iMy7I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 421,\n\t\t\t\t\t\t\t\t\t\"top\": 481,\n\t\t\t\t\t\t\t\t\t\"width\": 97,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK55iN7WY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 421,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 97,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK55iOXTg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -696,\n\t\t\t\t\t\t\t\t\t\"top\": -296,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFzK55iPcVc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5ZiEMoA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -696,\n\t\t\t\t\t\t\t\t\t\"top\": -296,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFxkJJWqH+E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 421,\n\t\t\t\t\t\t\t\"top\": 456,\n\t\t\t\t\t\t\t\"width\": 97,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piHWYU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK55iMy7I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK55iN7WY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK55iOXTg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK55iPcVc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJip6EoNT0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJiqKEpUGs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJiqKEq9GM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEpUGs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJiqKErHZE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEpUGs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 141,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 710,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 655,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"core\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJiqKEso2w=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEpUGs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJiqKEtkgk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEpUGs=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -448,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 703,\n\t\t\t\t\t\t\t\t\t\"width\": 665,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEq9GM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKErHZE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEso2w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEtkgk=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\"top\": 688,\n\t\t\t\t\t\t\t\"width\": 665,\n\t\t\t\t\t\t\t\"height\": 160,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJiqKEpUGs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XaFCtvY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XaFD3us=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFEmic=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFD3us=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFFD/Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFD3us=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 557,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 775,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"array.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFGd2A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFD3us=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFHybI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFD3us=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 272,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\t\t\"top\": 768,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFEmic=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFFD/Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFGd2A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFHybI=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFIVZg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\t\t\"top\": 793,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4XqFJEe0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\t\t\"top\": 803,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4X6FKx4o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGJ4X6FLYgE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 72,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\"top\": 768,\n\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFD3us=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFIVZg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XqFJEe0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4X6FKx4o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4X6FLYgE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGLjx6Fxl7k=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6FvWeI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGLjyKFyffk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6FvWeI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 663,\n\t\t\t\t\t\t\t\t\t\"top\": 633,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGLjyKFzJeM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6FvWeI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 677,\n\t\t\t\t\t\t\t\t\t\"top\": 639,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGLjyKF0ltY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6FvWeI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 636,\n\t\t\t\t\t\t\t\t\t\"top\": 622,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjx6Fxl7k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"704:501;596:767\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjyKFyffk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjyKFzJeM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGLjyKF0ltY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGMlpKGHAQA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGFzvA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGMlpKGI1RY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGFzvA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 759,\n\t\t\t\t\t\t\t\t\t\"top\": 515,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGMlpKGJiN4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGFzvA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 771,\n\t\t\t\t\t\t\t\t\t\"top\": 506,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGMlpKGKDAY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGFzvA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 734,\n\t\t\t\t\t\t\t\t\t\"top\": 532,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGHAQA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"728:501;767:559\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGI1RY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGJiN4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGMlpKGKDAY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnq56GYALc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnq6KGZqFA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 201,\n\t\t\t\t\t\t\t\t\t\"top\": 770,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnq6KGafLE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\t\t\"top\": 769,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnq6KGbkos=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq5qGWd3A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 172,\n\t\t\t\t\t\t\t\t\t\"top\": 773,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq56GYALc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"187:765;188:791\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq6KGZqFA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq6KGafLE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnq6KGbkos=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnvt6Gp5ew=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnvt6GqbGE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 333,\n\t\t\t\t\t\t\t\t\t\"top\": 771,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnvt6Grtqg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 348,\n\t\t\t\t\t\t\t\t\t\"top\": 771,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGnvt6GsNlg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvtqGnGyg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": 772,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Gp5ew=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"320:765;319:791\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6GqbGE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6Grtqg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGnvt6GsNlg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGqxTKG7bkA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG5wjw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGqxTaG8XBI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG5wjw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 619,\n\t\t\t\t\t\t\t\t\t\"top\": 505,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGqxTaG9igY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG5wjw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 624,\n\t\t\t\t\t\t\t\t\t\"top\": 491,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGqxTaG+s6U=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG5wjw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 610,\n\t\t\t\t\t\t\t\t\t\"top\": 534,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTKG7bkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"518:494;713:559\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTaG8XBI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTaG9igY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGqxTaG+s6U=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrMFKHMaow=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrME6HKk7E=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrMFKHNzoM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrME6HKk7E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 542,\n\t\t\t\t\t\t\t\t\t\"top\": 622,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrMFKHOvNI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrME6HKk7E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 556,\n\t\t\t\t\t\t\t\t\t\"top\": 617,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrMFKHPiVU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrME6HKk7E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 513,\n\t\t\t\t\t\t\t\t\t\"top\": 633,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHMaow=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"478:501;578:767\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHNzoM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHOvNI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrMFKHPiVU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHaHfwls=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHaHgtBU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 513,\n\t\t\t\t\t\t\t\t\t\"top\": 633,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHhSD4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 499,\n\t\t\t\t\t\t\t\t\t\"top\": 638,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHirZI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHbh/M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 542,\n\t\t\t\t\t\t\t\t\t\"top\": 622,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHja2g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHcSME=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 554,\n\t\t\t\t\t\t\t\t\t\"top\": 741,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHkS3I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHcSME=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 541,\n\t\t\t\t\t\t\t\t\t\"top\": 744,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHllT0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHcSME=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 582,\n\t\t\t\t\t\t\t\t\t\"top\": 736,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHmElU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHd2lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 473,\n\t\t\t\t\t\t\t\t\t\"top\": 524,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHnxtU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHd2lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 461,\n\t\t\t\t\t\t\t\t\t\"top\": 531,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHowKw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHd2lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 497,\n\t\t\t\t\t\t\t\t\t\"top\": 510,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWHqHpIPM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHcSME=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -320,\n\t\t\t\t\t\t\t\t\t\"top\": -88,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGrWH6HqQKg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHfwls=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHKHd2lk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -320,\n\t\t\t\t\t\t\t\t\t\"top\": -88,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"578:767;478:501\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHaHgtBU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHhSD4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHirZI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHja2g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHkS3I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHllT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHmElU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHnxtU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHowKw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWHqHpIPM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGrWH6HqQKg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwQTaLZZfc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTKLXKW4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwQTaLaU44=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTKLXKW4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 775,\n\t\t\t\t\t\t\t\t\t\"top\": 435,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwQTaLbjgM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTKLXKW4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 785,\n\t\t\t\t\t\t\t\t\t\"top\": 446,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwQTaLc9A0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTKLXKW4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 754,\n\t\t\t\t\t\t\t\t\t\"top\": 412,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLZZfc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyW9pXGlaM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"793:405;738:455\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLaU44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLbjgM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwQTaLc9A0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwVTaL50Do=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTKL3GS0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwVTaL6WAw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTKL3GS0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 814,\n\t\t\t\t\t\t\t\t\t\"top\": 478,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwVTaL75lI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTKL3GS0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 829,\n\t\t\t\t\t\t\t\t\t\"top\": 481,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGwVTaL8zNw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTKL3GS0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 785,\n\t\t\t\t\t\t\t\t\t\"top\": 473,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL50Do=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyptpbluc8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"814:405;786:559\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL6WAw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL75lI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGwVTaL8zNw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGxt3qOegCY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOc9Cg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGxt36OfnEY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOc9Cg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 888,\n\t\t\t\t\t\t\t\t\t\"top\": 468,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGxt36OgDrc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOc9Cg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 901,\n\t\t\t\t\t\t\t\t\t\"top\": 461,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHGxt36OhbhI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOc9Cg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 861,\n\t\t\t\t\t\t\t\t\t\"top\": 483,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt3qOegCY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyjI5a8Kvc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"831:405;919:559\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt36OfnEY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt36OgDrc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGxt36OhbhI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZKynkHQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZKylPT8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZayohYE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZKynkHQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZKylPT8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZaypHSw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayohYE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1792,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1168,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZayqMV4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayohYE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1069,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 382,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 199,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"thread\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZayrLik=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayohYE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1792,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1168,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/kZaysAlM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayohYE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1792,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1168,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\t\t\"top\": 375,\n\t\t\t\t\t\t\t\t\t\"width\": 209,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZaypHSw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayqMV4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayrLik=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZaysAlM=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1064,\n\t\t\t\t\t\t\t\"top\": 360,\n\t\t\t\t\t\t\t\"width\": 209,\n\t\t\t\t\t\t\t\"height\": 168,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZayohYE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RJ6xo2hI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RJ6xpDDM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxq450=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xpDDM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -952,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxrs6s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xpDDM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1133,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 431,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"worker.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxsn6c=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xpDDM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -952,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 73,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from thread)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxtXbA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xpDDM=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 1872,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -952,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 424,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxq450=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxrs6s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxsn6c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxtXbA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxurXM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 449,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKKxvzKM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\t\t\"top\": 459,\n\t\t\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKaxwRyc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 944,\n\t\t\t\t\t\t\t\t\t\"top\": -424,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHG/RKaxxtCs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJqxmjag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 944,\n\t\t\t\t\t\t\t\t\t\"top\": -424,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/kZKynkHQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 1128,\n\t\t\t\t\t\t\t\"top\": 424,\n\t\t\t\t\t\t\t\"width\": 82,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xpDDM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxurXM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKKxvzKM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKaxwRyc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RKaxxtCs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHB2Fq14MJo=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2E612aDc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHB2F615c1c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2E612aDc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 820,\n\t\t\t\t\t\t\t\t\t\"top\": 293,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHB2F616N3I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2E612aDc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 825,\n\t\t\t\t\t\t\t\t\t\"top\": 279,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHB2F617nKw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2E612aDc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 809,\n\t\t\t\t\t\t\t\t\t\"top\": 322,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2Fq14MJo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"503:197;1127:431\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2F615c1c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2F616N3I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHB2F617nKw=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCH1K24vVY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K22V0Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCH1K25cGg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K22V0Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 949,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCH1a26amA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K22V0Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 957,\n\t\t\t\t\t\t\t\t\t\"top\": 278,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHCH1a27Pvc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K22V0Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 934,\n\t\t\t\t\t\t\t\t\t\"top\": 316,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K24vVY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHG/RJ6xo2hI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"754:197;1130:423\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1K25cGg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1a26amA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHCH1a27Pvc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/a7HVbM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/a7IYeg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 359,\n\t\t\t\t\t\t\t\t\t\"top\": 203,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/a7JE0Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 351,\n\t\t\t\t\t\t\t\t\t\"top\": 190,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/a7KIGE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7DPvI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 376,\n\t\t\t\t\t\t\t\t\t\"top\": 228,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7L1+g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7EAnY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 342,\n\t\t\t\t\t\t\t\t\t\"top\": 214,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7MFrg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7EAnY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 337,\n\t\t\t\t\t\t\t\t\t\"top\": 201,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7N9/I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7EAnY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 353,\n\t\t\t\t\t\t\t\t\t\"top\": 239,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7OpJY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7FK4E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 377,\n\t\t\t\t\t\t\t\t\t\"top\": 192,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7PCYY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7FK4E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 367,\n\t\t\t\t\t\t\t\t\t\"top\": 182,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7Qdr8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7FK4E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 395,\n\t\t\t\t\t\t\t\t\t\"top\": 213,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7R75I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7EAnY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -336,\n\t\t\t\t\t\t\t\t\t\"top\": -80,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDZ/q7SvXQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7HVbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/K7FK4E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -336,\n\t\t\t\t\t\t\t\t\t\"top\": -80,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"329:247;407:197\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7IYeg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7JE0Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/a7KIGE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7L1+g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7MFrg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7N9/I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7OpJY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7PCYY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7Qdr8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7R75I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDZ/q7SvXQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68ZoBE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68adsE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 580,\n\t\t\t\t\t\t\t\t\t\"top\": 310,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68bB7M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 568,\n\t\t\t\t\t\t\t\t\t\"top\": 301,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68c2s0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8VKcc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 603,\n\t\t\t\t\t\t\t\t\t\"top\": 329,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68dz0w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8WF48=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 492,\n\t\t\t\t\t\t\t\t\t\"top\": 419,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68eESM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8WF48=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 483,\n\t\t\t\t\t\t\t\t\t\"top\": 409,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68f3k0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8WF48=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 511,\n\t\t\t\t\t\t\t\t\t\"top\": 440,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68gyRw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8X3Y0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 668,\n\t\t\t\t\t\t\t\t\t\"top\": 201,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68hHGA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8X3Y0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 657,\n\t\t\t\t\t\t\t\t\t\"top\": 195,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68i5gI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8X3Y0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 693,\n\t\t\t\t\t\t\t\t\t\"top\": 215,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68jf8Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8WF48=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHDrE68kubs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68ZoBE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrEq8X3Y0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"488:455;697:197\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68adsE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68bB7M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68c2s0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68dz0w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68eESM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68f3k0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68gyRw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68hHGA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68i5gI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68jf8Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHDrE68kubs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD2Aq94xHI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq92KiE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD2Aq95ppo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq92KiE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 376,\n\t\t\t\t\t\t\t\t\t\"top\": 228,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD2Aq96k04=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq92KiE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\"top\": 241,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD2Aq97XLY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq92KiE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 359,\n\t\t\t\t\t\t\t\t\t\"top\": 203,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq94xHI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyblZYYzdE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"407:197;329:247\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq95ppo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq96k04=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD2Aq97XLY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD7mq+2IXM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+0ft0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD7mq+3mv4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+0ft0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 603,\n\t\t\t\t\t\t\t\t\t\"top\": 329,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD7m6+4324=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+0ft0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 615,\n\t\t\t\t\t\t\t\t\t\"top\": 338,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHD7m6+5leg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+0ft0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 580,\n\t\t\t\t\t\t\t\t\t\"top\": 310,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+2IXM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyaDpXvuYI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"697:197;488:455\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7mq+3mv4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7m6+4324=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHD7m6+5leg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLGeneralizationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHGZKrGsQOQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGqXrE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHGZKrGtPkg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGqXrE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 336,\n\t\t\t\t\t\t\t\t\t\"top\": 390,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHGZKrGuu2Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGqXrE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 343,\n\t\t\t\t\t\t\t\t\t\"top\": 377,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHGZKrGvTkE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGqXrE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 323,\n\t\t\t\t\t\t\t\t\t\"top\": 417,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGsQOQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzK5piG7DA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"239:365;422:455\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGtPkg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGuu2Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHGZKrGvTkE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8ArOqILQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7OrREk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 174,\n\t\t\t\t\t\t\t\t\t\"top\": 535,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7Osjo4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 159,\n\t\t\t\t\t\t\t\t\t\"top\": 535,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7Ot5wI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOmRco=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 203,\n\t\t\t\t\t\t\t\t\t\"top\": 536,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7Oup18=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOnTL8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 171,\n\t\t\t\t\t\t\t\t\t\"top\": 686,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7OvGVc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOnTL8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 158,\n\t\t\t\t\t\t\t\t\t\"top\": 684,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7OwbLo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOnTL8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 198,\n\t\t\t\t\t\t\t\t\t\"top\": 691,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7Ox7vM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOo1Sw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 176,\n\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7OyZWo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOo1Sw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 163,\n\t\t\t\t\t\t\t\t\t\"top\": 386,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7Oz/6g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOo1Sw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 204,\n\t\t\t\t\t\t\t\t\t\"top\": 380,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7O0MlY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOnTL8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHH8A7O1Xbs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOqILQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8ArOo1Sw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"186:719;192:365\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7OrREk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7Osjo4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7Ot5wI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7Oup18=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7OvGVc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7OwbLo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7Ox7vM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7OyZWo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7Oz/6g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7O0MlY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHH8A7O1Xbs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QajbM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QbkGo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 241,\n\t\t\t\t\t\t\t\t\t\"top\": 540,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7Qc74o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 227,\n\t\t\t\t\t\t\t\t\t\"top\": 545,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QdBnw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QWc3M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 270,\n\t\t\t\t\t\t\t\t\t\"top\": 531,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7Qe1Gc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QXMuA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 290,\n\t\t\t\t\t\t\t\t\t\"top\": 692,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QfrTw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QXMuA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 277,\n\t\t\t\t\t\t\t\t\t\"top\": 694,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7Qgqbs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QXMuA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 318,\n\t\t\t\t\t\t\t\t\t\"top\": 688,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QhuXs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QYUYc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 192,\n\t\t\t\t\t\t\t\t\t\"top\": 388,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7Qi9mo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QYUYc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 180,\n\t\t\t\t\t\t\t\t\t\"top\": 394,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QjFDA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QYUYc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 217,\n\t\t\t\t\t\t\t\t\t\"top\": 375,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7Qk84c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QXMuA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIBi7QlFM0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QajbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QYUYc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 216,\n\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"313:719;199:365\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QbkGo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7Qc74o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QdBnw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7Qe1Gc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QfrTw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7Qgqbs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QhuXs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7Qi9mo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QjFDA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7Qk84c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIBi7QlFM0=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVkrSZV7o=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVkrSaF+0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 495,\n\t\t\t\t\t\t\t\t\t\"top\": 369,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7SbH/k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 494,\n\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7Scx/Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSVUkA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 496,\n\t\t\t\t\t\t\t\t\t\"top\": 340,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7SdTU4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSW4DQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 708,\n\t\t\t\t\t\t\t\t\t\"top\": 384,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7SeMd0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSW4DQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 397,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7SfyGM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSW4DQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 714,\n\t\t\t\t\t\t\t\t\t\"top\": 357,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7Sg/fk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSXJ+E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 282,\n\t\t\t\t\t\t\t\t\t\"top\": 356,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7ShD8g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSXJ+E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 284,\n\t\t\t\t\t\t\t\t\t\"top\": 370,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7Sire8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSXJ+E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 328,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7Sj3tE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSW4DQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIVk7Sk1LE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSZV7o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSXJ+E=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -96,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"735:377;258:346\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVkrSaF+0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7SbH/k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7Scx/Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7SdTU4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7SeMd0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7SfyGM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7Sg/fk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7ShD8g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7Sire8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7Sj3tE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIVk7Sk1LE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIq0rUlOjs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUjTho=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIq0rUm3rI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUjTho=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 203,\n\t\t\t\t\t\t\t\t\t\"top\": 536,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIq0rUngO0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUjTho=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 218,\n\t\t\t\t\t\t\t\t\t\"top\": 536,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIq0rUoxCM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUjTho=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 174,\n\t\t\t\t\t\t\t\t\t\"top\": 535,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUlOjs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"192:365;186:719\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUm3rI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUngO0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIq0rUoxCM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIvk7WQ8Us=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvkrWOA8M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIvk7WRdTY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvkrWOA8M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 270,\n\t\t\t\t\t\t\t\t\t\"top\": 531,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIvk7WSxiM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvkrWOA8M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 284,\n\t\t\t\t\t\t\t\t\t\"top\": 526,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHIvk7WTBUE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvkrWOA8M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 241,\n\t\t\t\t\t\t\t\t\t\"top\": 540,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WQ8Us=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"199:365;313:719\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WRdTY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WSxiM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHIvk7WTBUE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHI0w7X7vM0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X5fe0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHI0w7X8Thg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X5fe0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 497,\n\t\t\t\t\t\t\t\t\t\"top\": 340,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHI0w7X9S8I=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X5fe0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 498,\n\t\t\t\t\t\t\t\t\t\"top\": 325,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHI0w7X+22E=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X5fe0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 494,\n\t\t\t\t\t\t\t\t\t\"top\": 369,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X7vM0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFytbpcOd/U=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"258:346;735:377\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X8Thg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X9S8I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHI0w7X+22E=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLAssociationView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPL12RiI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPL13yWY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 234,\n\t\t\t\t\t\t\t\t\t\"top\": 287,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPL14FxE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 225,\n\t\t\t\t\t\t\t\t\t\"top\": 275,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb15dxE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71y8uU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 251,\n\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb16DB8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71zxWo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 237,\n\t\t\t\t\t\t\t\t\t\"top\": 285,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb17wzI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71zxWo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 231,\n\t\t\t\t\t\t\t\t\t\"top\": 273,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb18Uwg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71zxWo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 249,\n\t\t\t\t\t\t\t\t\t\"top\": 310,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 2,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb19bus=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO710h4k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 231,\n\t\t\t\t\t\t\t\t\t\"top\": 290,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb1+CzE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO710h4k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 221,\n\t\t\t\t\t\t\t\t\t\"top\": 280,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -0.7853981633974483,\n\t\t\t\t\t\t\t\t\t\"distance\": 40,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb1/BVk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO710h4k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 250,\n\t\t\t\t\t\t\t\t\t\"top\": 309,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 0.5235987755982988,\n\t\t\t\t\t\t\t\t\t\"distance\": 25,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 0,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb2ABmk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO71zxWo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -80,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLQualifierCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHKsPb2BlHI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL12RiI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsO710h4k=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": -80,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"225:319;261:293\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL13yWY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPL14FxE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb15dxE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"tailRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb16DB8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb17wzI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb18Uwg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headRoleNameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb19bus=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headPropertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb1+CzE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headMultiplicityLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb1/BVk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tailQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb2ABmk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"headQualifiersCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHKsPb2BlHI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHK6E74R1Ec=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74POAA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHK6E74SvC4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74POAA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 251,\n\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHK6FL4Tpuw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74POAA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 260,\n\t\t\t\t\t\t\t\t\t\"top\": 324,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHK6FL4Ueb4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74POAA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 234,\n\t\t\t\t\t\t\t\t\t\"top\": 287,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74R1Ec=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFzB0pg0a44=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"261:293;225:319\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6E74SvC4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6FL4Tpuw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHK6FL4Ueb4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHSf7cWURUk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7MWSFj4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHSf7cWVggM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7MWSFj4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 453,\n\t\t\t\t\t\t\t\t\t\"top\": 516,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHSf7cWW5yo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7MWSFj4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 466,\n\t\t\t\t\t\t\t\t\t\"top\": 509,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHHSf7cWXNhk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7MWSFj4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 426,\n\t\t\t\t\t\t\t\t\t\"top\": 531,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWURUk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XaFCtvY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy/tZgLHvQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"307:293;574:767\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWVggM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWW5yo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHHSf7cWXNhk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipVtjM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipWjY4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipXk+w=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipWjY4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -244,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 928,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipYmSQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipWjY4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 637,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 775,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"rectangle.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipZ+XA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipWjY4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -244,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 928,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipatsE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipWjY4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -244,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 928,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 768,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipXk+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipYmSQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipZ+XA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipatsE=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipbZ/0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 793,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYipcT0k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\t\t\"top\": 803,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYypdFNI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -254,\n\t\t\t\t\t\t\t\t\t\"top\": 724,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswZnYypeYYs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipVtjM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -254,\n\t\t\t\t\t\t\t\t\t\"top\": 724,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 632,\n\t\t\t\t\t\t\t\"top\": 768,\n\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipWjY4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipbZ/0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYipcT0k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYypdFNI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswZnYypeYYs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc3RwA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc4C3A=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc5kUI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc4C3A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -616,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 544,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc6THM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc4C3A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 253,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 799,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 134,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"resizeAndMergeBase\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc7p48=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc4C3A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -616,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 544,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbZc8l9I=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc4C3A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -616,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 544,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 792,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc5kUI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc6THM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc7p48=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc8l9I=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbpc9Q/A=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 817,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbpc+c/o=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 827,\n\t\t\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbpc/wXI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -520,\n\t\t\t\t\t\t\t\t\t\"top\": 400,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFyvbpdAAyo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc3RwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc1D+I=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -520,\n\t\t\t\t\t\t\t\t\t\"top\": 400,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\"top\": 792,\n\t\t\t\t\t\t\t\"width\": 144,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbZc4C3A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbpc9Q/A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbpc+c/o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbpc/wXI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFyvbpdAAyo=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FZeQTuQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeRMeY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeSFbU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeRMeY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -960,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeTkoY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeRMeY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 253,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 727,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 136,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"resizeAndMergeCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeUTNc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeRMeY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -960,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeVlXs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeRMeY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -960,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 392,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 720,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeSFbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeTkoY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeUTNc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeVlXs=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeWkb8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 745,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeXKZk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\t\t\"top\": 755,\n\t\t\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4FpeYWpw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -696,\n\t\t\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy4F5eZQQc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeQTuQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FZeOtro=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -696,\n\t\t\t\t\t\t\t\t\t\"top\": 320,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 248,\n\t\t\t\t\t\t\t\"top\": 720,\n\t\t\t\t\t\t\t\"width\": 146,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeRMeY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeWkb8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeXKZk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4FpeYWpw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy4F5eZQQc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rZe5yb0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe6V8M=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe70Ts=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe6V8M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe8JrM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe6V8M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 161,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 799,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 57,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"nmsBase\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe9fX8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe6V8M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe+Aic=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe6V8M=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 288,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 156,\n\t\t\t\t\t\t\t\t\t\"top\": 792,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe70Ts=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe8JrM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe9fX8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe+Aic=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpe/fWU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 156,\n\t\t\t\t\t\t\t\t\t\"top\": 817,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpfAyfc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 156,\n\t\t\t\t\t\t\t\t\t\"top\": 827,\n\t\t\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpfBpkI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -192,\n\t\t\t\t\t\t\t\t\t\"top\": 272,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy7rpfC4aM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe5yb0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rZe3LU0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -192,\n\t\t\t\t\t\t\t\t\t\"top\": 272,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 156,\n\t\t\t\t\t\t\t\"top\": 792,\n\t\t\t\t\t\t\t\"width\": 67,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe6V8M=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpe/fWU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpfAyfc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpfBpkI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy7rpfC4aM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95Zfi54c=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHDdYEV2Qawk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfjA10=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfk5rs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfjA10=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pflDeI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfjA10=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 157,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 727,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 59,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"nmsCaffe\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfmtA4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfjA10=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfnV80=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfjA10=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -744,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 56,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\"top\": 720,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfk5rs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pflDeI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfmtA4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfnV80=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfogx8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\"top\": 745,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfpvIw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\"top\": 755,\n\t\t\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfqAaA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -540,\n\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHFy95pfr/Ks=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfi54c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95Zfg+a8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -540,\n\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJip6EoNT0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\"top\": 720,\n\t\t\t\t\t\t\t\"width\": 69,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfjA10=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfogx8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfpvIw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfqAaA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHFy95pfr/Ks=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"_type\": \"UMLClassDiagram\",\n\t\t\t\t\t\"_id\": \"AAAAAAFbHImRMcuZ6y8=\",\n\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\"$ref\": \"AAAAAAFF+qBWK6M3Z8Y=\"\n\t\t\t\t\t},\n\t\t\t\t\t\"name\": \"utilities\",\n\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackage\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVcvEP2c=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"name\": \"utilities\",\n\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01c4qGfA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"pointerContainer.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dM5Tzpk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"macros.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8c2vnbk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"fastMath.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kyic4BM68=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"Class12\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWc2GeKg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"string\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Lrs9H3Qto=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncc00FC4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"profiler\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4BsD9FeWAY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4CBE9Fv0d4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWc1dlR0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"fileSystem\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Gy7dHE1fY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOcziMM4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cuda.hu\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQcy5iag=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"openCv\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E09tGR0l4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E6fdGi9bg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEc0Lyxc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"enumClasses.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdscyQvqc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"errorAndLog\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4ING9HmZX0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxnJbU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"cuda\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Fr9NGzad4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXxMw+M4c=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"check.hpp\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Hu1NHV2CI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgc3Y4Vk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLClass\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO76bJsmb4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"name\": \"keypoint\",\n\t\t\t\t\t\t\t\t\t\"ownedElements\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPht7KYSAs=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPmlrKpfyc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswRgfbSHUnE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"UMLDependency\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswYObrTJy5s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visibility\": \"public\",\n\t\t\t\t\t\t\t\t\t\"isAbstract\": false,\n\t\t\t\t\t\t\t\t\t\"isFinalSpecialization\": false,\n\t\t\t\t\t\t\t\t\t\"isLeaf\": false,\n\t\t\t\t\t\t\t\t\t\"isActive\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visibility\": \"public\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\"defaultDiagram\": false,\n\t\t\t\t\t\"ownedViews\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVcvGkAM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVsvHUjA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvEP2c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVsvIu8A=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvHUjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVsvJ7wA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvHUjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 22,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 663,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"utilities\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVsvKUOk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvHUjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbHInAVsvLLGo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvHUjA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -288,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\t\t\"top\": 15,\n\t\t\t\t\t\t\t\t\t\"width\": 673,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvIu8A=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvJ7wA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvKUOk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvLLGo=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 0,\n\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\"width\": 673,\n\t\t\t\t\t\t\t\"height\": 417,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVsvHUjA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01c4swqY=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4tOrE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4u+5Q=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4tOrE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -368,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4vnZw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4tOrE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 373,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 135,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"pointerContainer.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4wkug=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4tOrE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -368,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4xtAc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4tOrE=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -368,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 368,\n\t\t\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\t\t\"width\": 145,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4u+5Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4vnZw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4wkug=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4xtAc=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4yQdo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 368,\n\t\t\t\t\t\t\t\t\t\"top\": 361,\n\t\t\t\t\t\t\t\t\t\"width\": 145,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s4zOB0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 368,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 145,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s400Zk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 328,\n\t\t\t\t\t\t\t\t\t\"top\": -224,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K01s41rLU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4qGfA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 328,\n\t\t\t\t\t\t\t\t\t\"top\": -224,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 368,\n\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\"width\": 145,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4tOrE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4yQdo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s4zOB0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s400Zk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01s41rLU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5VSwA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5WSt4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5X3Q8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5WSt4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 360,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5YIww=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5WSt4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 533,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 74,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"macros.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5ZFOY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5WSt4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 360,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5a6Mg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5WSt4=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 360,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 528,\n\t\t\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\t\t\"width\": 84,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5X3Q8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5YIww=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5ZFOY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5a6Mg=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5b8Z0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 528,\n\t\t\t\t\t\t\t\t\t\"top\": 361,\n\t\t\t\t\t\t\t\t\t\"width\": 84,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2dc5cwkQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 528,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 84,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2ds5dEyY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1K2ds5e3eI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dM5Tzpk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": -184,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 528,\n\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\"width\": 84,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5WSt4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5b8Z0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5cwkQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2ds5dEyY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2ds5e3eI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s2xHTc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s2yIEA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s2zPBw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2yIEA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s20FrI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2yIEA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 269,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 81,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"fastMath.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s21Q+w=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2yIEA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8s22MnU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2yIEA=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -200,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\t\t\"width\": 91,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2zPBw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s20FrI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s21Q+w=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s22MnU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8823brw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 361,\n\t\t\t\t\t\t\t\t\t\"width\": 91,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8824w58=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 91,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku88255K4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\"top\": -136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Ku8826veA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8c2vnbk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\"top\": -136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\"width\": 91,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2yIEA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8823brw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8824w58=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku88255K4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8826veA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2IQv0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2JULk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2KKQY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2JULk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -664,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2Lzt0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2JULk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 237,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 40,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2MG94=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2JULk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -664,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2N77s=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2JULk=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -664,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2KKQY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2Lzt0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2MG94=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2N77s=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2OxRg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2PXAg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2QN9w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -264,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KrWs2RYAs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWc2GeKg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -264,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2JULk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2OxRg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2PXAg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2QN9w=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2RYAs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncc02gVk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs03gFU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs04bDY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs03gFU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 904,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs05CB0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs03gFU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 485,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 46,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"profiler\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs06ibk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs03gFU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 904,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs07GGE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs03gFU=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 904,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 480,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 56,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs04bDY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs05CB0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs06ibk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs07GGE=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs088O0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 480,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 56,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs09XXQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 480,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 56,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs0+jHg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 616,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kncs0/RWM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc00FC4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 616,\n\t\t\t\t\t\t\t\t\t\"top\": -104,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 480,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 56,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs03gFU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs088O0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs09XXQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs0+jHg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncs0/RWM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWc1fkwU=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWc1g2ts=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWc1hB04=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1g2ts=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1iAvo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1g2ts=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 325,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 66,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"fileSystem\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1jDbM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1g2ts=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1ka5Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1g2ts=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 152,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -248,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 76,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1hB04=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1iAvo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1jDbM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1ka5Y=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1l/fg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 76,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1m9eg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 76,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1nI70=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KpWs1ozx4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1dlR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 224,\n\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 320,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 76,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1g2ts=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1l/fg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1m9eg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1nI70=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWs1ozx4=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOczkikk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOczlmqY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszmAhY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczlmqY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOsznFaQ=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczlmqY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 37,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 51,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cuda.hu\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszo2ZY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczlmqY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszpCoA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczlmqY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -344,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszmAhY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOsznFaQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszo2ZY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszpCoA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszqmag=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 361,\n\t\t\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszr+l4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOszscnw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KjOsztBoE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczkikk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOcziMM4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\"top\": 136,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOczlmqY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszqmag=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszr+l4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOszscnw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KjOsztBoE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQcy7aPg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQcy8sZI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQcy9Ub8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy8sZI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQsy+VSE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy8sZI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 413,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 48,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"openCv\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQsy/1Dw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy8sZI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQszAxeA=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy8sZI=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 680,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy9Ub8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQsy+VSE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQsy/1Dw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQszAxeA=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQszBvuw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQszCmpw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQszDaqk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\t\t\"top\": 24,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KhQszEXgU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy5iag=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 520,\n\t\t\t\t\t\t\t\t\t\"top\": 24,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 408,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 58,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy8sZI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQszBvuw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQszCmpw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQszDaqk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQszEXgU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEc0N0+0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0Oktw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0PWMc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Oktw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -736,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0Qdfk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Oktw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 125,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 343,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 111,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"enumClasses.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0RMAk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Oktw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -736,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0SehU=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Oktw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -736,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 312,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0PWMc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Qdfk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0RMAk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0SehU=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0Tmvs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 361,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0UIgM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\t\t\"top\": 371,\n\t\t\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0VZm8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -312,\n\t\t\t\t\t\t\t\t\t\"top\": 144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KlEs0WULQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0Lyxc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -312,\n\t\t\t\t\t\t\t\t\t\"top\": 144,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 120,\n\t\t\t\t\t\t\t\"top\": 336,\n\t\t\t\t\t\t\t\"width\": 121,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Oktw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0Tmvs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0UIgM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0VZm8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEs0WULQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdscySwQk=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdscyT+vw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyUZ6M=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyT+vw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyVOFw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyT+vw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 237,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 263,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 80,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"errorAndLog\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyW6es=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyT+vw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyXkAM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyT+vw=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -328,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 416,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\t\t\"width\": 90,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyUZ6M=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyVOFw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyW6es=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyXkAM=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyYCdk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 281,\n\t\t\t\t\t\t\t\t\t\"width\": 90,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KdssyZccY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\t\t\"top\": 291,\n\t\t\t\t\t\t\t\t\t\"width\": 90,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kdssyakz4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -48,\n\t\t\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kdssyb1+w=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyQvqc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -48,\n\t\t\t\t\t\t\t\t\t\"top\": 240,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 232,\n\t\t\t\t\t\t\t\"top\": 256,\n\t\t\t\t\t\t\t\"width\": 90,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscyT+vw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyYCdk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdssyZccY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kdssyakz4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kdssyb1+w=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxpeN0=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxqp8A=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxrrSo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxqp8A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxsPz8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxqp8A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 141,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 40,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"cuda\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxtygM=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxqp8A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxu1XY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxqp8A=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -112,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxrrSo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxsPz8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxtygM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxu1XY=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxvqPk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarMxwU/Y=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarcxxIy8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 64,\n\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KarcxymOo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxnJbU=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 64,\n\t\t\t\t\t\t\t\t\t\"top\": 128,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 136,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 50,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxqp8A=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxvqPk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxwU/Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarcxxIy8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarcxymOo=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXx8xAegg=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXx8xBHCg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXyMxCMr8=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xBHCg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 184,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXyMxDUz4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xBHCg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 37,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 65,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"check.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXyMxEMW0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xBHCg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 184,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXyMxFJIo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xBHCg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -32,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 184,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXyMxCMr8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXyMxDUz4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXyMxEMW0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXyMxFJIo=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXyMxGVe4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXycxHW14=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXycxIQTQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\"top\": 120,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1KXycxJfUY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXxMw+M4c=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 128,\n\t\t\t\t\t\t\t\t\t\"top\": 120,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 32,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 75,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xBHCg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXyMxGVe4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXycxHW14=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXycxIQTQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXycxJfUY=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3av4U=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3b5Ko=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3cEHY=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3b5Ko=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3dciw=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3b5Ko=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 45,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 71,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 79,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"headers.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3eO0Q=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3b5Ko=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3f4dg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3b5Ko=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -384,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -704,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 64,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3cEHY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3dciw=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3eO0Q=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3f4dg=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3gldc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 89,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3hYiQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\t\t\"top\": 99,\n\t\t\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3iFWs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": -384,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH1Kwgs3jwjk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3av4U=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgc3Y4Vk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": -384,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 40,\n\t\t\t\t\t\t\t\"top\": 64,\n\t\t\t\t\t\t\t\"width\": 89,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3b5Ko=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3gldc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3hYiQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3iFWs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kwgs3jwjk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4BsENFgLzs=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsD9FeWAY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4BsENFhdlY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsD9FeWAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 552,\n\t\t\t\t\t\t\t\t\t\"top\": 255,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4BsENFiNmE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsD9FeWAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 566,\n\t\t\t\t\t\t\t\t\t\"top\": 250,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4BsEdFjFAA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsD9FeWAY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 523,\n\t\t\t\t\t\t\t\t\t\"top\": 264,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFgLzs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K2dc5VSwA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"515:197;561:335\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFhdlY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsENFiNmE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4BsEdFjFAA=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4CBE9FxtfM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9Fv0d4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4CBE9FyVXY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9Fv0d4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 406,\n\t\t\t\t\t\t\t\t\t\"top\": 229,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4CBE9Fzf68=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9Fv0d4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 412,\n\t\t\t\t\t\t\t\t\t\"top\": 243,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4CBE9F0nnM=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9Fv0d4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 393,\n\t\t\t\t\t\t\t\t\t\"top\": 202,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FxtfM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Kncc02gVk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"479:187;322:257\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9FyVXY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9Fzf68=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4CBE9F0nnM=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E0+NGTP+8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E09tGR0l4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E0+NGUMlE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E09tGR0l4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 384,\n\t\t\t\t\t\t\t\t\t\"top\": 268,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E0+dGV+Ow=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E09tGR0l4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 396,\n\t\t\t\t\t\t\t\t\t\"top\": 276,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E0+dGWcts=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E09tGR0l4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 359,\n\t\t\t\t\t\t\t\t\t\"top\": 251,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGTP+8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1Ku8s2xHTc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"420:197;325:335\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+NGUMlE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+dGV+Ow=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E0+dGWcts=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E6fdGklB8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGi9bg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E6fdGlbKw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGi9bg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 367,\n\t\t\t\t\t\t\t\t\t\"top\": 230,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E6ftGmO7g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGi9bg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 375,\n\t\t\t\t\t\t\t\t\t\"top\": 243,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4E6ftGnFJI=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGi9bg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 350,\n\t\t\t\t\t\t\t\t\t\"top\": 205,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGklB8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KhQcy7aPg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"407:193;311:255\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6fdGlbKw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6ftGmO7g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4E6ftGnFJI=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Fr9NG1RIQ=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NGzad4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Fr9dG2390=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NGzad4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 228,\n\t\t\t\t\t\t\t\t\t\"top\": 208,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Fr9dG3O08=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NGzad4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 238,\n\t\t\t\t\t\t\t\t\t\"top\": 197,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Fr9dG4NUk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NGzad4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 207,\n\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9NG1RIQ=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KarMxpeN0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"186:197;250:255\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9dG2390=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9dG3O08=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Fr9dG4NUk=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Gy7dHGzzo=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHE1fY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Gy7dHHlHQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHE1fY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 327,\n\t\t\t\t\t\t\t\t\t\"top\": 229,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Gy7dHIT5k=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHE1fY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 339,\n\t\t\t\t\t\t\t\t\t\"top\": 238,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Gy7dHJKCc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHE1fY=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 304,\n\t\t\t\t\t\t\t\t\t\"top\": 210,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHGzzo=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KpWc1fkwU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"339:197;294:255\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHHlHQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHIT5k=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Gy7dHJKCc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Hu1NHXdIA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHV2CI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Hu1NHYER0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHV2CI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 175,\n\t\t\t\t\t\t\t\t\t\"top\": 204,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Hu1dHZv38=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHV2CI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 182,\n\t\t\t\t\t\t\t\t\t\"top\": 191,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4Hu1dHaviE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHV2CI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 162,\n\t\t\t\t\t\t\t\t\t\"top\": 231,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHXdIA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KXx8xAegg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"107:193;231:255\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1NHYER0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1dHZv38=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Hu1dHaviE=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4INHNHo6s4=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4ING9HmZX0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4INHNHpeYU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4ING9HmZX0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 237,\n\t\t\t\t\t\t\t\t\t\"top\": 323,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4INHNHq3gY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4ING9HmZX0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 247,\n\t\t\t\t\t\t\t\t\t\"top\": 334,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4INHNHrebU=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4ING9HmZX0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 218,\n\t\t\t\t\t\t\t\t\t\"top\": 300,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHo6s4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KlEc0N0+0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"248:301;208:335\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHpeYU=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHq3gY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4INHNHrebU=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4LrtNH5rUE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Lrs9H3Qto=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4LrtNH66bA=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Lrs9H3Qto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 280,\n\t\t\t\t\t\t\t\t\t\"top\": 216,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4LrtNH7PTw=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Lrs9H3Qto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 295,\n\t\t\t\t\t\t\t\t\t\"top\": 213,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFbH4LrtNH89TQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4Lrs9H3Qto=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 251,\n\t\t\t\t\t\t\t\t\t\"top\": 223,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH5rUE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KrWs2IQv0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"260:197;272:255\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH66bA=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH7PTw=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH4LrtNH89TQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO767JuzTE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO767Jv7cY=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77LJwV44=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767Jv7cY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77LJxhXE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767Jv7cY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 589,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 159,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 54,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"keypoint\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77LJyqRc=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767Jv7cY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 78,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from utilities)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77LJz4mI=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767Jv7cY=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 208,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -144,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\t\t\"width\": 64,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77LJwV44=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77LJxhXE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77LJyqRc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77LJz4mI=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77LJ0Um8=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 177,\n\t\t\t\t\t\t\t\t\t\"width\": 64,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77bJ1zqg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\t\t\"top\": 187,\n\t\t\t\t\t\t\t\t\t\"width\": 64,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77bJ2ZoE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 104,\n\t\t\t\t\t\t\t\t\t\"top\": -120,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswO77bJ3Yfc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO76bJsmb4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 104,\n\t\t\t\t\t\t\t\t\t\"top\": -120,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHInAVcvGkAM=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 584,\n\t\t\t\t\t\t\t\"top\": 152,\n\t\t\t\t\t\t\t\"width\": 64,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767Jv7cY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77LJ0Um8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77bJ1zqg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77bJ2ZoE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO77bJ3Yfc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPht7KaXPM=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KYSAs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPhuLKbI0g=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KYSAs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 456,\n\t\t\t\t\t\t\t\t\t\"top\": 232,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPhuLKcUrE=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KYSAs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 460,\n\t\t\t\t\t\t\t\t\t\"top\": 246,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPhuLKdcZs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KYSAs=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 447,\n\t\t\t\t\t\t\t\t\t\"top\": 203,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPht7KaXPM=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1KdscySwQk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"583:184;322:264\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPhuLKbI0g=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPhuLKcUrE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPhuLKdcZs=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPmlrKrC/8=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKpfyc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPmmLKswyg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKpfyc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 537,\n\t\t\t\t\t\t\t\t\t\"top\": 270,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPmmLKtd10=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKpfyc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 548,\n\t\t\t\t\t\t\t\t\t\"top\": 280,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswPmmLKutEc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKpfyc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 516,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmlrKrC/8=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbH1K01c4swqY=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"593:197;462:335\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmmLKswyg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmmLKtd10=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswPmmLKutEc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLPackageView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMiotLBc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyoufrg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMiotLBc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJipqEm58o=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyovxio=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoufrg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 684,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyowDWk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoufrg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 697,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 246,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 191,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"core\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyoxlOg=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoufrg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 684,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from pose)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyoy7m4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoufrg=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 684,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1352,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 692,\n\t\t\t\t\t\t\t\t\t\"top\": 239,\n\t\t\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyovxio=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyowDWk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoxlOg=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoy7m4=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containedViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#e2e2e2\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 692,\n\t\t\t\t\t\t\t\"top\": 224,\n\t\t\t\t\t\t\t\"width\": 201,\n\t\t\t\t\t\t\t\"height\": 160,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyoufrg=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyozWzc=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyo0nco=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyo12jk=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo0nco=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 420,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsMyo2Jk4=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo0nco=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 709,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 303,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 61,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"array.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo3wc0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo0nco=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 420,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo4KUo=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo0nco=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 420,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -1304,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo12jk=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo2Jk4=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo3wc0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo4KUo=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo59gQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 321,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo62r0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\t\t\"top\": 331,\n\t\t\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo7VEo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": -656,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswQsNCo8cwg=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHGJ4XKFAf+Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 264,\n\t\t\t\t\t\t\t\t\t\"top\": -656,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMiotLBc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 704,\n\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\"width\": 71,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyo0nco=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo59gQ=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo62r0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo7VEo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsNCo8cwg=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswRgfrSJFJE=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfbSHUnE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswRgfrSKZRk=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfbSHUnE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 688,\n\t\t\t\t\t\t\t\t\t\"top\": 230,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswRgfrSLYpo=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfbSHUnE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 699,\n\t\t\t\t\t\t\t\t\t\"top\": 220,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswRgfrSM3LQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfbSHUnE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 665,\n\t\t\t\t\t\t\t\t\t\"top\": 249,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSJFJE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMyozWzc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"635:197;719:295\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSKZRk=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSLYpo=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswRgfrSM3LQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLClassView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRobSeQTI=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLNameCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRobSflPc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRorSg5C0=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSflPc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -64,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRorShg3Y=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSflPc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;1\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": 789,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": 303,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 88,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"rectangle.hpp\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRorSiCCE=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSflPc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -64,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 72,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"text\": \"(from core)\",\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\"_type\": \"LabelView\",\n\t\t\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRorSj40E=\",\n\t\t\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSflPc=\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"left\": -64,\n\t\t\t\t\t\t\t\t\t\t\t\"top\": -24,\n\t\t\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 1,\n\t\t\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 25,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRorSg5C0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRorShg3Y=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"namespaceLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRorSiCCE=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRorSj40E=\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLAttributeCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRorSkfOs=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 321,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLOperationCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRo7Sl4M0=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\t\t\"top\": 331,\n\t\t\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLReceptionCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRo7SmR9Q=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"UMLTemplateParameterCompartmentView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswXRpLSn0qc=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRoLSckR0=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": -56,\n\t\t\t\t\t\t\t\t\t\"top\": 0,\n\t\t\t\t\t\t\t\t\t\"width\": 10,\n\t\t\t\t\t\t\t\t\t\"height\": 10,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"containerView\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswQsMiotLBc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": true,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"left\": 784,\n\t\t\t\t\t\t\t\"top\": 296,\n\t\t\t\t\t\t\t\"width\": 98,\n\t\t\t\t\t\t\t\"height\": 45,\n\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showNamespace\": false,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"showType\": true,\n\t\t\t\t\t\t\t\"nameCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSflPc=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"wordWrap\": false,\n\t\t\t\t\t\t\t\"suppressAttributes\": false,\n\t\t\t\t\t\t\t\"suppressOperations\": false,\n\t\t\t\t\t\t\t\"suppressReceptions\": true,\n\t\t\t\t\t\t\t\"showMultiplicity\": true,\n\t\t\t\t\t\t\t\"showOperationSignature\": true,\n\t\t\t\t\t\t\t\"attributeCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRorSkfOs=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operationCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRo7Sl4M0=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"receptionCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRo7SmR9Q=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"templateParameterCompartment\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRpLSn0qc=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"_type\": \"UMLDependencyView\",\n\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswYOb7TLOOA=\",\n\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFbHImRMcuZ6y8=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYObrTJy5s=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"subViews\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswYOb7TMUQ4=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYObrTJy5s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 730,\n\t\t\t\t\t\t\t\t\t\"top\": 226,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswYOcLTN/Ro=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYObrTJy5s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": null,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 738,\n\t\t\t\t\t\t\t\t\t\"top\": 214,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": 1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 30,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"_type\": \"EdgeLabelView\",\n\t\t\t\t\t\t\t\t\t\"_id\": \"AAAAAAFcswYOcLTOwQQ=\",\n\t\t\t\t\t\t\t\t\t\"_parent\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"model\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYObrTJy5s=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"visible\": false,\n\t\t\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\t\t\"left\": 713,\n\t\t\t\t\t\t\t\t\t\"top\": 251,\n\t\t\t\t\t\t\t\t\t\"width\": 0,\n\t\t\t\t\t\t\t\t\t\"height\": 13,\n\t\t\t\t\t\t\t\t\t\"autoResize\": false,\n\t\t\t\t\t\t\t\t\t\"alpha\": -1.5707963267948966,\n\t\t\t\t\t\t\t\t\t\"distance\": 15,\n\t\t\t\t\t\t\t\t\t\"hostEdge\": {\n\t\t\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TLOOA=\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"edgePosition\": 1,\n\t\t\t\t\t\t\t\t\t\"underline\": false,\n\t\t\t\t\t\t\t\t\t\"horizontalAlignment\": 2,\n\t\t\t\t\t\t\t\t\t\"verticalAlignment\": 5,\n\t\t\t\t\t\t\t\t\t\"wordWrap\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"visible\": true,\n\t\t\t\t\t\t\t\"enabled\": true,\n\t\t\t\t\t\t\t\"lineColor\": \"#000000\",\n\t\t\t\t\t\t\t\"fillColor\": \"#ffffff\",\n\t\t\t\t\t\t\t\"fontColor\": \"#000000\",\n\t\t\t\t\t\t\t\"font\": \"Arial;13;0\",\n\t\t\t\t\t\t\t\"showShadow\": true,\n\t\t\t\t\t\t\t\"containerChangeable\": false,\n\t\t\t\t\t\t\t\"containerExtending\": false,\n\t\t\t\t\t\t\t\"head\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswXRobSeQTI=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tail\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswO767JuzTE=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"lineStyle\": 1,\n\t\t\t\t\t\t\t\"points\": \"648:196;797:295\",\n\t\t\t\t\t\t\t\"stereotypeDisplay\": \"label\",\n\t\t\t\t\t\t\t\"showVisibility\": true,\n\t\t\t\t\t\t\t\"showProperty\": true,\n\t\t\t\t\t\t\t\"nameLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOb7TMUQ4=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"stereotypeLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOcLTN/Ro=\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"propertyLabel\": {\n\t\t\t\t\t\t\t\t\"$ref\": \"AAAAAAFcswYOcLTOwQQ=\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"visibility\": \"public\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "examples/CMakeLists.txt",
    "content": "add_subdirectory(calibration)\r\nadd_subdirectory(deprecated)\r\nadd_subdirectory(openpose)\r\nadd_subdirectory(tutorial_api_cpp)\r\nadd_subdirectory(tutorial_api_python)\r\nadd_subdirectory(user_code)\r\nif (UNIX OR APPLE)\r\n  add_subdirectory(tests)\r\nendif (UNIX OR APPLE)\r\n"
  },
  {
    "path": "examples/calibration/CMakeLists.txt",
    "content": "set(EXAMPLE_FILES\n    calibration.cpp)\n\nforeach(EXAMPLE_FILE ${EXAMPLE_FILES})\n\n  get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)\n\n  if (UNIX OR APPLE)\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\n  elseif (WIN32)\n    set(EXE_NAME \"Calibration\")\n  endif ()\n\n  message(STATUS \"Adding Example ${EXE_NAME}\")\n  add_executable(${EXE_NAME} ${EXAMPLE_FILE})\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\n\n  if (WIN32)\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"Examples\")\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${CL}.vcxproj.user\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\n    # Properties->General->Output Directory\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  endif (WIN32)\n\nendforeach()\n"
  },
  {
    "path": "examples/calibration/calibration.cpp",
    "content": "// ------------------------- OpenPose Calibration Toolbox -------------------------\n// Check `doc/advanced/calibration_module.md`.\n// Implemented on top of OpenCV.\n// It computes and saves the intrinsics parameters of the input images.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Calibration\nDEFINE_int32(mode,                      1,              \"Select 1 for intrinsic camera parameter calibration, 2 for extrinsic calibration.\");\nDEFINE_string(calibration_image_dir,    \"images/intrinsics/\", \"Directory where the images for camera parameter calibration are placed.\");\nDEFINE_double(grid_square_size_mm,      127.0,          \"Chessboard square length (in millimeters).\");\nDEFINE_string(grid_number_inner_corners,\"9x6\",          \"Number of inner corners in width and height, i.e., number of total squares in width\"\n                                                        \" and height minus 1.\");\n// Mode 1 - Intrinsics\nDEFINE_string(camera_serial_number,     \"18079958\",     \"Camera serial number.\");\n// Mode 2 - Extrinsics\nDEFINE_bool(omit_distortion,            false,          \"Set to true if image views are already undistorted (e.g., if recorded from OpenPose\"\n                                                        \" after intrinsic parameter calibration).\");\nDEFINE_bool(combine_cam0_extrinsics,    false,          \"Set to true if cam0 extrinsics are not [R=I, t=0]. I will make no effect if cam0 is\"\n                                                        \" already the origin. See doc/advanced/calibration_module.md for an example.\");\nDEFINE_int32(cam0,                      1,              \"Baseline camera for extrinsic calibration, cam1 will be calibrated assuming cam0 the\"\n                                                        \" world coordinate origin.\");\nDEFINE_int32(cam1,                      0,              \"Target camera to estimate its extrinsic parameters, it will be calibrated assuming cam0\"\n                                                        \" as the world coordinate origin.\");\n// Modes 3-4\nDEFINE_int32(number_cameras,            4,              \"Number of cameras (for mode 3-4).\");\n// Producer\nDEFINE_string(camera_parameter_folder,  \"models/cameraParameters/flir/\", \"String with the folder where the camera parameters are or will be\"\n                                                        \" located.\");\n\nint openPoseDemo()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose calibration toolbox...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n\n        // Common parameters\n        const auto gridInnerCorners = op::flagsToPoint(op::String(FLAGS_grid_number_inner_corners), \"12x7\");\n        const auto calibrationImageDir = op::formatAsDirectory(FLAGS_calibration_image_dir);\n        const auto gridSqureSizeMm = (float)FLAGS_grid_square_size_mm;\n\n        // Calibration - Intrinsics\n        if (FLAGS_mode == 1)\n        {\n            op::opLog(\"Running calibration (intrinsic parameters)...\", op::Priority::High);\n            // Parameters\n            // const auto flags = 0;                                                                   // 5 parameters\n            const auto flags = cv::CALIB_RATIONAL_MODEL;                                            // 8 parameters\n            // const auto flags = cv::CALIB_RATIONAL_MODEL | cv::CALIB_THIN_PRISM_MODEL;               // 12 parameters\n            // const auto flags = cv::CALIB_RATIONAL_MODEL | cv::CALIB_THIN_PRISM_MODEL | cv::CALIB_TILTED_MODEL; // 14\n            // const auto saveImagesWithCorners = false;\n            const auto saveImagesWithCorners = true;\n            // Run calibration\n            op::estimateAndSaveIntrinsics(\n                gridInnerCorners, gridSqureSizeMm, flags,\n                op::formatAsDirectory(FLAGS_camera_parameter_folder), calibrationImageDir, FLAGS_camera_serial_number,\n                saveImagesWithCorners);\n            op::opLog(\"Intrinsic calibration completed!\", op::Priority::High);\n        }\n\n        // Calibration - Extrinsics\n        else if (FLAGS_mode == 2)\n        {\n            op::opLog(\"Running calibration (extrinsic parameters)...\", op::Priority::High);\n            // Run calibration\n            op::estimateAndSaveExtrinsics(\n                FLAGS_camera_parameter_folder, calibrationImageDir, gridInnerCorners, gridSqureSizeMm,\n                FLAGS_cam0, FLAGS_cam1, FLAGS_omit_distortion, FLAGS_combine_cam0_extrinsics);\n            // Logging\n            op::opLog(\"Extrinsic calibration completed!\", op::Priority::High);\n        }\n\n        // Calibration - Extrinsics - Bundle Adjustment (BA)\n        else if (FLAGS_mode == 3)\n        {\n            op::opLog(\"Running calibration (bundle adjustment over extrinsic parameters)...\", op::Priority::High);\n            // Sanity check\n            if (!FLAGS_omit_distortion)\n                op::error(\"This mode assumes that the images are already undistorted (add flag `--omit_distortion`.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n            // Parameters\n            const auto saveImagesWithCorners = false;\n            // Run calibration\n            op::refineAndSaveExtrinsics(\n                FLAGS_camera_parameter_folder, calibrationImageDir, gridInnerCorners, gridSqureSizeMm,\n                FLAGS_number_cameras, FLAGS_omit_distortion, saveImagesWithCorners);\n            // Logging\n            op::opLog(\"Extrinsic calibration (bundle adjustment) completed!\", op::Priority::High);\n        }\n\n        // // Calibration - Extrinsics Refinement with Visual SFM\n        // else if (FLAGS_mode == 4)\n        // {\n        //     op::opLog(\"Running calibration (intrinsic parameters)...\", op::Priority::High);\n        //     // Obtain & save intrinsics\n        //     const auto saveImagesWithCorners = false;\n        //     // const auto saveImagesWithCorners = true;\n        //     // Run camera calibration code\n        //     op::estimateAndSaveSiftFile(\n        //         gridInnerCorners, calibrationImageDir, FLAGS_number_cameras, saveImagesWithCorners);\n        //     op::opLog(\"Intrinsic calibration completed!\", op::Priority::High);\n        // }\n\n        else\n            op::error(\"Unknown `--mode \" + std::to_string(FLAGS_mode) + \"`.\", __LINE__, __FUNCTION__, __FILE__);\n\n        // Measuring total time\n        op::printTime(\n            opTimer, \"OpenPose calibration toolbox successfully finished. Total time: \", \" seconds.\",\n            op::Priority::High);\n\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running openPoseDemo\n    return openPoseDemo();\n}\n"
  },
  {
    "path": "examples/deprecated/CMakeLists.txt",
    "content": "set(EXAMPLE_FILES\n    tutorial_add_module_custom_post_processing.cpp\n    tutorial_api_thread_1_user_processing_function.cpp\n    tutorial_api_thread_2_user_input_processing_output_and_datum.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\n\nforeach(EXAMPLE_FILE ${EXAMPLE_FILES})\n\n  get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)\n\n  if (UNIX OR APPLE)\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\n  elseif (WIN32)\n    set(EXE_NAME \"${SOURCE_NAME}\")\n  endif ()\n\n  message(STATUS \"Adding Example ${EXE_NAME}\")\n  add_executable(${EXE_NAME} ${EXAMPLE_FILE})\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\n\n  if (WIN32)\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"Examples/Tutorial/Deprecated\")\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\n    # Properties->General->Output Directory\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  endif (WIN32)\n\nendforeach()\n"
  },
  {
    "path": "examples/deprecated/README.md",
    "content": "# Deprecated Examples\nYou are most probably looking for the [examples/tutorial_api_cpp/](../tutorial_api_cpp/) or [examples/tutorial_api_python/](../tutorial_api_python/), which provide examples of the thread API already applied to body pose estimation.\n\nThis directory is for OpenPose deployers, not for OpenPose uses, as it only provides (potentially not updated) examples for:\n- The basic OpenPose thread mechanism API, and it is only meant for people interested in the multi-thread architecture without been interested in the OpenPose pose estimation algorithm.\n- How to add a new module to OpenPose. And this is already and better explained in [examples/tutorial_api_cpp/](../tutorial_api_cpp/) or [examples/tutorial_api_python/](../tutorial_api_python/).\n"
  },
  {
    "path": "examples/deprecated/tutorial_add_module/userDatum.hpp",
    "content": "#ifndef OPENPOSE_TUTORIAL_USER_DATUM_HPP\n#define OPENPOSE_TUTORIAL_USER_DATUM_HPP\n\n#include <openpose/core/datum.hpp>\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    // If the user needs his own variables to be shared across Worker classes, he can directly add them here.\n    struct UserDatum : public Datum\n    {\n        /**\n         * Description of your variable.\n         */\n        bool boolThatUserNeedsForSomeReason;\n\n        UserDatum() {};\n\n        virtual ~UserDatum(){};\n    };\n}\n\n#endif // OPENPOSE_TUTORIAL_USER_DATUM_HPP\n"
  },
  {
    "path": "examples/deprecated/tutorial_add_module/userPostProcessing.hpp",
    "content": "#ifndef OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP\n#define OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// OpenPose dependencies\n#include <openpose/core/common.hpp>\n#include <openpose/core/cvMatToOpInput.hpp>\n\nnamespace op\n{\n    /**\n     * Add your class description here.\n     */\n    class UserPostProcessing\n    {\n    public:\n        /**\n         * Add your constructor description here.\n         */\n        UserPostProcessing();\n\n        /**\n         * Add your initializationOnThread description here.\n         * This is equivalent to the constructor, but it is run in the thread where this function will operate\n         */\n        void initializationOnThread();\n\n        /**\n         * Add your information about what your class does and their inputs/outputs.\n         * @param output is the modified cv::Mat.\n         * @param input is the input cv::Mat.\n         * @return If it is not void, add returning information here.\n         */\n        void doSomething(cv::Mat& output, const cv::Mat& input);\n\n    private:\n        /**\n         * Description of your variable here.\n         */\n        // bool mSomeVariableHere;\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    UserPostProcessing::UserPostProcessing()\n    {\n        try\n        {\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void UserPostProcessing::initializationOnThread()\n    {\n        try\n        {\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void UserPostProcessing::doSomething(cv::Mat& output, const cv::Mat& input)\n    {\n        try\n        {\n            // Random operation on data\n            cv::bitwise_not(input, output);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // COMPILE_TEMPLATE_DATUM(UserPostProcessing);\n}\n\n#endif // OPENPOSE_EXAMPLES_TUTORIAL_USER_POST_PROCESSING_HPP\n"
  },
  {
    "path": "examples/deprecated/tutorial_add_module/wUserPostProcessing.hpp",
    "content": "#ifndef OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP\n#define OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/cvMatToOpInput.hpp>\n#include <openpose/thread/worker.hpp>\n#include \"userPostProcessing.hpp\"\n\nnamespace op\n{\n    template<typename TDatums>\n    class WUserPostProcessing : public Worker<TDatums>\n    {\n    public:\n        WUserPostProcessing(const std::shared_ptr<UserPostProcessing>& userPostProcessing);\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<UserPostProcessing> spUserPostProcessing;\n\n        DELETE_COPY(WUserPostProcessing);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WUserPostProcessing<TDatums>::WUserPostProcessing(const std::shared_ptr<UserPostProcessing>& userPostProcessing) :\n        spUserPostProcessing{userPostProcessing}\n    {\n    }\n\n    template<typename TDatums>\n    void WUserPostProcessing<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WUserPostProcessing<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                for (auto& datum : *tDatums)\n                {\n                    // THESE 2 ARE THE ONLY LINES THAT THE USER MUST MODIFY ON THIS HPP FILE, by using the proper\n                    // function and datum elements\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datum->cvOutputData);\n                    spUserPostProcessing->doSomething(cvOutputData, cvOutputData);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // COMPILE_TEMPLATE_DATUM(WUserPostProcessing);\n}\n\n#endif // OPENPOSE_EXAMPLES_TUTORIAL_W_USER_POST_PROCESSING_HPP\n"
  },
  {
    "path": "examples/deprecated/tutorial_add_module_custom_post_processing.cpp",
    "content": "// ------------------------- OpenPose Library Tutorial - Adding Module - Example 1 - Custom Post Processing -------------------------\n// Purpose of this example\n// To create a class in OpenPose format so it can be later added to the library.\n\n// How to use?\n// 1. `userPostProcessing.hpp`: Implement your custom functionality there.\n// 2. `wUserPostProcessing.hpp`: Change 1 line in `work(TDatums& tDatums)` to use your custom function from\n// `userPostProcessing.hpp`.\n// 3. `userDatum.hpp`: Add any required output of your post-processing class there.\n// 4. `tutorial_add_module_custom_post_processing.cpp`: Change 1 line, when creating the `UserPostProcessing` class, add any specific\n// arguments/parameters than your class need.\n// 5. `tutorial_add_module_custom_post_processing.bin`: Compile and run this file (as you usually run the OpenPose demo) in order to\n// test your custom functionality.\n\n// Syntax rules\n// 1. Class/template variables start by up (unique_ptr), sp (sahred_ptr), p (pointer) or m (non-pointer), and they\n// have no underscores, e.g., mThisIsAVariable.\n// 2. The internal temporary function variable equivalent would be thisIsAVariable.\n// 3. Every line cannot have more than 120 characters.\n// 4. If extra classes and files are required, add those extra files inside the OpenPose include and src folders,\n// under a new folder (i.e., `include/newMethod/` and `src/newMethod/`), including `namespace op` on those files.\n\n// This example is a sub-case of `tutorial_api_cpp/16_synchronous_custom_postprocessing.cpp`, where only custom post-processing is\n// considered.\n\n// Command-line user interface\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n#include \"tutorial_add_module/userDatum.hpp\"\n#include \"tutorial_add_module/wUserPostProcessing.hpp\"\n\nvoid configureWrapper(op::WrapperT<op::UserDatum>& opWrapperT)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapperT.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapperT.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapperT.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapperT.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapperT.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapperT.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapperT.configure(wrapperStructGui);\n\n        // Custom post-processing\n        auto userPostProcessing = std::make_shared<op::UserPostProcessing>(/* Your class arguments here */);\n        auto wUserPostProcessing = std::make_shared<op::WUserPostProcessing<std::shared_ptr<std::vector<std::shared_ptr<op::UserDatum>>>>>(\n            userPostProcessing\n        );\n        // Add custom processing\n        const auto workerProcessingOnNewThread = false;\n        opWrapperT.setWorker(op::WorkerType::PostProcessing, wUserPostProcessing, workerProcessingOnNewThread);\n\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapperT.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialAddModule1()\n{\n   try\n   {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configure OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::WrapperT<op::UserDatum> opWrapperT;\n        configureWrapper(opWrapperT);\n\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        // Start, run & stop threads - it blocks this thread until all others have finished\n        opWrapperT.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return successful message\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialAddModule1\n    return tutorialAddModule1();\n}\n"
  },
  {
    "path": "examples/deprecated/tutorial_api_thread_1_user_processing_function.cpp",
    "content": "// ------------------------- OpenPose Library Tutorial - Thread - Example 1 - User Processing Function -------------------------\n// This directory only provides examples for the basic OpenPose thread mechanism API, and it is only meant for people\n// interested in the multi-thread architecture without been interested in the OpenPose pose estimation algorithm.\n// You are most probably looking for the [examples/tutorial_api_cpp/](../tutorial_api_cpp/) or\n// [examples/tutorial_api_python/](../tutorial_api_python/), which provide examples of the thread API already applied\n// to body pose estimation.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// This class can be implemented either as a template or as a simple class given\n// that the user usually knows which kind of data he will move between the queues,\n// in this case we assume a std::shared_ptr of a std::vector of op::Datum\nclass WUserClass : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>\n{\npublic:\n    WUserClass()\n    {\n        // User's constructor here\n    }\n\n    void initializationOnThread() {}\n\n    void work(std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's processing here\n                // datumPtr->cvInputData: initial cv::Mat obtained from the frames producer (video, webcam, etc.)\n                // datumPtr->cvOutputData: final cv::Mat to be displayed\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                for (auto& datumPtr : *datumsPtr)\n                {\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);\n                    cv::bitwise_not(cvOutputData, cvOutputData);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            op::opLog(\"Some kind of unexpected error happened.\");\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nint openPoseTutorialThread1()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // ------------------------- INITIALIZATION -------------------------\n        // Step 1 - Set logging level\n            // - 0 will output all the logging messages\n            // - 255 will output nothing\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        // Step 2 - Read GFlags (user defined configuration)\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        const auto displayProducerFpsMode = (FLAGS_process_real_time\n                                          ? op::ProducerFpsMode::OriginalFps : op::ProducerFpsMode::RetrievalFps);\n        auto producerSharedPtr = createProducer(\n            producerType, producerString.getStdString(), cameraSize, FLAGS_camera_parameter_path, FLAGS_frame_undistort,\n            FLAGS_3d_views);\n        producerSharedPtr->setProducerFpsMode(displayProducerFpsMode);\n        op::opLog(\"\", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        // Step 3 - Setting producer\n        auto videoSeekSharedPtr = std::make_shared<std::pair<std::atomic<bool>, std::atomic<int>>>();\n        videoSeekSharedPtr->first = false;\n        videoSeekSharedPtr->second = 0;\n        const op::Point<int> producerSize{\n            (int)producerSharedPtr->get(op::getCvCapPropFrameWidth()),\n            (int)producerSharedPtr->get(op::getCvCapPropFrameHeight())};\n        // Step 4 - Setting thread workers && manager\n        typedef std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> TypedefDatumsSP;\n        op::ThreadManager<TypedefDatumsSP> threadManager;\n        // Step 5 - Initializing the worker classes\n        // Frames producer (e.g., video, webcam, ...)\n        auto DatumProducer = std::make_shared<op::DatumProducer<op::Datum>>(producerSharedPtr);\n        auto wDatumProducer = std::make_shared<op::WDatumProducer<op::Datum>>(DatumProducer);\n        // Specific WUserClass\n        auto wUserClass = std::make_shared<WUserClass>();\n        // GUI (Display)\n        auto gui = std::make_shared<op::Gui>(outputSize, FLAGS_fullscreen, threadManager.getIsRunningSharedPtr());\n        auto wGui = std::make_shared<op::WGui<TypedefDatumsSP>>(gui);\n\n        // ------------------------- CONFIGURING THREADING -------------------------\n        // In this simple multi-thread example, we will do the following:\n            // 3 (virtual) queues: 0, 1, 2\n            // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the\n            // beginning and end of the processing sequence\n            // 2 threads: 0, 1\n            // wDatumProducer will generate frames (there is no real queue 0) and push them on queue 1\n            // wGui will pop frames from queue 1 and process them (there is no real queue 2)\n        auto threadId = 0ull;\n        auto queueIn = 0ull;\n        auto queueOut = 1ull;\n        threadManager.add(threadId++, wDatumProducer, queueIn++, queueOut++);   // Thread 0, queues 0 -> 1\n        threadManager.add(threadId++, wUserClass, queueIn++, queueOut++);       // Thread 1, queues 1 -> 2\n        threadManager.add(threadId++, wGui, queueIn++, queueOut++);             // Thread 2, queues 2 -> 3\n\n        // Equivalent single-thread version\n        // const auto threadId = 0ull;\n        // auto queueIn = 0ull;\n        // auto queueOut = 1ull;\n        // threadManager.add(threadId, wDatumProducer, queueIn++, queueOut++);     // Thread 0, queues 0 -> 1\n        // threadManager.add(threadId, wUserClass, queueIn++, queueOut++);         // Thread 1, queues 1 -> 2\n        // threadManager.add(threadId, wGui, queueIn++, queueOut++);               // Thread 2, queues 2 -> 3\n\n        // Smart multi-thread version\n        // Assume wUser is the slowest process, and that wDatumProducer + wGui is faster than wGui itself,\n        // then, we can group the last 2 in the same thread and keep wGui in a different thread:\n        // const auto threadId = 0ull;\n        // auto queueIn = 0ull;\n        // auto queueOut = 1ull;\n        // threadManager.add(threadId, wDatumProducer, queueIn++, queueOut++);     // Thread 0, queues 0 -> 1\n        // threadManager.add(threadId+1, wUserClass, queueIn++, queueOut++);       // Thread 1, queues 1 -> 2\n        // threadManager.add(threadId, wGui, queueIn++, queueOut++);               // Thread 0, queues 2 -> 3\n\n        // ------------------------- STARTING AND STOPPING THREADING -------------------------\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        // Two different ways of running the program on multithread environment\n            // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)\n        threadManager.exec();\n            // Option b) Giving to the user the control of this thread\n        // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main\n        // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to:\n        // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections`\n        // // Start threads\n        // threadManager.start();\n        // // Keep program alive while running threads. Here the user could perform any other desired function\n        // while (threadManager.isRunning())\n        //     std::this_thread::sleep_for(std::chrono::milliseconds{33});\n        // // Stop and join threads\n        // op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        // threadManager.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running openPoseTutorialThread1\n    return openPoseTutorialThread1();\n}\n"
  },
  {
    "path": "examples/deprecated/tutorial_api_thread_2_user_input_processing_output_and_datum.cpp",
    "content": "// ------------------------- OpenPose Library Tutorial - Thread - Example 2 - User Input Processing And Output -------------------------\n// This directory only provides examples for the basic OpenPose thread mechanism API, and it is only meant for people\n// interested in the multi-thread architecture without been interested in the OpenPose pose estimation algorithm.\n// You are most probably looking for the [examples/tutorial_api_cpp/](../tutorial_api_cpp/) or\n// [examples/tutorial_api_python/](../tutorial_api_python/), which provide examples of the thread API already applied\n// to body pose estimation.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// GFlags: DEFINE_bool, _int32, _int64, _uint64, _double, _string\n#include <gflags/gflags.h>\n// Allow Google Flags in Ubuntu 14\n#ifndef GFLAGS_GFLAGS_H_\n    namespace gflags = google;\n#endif\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// See all the available parameter options with the `--help` flag. E.g., `build/examples/openpose/openpose.bin --help`\n// Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose\n// executable. E.g., for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.\n// Debugging/Other\nDEFINE_int32(logging_level,             3,              \"The logging level. Integer in the range [0, 255]. 0 will output any opLog() message,\"\n                                                        \" while 255 will not output any. Current OpenPose library messages are in the range 0-4:\"\n                                                        \" 1 for low priority messages and 4 for important ones.\");\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",      \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n// Consumer\nDEFINE_bool(fullscreen,                 false,          \"Run in full-screen mode (press f during runtime to toggle).\");\n\n// If the user needs his own variables, he can inherit the op::Datum struct and add them in there.\n// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define\n// WrapperT<std::vector<std::shared_ptr<UserDatum>>> instead of Wrapper\n// (or equivalently WrapperT<std::vector<std::shared_ptr<UserDatum>>>)\nstruct UserDatum : public op::Datum\n{\n    bool boolThatUserNeedsForSomeReason;\n\n    UserDatum(const bool boolThatUserNeedsForSomeReason_ = false) :\n        boolThatUserNeedsForSomeReason{boolThatUserNeedsForSomeReason_}\n    {}\n};\n\n// The W-classes can be implemented either as a template or as simple classes given\n// that the user usually knows which kind of data he will move between the queues,\n// in this case we assume a std::shared_ptr of a std::vector of UserDatum\n\n// This worker will just read and return all the basic image file formats in a directory\nclass WUserInput : public op::WorkerProducer<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    WUserInput(const std::string& directoryPath) :\n        mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats\n        // If we want only e.g., \"jpg\" + \"png\" images\n        // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector<std::string>{\"jpg\", \"png\"})},\n        mCounter{0}\n    {\n        if (mImageFiles.empty())\n            op::error(\"No images found on: \" + directoryPath, __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    void initializationOnThread() {}\n\n    std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> workProducer()\n    {\n        try\n        {\n            // Close program when empty frame\n            if (mImageFiles.size() <= mCounter)\n            {\n                op::opLog(\n                    \"Last frame read and added to queue. Closing program after it is processed.\", op::Priority::High);\n                // This function stops this worker, which will eventually stop the whole thread system once all the\n                // frames have been processed\n                this->stop();\n                return nullptr;\n            }\n            else\n            {\n                // Create new datum\n                auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<UserDatum>>>();\n                datumsPtr->emplace_back();\n                auto& datumPtr = datumsPtr->at(0);\n                datumPtr = std::make_shared<UserDatum>();\n\n                // Fill datum\n                const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));\n                datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);\n\n                // If empty frame -> return nullptr\n                if (datumPtr->cvInputData.empty())\n                {\n                    op::opLog(\"Empty frame detected on path: \" + mImageFiles.at(mCounter-1) + \". Closing program.\",\n                        op::Priority::High);\n                    this->stop();\n                    datumsPtr = nullptr;\n                }\n\n                return datumsPtr;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            op::opLog(\"Some kind of unexpected error happened.\");\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\nprivate:\n    const std::vector<std::string> mImageFiles;\n    unsigned long long mCounter;\n};\n\n// This worker will just invert the image\nclass WUserPostProcessing : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    WUserPostProcessing()\n    {\n        // User's constructor here\n    }\n\n    void initializationOnThread() {}\n\n    void work(std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's post-processing (after OpenPose processing & before OpenPose outputs) here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                for (auto& datumPtr : *datumsPtr)\n                {\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);\n                    cv::bitwise_not(cvOutputData, cvOutputData);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            op::opLog(\"Some kind of unexpected error happened.\");\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\n// This worker will just read and return all the jpg files in a directory\nclass WUserOutput : public op::WorkerConsumer<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    void initializationOnThread() {}\n\n    void workConsumer(const std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's displaying/saving/other processing here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial Thread API\", cvMat);\n                // It displays the image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n                cv::waitKey(1);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            op::opLog(\"Some kind of unexpected error happened.\");\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nint openPoseTutorialThread2()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // ------------------------- INITIALIZATION -------------------------\n        // Step 1 - Set logging level\n            // - 0 will output all the logging messages\n            // - 255 will output nothing\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        // Step 2 - Setting thread workers && manager\n        typedef std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> TypedefDatumsSP;\n        op::ThreadManager<TypedefDatumsSP> threadManager;\n        // Step 3 - Initializing the worker classes\n        // Frames producer (e.g., video, webcam, ...)\n        auto wUserInput = std::make_shared<WUserInput>(FLAGS_image_dir);\n        // Processing\n        auto wUserProcessing = std::make_shared<WUserPostProcessing>();\n        // GUI (Display)\n        auto wUserOutput = std::make_shared<WUserOutput>();\n\n        // ------------------------- CONFIGURING THREADING -------------------------\n        // In this simple multi-thread example, we will do the following:\n            // 3 (virtual) queues: 0, 1, 2\n            // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the\n            // beginning and end of the processing sequence\n            // 2 threads: 0, 1\n            // wUserInput will generate frames (there is no real queue 0) and push them on queue 1\n            // wGui will pop frames from queue 1 and process them (there is no real queue 2)\n        auto threadId = 0ull;\n        auto queueIn = 0ull;\n        auto queueOut = 1ull;\n        threadManager.add(threadId++, wUserInput, queueIn++, queueOut++);       // Thread 0, queues 0 -> 1\n        threadManager.add(threadId++, wUserProcessing, queueIn++, queueOut++);  // Thread 1, queues 1 -> 2\n        threadManager.add(threadId++, wUserOutput, queueIn++, queueOut++);      // Thread 2, queues 2 -> 3\n\n        // ------------------------- STARTING AND STOPPING THREADING -------------------------\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        // Two different ways of running the program on multithread environment\n            // Option a) Using the main thread (this thread) for processing (it saves 1 thread, recommended)\n        threadManager.exec();\n            // Option b) Giving to the user the control of this thread\n        // // VERY IMPORTANT NOTE: if OpenCV is compiled with Qt support, this option will not work. Qt needs the main\n        // // thread to plot visual results, so the final GUI (which uses OpenCV) would return an exception similar to:\n        // // `QMetaMethod::invoke: Unable to invoke methods with return values in queued connections`\n        // // Start threads\n        // threadManager.start();\n        // // Keep program alive while running threads. Here the user could perform any other desired function\n        // while (threadManager.isRunning())\n        //     std::this_thread::sleep_for(std::chrono::milliseconds{33});\n        // // Stop and join threads\n        // op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        // threadManager.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running openPoseTutorialThread2\n    return openPoseTutorialThread2();\n}\n"
  },
  {
    "path": "examples/openpose/CMakeLists.txt",
    "content": "set(EXAMPLE_FILES\r\n    openpose.cpp)\r\n\r\nforeach(EXAMPLE_FILE ${EXAMPLE_FILES})\r\n\r\n  get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)\r\n\r\n  if (UNIX OR APPLE)\r\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\r\n  elseif (WIN32)\r\n    set(EXE_NAME \"OpenPoseDemo\")\r\n  endif ()\r\n\r\n  message(STATUS \"Adding Example ${EXE_NAME}\")\r\n  add_executable(${EXE_NAME} ${EXAMPLE_FILE})\r\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\r\n\r\n  if (WIN32)\r\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"Examples\")\r\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user\r\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\r\n    # Properties->General->Output Directory\r\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\r\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\r\n  endif (WIN32)\r\n\r\nendforeach()\r\n"
  },
  {
    "path": "examples/openpose/openpose.cpp",
    "content": "// ------------------------------------------------ OpenPose C++ Demo ------------------------------------------------\n// This example summarizes all the functionality of the OpenPose library. It can...\n    // 1. Read a frames source (images, video, webcam, 3D stereo Flir cameras, etc.).\n    // 2. Extract and render body/hand/face/foot keypoint/heatmap/PAF of that image.\n    // 3. Save the results on disk.\n    // 4. Display the rendered pose.\n// For more details on the OpenPose examples, see\n// - https://cmu-perceptual-computing-lab.github.io/openpose\n// - https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/00_index.md\n\n// Command-line user interface\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapper.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint openPoseDemo()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configure OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper;\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return successful message\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running openPoseDemo\n    return openPoseDemo();\n}\n"
  },
  {
    "path": "examples/tests/CMakeLists.txt",
    "content": "set(EXAMPLE_FILES\n    handFromJsonTest.cpp\n    resizeTest.cpp)\n\nforeach(EXAMPLE_FILE ${EXAMPLE_FILES})\n\n  get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)\n\n  if (UNIX OR APPLE)\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\n  elseif (WIN32)\n    set(EXE_NAME \"${SOURCE_NAME}\")\n  endif ()\n\n  message(STATUS \"Adding Example ${EXE_NAME}\")\n  add_executable(${EXE_NAME} ${EXAMPLE_FILE})\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\n\n  if (WIN32)\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"Examples/Tutorial/Tests\")\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\n    # Properties->General->Output Directory\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  endif (WIN32)\n\nendforeach()\n"
  },
  {
    "path": "examples/tests/README.md",
    "content": "# Test Examples\n**Disclaimer**: This folder is meant for internal OpenPose developers. The Examples might highly change, and we will not answer questions about them nor provide official support for them.\n\n**If the OpenPose library does not compile for an error happening due to a file from this folder, notify us**.\n"
  },
  {
    "path": "examples/tests/clTest.cpp",
    "content": "// ------------------------- OpenPose Resize Layer Testing -------------------------\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n// Caffe dependencies\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n// OpenCL dependencies\n#ifdef USE_OPENCL\n#include <openpose_private/gpu/opencl.hcl>\n#include <openpose_private/gpu/cl2.hpp>\n\nDEFINE_string(image_path,               \"examples/media/COCO_val2014_000000000192.jpg\",     \"Process the desired image.\");\n\n//    cv::Mat gpuResize(cv::Mat& img, const cv::Size& newSize)\n//    {\n//        #ifdef USE_CUDA\n//            // Upload to Source to GPU\n//            float* cpuPtr = &img.at<float>(0);\n//            float* gpuPtr;\n//            cudaMallocHost((void **)&gpuPtr, img.size().width * img.size().height * sizeof(float));\n//            cudaMemcpy(gpuPtr, cpuPtr, img.size().width * img.size().height * sizeof(float),\n//                       cudaMemcpyHostToDevice);\n\n//            // Upload to Dest to GPU\n//            cv::Mat newImg = cv::Mat(newSize,CV_32FC1,cv::Scalar(0));\n//            float* newCpuPtr = &newImg.at<float>(0);\n//            float* newGpuPtr;\n//            cudaMallocHost((void **)&newGpuPtr, newSize.width * newSize.height * sizeof(float));\n//            cudaMemcpy(newGpuPtr, newCpuPtr, newSize.width * newSize.height * sizeof(float),\n//                       cudaMemcpyHostToDevice);\n\n//            std::vector<const float*> sourcePtrs;\n//            sourcePtrs.emplace_back(gpuPtr);\n//            std::array<int, 4> targetSize = {1,1,newImg.size().height,newImg.size().width};\n//            std::array<int, 4> sourceSize = {1,1,img.size().height,img.size().width};\n//            std::vector<std::array<int, 4>> sourceSizes;\n//            sourceSizes.emplace_back(sourceSize);\n//            op::resizeAndMergeGpu(newGpuPtr, sourcePtrs, targetSize, sourceSizes);\n//            cudaMemcpy(newCpuPtr, newGpuPtr, newImg.size().width * newImg.size().height * sizeof(float),\n//                       cudaMemcpyDeviceToHost);\n\n//            cudaFree(gpuPtr);\n//            cudaFree(newGpuPtr);\n//            return newImg;\n//        #else\n//            UNUSED(img);\n//            UNUSED(newSize);\n//            op::error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n//                  \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n//        #endif\n//    }\n\n//    cv::Mat cpuResize(cv::Mat& img, cv::Size newSize)\n//    {\n//        // Upload to Source to GPU\n//        float* cpuPtr = &img.at<float>(0);\n\n//        // Upload to Dest to GPU\n//        cv::Mat newImg = cv::Mat(newSize,CV_32FC1,cv::Scalar(0));\n\n//        std::vector<const float*> sourcePtrs;\n//        sourcePtrs.emplace_back(cpuPtr);\n//        std::array<int, 4> targetSize = {1,1,newImg.size().height,newImg.size().width};\n//        std::array<int, 4> sourceSize = {1,1,img.size().height,img.size().width};\n//        std::vector<std::array<int, 4>> sourceSizes;\n//        sourceSizes.emplace_back(sourceSize);\n//        op::resizeAndMergeCpu(&newImg.at<float>(0), sourcePtrs, targetSize, sourceSizes);\n\n//        return newImg;\n//    }\n\ntypedef cl::KernelFunctor<cl::Buffer, int, int, float> ScaleFunctor;\nconst std::string scaleKernelString = MULTI_LINE_STRING(\n            __kernel void scaleKernel(__global float* targetPtr, const int targetWidth, const int targetHeight,\n                                      const float scale)\n{\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n                int c = get_global_id(2);\n\n                __global float* targetPtrC = &targetPtr[c*targetWidth*targetHeight];\n                targetPtrC[y*targetWidth+x] *= scale;\n            }\n            );\n\nint clTest()\n{\n    try\n    {\n        // logging_level\n        cv::Mat img = cv::imread(FLAGS_image_path);\n        if(img.empty())\n            op::error(\"Could not open or find the image: \" + FLAGS_image_path, __LINE__, __FUNCTION__, __FILE__);\n        cv::Mat imgResize; cv::resize(img, imgResize, cv::Size(368,368));\n        cv::Mat imgFloat; imgResize.convertTo(imgFloat, CV_32FC3);\n        imgFloat /= 255.;\n        int imageVolume = imgFloat.size().width * imgFloat.size().height * imgFloat.channels();\n        std::cout << imgFloat.channels() << std::endl;\n\n        // Setup caffe\n        caffe::Caffe::set_mode(caffe::Caffe::GPU);\n        std::vector<int> devices;\n        const int maxNumberGpu = op::OpenCL::getTotalGPU();\n        for (auto i = 0; i < maxNumberGpu; i++){\n            devices.emplace_back(i);\n            std::cout << i << std::endl;\n        }\n        caffe::Caffe::SetDevices(devices);\n\n        // Load model\n        std::unique_ptr<caffe::Net<float>> upCaffeNet;\n        caffe::Caffe::set_mode(caffe::Caffe::GPU);\n        caffe::Caffe::SelectDevice(0, true);\n        upCaffeNet.reset(new caffe::Net<float>{\n            \"models/pose/coco/pose_deploy_linevec.prototxt\", caffe::TEST, caffe::Caffe::GetDefaultDevice()});\n        upCaffeNet->CopyTrainedLayersFrom(\"models/pose/coco/pose_iter_440000.caffemodel\");\n        op::OpenCL::getInstance(0, CL_DEVICE_TYPE_GPU, true);\n\n        // Reshape net to image size\n        upCaffeNet->blobs()[0]->Reshape({1,imgFloat.channels(),imgResize.size().width,imgResize.size().height});\n        upCaffeNet->Reshape();\n\n        // Convert to caffe image\n        caffe::BlobProto blob_proto;\n        blob_proto.set_channels(3);\n        blob_proto.set_height(imgResize.size().width);\n        blob_proto.set_width(imgResize.size().height);\n        blob_proto.clear_data();\n        for (int c = 0; c < 3; ++c)\n            for (int h = 0; h < imgResize.size().height; ++h)\n                for (int w = 0; w < imgResize.size().width; ++w)\n                    blob_proto.add_data(imgResize.at<cv::Vec3f>(h, w)[c]);\n        blob_proto.set_num(1);\n        caffe::Blob<float>* input_layer = upCaffeNet->input_blobs()[0];\n        input_layer->FromProto(blob_proto);\n        upCaffeNet->Forward(0);\n\n        boost::shared_ptr<caffe::Blob<float>> output_blob = upCaffeNet->blob_by_name(\"net_output\");\n\n        // Test\n        cl::Device& device = op::OpenCL::getInstance(0)->getDevice();\n        cl_uint mem_align;\n        clGetDeviceInfo(device.get(), CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(mem_align), &mem_align, nullptr);\n        std::cout << \"Alignment in bits of the base address : \" << mem_align << std::endl;\n\n        // GPU Test\n        cv::Mat finalImage = imgFloat;\n        try{\n\n            // Get\n            float* gpuPtr = output_blob->mutable_gpu_data();\n            cl::Buffer outputBuffer((cl_mem)gpuPtr, true);\n\n            // Read it\n            // Read back image to GPU\n            float* heatmaps = new float[output_blob->shape()[1] * output_blob->shape()[2] * output_blob->shape()[3]];\n            op::OpenCL::getInstance(0)->getQueue().enqueueReadBuffer(\n                outputBuffer, CL_TRUE, 0,\n                output_blob->shape()[1] * output_blob->shape()[2] * output_blob->shape()[3] * sizeof(float), heatmaps);\n\n            int heatmapChannels = output_blob->shape()[1];\n            int shape = output_blob->shape()[2] * output_blob->shape()[3];\n            for(int i=0; i<heatmapChannels; i++){\n                cv::Mat hm(cv::Size(output_blob->shape()[2], output_blob->shape()[3]), CV_32FC1);\n                // Read subbuffer\n                cl_buffer_region sourceRegion;\n                op::OpenCL::getBufferRegion<float>(sourceRegion, i * shape, shape);\n                cl::Buffer regionBuffer = outputBuffer.createSubBuffer(CL_MEM_READ_WRITE,\n                                                                      CL_BUFFER_CREATE_TYPE_REGION,\n                                                                      &sourceRegion);\n            }\n        }\n        #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n            catch (const cl::Error& e)\n            {\n                op::error(std::string(e.what()) + \" : \" + op::OpenCL::clErrorToString(e.err()) + \" ID: \" +\n                          std::to_string(0), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #endif\n        catch (const std::exception& e)\n        {\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n\n        cv::imshow(\"win\", finalImage);\n        cv::waitKey(0);\n\n        // Load model\n\n        //            img.convertTo(img, CV_32FC1);\n        //            img = cpuResize(img, cv::Size(img.size().width/4,img.size().height/4));\n        //            img*=0.005;\n\n        //            cv::Mat gpuImg = gpuResize(img, cv::Size(img.size().width*8,img.size().height*8));\n        //            cv::Mat cpuImg = cpuResize(img, cv::Size(img.size().width*8,img.size().height*8));\n        //            cv::imshow(\"gpuImg\", gpuImg);\n        //            cv::imshow(\"cpuImg\", cpuImg);\n\n        //            op::opLog(\"Done\");\n        //            cv::waitKey(0);\n\n        return 0;\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return -1;\n    }\n}\n#endif\n\nint main()\n{\n#ifdef USE_OPENCL\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running handFromJsonTest\n    std::thread t(&clTest);\n    t.join();\n    return 0;\n#else\n    op::error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_OPENCL` macro definitions in order to run\"\n              \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n    return -1;\n#endif\n}\n"
  },
  {
    "path": "examples/tests/handFromJsonTest.cpp",
    "content": "// ----------------------- OpenPose Tests - Hand Keypoint Detection from JSON Ground-Truth Data -----------------------\n// Example to test hands accuracy given ground-truth bounding boxes.\n\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n#include \"wrapperHandFromJsonTest.hpp\"\n\n// For info about the flags, check `examples/openpose/openpose.bin`.\n// Producer\nDEFINE_string(image_dir,                \"\", \"\");\nDEFINE_string(hand_ground_truth,        \"\", \"\");\n// OpenPose\nDEFINE_string(model_folder,             \"models/\",      \"\");\nDEFINE_int32(num_gpu,                   -1,             \"\");\nDEFINE_int32(num_gpu_start,             0,              \"\");\n// OpenPose Hand\nDEFINE_bool(hand,                       true,           \"\");\nDEFINE_string(hand_net_resolution,      \"368x368\",      \"\");\nDEFINE_int32(hand_scale_number,         1,              \"\");\nDEFINE_double(hand_scale_range,         0.4,            \"\");\n// Display\nDEFINE_int32(display,                   -1,             \"\");\n// Result Saving\nDEFINE_string(write_json,               \"\",             \"\");\n\nint handFromJsonTest()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto timerBegin = std::chrono::high_resolution_clock::now();\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n\n        // Applying user defined configuration - GFlags to program variables\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // producerType\n        const auto producerSharedPtr = op::createProducer(op::ProducerType::ImageDirectory, FLAGS_image_dir);\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::WrapperHandFromJsonTest<op::Datum> opWrapper;\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        op::WrapperStructPose wrapperStructPose{\n            op::PoseMode::Disabled, op::flagsToPoint(\"656x368\", \"?x?\"), -1.0, op::flagsToPoint(\"1280x720\", \"?x?\"),\n            op::ScaleMode::InputResolution, FLAGS_num_gpu, FLAGS_num_gpu_start, 1, 0.15f, op::RenderMode::None,\n            op::PoseModel::BODY_25, true, 0.f, 0.f, 0, \"models/\", {}, op::ScaleMode::ZeroToOneFixedAspect, false,\n            0.05f, -1, false};\n        wrapperStructPose.modelFolder = op::String(FLAGS_model_folder);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, op::Detector::Provided, handNetInputSize, FLAGS_hand_scale_number,\n            (float)FLAGS_hand_scale_range, op::flagsToRenderMode(1)};\n        // Configure wrapper\n        opWrapper.configure(wrapperStructPose, wrapperStructHand, producerSharedPtr, FLAGS_hand_ground_truth,\n                            FLAGS_write_json, op::flagsToDisplayMode(FLAGS_display, false));\n\n        // Start processing\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        const auto now = std::chrono::high_resolution_clock::now();\n        const auto totalTimeSec = double(\n            std::chrono::duration_cast<std::chrono::nanoseconds>(now-timerBegin).count()* 1e-9);\n        const auto message = \"OpenPose demo successfully finished. Total time: \"\n                           + std::to_string(totalTimeSec) + \" seconds.\";\n        op::opLog(message, op::Priority::High);\n\n        return 0;\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running handFromJsonTest\n    return handFromJsonTest();\n}\n"
  },
  {
    "path": "examples/tests/resizeTest.cpp",
    "content": "// ------------------------- OpenPose Resize Layer Testing -------------------------\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n#ifdef USE_CUDA\n    #ifdef USE_CAFFE\n        #include <caffe/net.hpp>\n    #endif\n\n    DEFINE_string(image_path,               \"examples/media/COCO_val2014_000000000192.jpg\",     \"Process the desired image.\");\n\n    cv::Mat gpuResize(cv::Mat& img, const cv::Size& newSize)\n    {\n        #if defined USE_CAFFE && defined USE_CUDA\n            // Upload to Source to GPU\n            float* cpuPtr = &img.at<float>(0);\n            float* gpuPtr;\n            cudaMallocHost((void **)&gpuPtr, img.size().width * img.size().height * sizeof(float));\n            cudaMemcpy(gpuPtr, cpuPtr, img.size().width * img.size().height * sizeof(float),\n                       cudaMemcpyHostToDevice);\n\n            // Upload to Dest to GPU\n            cv::Mat newImg = cv::Mat(newSize,CV_32FC1,cv::Scalar(0));\n            float* newCpuPtr = &newImg.at<float>(0);\n            float* newGpuPtr;\n            cudaMallocHost((void **)&newGpuPtr, newSize.width * newSize.height * sizeof(float));\n            cudaMemcpy(newGpuPtr, newCpuPtr, newSize.width * newSize.height * sizeof(float),\n                       cudaMemcpyHostToDevice);\n\n            std::vector<const float*> sourcePtrs;\n            sourcePtrs.emplace_back(gpuPtr);\n            std::array<int, 4> targetSize = {1,1,newImg.size().height,newImg.size().width};\n            std::array<int, 4> sourceSize = {1,1,img.size().height,img.size().width};\n            std::vector<std::array<int, 4>> sourceSizes;\n            sourceSizes.emplace_back(sourceSize);\n            op::resizeAndMergeGpu(newGpuPtr, sourcePtrs, targetSize, sourceSizes);\n            cudaMemcpy(newCpuPtr, newGpuPtr, newImg.size().width * newImg.size().height * sizeof(float),\n                       cudaMemcpyDeviceToHost);\n\n            cudaFree(gpuPtr);\n            cudaFree(newGpuPtr);\n            return newImg;\n        #else\n            UNUSED(img);\n            UNUSED(newSize);\n            op::error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                  \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            return cv::Mat();\n        #endif\n    }\n\n    cv::Mat cpuResize(cv::Mat& img, cv::Size newSize)\n    {\n        // Upload to Source to GPU\n        float* cpuPtr = &img.at<float>(0);\n\n        // Upload to Dest to GPU\n        cv::Mat newImg = cv::Mat(newSize,CV_32FC1,cv::Scalar(0));\n\n        std::vector<const float*> sourcePtrs;\n        sourcePtrs.emplace_back(cpuPtr);\n        std::array<int, 4> targetSize = {1,1,newImg.size().height,newImg.size().width};\n        std::array<int, 4> sourceSize = {1,1,img.size().height,img.size().width};\n        std::vector<std::array<int, 4>> sourceSizes;\n        sourceSizes.emplace_back(sourceSize);\n        op::resizeAndMergeCpu(&newImg.at<float>(0), sourcePtrs, targetSize, sourceSizes);\n\n        return newImg;\n    }\n\n    int resizeTest()\n    {\n        try\n        {\n            // logging_level\n            op::Matrix opImg = op::loadImage(FLAGS_image_path, op::getCvLoadImageGrayScale());\n            cv::Mat img = OP_OP2CVMAT(opImg);\n            if(img.empty())\n                op::error(\"Could not open or find the image: \" + FLAGS_image_path, __LINE__, __FUNCTION__, __FILE__);\n            img.convertTo(img, CV_32FC1);\n            img = cpuResize(img, cv::Size(img.size().width/4,img.size().height/4));\n            img*=0.005;\n\n            cv::Mat gpuImg = gpuResize(img, cv::Size(img.size().width*8,img.size().height*8));\n            cv::Mat cpuImg = cpuResize(img, cv::Size(img.size().width*8,img.size().height*8));\n            cv::imshow(\"gpuImg\", gpuImg);\n            cv::imshow(\"cpuImg\", cpuImg);\n\n            op::opLog(\"Done\");\n            cv::waitKey(0);\n\n            return 0;\n        }\n        catch (const std::exception& e)\n        {\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n#endif\n\nint main(int argc, char *argv[])\n{\n    #ifdef USE_CUDA\n        // Parsing command line flags\n        gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n        // Running handFromJsonTest\n        return resizeTest();\n    #else\n        op::error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n              \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        return 0;\n    #endif\n}\n"
  },
  {
    "path": "examples/tests/wrapperHandFromJsonTest.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_HAND_FROM_JSON_TEST_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_HAND_FROM_JSON_TEST_HPP\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\nnamespace op\n{\n    template<typename TDatum,\n             typename TDatums = std::vector<std::shared_ptr<TDatum>>,\n             typename TWorker = std::shared_ptr<Worker<std::shared_ptr<TDatums>>>,\n             typename TQueue = Queue<std::shared_ptr<TDatums>>>\n    class WrapperHandFromJsonTest\n    {\n    public:\n        /**\n         * Constructor.\n         */\n        explicit WrapperHandFromJsonTest();\n\n        /**\n         * Destructor.\n         * It automatically frees resources.\n         */\n        ~WrapperHandFromJsonTest();\n\n        void configure(const WrapperStructPose& wrapperStructPose,\n                       const WrapperStructHand& wrapperStructHand,\n                       const std::shared_ptr<Producer>& producerSharedPtr,\n                       const std::string& handGroundTruth,\n                       const std::string& writeJson,\n                       const DisplayMode displayMode = DisplayMode::NoDisplay);\n\n        /**\n         * Function to start multi-threading.\n         * Similar to start(), but exec() blocks the thread that calls the function (it saves 1 thread). Use exec() instead of\n         * start() if the calling thread will otherwise be waiting for the WrapperHandFromJsonTest to end.\n         */\n        void exec();\n\n    private:\n        ThreadManager<std::shared_ptr<TDatums>> mThreadManager;\n        // Workers\n        TWorker wDatumProducer;\n        TWorker spWIdGenerator;\n        TWorker spWScaleAndSizeExtractor;\n        TWorker spWCvMatToOpInput;\n        TWorker spWCvMatToOpOutput;\n        std::vector<std::vector<TWorker>> spWPoses;\n        std::vector<TWorker> mPostProcessingWs;\n        std::vector<TWorker> mOutputWs;\n        TWorker spWGui;\n\n        /**\n         * Frees TWorker variables (private internal function).\n         * For most cases, this class is non-necessary, since std::shared_ptr are automatically cleaned on destruction of each class.\n         * However, it might be useful if the same WrapperHandFromJsonTest is gonna be started twice (not recommended on most cases).\n         */\n        void reset();\n\n        /**\n         * Set ThreadManager from TWorkers (private internal function).\n         * After any configure() has been called, the TWorkers are initialized. This function resets the ThreadManager and adds them.\n         * Common code for start() and exec().\n         */\n        void configureThreadManager();\n\n        /**\n         * TWorker concatenator (private internal function).\n         * Auxiliary function that concatenate std::vectors of TWorker. Since TWorker is some kind of smart pointer (usually\n         * std::shared_ptr), its copy still shares the same internal data. It will not work for TWorker classes that do not share\n         * the data when moved.\n         * @param workersA First std::shared_ptr<TDatums> element to be concatenated.\n         * @param workersB Second std::shared_ptr<TDatums> element to be concatenated.\n         * @return Concatenated std::vector<TWorker> of both workersA and workersB.\n         */\n        std::vector<TWorker> mergeWorkers(const std::vector<TWorker>& workersA, const std::vector<TWorker>& workersB);\n\n        DELETE_COPY(WrapperHandFromJsonTest);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/core/headers.hpp>\n#include <openpose/face/headers.hpp>\n#include <openpose/filestream/headers.hpp>\n#include <openpose/gui/headers.hpp>\n#include <openpose/gpu/gpu.hpp>\n#include <openpose/hand/headers.hpp>\n#include <openpose/pose/headers.hpp>\n#include <openpose/producer/headers.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n#include <openpose/utilities/fileSystem.hpp>\nnamespace op\n{\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::WrapperHandFromJsonTest()\n    {\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::~WrapperHandFromJsonTest()\n    {\n        try\n        {\n            mThreadManager.stop();\n            reset();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::configure(\n        const WrapperStructPose& wrapperStructPose,\n        const WrapperStructHand& wrapperStructHand,\n        const std::shared_ptr<Producer>& producerSharedPtr,\n        const std::string& handGroundTruth,\n        const std::string& writeJson,\n        const DisplayMode displayMode)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n            // Shortcut\n            typedef std::shared_ptr<TDatums> TDatumsPtr;\n\n            // Check no wrong/contradictory flags enabled\n            if (wrapperStructPose.scaleGap <= 0.f && wrapperStructPose.scalesNumber > 1)\n                error(\"The scale gap must be greater than 0 (it has no effect if the number of scales is 1).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            const std::string additionalMessage = \" You could also set mThreadManagerMode = mThreadManagerMode::Asynchronous(Out)\"\n                                                  \" and/or add your own output worker class before calling this function.\";\n            const auto savingSomething = !writeJson.empty();\n            const auto displayGui = (displayMode != DisplayMode::NoDisplay);\n            if (!displayGui && !savingSomething)\n            {\n                const auto message = \"No output is selected (`--display 0`) and no results are generated (no `write_X` flags enabled). Thus,\"\n                                     \" no output would be generated.\" + additionalMessage;\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Get number GPUs\n            auto gpuNumber = wrapperStructPose.gpuNumber;\n            auto gpuNumberStart = wrapperStructPose.gpuNumberStart;\n            // If number GPU < 0 --> set it to all the available GPUs\n            if (gpuNumber < 0)\n            {\n                // Get total number GPUs\n                gpuNumber = getGpuNumber();\n                // Reset initial GPU to 0 (we want them all)\n                gpuNumberStart = 0;\n                // Logging message\n                opLog(\"Auto-detecting GPUs... Detected \" + std::to_string(gpuNumber) + \" GPU(s), using them all.\", Priority::High);\n            }\n\n            // Proper format\n            const auto writeJsonCleaned = formatAsDirectory(writeJson);\n\n            // Common parameters\n            const auto finalOutputSize = wrapperStructPose.outputSize;\n            const Point<int> producerSize{\n                (int)producerSharedPtr->get(getCvCapPropFrameWidth()),\n                (int)producerSharedPtr->get(getCvCapPropFrameHeight())};\n            if (finalOutputSize.x == -1 || finalOutputSize.y == -1)\n            {\n                const auto message = \"Output resolution cannot be (-1 x -1) unless producerSharedPtr is also set.\";\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Producer\n            const auto datumProducer = std::make_shared<DatumProducer<TDatum>>(producerSharedPtr);\n            wDatumProducer = std::make_shared<WDatumProducer<TDatum>>(datumProducer);\n\n            // Get input scales and sizes\n            const auto scaleAndSizeExtractor = std::make_shared<ScaleAndSizeExtractor>(\n                wrapperStructPose.netInputSize, (float)wrapperStructPose.netInputSizeDynamicBehavior, finalOutputSize,\n                wrapperStructPose.scalesNumber, wrapperStructPose.scaleGap);\n            spWScaleAndSizeExtractor = std::make_shared<WScaleAndSizeExtractor<TDatumsPtr>>(scaleAndSizeExtractor);\n\n            // Input cvMat to OpenPose format\n            const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>(wrapperStructPose.poseModel);\n            spWCvMatToOpInput = std::make_shared<WCvMatToOpInput<TDatumsPtr>>(cvMatToOpInput);\n            if (displayGui)\n            {\n                const auto cvMatToOpOutput = std::make_shared<CvMatToOpOutput>();\n                spWCvMatToOpOutput = std::make_shared<WCvMatToOpOutput<TDatumsPtr>>(cvMatToOpOutput);\n            }\n\n            // Hand extractor(s)\n            if (wrapperStructHand.enable)\n            {\n                spWPoses.resize(gpuNumber);\n                const auto handDetector = std::make_shared<HandDetectorFromTxt>(handGroundTruth);\n                for (auto gpuId = 0u; gpuId < spWPoses.size(); gpuId++)\n                {\n                    // Hand detector\n                    // If tracking\n                    if (wrapperStructHand.detector == Detector::BodyWithTracking)\n                        error(\"Tracking not valid for hand detector from JSON files.\", __LINE__, __FUNCTION__, __FILE__);\n                    // If detection\n                    else\n                        spWPoses.at(gpuId) = {std::make_shared<WHandDetectorFromTxt<TDatumsPtr>>(handDetector)};\n                    // Hand keypoint extractor\n                    const auto netOutputSize = wrapperStructHand.netInputSize;\n                    const auto handExtractor = std::make_shared<HandExtractorCaffe>(\n                        wrapperStructHand.netInputSize, netOutputSize, wrapperStructPose.modelFolder.getStdString(),\n                        gpuId + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange\n                    );\n                    spWPoses.at(gpuId).emplace_back(std::make_shared<WHandExtractorNet<TDatumsPtr>>(handExtractor));\n                }\n            }\n\n            // Hand renderer(s)\n            std::vector<TWorker> cpuRenderers;\n            if (displayGui)\n            {\n                // Construct hand renderer\n                const auto handRenderer = std::make_shared<HandCpuRenderer>(wrapperStructHand.renderThreshold,\n                                                                            wrapperStructHand.alphaKeypoint,\n                                                                            wrapperStructHand.alphaHeatMap);\n                // Add worker\n                cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsPtr>>(handRenderer));\n            }\n\n            // Itermediate workers (e.g., OpenPose format to cv::Mat, json & frames recorder, ...)\n            mPostProcessingWs.clear();\n            // Frame buffer and ordering\n            if (spWPoses.size() > 1)\n                mPostProcessingWs.emplace_back(std::make_shared<WQueueOrderer<TDatumsPtr>>());\n            // Frames processor (OpenPose format -> cv::Mat format)\n            if (displayGui)\n            {\n                mPostProcessingWs = mergeWorkers(mPostProcessingWs, cpuRenderers);\n                const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>();\n                mPostProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsPtr>>(opOutputToCvMat));\n            }\n            // Re-scale pose if desired\n            if (wrapperStructPose.keypointScaleMode != ScaleMode::InputResolution)\n                error(\"Only wrapperStructPose.keypointScaleMode == ScaleMode::InputResolution.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n\n            mOutputWs.clear();\n            // Write people pose data on disk (json format)\n            if (!writeJsonCleaned.empty())\n            {\n                const auto jsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned);\n                mOutputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsPtr>>(jsonSaver));\n            }\n            // Minimal graphical user interface (GUI)\n            spWGui = nullptr;\n            if (displayGui)\n            {\n                const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(gpuNumber, displayGui);\n                mOutputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsPtr>>(guiInfoAdder));\n                const auto gui = std::make_shared<Gui>(\n                    finalOutputSize, false, mThreadManager.getIsRunningSharedPtr()\n                );\n                spWGui = {std::make_shared<WGui<TDatumsPtr>>(gui)};\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::exec()\n    {\n        try\n        {\n            configureThreadManager();\n            mThreadManager.exec();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::reset()\n    {\n        try\n        {\n            mThreadManager.reset();\n            // Reset\n            wDatumProducer = nullptr;\n            spWScaleAndSizeExtractor = nullptr;\n            spWCvMatToOpInput = nullptr;\n            spWCvMatToOpOutput = nullptr;\n            spWPoses.clear();\n            mPostProcessingWs.clear();\n            mOutputWs.clear();\n            spWGui = nullptr;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    void WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::configureThreadManager()\n    {\n        try\n        {\n            // Sanity checks\n            if (spWCvMatToOpInput == nullptr)\n                error(\"Configure the WrapperHandFromJsonTest class before calling `start()`.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (wDatumProducer == nullptr)\n            {\n                const auto message = \"You need to use the OpenPose default producer.\";\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n            if (mOutputWs.empty() && spWGui == nullptr)\n            {\n                error(\"No output selected.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Thread Manager:\n            // Clean previous thread manager (avoid configure to crash the program if used more than once)\n            mThreadManager.reset();\n            auto threadId = 0ull;\n            auto queueIn = 0ull;\n            auto queueOut = 1ull;\n            // If custom user Worker in same thread or producer on same thread\n            spWIdGenerator = std::make_shared<WIdGenerator<std::shared_ptr<TDatums>>>();\n            // OpenPose producer\n            // Thread 0 or 1, queues 0 -> 1\n            if (spWCvMatToOpOutput == nullptr)\n                mThreadManager.add(threadId++, {wDatumProducer, spWIdGenerator, spWScaleAndSizeExtractor,\n                                   spWCvMatToOpInput}, queueIn++, queueOut++);\n            else\n                mThreadManager.add(threadId++, {wDatumProducer, spWIdGenerator, spWScaleAndSizeExtractor,\n                                   spWCvMatToOpInput, spWCvMatToOpOutput}, queueIn++, queueOut++);\n            // Pose estimation & rendering\n            // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs\n            if (!spWPoses.empty())\n            {\n                for (auto& wPose : spWPoses)\n                    mThreadManager.add(threadId++, wPose, queueIn, queueOut);\n                queueIn++;\n                queueOut++;\n            }\n            // If custom user Worker in same thread or producer on same thread\n            // Post processing workers + User post processing workers + Output workers\n            // Thread 2 or 3, queues 2 -> 3\n            mThreadManager.add(threadId++, mergeWorkers(mPostProcessingWs, mOutputWs), queueIn++, queueOut++);\n            // OpenPose GUI\n            // Thread Y+1, queues Q+1 -> Q+2\n            if (spWGui != nullptr)\n                mThreadManager.add(threadId++, spWGui, queueIn++, queueOut++);\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TWorker, typename TQueue>\n    std::vector<TWorker> WrapperHandFromJsonTest<TDatum, TDatums, TWorker, TQueue>::mergeWorkers(const std::vector<TWorker>& workersA, const std::vector<TWorker>& workersB)\n    {\n        try\n        {\n            auto workersToReturn(workersA);\n            for (auto& worker : workersB)\n                workersToReturn.emplace_back(worker);\n            return workersToReturn;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<TWorker>{};\n        }\n    }\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_HAND_FROM_JSON_TEST_HPP\n"
  },
  {
    "path": "examples/tutorial_api_cpp/01_body_from_image_default.cpp",
    "content": "// ----------------------------- OpenPose C++ API Tutorial - Example 1 - Body from image -----------------------------\n// It reads an image, process it, and displays it with the pose keypoints.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000192.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Alternative 1\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n\n            // // Alternative 2\n            // op::opLog(datumsPtr->at(0)->poseKeypoints, op::Priority::High);\n\n            // // Alternative 3\n            // std::cout << datumsPtr->at(0)->poseKeypoints << std::endl;\n\n            // // Alternative 4 - Accessing each element of the keypoints\n            // op::opLog(\"\\nKeypoints:\", op::Priority::High);\n            // const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;\n            // op::opLog(\"Person pose keypoints:\", op::Priority::High);\n            // for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)\n            // {\n            //     op::opLog(\"Person \" + std::to_string(person) + \" (x, y, score):\", op::Priority::High);\n            //     for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)\n            //     {\n            //         std::string valueToPrint;\n            //         for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)\n            //             valueToPrint += std::to_string(   poseKeypoints[{person, bodyPart, xyscore}]   ) + \" \";\n            //         op::opLog(valueToPrint, op::Priority::High);\n            //     }\n            // }\n            // op::opLog(\" \", op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Process and display image\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);\n        if (datumProcessed != nullptr)\n        {\n            printKeypoints(datumProcessed);\n            if (!FLAGS_no_display)\n                display(datumProcessed);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/02_whole_body_from_image_default.cpp",
    "content": "// -------------------------- OpenPose C++ API Tutorial - Example 2 - Whole body from image --------------------------\n// It reads an image, process it, and displays it with the pose, hand, and face keypoints.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_POSE\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000241.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        // Add hand and face\n        opWrapper.configure(op::WrapperStructFace{true});\n        opWrapper.configure(op::WrapperStructHand{true});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Process and display image\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);\n        if (datumProcessed != nullptr)\n        {\n            printKeypoints(datumProcessed);\n            if (!FLAGS_no_display)\n                display(datumProcessed);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/03_keypoints_from_image.cpp",
    "content": "// ----------------------- OpenPose C++ API Tutorial - Example 3 - Body from image -----------------------\n// It reads an image, process it, and displays it with the pose (and optionally hand and face) keypoints. In addition,\n// it includes all the OpenPose configuration flags (enable/disable hand, face, output saving, etc.).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000294.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Process and display image\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);\n        if (datumProcessed != nullptr)\n        {\n            printKeypoints(datumProcessed);\n            if (!FLAGS_no_display)\n                display(datumProcessed);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/04_keypoints_from_images.cpp",
    "content": "// ----------------------- OpenPose C++ API Tutorial - Example 4 - Body from images ----------------------\n// It reads images, process them, and display them with the pose (and optionally hand and face) keypoints. In addition,\n// it includes all the OpenPose configuration flags (enable/disable hand, face, output saving, etc.).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nbool display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n        const auto key = (char)cv::waitKey(1);\n        return (key == 27);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return true;\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Read frames on directory\n        const auto imagePaths = op::getFilesOnDirectory(FLAGS_image_dir, op::Extensions::Images);\n\n        // Process and display images\n        for (const auto& imagePath : imagePaths)\n        {\n            const cv::Mat cvImageToProcess = cv::imread(imagePath);\n            const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n            auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);\n            if (datumProcessed != nullptr)\n            {\n                printKeypoints(datumProcessed);\n                if (!FLAGS_no_display)\n                {\n                    const auto userWantsToExit = display(datumProcessed);\n                    if (userWantsToExit)\n                    {\n                        op::opLog(\"User pressed Esc to exit demo.\", op::Priority::High);\n                        break;\n                    }\n                }\n            }\n            else\n                op::opLog(\"Image \" + imagePath + \" could not be processed.\", op::Priority::High);\n        }\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/05_keypoints_from_images_multi_gpu.cpp",
    "content": "// --------------- OpenPose C++ API Tutorial - Example 5 - Body from images and multi GPU ---------------\n// It reads images, process them, and display them with the pose (and optionally hand and face) keypoints. In addition,\n// it includes all the OpenPose configuration flags (enable/disable hand, face, output saving, etc.).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n// OpenPose\nDEFINE_bool(latency_is_irrelevant_and_computer_with_lots_of_ram, false,\n    \"If false, it will read and then then process images right away. If true, it will first store all the frames and\"\n    \" later process them (slightly faster). However: 1) Latency will hugely increase (no frames will be processed\"\n    \" until they have all been read). And 2) The program might go out of RAM memory with long videos or folders with\"\n    \" many images (so the computer might freeze).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nbool display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n        const auto key = (char)cv::waitKey(1);\n        return (key == 27);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return true;\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n        // Increase maximum wrapper queue size\n        if (FLAGS_latency_is_irrelevant_and_computer_with_lots_of_ram)\n            opWrapper.setDefaultMaxSizeQueues(std::numeric_limits<long long>::max());\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Read frames on directory\n        const auto imagePaths = op::getFilesOnDirectory(FLAGS_image_dir, op::Extensions::Images);\n\n        // Process and display images\n        // Option a) Harder to implement but the fastest method\n        // Create 2 different threads:\n        //     1. One pushing images to OpenPose all the time.\n        //     2. A second one retrieving those frames.\n        // Option b) Much easier and faster to implement but slightly slower runtime performance\n        if (!FLAGS_latency_is_irrelevant_and_computer_with_lots_of_ram)\n        {\n            // Read number of GPUs in your system\n            const auto numberGPUs = op::getGpuNumber();\n\n            for (auto imageBaseId = 0u ; imageBaseId < imagePaths.size() ; imageBaseId+=numberGPUs)\n            {\n                // Read and push images into OpenPose wrapper\n                for (auto gpuId = 0 ; gpuId < numberGPUs ; gpuId++)\n                {\n                    const auto imageId = imageBaseId+gpuId;\n                    if (imageId < imagePaths.size())\n                    {\n                        const auto& imagePath = imagePaths.at(imageId);\n                        // Faster alternative that moves imageToProcess\n                        cv::Mat cvImageToProcess = cv::imread(imagePath);\n                        op::Matrix imageToProcess = OP_CV2OPMAT(cvImageToProcess);\n                        opWrapper.waitAndEmplace(imageToProcess);\n                        // // Slower but safer alternative that copies imageToProcess\n                        // const auto imageToProcess = cv::imread(imagePath);\n                        // opWrapper.waitAndPush(imageToProcess);\n                    }\n                }\n                // Retrieve processed results from OpenPose wrapper\n                for (auto gpuId = 0 ; gpuId < numberGPUs ; gpuId++)\n                {\n                    const auto imageId = imageBaseId+gpuId;\n                    if (imageId < imagePaths.size())\n                    {\n                        std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> datumProcessed;\n                        const auto status = opWrapper.waitAndPop(datumProcessed);\n                        if (status && datumProcessed != nullptr)\n                        {\n                            printKeypoints(datumProcessed);\n                            if (!FLAGS_no_display)\n                            {\n                                const auto userWantsToExit = display(datumProcessed);\n                                if (userWantsToExit)\n                                {\n                                    op::opLog(\"User pressed Esc to exit demo.\", op::Priority::High);\n                                    break;\n                                }\n                            }\n                        }\n                        else\n                            op::opLog(\"Image could not be processed.\", op::Priority::High);\n                    }\n                }\n            }\n        }\n        // Option c) Even easier and faster to implement than option b. In addition, its runtime performance should\n        // be slightly faster too, but:\n        //  - Latency will hugely increase (no frames will be processed until they have all been read).\n        //  - The program might go out of RAM memory with long videos or folders with many images (so the computer\n        //    might freeze).\n        else\n        {\n            // Read and push all images into OpenPose wrapper\n            op::opLog(\"Loading images into OpenPose wrapper...\", op::Priority::High);\n            for (const auto& imagePath : imagePaths)\n            {\n                // Faster alternative that moves imageToProcess\n                cv::Mat cvImageToProcess = cv::imread(imagePath);\n                op::Matrix imageToProcess = OP_CV2OPMAT(cvImageToProcess);\n                opWrapper.waitAndEmplace(imageToProcess);\n                // // Slower but safer alternative that copies imageToProcess\n                // const auto imageToProcess = cv::imread(imagePath);\n                // opWrapper.waitAndPush(imageToProcess);\n            }\n            // Retrieve processed results from OpenPose wrapper\n            op::opLog(\"Retrieving results from OpenPose wrapper...\", op::Priority::High);\n            for (auto imageId = 0u ; imageId < imagePaths.size() ; imageId++)\n            {\n                std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> datumProcessed;\n                const auto status = opWrapper.waitAndPop(datumProcessed);\n                if (status && datumProcessed != nullptr)\n                {\n                    printKeypoints(datumProcessed);\n                    if (!FLAGS_no_display)\n                    {\n                        const auto userWantsToExit = display(datumProcessed);\n                        if (userWantsToExit)\n                        {\n                            op::opLog(\"User pressed Esc to exit demo.\", op::Priority::High);\n                            break;\n                        }\n                    }\n                }\n                else\n                    op::opLog(\"Image could not be processed.\", op::Priority::High);\n            }\n        }\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/06_face_from_image.cpp",
    "content": "// ----------------------------- OpenPose C++ API Tutorial - Example 6 - Face from Image -----------------------------\n// It reads an image and the face location, process it, and displays the face keypoints. In addition,\n// it includes all the OpenPose configuration flags.\n// Input: An image and the face rectangle locations.\n// Output: OpenPose face keypoint detection.\n// NOTE: This demo is auto-selecting the following flags: `--body 0 --face --face_detector 2`\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000241.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Required flags to enable heatmaps\n        FLAGS_body = 0;\n        FLAGS_face = true;\n        FLAGS_face_detector = 2;\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Read image and face rectangle locations\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        const std::vector<op::Rectangle<float>> faceRectangles{\n            op::Rectangle<float>{330.119385f, 277.532715f, 48.717274f, 48.717274f}, // Face of person 0\n            op::Rectangle<float>{24.036991f, 267.918793f, 65.175171f, 65.175171f},  // Face of person 1\n            op::Rectangle<float>{151.803436f, 32.477852f, 108.295761f, 108.295761f} // Face of person 2\n        };\n\n        // Create new datum\n        auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n        datumsPtr->emplace_back();\n        auto& datumPtr = datumsPtr->at(0);\n        datumPtr = std::make_shared<op::Datum>();\n        // Fill datum with image and faceRectangles\n        datumPtr->cvInputData = imageToProcess;\n        datumPtr->faceRectangles = faceRectangles;\n\n        // Process and display image\n        opWrapper.emplaceAndPop(datumsPtr);\n        if (datumsPtr != nullptr)\n        {\n            printKeypoints(datumsPtr);\n            if (!FLAGS_no_display)\n                display(datumsPtr);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Info\n        op::opLog(\"NOTE: In addition with the user flags, this demo has auto-selected the following flags:\\n\"\n                \"\\t`--body 0 --face --face_detector 2`\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/07_hand_from_image.cpp",
    "content": "// ----------------------------- OpenPose C++ API Tutorial - Example 7 - Face from Image -----------------------------\n// It reads an image and the hand location, process it, and displays the hand keypoints. In addition,\n// it includes all the OpenPose configuration flags.\n// Input: An image and the hand rectangle locations.\n// Output: OpenPose hand keypoint detection.\n// NOTE: This demo is auto-selecting the following flags: `--body 0 --hand --hand_detector 2`\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000241.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Required flags to enable heatmaps\n        FLAGS_body = 0;\n        FLAGS_hand = true;\n        FLAGS_hand_detector = 2;\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Read image and hand rectangle locations\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        const std::vector<std::array<op::Rectangle<float>, 2>> handRectangles{\n            // Left/Right hands of person 0\n            std::array<op::Rectangle<float>, 2>{\n                op::Rectangle<float>{320.035889f, 377.675049f, 69.300949f, 69.300949f}, // Left hand\n                op::Rectangle<float>{0.f, 0.f, 0.f, 0.f}},                              // Right hand\n            // Left/Right hands of person 1\n            std::array<op::Rectangle<float>, 2>{\n                op::Rectangle<float>{80.155792f, 407.673492f, 80.812706f, 80.812706f},  // Left hand\n                op::Rectangle<float>{46.449715f, 404.559753f, 98.898178f, 98.898178f}}, // Right hand\n            // Left/Right hands of person 2\n            std::array<op::Rectangle<float>, 2>{\n                op::Rectangle<float>{185.692673f, 303.112244f, 157.587555f, 157.587555f},// Left hand\n                op::Rectangle<float>{88.984360f, 268.866547f, 117.818230f, 117.818230f}} // Right hand\n        };\n\n        // Create new datum\n        auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n        datumsPtr->emplace_back();\n        auto& datumPtr = datumsPtr->at(0);\n        datumPtr = std::make_shared<op::Datum>();\n        // Fill datum with image and handRectangles\n        datumPtr->cvInputData = imageToProcess;\n        datumPtr->handRectangles = handRectangles;\n\n        // Process and display image\n        opWrapper.emplaceAndPop(datumsPtr);\n        if (datumsPtr != nullptr)\n        {\n            printKeypoints(datumsPtr);\n            if (!FLAGS_no_display)\n                display(datumsPtr);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Info\n        op::opLog(\"NOTE: In addition with the user flags, this demo has auto-selected the following flags:\\n\"\n                \"\\t`--body 0 --hand --hand_detector 2`\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/08_heatmaps_from_image.cpp",
    "content": "// ----------------------- OpenPose C++ API Tutorial - Example 8 - Heatmaps from image -----------------------\n// It reads an image, process it, and displays it with the body heatmaps. In addition, it includes all the\n// OpenPose configuration flags (enable/disable hand, face, output saving, etc.).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000294.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nbool display(\n    const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr, const int desiredChannel = 0)\n{\n    try\n    {\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Note: Heatmaps are in net_resolution size, which does not necessarily match the final image size\n            // Read heatmaps\n            auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n            // Read desired channel\n            const auto numberChannels = poseHeatMaps.getSize(0);\n            const auto height = poseHeatMaps.getSize(1);\n            const auto width = poseHeatMaps.getSize(2);\n            const cv::Mat desiredChannelHeatMap(\n                height, width, CV_32F, &poseHeatMaps.getPtr()[desiredChannel % numberChannels*height*width]);\n            // Read image used from OpenPose body network (same resolution than heatmaps)\n            auto& inputNetData = datumsPtr->at(0)->inputNetData[0];\n            const cv::Mat inputNetDataB(\n                height, width, CV_32F, &inputNetData.getPtr()[0]);\n            const cv::Mat inputNetDataG(\n                height, width, CV_32F, &inputNetData.getPtr()[height*width]);\n            const cv::Mat inputNetDataR(\n                height, width, CV_32F, &inputNetData.getPtr()[2*height*width]);\n            cv::Mat netInputImage;\n            cv::merge(std::vector<cv::Mat>{inputNetDataB, inputNetDataG, inputNetDataR}, netInputImage);\n            netInputImage = (netInputImage+0.5)*255;\n            // Turn into uint8 cv::Mat\n            cv::Mat netInputImageUint8;\n            netInputImage.convertTo(netInputImageUint8, CV_8UC1);\n            cv::Mat desiredChannelHeatMapUint8;\n            desiredChannelHeatMap.convertTo(desiredChannelHeatMapUint8, CV_8UC1);\n            // Combining both images\n            cv::Mat imageToRender;\n            cv::applyColorMap(desiredChannelHeatMapUint8, desiredChannelHeatMapUint8, cv::COLORMAP_JET);\n            cv::addWeighted(netInputImageUint8, 0.5, desiredChannelHeatMapUint8, 0.5, 0., imageToRender);\n            // Display image\n            if (!imageToRender.empty())\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", imageToRender);\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n        const auto key = (char)cv::waitKey(1);\n        return (key == 27);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        return true;\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            const auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n            const auto numberChannels = poseHeatMaps.getSize(0);\n            const auto height = poseHeatMaps.getSize(1);\n            const auto width = poseHeatMaps.getSize(2);\n            op::opLog(\"Body heatmaps has \" + std::to_string(numberChannels) + \" channels, and each channel has a\"\n                    \" dimension of \" + std::to_string(width) + \" x \" + std::to_string(height) + \" pixels.\",\n                    op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Required flags to enable heatmaps\n        FLAGS_heatmaps_add_parts = true;\n        FLAGS_heatmaps_add_bkg = true;\n        FLAGS_heatmaps_add_PAFs = true;\n        FLAGS_heatmaps_scale = 2;\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Process and display image\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n        auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);\n        if (datumProcessed != nullptr)\n        {\n            printKeypoints(datumProcessed);\n            if (!FLAGS_no_display)\n            {\n                const auto numberChannels = datumProcessed->at(0)->poseHeatMaps.getSize(0);\n                for (auto desiredChannel = 0 ; desiredChannel < numberChannels ; desiredChannel++)\n                    if (display(datumProcessed, desiredChannel))\n                        break;\n            }\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Info\n        op::opLog(\"NOTE: In addition with the user flags, this demo has auto-selected the following flags:\\n\"\n                \"\\t`--heatmaps_add_parts --heatmaps_add_bkg --heatmaps_add_PAFs`\",\n                op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/09_keypoints_from_heatmaps.cpp",
    "content": "// ----------------------- OpenPose C++ API Tutorial - Example 9 - Keypoints from heatmaps -----------------------\n// It reads a custom set of heatmaps and run the OpenPose greedy connection algorithm.\n// OpenPose will not run its internal body pose estimation network and will instead use\n// this data as the substitute of its network. The size of this element must match the size of the output of\n// its internal network, or it will lead to core dumped (segmentation) errors. You can modify the pose\n// estimation flags to match the dimension of both elements (e.g., `--net_resolution`, `--scale_number`, etc.).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_path, \"examples/media/COCO_val2014_000000000294.jpg\",\n    \"Process an image. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nvoid display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // User's displaying/saving/other processing here\n            // datum.cvOutputData: rendered frame with pose or heatmaps\n            // datum.poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n            {\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                cv::waitKey(0);\n            }\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n{\n    try\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"Body keypoints: \" + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Image to process\n        const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);\n        const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);\n\n        // Required flags to disable the OpenPose network\n        FLAGS_body = 2;\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapper);\n\n        // Heatmap set selection\n        std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> datumHeatmaps;\n        // Using a random set of heatmaps\n        // Replace the following lines inside the try-catch block with your custom heatmap generator\n        try\n        {\n            op::opLog(\"Temporarily running another OpenPose instance to get the heatmaps...\", op::Priority::High);\n            // Required flags to enable heatmaps\n            FLAGS_heatmaps_add_parts = true;\n            FLAGS_heatmaps_add_bkg = true;\n            FLAGS_heatmaps_add_PAFs = true;\n            FLAGS_heatmaps_scale = 3;\n            FLAGS_upsampling_ratio = 1;\n            FLAGS_body = 1;\n\n            // Configuring OpenPose\n            op::Wrapper opWrapperGetHeatMaps{op::ThreadManagerMode::Asynchronous};\n            configureWrapper(opWrapperGetHeatMaps);\n\n            // Starting OpenPose\n            opWrapperGetHeatMaps.start();\n\n            // Get heatmaps\n            datumHeatmaps = opWrapperGetHeatMaps.emplaceAndPop(imageToProcess);\n            if (datumHeatmaps == nullptr)\n                op::error(\"Image could not be processed.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n\n        // Starting OpenPose\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // Create new datum\n        auto datumProcessed = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n        datumProcessed->emplace_back();\n        auto& datumPtr = datumProcessed->at(0);\n        datumPtr = std::make_shared<op::Datum>();\n\n        // Fill datum\n        datumPtr->cvInputData = imageToProcess;\n        datumPtr->poseNetOutput = datumHeatmaps->at(0)->poseHeatMaps;\n\n        // Display image\n        if (opWrapper.emplaceAndPop(datumProcessed))\n        {\n            printKeypoints(datumProcessed);\n            if (!FLAGS_no_display)\n                display(datumProcessed);\n        }\n        else\n            op::opLog(\"Image could not be processed.\", op::Priority::High);\n\n        // Info\n        op::opLog(\"NOTE: In addition with the user flags, this demo has auto-selected the following flags:\\n\"\n                \"\\t`--body 2`\", op::Priority::High);\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/10_asynchronous_custom_input.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 10 - Custom Input -------------------------\n// Asynchronous mode: ideal for fast prototyping when performance is not an issue.\n// In this function, the user can implement its own way to create frames (e.g., reading his own folder of images)\n// and emplaces/pushes the frames to OpenPose.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n\n// This worker will just read and return all the basic image file formats in a directory\nclass UserInputClass\n{\npublic:\n    UserInputClass(const std::string& directoryPath) :\n        mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats\n        // If we want only e.g., \"jpg\" + \"png\" images\n        // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector<std::string>{\"jpg\", \"png\"})},\n        mCounter{0},\n        mClosed{false}\n    {\n        if (mImageFiles.empty())\n            op::error(\"No images found on: \" + directoryPath, __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> createDatum()\n    {\n        // Close program when empty frame\n        if (mClosed || mImageFiles.size() <= mCounter)\n        {\n            op::opLog(\"Last frame read and added to queue. Closing program after it is processed.\", op::Priority::High);\n            // This function stops this worker, which will eventually stop the whole thread system once all the frames\n            // have been processed\n            mClosed = true;\n            return nullptr;\n        }\n        else // if (!mClosed)\n        {\n            // Create new datum\n            auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n            datumsPtr->emplace_back();\n            auto& datumPtr = datumsPtr->at(0);\n            datumPtr = std::make_shared<op::Datum>();\n\n            // Fill datum\n            const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));\n            datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);\n\n            // If empty frame -> return nullptr\n            if (datumPtr->cvInputData.empty())\n            {\n                op::opLog(\"Empty frame detected on path: \" + mImageFiles.at(mCounter-1) + \". Closing program.\",\n                        op::Priority::High);\n                mClosed = true;\n                datumsPtr = nullptr;\n            }\n\n            return datumsPtr;\n        }\n    }\n\n    bool isFinished() const\n    {\n        return mClosed;\n    }\n\nprivate:\n    const std::vector<std::string> mImageFiles;\n    unsigned long long mCounter;\n    bool mClosed;\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::AsynchronousIn};\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // User processing\n        UserInputClass userInputClass(FLAGS_image_dir);\n        bool userWantsToExit = false;\n        while (!userWantsToExit && !userInputClass.isFinished())\n        {\n            // Push frame\n            auto datumToProcess = userInputClass.createDatum();\n            if (datumToProcess != nullptr)\n            {\n                auto successfullyEmplaced = opWrapper.waitAndEmplace(datumToProcess);\n                if (!successfullyEmplaced)\n                    op::opLog(\"Processed datum could not be emplaced.\", op::Priority::High);\n            }\n        }\n\n        op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        opWrapper.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 10 - Custom Input -------------------------\n// Asynchronous mode: ideal for fast prototyping when performance is not an issue.\n// In this function, the user can implement its own way to create frames (e.g., reading his own folder of images)\n// and emplaces/pushes the frames to OpenPose.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(video,                \"3d_4camera_video.avi\",\n    \"Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video.\");\nDEFINE_string(camera_parameter_path,    \"models/cameraParameters/flir/\",\n    \"String with the folder where the camera parameters are located. If there is only 1 XML file (for single\"\n    \" video, webcam, or images from the same camera), you must specify the whole XML file path (ending in .xml).\");\n\n// This worker will just read and return all the basic image file formats in a directory\nclass UserInputClass\n{\npublic:\n    UserInputClass(const std::string& videoPath, const std::string& cameraParameterPath) :\n        mClosed{false},\n        mFrameCounter{0ull},\n        mVideoCapture{videoPath}\n    {\n        if (!mVideoCapture.isOpened())\n        {\n            mClosed = true;\n            op::error(\"No video \" + videoPath + \" opened.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n\n        // Create CameraParameterReader\n        mCameraParameterReader.readParameters(cameraParameterPath);\n    }\n\n    std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> createDatum()\n    {\n        if (mClosed)\n        {\n            op::opLog(\"Video already closed, nullptr returned.\", op::Priority::High);\n            return nullptr;\n        }\n\n        // Read cv::Mat\n        cv::Mat cvInputData;\n        mVideoCapture >> cvInputData;\n        // If empty frame -> return nullptr\n        if (cvInputData.empty())\n        {\n            // Close program when empty frame\n            op::opLog(\"Empty frame detected, closing program.\", op::Priority::High);\n            mClosed = true;\n            return nullptr;\n        }\n\n        // Create new datum and add 3D information (cv::Mat splitted and camera parameters)\n        auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n        op::createMultiviewTDatum<op::Datum>(datumsPtr, mFrameCounter, mCameraParameterReader, (void*)&cvInputData);\n\n        return datumsPtr;\n    }\n\n    bool isFinished() const\n    {\n        return mClosed;\n    }\n\nprivate:\n    bool mClosed;\n    unsigned long long mFrameCounter;\n    cv::VideoCapture mVideoCapture;\n    op::CameraParameterReader mCameraParameterReader;\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Required flags to enable 3-D\n        FLAGS_3d = true;\n        FLAGS_number_people_max = 1;\n        FLAGS_3d_min_views = 3;\n        FLAGS_output_resolution = \"320x256\"; // Optional, but otherwise it gets too big to render in real time\n        // FLAGS_3d_views = X; // Not required because it only affects OpenPose producers (rather than custom ones)\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::AsynchronousIn};\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // User processing\n        UserInputClass userInputClass(FLAGS_video, FLAGS_camera_parameter_path);\n        bool userWantsToExit = false;\n        while (!userWantsToExit && !userInputClass.isFinished())\n        {\n            if (!opWrapper.isRunning())\n            {\n                op::opLog(\"OpenPose wrapper is no longer running, exiting video.\", op::Priority::High);\n                break;\n            }\n            // Push frame\n            auto datumToProcess = userInputClass.createDatum();\n            if (datumToProcess != nullptr)\n            {\n                auto successfullyEmplaced = opWrapper.waitAndEmplace(datumToProcess);\n                if (!successfullyEmplaced)\n                    op::opLog(\"Processed datum could not be emplaced.\", op::Priority::High);\n            }\n        }\n\n        op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        opWrapper.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/12_asynchronous_custom_output.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 11 - Custom Output -------------------------\n// Asynchronous mode: ideal for fast prototyping when performance is not an issue.\n// In this function, the user can implement its own way to render/display/storage the results.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nclass UserOutputClass\n{\npublic:\n    bool display(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        // User's displaying/saving/other processing here\n            // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n            // datumPtr->poseKeypoints: Array<float> with the estimated pose\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n            if (!cvMat.empty())\n                cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n            else\n                op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n        const auto key = (char)cv::waitKey(1);\n        return (key == 27);\n    }\n    void printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"\\nKeypoints:\");\n            // Accessing each element of the keypoints\n            const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;\n            op::opLog(\"Person pose keypoints:\");\n            for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)\n            {\n                op::opLog(\"Person \" + std::to_string(person) + \" (x, y, score):\");\n                for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)\n                {\n                    std::string valueToPrint;\n                    for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)\n                    {\n                        valueToPrint += std::to_string(   poseKeypoints[{person, bodyPart, xyscore}]   ) + \" \";\n                    }\n                    op::opLog(valueToPrint);\n                }\n            }\n            op::opLog(\" \");\n            // Alternative: just getting std::string equivalent\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n            // Heatmaps\n            const auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n            if (!poseHeatMaps.empty())\n            {\n                op::opLog(\"Pose heatmaps size: [\" + std::to_string(poseHeatMaps.getSize(0)) + \", \"\n                        + std::to_string(poseHeatMaps.getSize(1)) + \", \"\n                        + std::to_string(poseHeatMaps.getSize(2)) + \"]\");\n                const auto& faceHeatMaps = datumsPtr->at(0)->faceHeatMaps;\n                op::opLog(\"Face heatmaps size: [\" + std::to_string(faceHeatMaps.getSize(0)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(1)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(2)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(3)) + \"]\");\n                const auto& handHeatMaps = datumsPtr->at(0)->handHeatMaps;\n                op::opLog(\"Left hand heatmaps size: [\" + std::to_string(handHeatMaps[0].getSize(0)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(1)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(2)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(3)) + \"]\");\n                op::opLog(\"Right hand heatmaps size: [\" + std::to_string(handHeatMaps[1].getSize(0)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(1)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(2)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(3)) + \"]\");\n            }\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapper.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper{op::ThreadManagerMode::AsynchronousOut};\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.start();\n\n        // User processing\n        UserOutputClass userOutputClass;\n        bool userWantsToExit = false;\n        while (!userWantsToExit)\n        {\n            // Pop frame\n            std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> datumProcessed;\n            if (opWrapper.waitAndPop(datumProcessed))\n            {\n                if (!FLAGS_no_display)\n                    userWantsToExit = userOutputClass.display(datumProcessed);;\n                userOutputClass.printKeypoints(datumProcessed);\n            }\n            // If OpenPose finished reading images\n            else if (!opWrapper.isRunning())\n                break;\n            // Something else happened\n            else\n                op::opLog(\"Processed datum could not be emplaced.\", op::Priority::High);\n        }\n\n        op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        opWrapper.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/13_asynchronous_custom_input_output_and_datum.cpp",
    "content": "// --------------------- OpenPose C++ API Tutorial - Example 12 - Custom Input, Output, and Datum ---------------------\n// Asynchronous mode: ideal for fast prototyping when performance is not an issue.\n// In this function, the user can implement its own way to create frames (e.g., reading his own folder of images)\n// and its own way to render/display them after being processed by OpenPose.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// If the user needs his own variables, he can inherit the op::Datum struct and add them in there.\n// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define\n// WrapperT<std::vector<std::shared_ptr<UserDatum>>> instead of Wrapper\n// (or equivalently WrapperT<std::vector<std::shared_ptr<UserDatum>>>)\nstruct UserDatum : public op::Datum\n{\n    bool boolThatUserNeedsForSomeReason;\n\n    UserDatum(const bool boolThatUserNeedsForSomeReason_ = false) :\n        boolThatUserNeedsForSomeReason{boolThatUserNeedsForSomeReason_}\n    {}\n};\n\n// This worker will just read and return all the basic image file formats in a directory\nclass UserInputClass\n{\npublic:\n    UserInputClass(const std::string& directoryPath) :\n        mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats\n        // If we want only e.g., \"jpg\" + \"png\" images\n        // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector<std::string>{\"jpg\", \"png\"})},\n        mCounter{0},\n        mClosed{false}\n    {\n        if (mImageFiles.empty())\n            op::error(\"No images found on: \" + directoryPath, __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> createDatum()\n    {\n        // Close program when empty frame\n        if (mClosed || mImageFiles.size() <= mCounter)\n        {\n            op::opLog(\"Last frame read and added to queue. Closing program after it is processed.\", op::Priority::High);\n            // This function stops this worker, which will eventually stop the whole thread system once all the frames\n            // have been processed\n            mClosed = true;\n            return nullptr;\n        }\n        else // if (!mClosed)\n        {\n            // Create new datum\n            auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<UserDatum>>>();\n            datumsPtr->emplace_back();\n            auto& datumPtr = datumsPtr->at(0);\n            datumPtr = std::make_shared<UserDatum>();\n\n            // Fill datum\n            const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));\n            datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);\n\n            // If empty frame -> return nullptr\n            if (datumPtr->cvInputData.empty())\n            {\n                op::opLog(\"Empty frame detected on path: \" + mImageFiles.at(mCounter-1) + \". Closing program.\",\n                        op::Priority::High);\n                mClosed = true;\n                datumsPtr = nullptr;\n            }\n\n            return datumsPtr;\n        }\n    }\n\n    bool isFinished() const\n    {\n        return mClosed;\n    }\n\nprivate:\n    const std::vector<std::string> mImageFiles;\n    unsigned long long mCounter;\n    bool mClosed;\n};\n\n// This worker will just read and return all the jpg files in a directory\nclass UserOutputClass\n{\npublic:\n    bool display(const std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's displaying/saving/other processing here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n                const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n                if (!cvMat.empty())\n                    cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                else\n                    op::opLog(\"Empty cv::Mat as output.\", op::Priority::High);\n            }\n            else\n                op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n            const auto key = (char)cv::waitKey(1);\n            return (key == 27);\n        }\n        catch (const std::exception& e)\n        {\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return true;\n        }\n    }\n    void printKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        // Example: How to use the pose keypoints\n        if (datumsPtr != nullptr && !datumsPtr->empty())\n        {\n            op::opLog(\"\\nKeypoints:\");\n            // Accessing each element of the keypoints\n            const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;\n            op::opLog(\"Person pose keypoints:\");\n            for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)\n            {\n                op::opLog(\"Person \" + std::to_string(person) + \" (x, y, score):\");\n                for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)\n                {\n                    std::string valueToPrint;\n                    for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)\n                        valueToPrint += std::to_string(   poseKeypoints[{person, bodyPart, xyscore}]   ) + \" \";\n                    op::opLog(valueToPrint);\n                }\n            }\n            op::opLog(\" \");\n            // Alternative: just getting std::string equivalent\n            op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);\n            op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);\n            op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);\n            // Heatmaps\n            const auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n            if (!poseHeatMaps.empty())\n            {\n                op::opLog(\"Pose heatmaps size: [\" + std::to_string(poseHeatMaps.getSize(0)) + \", \"\n                        + std::to_string(poseHeatMaps.getSize(1)) + \", \"\n                        + std::to_string(poseHeatMaps.getSize(2)) + \"]\");\n                const auto& faceHeatMaps = datumsPtr->at(0)->faceHeatMaps;\n                op::opLog(\"Face heatmaps size: [\" + std::to_string(faceHeatMaps.getSize(0)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(1)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(2)) + \", \"\n                        + std::to_string(faceHeatMaps.getSize(3)) + \"]\");\n                const auto& handHeatMaps = datumsPtr->at(0)->handHeatMaps;\n                op::opLog(\"Left hand heatmaps size: [\" + std::to_string(handHeatMaps[0].getSize(0)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(1)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(2)) + \", \"\n                        + std::to_string(handHeatMaps[0].getSize(3)) + \"]\");\n                op::opLog(\"Right hand heatmaps size: [\" + std::to_string(handHeatMaps[1].getSize(0)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(1)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(2)) + \", \"\n                        + std::to_string(handHeatMaps[1].getSize(3)) + \"]\");\n            }\n        }\n        else\n            op::opLog(\"Nullptr or empty datumsPtr found.\", op::Priority::High);\n    }\n};\n\nvoid configureWrapper(op::WrapperT<UserDatum>& opWrapperT)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapperT.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapperT.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapperT.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapperT.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapperT.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapperT.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // Configuring OpenPose\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::WrapperT<UserDatum> opWrapperT{op::ThreadManagerMode::Asynchronous};\n        configureWrapper(opWrapperT);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapperT.start();\n\n        // User processing\n        UserInputClass userInputClass(FLAGS_image_dir);\n        UserOutputClass userOutputClass;\n        bool userWantsToExit = false;\n        while (!userWantsToExit && !userInputClass.isFinished())\n        {\n            // Push frame\n            auto datumToProcess = userInputClass.createDatum();\n            if (datumToProcess != nullptr)\n            {\n                auto successfullyEmplaced = opWrapperT.waitAndEmplace(datumToProcess);\n                // Pop frame\n                std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> datumProcessed;\n                if (successfullyEmplaced && opWrapperT.waitAndPop(datumProcessed))\n                {\n                    if (!FLAGS_no_display)\n                        userWantsToExit = userOutputClass.display(datumProcessed);\n                    userOutputClass.printKeypoints(datumProcessed);\n                }\n                else\n                    op::opLog(\"Processed datum could not be emplaced.\", op::Priority::High);\n            }\n        }\n\n        op::opLog(\"Stopping thread(s)\", op::Priority::High);\n        opWrapperT.stop();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/14_synchronous_custom_input.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 13 - Custom Input -------------------------\n// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime\n// performance.\n// In this function, the user can implement its own way to create frames (e.g., reading his own folder of images).\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n\n// This worker will just read and return all the basic image file formats in a directory\nclass WUserInput : public op::WorkerProducer<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>\n{\npublic:\n    WUserInput(const std::string& directoryPath) :\n        mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats\n        // If we want only e.g., \"jpg\" + \"png\" images\n        // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector<std::string>{\"jpg\", \"png\"})},\n        mCounter{0}\n    {\n        if (mImageFiles.empty())\n            op::error(\"No images found on: \" + directoryPath, __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    void initializationOnThread() {}\n\n    std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>> workProducer()\n    {\n        try\n        {\n            // Close program when empty frame\n            if (mImageFiles.size() <= mCounter)\n            {\n                op::opLog(\"Last frame read and added to queue. Closing program after it is processed.\",\n                        op::Priority::High);\n                // This function stops this worker, which will eventually stop the whole thread system once all the\n                // frames have been processed\n                this->stop();\n                return nullptr;\n            }\n            else\n            {\n                // Create new datum\n                auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<op::Datum>>>();\n                datumsPtr->emplace_back();\n                auto& datumPtr = datumsPtr->at(0);\n                datumPtr = std::make_shared<op::Datum>();\n\n                // Fill datum\n                const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));\n                datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);\n\n                // If empty frame -> return nullptr\n                if (datumPtr->cvInputData.empty())\n                {\n                    op::opLog(\"Empty frame detected on path: \" + mImageFiles.at(mCounter-1) + \". Closing program.\",\n                        op::Priority::High);\n                    this->stop();\n                    datumsPtr = nullptr;\n                }\n\n                return datumsPtr;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\nprivate:\n    const std::vector<std::string> mImageFiles;\n    unsigned long long mCounter;\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        // const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        const auto multipleView = false;\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Initializing the user custom classes\n        // Frames producer (e.g., video, webcam, ...)\n        auto wUserInput = std::make_shared<WUserInput>(FLAGS_image_dir);\n        // Add custom processing\n        const auto workerInputOnNewThread = true;\n        opWrapper.setWorker(op::WorkerType::Input, wUserInput, workerInputOnNewThread);\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper;\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/15_synchronous_custom_preprocessing.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 14 - Custom Pre-processing -------------------------\n// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime\n// performance.\n// In this function, the user can implement its own pre-processing, i.e., his function will be called after the image\n// has been read by OpenPose but before OpenPose processes the frames.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// This worker will just invert the image\nclass WUserPreProcessing : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>\n{\npublic:\n    WUserPreProcessing()\n    {\n        // User's constructor here\n    }\n\n    void initializationOnThread() {}\n\n    void work(std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's pre-processing (after OpenPose read the input image & before OpenPose processing) here\n                // datumPtr->cvInputData: input frame\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                for (auto& datumPtr : *datumsPtr)\n                {\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);\n                    cv::bitwise_not(cvOutputData, cvOutputData);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Initializing the user custom classes\n        // Processing\n        auto wUserPreProcessing = std::make_shared<WUserPreProcessing>();\n        // Add custom processing\n        const auto workerProcessingOnNewThread = true;\n        opWrapper.setWorker(op::WorkerType::PreProcessing, wUserPreProcessing, workerProcessingOnNewThread);\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapper.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper;\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/16_synchronous_custom_postprocessing.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 15 - Custom Post-processing -------------------------\n// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime\n// performance.\n// In this function, the user can implement its own post-processing, i.e., his function will be called after OpenPose\n// has processed the frames but before saving or visualizing any result.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// This worker will just invert the image\nclass WUserPostProcessing : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>\n{\npublic:\n    WUserPostProcessing()\n    {\n        // User's constructor here\n    }\n\n    void initializationOnThread() {}\n\n    void work(std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's post-processing (after OpenPose processing & before OpenPose outputs) here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                for (auto& datumPtr : *datumsPtr)\n                {\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);\n                    cv::bitwise_not(cvOutputData, cvOutputData);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Initializing the user custom classes\n        // Processing\n        auto wUserPostProcessing = std::make_shared<WUserPostProcessing>();\n        // Add custom processing\n        const auto workerProcessingOnNewThread = true;\n        opWrapper.setWorker(op::WorkerType::PostProcessing, wUserPostProcessing, workerProcessingOnNewThread);\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapper.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // GUI (comment or use default argument to disable any visual output)\n        const op::WrapperStructGui wrapperStructGui{\n            op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\n        opWrapper.configure(wrapperStructGui);\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper;\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/17_synchronous_custom_output.cpp",
    "content": "// ------------------------- OpenPose C++ API Tutorial - Example 16 - Custom Output -------------------------\n// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime\n// performance.\n// In this function, the user can implement its own way to render/display/storage the results.\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// This worker will just read and return all the jpg files in a directory\nclass WUserOutput : public op::WorkerConsumer<std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>>\n{\npublic:\n    void initializationOnThread() {}\n\n    void workConsumer(const std::shared_ptr<std::vector<std::shared_ptr<op::Datum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's displaying/saving/other processing here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                // Show in command line the resulting pose keypoints for body, face and hands\n                op::opLog(\"\\nKeypoints:\");\n                // Accessing each element of the keypoints\n                const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;\n                op::opLog(\"Person pose keypoints:\");\n                for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)\n                {\n                    op::opLog(\"Person \" + std::to_string(person) + \" (x, y, score):\");\n                    for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)\n                    {\n                        std::string valueToPrint;\n                        for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)\n                        {\n                            valueToPrint += std::to_string(   poseKeypoints[{person, bodyPart, xyscore}]   ) + \" \";\n                        }\n                        op::opLog(valueToPrint);\n                    }\n                }\n                op::opLog(\" \");\n                // Alternative: just getting std::string equivalent\n                op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString());\n                op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString());\n                op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString());\n                // Heatmaps\n                const auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n                if (!poseHeatMaps.empty())\n                {\n                    op::opLog(\"Pose heatmaps size: [\" + std::to_string(poseHeatMaps.getSize(0)) + \", \"\n                            + std::to_string(poseHeatMaps.getSize(1)) + \", \"\n                            + std::to_string(poseHeatMaps.getSize(2)) + \"]\");\n                    const auto& faceHeatMaps = datumsPtr->at(0)->faceHeatMaps;\n                    op::opLog(\"Face heatmaps size: [\" + std::to_string(faceHeatMaps.getSize(0)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(1)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(2)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(3)) + \"]\");\n                    const auto& handHeatMaps = datumsPtr->at(0)->handHeatMaps;\n                    op::opLog(\"Left hand heatmaps size: [\" + std::to_string(handHeatMaps[0].getSize(0)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(1)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(2)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(3)) + \"]\");\n                    op::opLog(\"Right hand heatmaps size: [\" + std::to_string(handHeatMaps[1].getSize(0)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(1)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(2)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(3)) + \"]\");\n                }\n\n                // Display results (if enabled)\n                if (!FLAGS_no_display)\n                {\n                    // Display rendered output image\n                    const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n                    if (!cvMat.empty())\n                    {\n                        cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                        // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n                        const char key = (char)cv::waitKey(1);\n                        if (key == 27)\n                            this->stop();\n                    }\n                    else\n                        op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nvoid configureWrapper(op::Wrapper& opWrapper)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // producerType\n        op::ProducerType producerType;\n        op::String producerString;\n        std::tie(producerType, producerString) = op::flagsToProducer(\n            op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\n            FLAGS_flir_camera, FLAGS_flir_camera_index);\n        // cameraSize\n        const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Initializing the user custom classes\n        // GUI (Display)\n        auto wUserOutput = std::make_shared<WUserOutput>();\n        // Add custom processing\n        const auto workerOutputOnNewThread = true;\n        opWrapper.setWorker(op::WorkerType::Output, wUserOutput, workerOutputOnNewThread);\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapper.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapper.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapper.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapper.configure(wrapperStructExtra);\n        // Producer (use default to disable any input)\n        const op::WrapperStructInput wrapperStructInput{\n            producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\n            FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\n            cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\n        opWrapper.configure(wrapperStructInput);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapper.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapper.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::Wrapper opWrapper;\n        configureWrapper(opWrapper);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapper.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/18_synchronous_custom_all_and_datum.cpp",
    "content": "// --- OpenPose C++ API Tutorial - Example 17 - Custom Input, Pre-processing, Post-processing, Output, and Datum ---\n// Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime\n// performance.\n// In this function, the user can implement its own way to read frames, implement its own post-processing (i.e., his\n// function will be called after OpenPose has processed the frames but before saving), visualizing any result\n// render/display/storage the results, and use their custom Datum structure\n\n// Third-party dependencies\n#include <opencv2/opencv.hpp>\n// Command-line user interface\n#define OPENPOSE_FLAGS_DISABLE_PRODUCER\n#define OPENPOSE_FLAGS_DISABLE_DISPLAY\n#include <openpose/flags.hpp>\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\n// Custom OpenPose flags\n// Producer\nDEFINE_string(image_dir,                \"examples/media/\",\n    \"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\");\n// Display\nDEFINE_bool(no_display,                 false,\n    \"Enable to disable the visual display.\");\n\n// If the user needs his own variables, he can inherit the op::Datum struct and add them in there.\n// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define\n// WrapperT<std::vector<std::shared_ptr<UserDatum>>> instead of Wrapper\n// (or equivalently WrapperT<std::vector<std::shared_ptr<UserDatum>>>)\nstruct UserDatum : public op::Datum\n{\n    bool boolThatUserNeedsForSomeReason;\n\n    UserDatum(const bool boolThatUserNeedsForSomeReason_ = false) :\n        boolThatUserNeedsForSomeReason{boolThatUserNeedsForSomeReason_}\n    {}\n};\n\n// This worker will just read and return all the basic image file formats in a directory\nclass WUserInput : public op::WorkerProducer<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    WUserInput(const std::string& directoryPath) :\n        mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats\n        // If we want only e.g., \"jpg\" + \"png\" images\n        // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector<std::string>{\"jpg\", \"png\"})},\n        mCounter{0}\n    {\n        if (mImageFiles.empty())\n            op::error(\"No images found on: \" + directoryPath, __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    void initializationOnThread() {}\n\n    std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>> workProducer()\n    {\n        try\n        {\n            // Close program when empty frame\n            if (mImageFiles.size() <= mCounter)\n            {\n                op::opLog(\n                    \"Last frame read and added to queue. Closing program after it is processed.\", op::Priority::High);\n                // This function stops this worker, which will eventually stop the whole thread system once all the\n                // frames have been processed\n                this->stop();\n                return nullptr;\n            }\n            else\n            {\n                // Create new datum\n                auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<UserDatum>>>();\n                datumsPtr->emplace_back();\n                auto& datumPtr = datumsPtr->at(0);\n                datumPtr = std::make_shared<UserDatum>();\n\n                // Fill datum\n                const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));\n                datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);\n\n                // If empty frame -> return nullptr\n                if (datumPtr->cvInputData.empty())\n                {\n                    op::opLog(\n                        \"Empty frame detected on path: \" + mImageFiles.at(mCounter-1) + \". Closing program.\",\n                        op::Priority::High);\n                    this->stop();\n                    datumsPtr = nullptr;\n                }\n\n                return datumsPtr;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\nprivate:\n    const std::vector<std::string> mImageFiles;\n    unsigned long long mCounter;\n};\n\n// This worker will just invert the image\nclass WUserPostProcessing : public op::Worker<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    WUserPostProcessing()\n    {\n        // User's constructor here\n    }\n\n    void initializationOnThread() {}\n\n    void work(std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's post-processing (after OpenPose processing & before OpenPose outputs) here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                for (auto& datumPtr : *datumsPtr)\n                {\n                    cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);\n                    cv::bitwise_not(cvOutputData, cvOutputData);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\n// This worker will just read and return all the jpg files in a directory\nclass WUserOutput : public op::WorkerConsumer<std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>>\n{\npublic:\n    void initializationOnThread() {}\n\n    void workConsumer(const std::shared_ptr<std::vector<std::shared_ptr<UserDatum>>>& datumsPtr)\n    {\n        try\n        {\n            // User's displaying/saving/other processing here\n                // datumPtr->cvOutputData: rendered frame with pose or heatmaps\n                // datumPtr->poseKeypoints: Array<float> with the estimated pose\n            if (datumsPtr != nullptr && !datumsPtr->empty())\n            {\n                // Show in command line the resulting pose keypoints for body, face and hands\n                op::opLog(\"\\nKeypoints:\");\n                // Accessing each element of the keypoints\n                const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;\n                op::opLog(\"Person pose keypoints:\");\n                for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)\n                {\n                    op::opLog(\"Person \" + std::to_string(person) + \" (x, y, score):\");\n                    for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)\n                    {\n                        std::string valueToPrint;\n                        for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)\n                        {\n                            valueToPrint += std::to_string(   poseKeypoints[{person, bodyPart, xyscore}]   ) + \" \";\n                        }\n                        op::opLog(valueToPrint);\n                    }\n                }\n                op::opLog(\" \");\n                // Alternative: just getting std::string equivalent\n                op::opLog(\"Face keypoints: \" + datumsPtr->at(0)->faceKeypoints.toString());\n                op::opLog(\"Left hand keypoints: \" + datumsPtr->at(0)->handKeypoints[0].toString());\n                op::opLog(\"Right hand keypoints: \" + datumsPtr->at(0)->handKeypoints[1].toString());\n                // Heatmaps\n                const auto& poseHeatMaps = datumsPtr->at(0)->poseHeatMaps;\n                if (!poseHeatMaps.empty())\n                {\n                    op::opLog(\"Pose heatmaps size: [\" + std::to_string(poseHeatMaps.getSize(0)) + \", \"\n                            + std::to_string(poseHeatMaps.getSize(1)) + \", \"\n                            + std::to_string(poseHeatMaps.getSize(2)) + \"]\");\n                    const auto& faceHeatMaps = datumsPtr->at(0)->faceHeatMaps;\n                    op::opLog(\"Face heatmaps size: [\" + std::to_string(faceHeatMaps.getSize(0)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(1)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(2)) + \", \"\n                            + std::to_string(faceHeatMaps.getSize(3)) + \"]\");\n                    const auto& handHeatMaps = datumsPtr->at(0)->handHeatMaps;\n                    op::opLog(\"Left hand heatmaps size: [\" + std::to_string(handHeatMaps[0].getSize(0)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(1)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(2)) + \", \"\n                            + std::to_string(handHeatMaps[0].getSize(3)) + \"]\");\n                    op::opLog(\"Right hand heatmaps size: [\" + std::to_string(handHeatMaps[1].getSize(0)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(1)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(2)) + \", \"\n                            + std::to_string(handHeatMaps[1].getSize(3)) + \"]\");\n                }\n\n                // Display results (if enabled)\n                if (!FLAGS_no_display)\n                {\n                    // Display rendered output image\n                    const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);\n                    if (!cvMat.empty())\n                    {\n                        cv::imshow(OPEN_POSE_NAME_AND_VERSION + \" - Tutorial C++ API\", cvMat);\n                        // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)\n                        const char key = (char)cv::waitKey(1);\n                        if (key == 27)\n                            this->stop();\n                    }\n                    else\n                        op::opLog(\"Empty cv::Mat as output.\", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n};\n\nvoid configureWrapper(op::WrapperT<UserDatum>& opWrapperT)\n{\n    try\n    {\n        // Configuring OpenPose\n\n        // logging_level\n        op::checkBool(\n            0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\n            __LINE__, __FUNCTION__, __FILE__);\n        op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);\n        op::Profiler::setDefaultX(FLAGS_profile_speed);\n\n        // Applying user defined configuration - GFlags to program variables\n        // outputSize\n        const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\n        // netInputSize\n        const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n        // faceNetInputSize\n        const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\n        // handNetInputSize\n        const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\n        // poseMode\n        const auto poseMode = op::flagsToPoseMode(FLAGS_body);\n        // poseModel\n        const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));\n        // JSON saving\n        if (!FLAGS_write_keypoint.empty())\n            op::opLog(\n                \"Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`\"\n                \" instead.\", op::Priority::Max);\n        // keypointScaleMode\n        const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);\n        // heatmaps to add\n        const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\n                                                      FLAGS_heatmaps_add_PAFs);\n        const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\n        // >1 camera view?\n        const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\n        // Face and hand detectors\n        const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);\n        const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);\n        // Enabling Google Logging\n        const bool enableGoogleLogging = true;\n\n        // Initializing the user custom classes\n        // Frames producer (e.g., video, webcam, ...)\n        auto wUserInput = std::make_shared<WUserInput>(FLAGS_image_dir);\n        // Processing\n        auto wUserPostProcessing = std::make_shared<WUserPostProcessing>();\n        // GUI (Display)\n        auto wUserOutput = std::make_shared<WUserOutput>();\n\n        // Add custom input\n        const auto workerInputOnNewThread = false;\n        opWrapperT.setWorker(op::WorkerType::Input, wUserInput, workerInputOnNewThread);\n        // Add custom processing\n        const auto workerProcessingOnNewThread = false;\n        opWrapperT.setWorker(op::WorkerType::PostProcessing, wUserPostProcessing, workerProcessingOnNewThread);\n        // Add custom output\n        const auto workerOutputOnNewThread = true;\n        opWrapperT.setWorker(op::WorkerType::Output, wUserOutput, workerOutputOnNewThread);\n\n        // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\n        const op::WrapperStructPose wrapperStructPose{\n            poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\n            FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\n            op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\n            (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\n            heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\n            FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\n            op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\n        opWrapperT.configure(wrapperStructPose);\n        // Face configuration (use op::WrapperStructFace{} to disable it)\n        const op::WrapperStructFace wrapperStructFace{\n            FLAGS_face, faceDetector, faceNetInputSize,\n            op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\n            (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\n        opWrapperT.configure(wrapperStructFace);\n        // Hand configuration (use op::WrapperStructHand{} to disable it)\n        const op::WrapperStructHand wrapperStructHand{\n            FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\n            op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\n            (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\n        opWrapperT.configure(wrapperStructHand);\n        // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)\n        const op::WrapperStructExtra wrapperStructExtra{\n            FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\n        opWrapperT.configure(wrapperStructExtra);\n        // Output (comment or use default argument to disable any output)\n        const op::WrapperStructOutput wrapperStructOutput{\n            FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\n            op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\n            FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\n            op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\n            op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\n            op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\n            op::String(FLAGS_udp_port)};\n        opWrapperT.configure(wrapperStructOutput);\n        // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});\n        // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\n        if (FLAGS_disable_multi_thread)\n            opWrapperT.disableMultiThreading();\n    }\n    catch (const std::exception& e)\n    {\n        op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    }\n}\n\nint tutorialApiCpp()\n{\n    try\n    {\n        op::opLog(\"Starting OpenPose demo...\", op::Priority::High);\n        const auto opTimer = op::getTimerInit();\n\n        // OpenPose wrapper\n        op::opLog(\"Configuring OpenPose...\", op::Priority::High);\n        op::WrapperT<UserDatum> opWrapperT;\n        configureWrapper(opWrapperT);\n\n        // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished\n        op::opLog(\"Starting thread(s)...\", op::Priority::High);\n        opWrapperT.exec();\n\n        // Measuring total time\n        op::printTime(opTimer, \"OpenPose demo successfully finished. Total time: \", \" seconds.\", op::Priority::High);\n\n        // Return\n        return 0;\n    }\n    catch (const std::exception&)\n    {\n        return -1;\n    }\n}\n\nint main(int argc, char *argv[])\n{\n    // Parsing command line flags\n    gflags::ParseCommandLineFlags(&argc, &argv, true);\n\n    // Running tutorialApiCpp\n    return tutorialApiCpp();\n}\n"
  },
  {
    "path": "examples/tutorial_api_cpp/CMakeLists.txt",
    "content": "set(EXAMPLE_FILES\n    01_body_from_image_default.cpp\n    02_whole_body_from_image_default.cpp\n    03_keypoints_from_image.cpp\n    04_keypoints_from_images.cpp\n    05_keypoints_from_images_multi_gpu.cpp\n    06_face_from_image.cpp\n    07_hand_from_image.cpp\n    08_heatmaps_from_image.cpp\n    09_keypoints_from_heatmaps.cpp\n    10_asynchronous_custom_input.cpp\n    11_asynchronous_custom_input_multi_camera.cpp\n    12_asynchronous_custom_output.cpp\n    13_asynchronous_custom_input_output_and_datum.cpp\n    14_synchronous_custom_input.cpp\n    15_synchronous_custom_preprocessing.cpp\n    16_synchronous_custom_postprocessing.cpp\n    17_synchronous_custom_output.cpp\n    18_synchronous_custom_all_and_datum.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\n\nforeach(EXAMPLE_FILE ${EXAMPLE_FILES})\n\n  get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)\n\n  if (UNIX OR APPLE)\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\n  elseif (WIN32)\n    set(EXE_NAME \"${SOURCE_NAME}\")\n  endif ()\n\n  message(STATUS \"Adding Example ${EXE_NAME}\")\n  add_executable(${EXE_NAME} ${EXAMPLE_FILE})\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\n\n  if (WIN32)\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"Examples/Tutorial/C++ API\")\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\n    # Properties->General->Output Directory\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  endif (WIN32)\n\nendforeach()\n"
  },
  {
    "path": "examples/tutorial_api_cpp/README.md",
    "content": "# C++ API Examples\nSee the [OpenPose C++ API doc](../../doc/04_cpp_api.md) for more details on this folder.\n\nThis folder provides examples to the basic OpenPose C++ API. The analogous Python API is exposed in [examples/tutorial_api_python/](../tutorial_api_python/).\n"
  },
  {
    "path": "examples/tutorial_api_python/01_body_from_image.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000192.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Process Image\n    datum = op.Datum()\n    imageToProcess = cv2.imread(args[0].image_path)\n    datum.cvInputData = imageToProcess\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n\n    # Display Image\n    print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    cv2.waitKey(0)\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/02_whole_body_from_image.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000241.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"face\"] = True\n    params[\"hand\"] = True\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Process Image\n    datum = op.Datum()\n    imageToProcess = cv2.imread(args[0].image_path)\n    datum.cvInputData = imageToProcess\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n\n    # Display Image\n    print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n    print(\"Face keypoints: \\n\" + str(datum.faceKeypoints))\n    print(\"Left hand keypoints: \\n\" + str(datum.handKeypoints[0]))\n    print(\"Right hand keypoints: \\n\" + str(datum.handKeypoints[1]))\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    cv2.waitKey(0)\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/04_keypoints_from_images.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\nimport time\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_dir\", default=\"../../../examples/media/\", help=\"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\")\n    parser.add_argument(\"--no_display\", default=False, help=\"Enable to disable the visual display.\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Read frames on directory\n    imagePaths = op.get_images_on_directory(args[0].image_dir);\n    start = time.time()\n\n    # Process and display images\n    for imagePath in imagePaths:\n        datum = op.Datum()\n        imageToProcess = cv2.imread(imagePath)\n        datum.cvInputData = imageToProcess\n        opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n\n        print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n\n        if not args[0].no_display:\n            cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n            key = cv2.waitKey(15)\n            if key == 27: break\n\n    end = time.time()\n    print(\"OpenPose demo successfully finished. Total time: \" + str(end - start) + \" seconds\")\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/05_keypoints_from_images_multi_gpu.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\nimport time\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_dir\", default=\"../../../examples/media/\", help=\"Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).\")\n    parser.add_argument(\"--no_display\", default=False, help=\"Enable to disable the visual display.\")\n    parser.add_argument(\"--num_gpu\", default=op.get_gpu_number(), help=\"Number of GPUs.\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"num_gpu\"] = int(vars(args[0])[\"num_gpu\"])\n    numberGPUs = int(params[\"num_gpu\"])\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Read frames on directory\n    imagePaths = op.get_images_on_directory(args[0].image_dir);\n\n    # Read number of GPUs in your system\n    start = time.time()\n\n    # Process and display images\n    for imageBaseId in range(0, len(imagePaths), numberGPUs):\n\n        # Create datums\n        images = []\n\n        # Read and push images into OpenPose wrapper\n        for gpuId in range(0, numberGPUs):\n\n            imageId = imageBaseId+gpuId\n            if imageId < len(imagePaths):\n\n                imagePath = imagePaths[imageBaseId+gpuId]\n                datum = op.Datum()\n                images.append(cv2.imread(imagePath))\n                datum.cvInputData = images[-1]\n                opWrapper.waitAndEmplace(op.VectorDatum([datum]))\n\n        # Retrieve processed results from OpenPose wrapper\n        for gpuId in range(0, numberGPUs):\n\n            imageId = imageBaseId+gpuId\n            if imageId < len(imagePaths):\n\n                datums = op.VectorDatum()\n                opWrapper.waitAndPop(datums)\n                datum = datums[0]\n\n                print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n\n                if not args[0].no_display:\n                    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n                    key = cv2.waitKey(15)\n                    if key == 27: break\n\n    end = time.time()\n    print(\"OpenPose demo successfully finished. Total time: \" + str(end - start) + \" seconds\")\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/06_face_from_image.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\nimport time\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000241.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"face\"] = True\n    params[\"face_detector\"] = 2\n    params[\"body\"] = 0\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Read image and face rectangle locations\n    imageToProcess = cv2.imread(args[0].image_path)\n    faceRectangles = [\n        op.Rectangle(330.119385, 277.532715, 48.717274, 48.717274),\n        op.Rectangle(24.036991, 267.918793, 65.175171, 65.175171),\n        op.Rectangle(151.803436, 32.477852, 108.295761, 108.295761),\n    ]\n\n    # Create new datum\n    datum = op.Datum()\n    datum.cvInputData = imageToProcess\n    datum.faceRectangles = faceRectangles\n\n    # Process and display image\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n    print(\"Face keypoints: \\n\" + str(datum.faceKeypoints))\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    cv2.waitKey(0)\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/07_hand_from_image.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\nimport time\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000241.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"hand\"] = True\n    params[\"hand_detector\"] = 2\n    params[\"body\"] = 0\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Read image and face rectangle locations\n    imageToProcess = cv2.imread(args[0].image_path)\n    handRectangles = [\n        # Left/Right hands person 0\n        [\n        op.Rectangle(320.035889, 377.675049, 69.300949, 69.300949),\n        op.Rectangle(0., 0., 0., 0.),\n        ],\n        # Left/Right hands person 1\n        [\n        op.Rectangle(80.155792, 407.673492, 80.812706, 80.812706),\n        op.Rectangle(46.449715, 404.559753, 98.898178, 98.898178),\n        ],\n        # Left/Right hands person 2\n        [\n        op.Rectangle(185.692673, 303.112244, 157.587555, 157.587555),\n        op.Rectangle(88.984360, 268.866547, 117.818230, 117.818230),\n        ]\n    ]\n\n    # Create new datum\n    datum = op.Datum()\n    datum.cvInputData = imageToProcess\n    datum.handRectangles = handRectangles\n\n    # Process and display image\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n    print(\"Left hand keypoints: \\n\" + str(datum.handKeypoints[0]))\n    print(\"Right hand keypoints: \\n\" + str(datum.handKeypoints[1]))\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    cv2.waitKey(0)\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/08_heatmaps_from_image.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000192.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"heatmaps_add_parts\"] = True\n    params[\"heatmaps_add_bkg\"] = True\n    params[\"heatmaps_add_PAFs\"] = True\n    params[\"heatmaps_scale\"] = 2\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Process Image\n    datum = op.Datum()\n    imageToProcess = cv2.imread(args[0].image_path)\n    datum.cvInputData = imageToProcess\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n\n    # Process outputs\n    outputImageF = (datum.inputNetData[0].copy())[0,:,:,:] + 0.5\n    outputImageF = cv2.merge([outputImageF[0,:,:], outputImageF[1,:,:], outputImageF[2,:,:]])\n    outputImageF = (outputImageF*255.).astype(dtype='uint8')\n    heatmaps = datum.poseHeatMaps.copy()\n    heatmaps = (heatmaps).astype(dtype='uint8')\n\n    # Display Image\n    counter = 0\n    while 1:\n        num_maps = heatmaps.shape[0]\n        heatmap = heatmaps[counter, :, :].copy()\n        heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)\n        combined = cv2.addWeighted(outputImageF, 0.5, heatmap, 0.5, 0)\n        cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", combined)\n        key = cv2.waitKey(-1)\n        if key == 27:\n            break\n        counter += 1\n        counter = counter % num_maps\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/09_keypoints_from_heatmaps.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\nimport numpy as np\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000294.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Load image\n    imageToProcess = cv2.imread(args[0].image_path)\n\n    def get_sample_heatmaps():\n        # These parameters are globally set. You need to unset variables set here if you have a new OpenPose object. See *\n        params = dict()\n        params[\"model_folder\"] = \"../../../models/\"\n        params[\"heatmaps_add_parts\"] = True\n        params[\"heatmaps_add_bkg\"] = True\n        params[\"heatmaps_add_PAFs\"] = True\n        params[\"heatmaps_scale\"] = 3\n        params[\"upsampling_ratio\"] = 1\n        params[\"body\"] = 1\n\n        # Starting OpenPose\n        opWrapper = op.WrapperPython()\n        opWrapper.configure(params)\n        opWrapper.start()\n\n        # Process Image and get heatmap\n        datum = op.Datum()\n        imageToProcess = cv2.imread(args[0].image_path)\n        datum.cvInputData = imageToProcess\n        opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n        poseHeatMaps = datum.poseHeatMaps.copy()\n        opWrapper.stop()\n\n        return poseHeatMaps\n\n    # Get Heatmap\n    poseHeatMaps = get_sample_heatmaps()\n\n    # Starting OpenPose\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n    params[\"body\"] = 2  # Disable OP Network\n    params[\"upsampling_ratio\"] = 0 # * Unset this variable\n    opWrapper = op.WrapperPython()\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Pass Heatmap and Run OP\n    datum = op.Datum()\n    datum.cvInputData = imageToProcess\n    datum.poseNetOutput = poseHeatMaps\n    opWrapper.emplaceAndPop(op.VectorDatum([datum]))\n\n    # Display Image\n    print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    cv2.waitKey(0)\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/12_asynchronous_custom_output.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\n\n\ndef display(datums):\n    datum = datums[0]\n    cv2.imshow(\"OpenPose 1.7.0 - Tutorial Python API\", datum.cvOutputData)\n    key = cv2.waitKey(1)\n    return (key == 27)\n\n\ndef printKeypoints(datums):\n    datum = datums[0]\n    print(\"Body keypoints: \\n\" + str(datum.poseKeypoints))\n    print(\"Face keypoints: \\n\" + str(datum.faceKeypoints))\n    print(\"Left hand keypoints: \\n\" + str(datum.handKeypoints[0]))\n    print(\"Right hand keypoints: \\n\" + str(datum.handKeypoints[1]))\n\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--no-display\", action=\"store_true\", help=\"Disable display.\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython(op.ThreadManagerMode.AsynchronousOut)\n    opWrapper.configure(params)\n    opWrapper.start()\n\n    # Main loop\n    userWantsToExit = False\n    while not userWantsToExit:\n        # Pop frame\n        datumProcessed = op.VectorDatum()\n        if opWrapper.waitAndPop(datumProcessed):\n            if not args[0].no_display:\n                # Display image\n                userWantsToExit = display(datumProcessed)\n            printKeypoints(datumProcessed)\n        else:\n            break\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/tutorial_api_python/CMakeLists.txt",
    "content": "### Add Python Test\nconfigure_file(01_body_from_image.py 01_body_from_image.py)\nconfigure_file(02_whole_body_from_image.py 02_whole_body_from_image.py)\nconfigure_file(04_keypoints_from_images.py 04_keypoints_from_images.py)\nconfigure_file(05_keypoints_from_images_multi_gpu.py 05_keypoints_from_images_multi_gpu.py)\nconfigure_file(06_face_from_image.py 06_face_from_image.py)\nconfigure_file(07_hand_from_image.py 07_hand_from_image.py)\nconfigure_file(08_heatmaps_from_image.py 08_heatmaps_from_image.py)\nconfigure_file(09_keypoints_from_heatmaps.py 09_keypoints_from_heatmaps.py)\nconfigure_file(openpose_python.py openpose_python.py)\n"
  },
  {
    "path": "examples/tutorial_api_python/README.md",
    "content": "# Python API Examples\nSee the [OpenPose Python API doc](../../doc/03_python_api.md) for more details on this folder.\n\nThis folder provides examples to the basic OpenPose Python API. The analogous C++ API is exposed in [examples/tutorial_api_cpp/](../tutorial_api_cpp/).\n"
  },
  {
    "path": "examples/tutorial_api_python/openpose_python.py",
    "content": "# From Python\n# It requires OpenCV installed for Python\nimport sys\nimport cv2\nimport os\nfrom sys import platform\nimport argparse\n\ntry:\n    # Import Openpose (Windows/Ubuntu/OSX)\n    dir_path = os.path.dirname(os.path.realpath(__file__))\n    try:\n        # Windows Import\n        if platform == \"win32\":\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append(dir_path + '/../../python/openpose/Release');\n            os.environ['PATH']  = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' +  dir_path + '/../../bin;'\n            import pyopenpose as op\n        else:\n            # Change these variables to point to the correct folder (Release/x64 etc.)\n            sys.path.append('../../python');\n            # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.\n            # sys.path.append('/usr/local/python')\n            from openpose import pyopenpose as op\n    except ImportError as e:\n        print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')\n        raise e\n\n    # Flags\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--image_path\", default=\"../../../examples/media/COCO_val2014_000000000192.jpg\", help=\"Process an image. Read all standard formats (jpg, png, bmp, etc.).\")\n    args = parser.parse_known_args()\n\n    # Custom Params (refer to include/openpose/flags.hpp for more parameters)\n    params = dict()\n    params[\"model_folder\"] = \"../../../models/\"\n\n    # Add others in path?\n    for i in range(0, len(args[1])):\n        curr_item = args[1][i]\n        if i != len(args[1])-1: next_item = args[1][i+1]\n        else: next_item = \"1\"\n        if \"--\" in curr_item and \"--\" in next_item:\n            key = curr_item.replace('-','')\n            if key not in params:  params[key] = \"1\"\n        elif \"--\" in curr_item and \"--\" not in next_item:\n            key = curr_item.replace('-','')\n            if key not in params: params[key] = next_item\n\n    # Construct it from system arguments\n    # op.init_argv(args[1])\n    # oppython = op.OpenposePython()\n\n    # Starting OpenPose\n    opWrapper = op.WrapperPython(op.ThreadManagerMode.Synchronous)\n    opWrapper.configure(params)\n    opWrapper.execute()\nexcept Exception as e:\n    print(e)\n    sys.exit(-1)\n"
  },
  {
    "path": "examples/user_code/CMakeLists.txt",
    "content": "# Uncomment these lines with your custom file names\n# set(USER_CODE_FILES\n#     ADD_HERE_YOUR_FILE1.cpp\n#     ADD_HERE_YOUR_FILE1.hpp\n#     ADD_HERE_YOUR_FILE2.cpp\n#     # ...\n#     ADD_HERE_YOUR_FILEn.cpp)\n\nforeach(USER_CODE_FILE ${USER_CODE_FILES})\n\n  get_filename_component(SOURCE_NAME ${USER_CODE_FILE} NAME_WE)\n\n  if (UNIX OR APPLE)\n    set(EXE_NAME \"${SOURCE_NAME}.bin\")\n  elseif (WIN32)\n    set(EXE_NAME \"UserCustomCode\")\n  endif ()\n\n  message(STATUS \"Adding Example ${EXE_NAME}\")\n  add_executable(${EXE_NAME} ${USER_CODE_FILE})\n  target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})\n\n  if (WIN32)\n    set_property(TARGET ${EXE_NAME} PROPERTY FOLDER \"User Code\")\n    configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user\n        ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)\n    # Properties->General->Output Directory\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n    set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  endif (WIN32)\n\nendforeach()\n"
  },
  {
    "path": "examples/user_code/README.md",
    "content": "Adding and Testing Custom Code\n====================================\n\n\n\n## Purpose\nYou can quickly add your custom code into this folder so that quick prototypes can be easily tested without having to create a whole new project just for it.\n\n\n\n## How-to\n1. Install/compile OpenPose as usual.\n2. Add your custom cpp / hpp files in this folder. Hint: You might want to start by copying the [OpenPoseDemo](../openpose/openpose.cpp) example or any of the [examples/tutorial_api_cpp/](../tutorial_api_cpp/) examples.\n3. Add the name of your custom cpp / hpp files at the top of the [examples/user_code/CMakeLists.txt](CMakeLists.txt) file.\n4. Re-run CMake (`Configure` and `Generate`).\n5. Then, you can simply modify their content.\n6. You can know compile OpenPose after each change in your files:\n\t- Ubuntu:\n\t```\n\tcd build/\n\tmake -j`nproc`\n\t```\n\t- Mac:\n\t```\n\tcd build/\n\tmake -j`sysctl -n hw.logicalcpu`\n\t```\n\t- Windows: Compile from Visual Studio (F5, F7, green play button, etc.).\n5. **Run step 4 every time that you make changes into your code**.\n\n\n\n## Running your Custom Code\nRun:\n```\n./build/examples/user_code/{your_custom_file_name}\n```\n"
  },
  {
    "path": "include/openpose/3d/cameraParameterReader.hpp",
    "content": "﻿#ifndef OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP\n#define OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API CameraParameterReader\n    {\n    public:\n        explicit CameraParameterReader();\n\n        virtual ~CameraParameterReader();\n\n        // cameraExtrinsics is optional\n        explicit CameraParameterReader(const std::string& serialNumber,\n                                       const Matrix& cameraIntrinsics,\n                                       const Matrix& cameraDistortion,\n                                       const Matrix& cameraExtrinsics = Matrix(),\n                                       const Matrix& cameraExtrinsicsInitial = Matrix());\n\n        // serialNumbers is optional. If empty, it will load all the XML files available in the\n        // cameraParameterPath folder\n        void readParameters(const std::string& cameraParameterPath,\n                            const std::vector<std::string>& serialNumbers = {});\n\n        // It simply calls the previous readParameters with a single element\n        void readParameters(const std::string& cameraParameterPath,\n                            const std::string& serialNumber);\n\n        void writeParameters(const std::string& cameraParameterPath) const;\n\n        unsigned long long getNumberCameras() const;\n\n        const std::vector<std::string>& getCameraSerialNumbers() const;\n\n        const std::vector<Matrix>& getCameraMatrices() const;\n\n        const std::vector<Matrix>& getCameraDistortions() const;\n\n        const std::vector<Matrix>& getCameraIntrinsics() const;\n\n        const std::vector<Matrix>& getCameraExtrinsics() const;\n\n        const std::vector<Matrix>& getCameraExtrinsicsInitial() const;\n\n        bool getUndistortImage() const;\n\n        void setUndistortImage(const bool undistortImage);\n\n        void undistort(Matrix& frame, const unsigned int cameraIndex = 0u);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplCameraParameterReader;\n        std::shared_ptr<ImplCameraParameterReader> spImpl;\n\n        DELETE_COPY(CameraParameterReader);\n    };\n}\n\n#endif // OPENPOSE_3D_CAMERA_PARAMETER_READER_HPP\n"
  },
  {
    "path": "include/openpose/3d/headers.hpp",
    "content": "#ifndef OPENPOSE_3D_HEADERS_HPP\n#define OPENPOSE_3D_HEADERS_HPP\n\n// 3d module\n#include <openpose/3d/cameraParameterReader.hpp>\n#include <openpose/3d/jointAngleEstimation.hpp>\n#include <openpose/3d/poseTriangulation.hpp>\n#include <openpose/3d/wJointAngleEstimation.hpp>\n#include <openpose/3d/wPoseTriangulation.hpp>\n\n#endif // OPENPOSE_3D_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/3d/jointAngleEstimation.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP\n#define OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP\n\n#ifdef USE_EIGEN\n    #include <Eigen/Core>\n#endif\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/totalmodel.h>\n#endif\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    OP_API int mapOPToAdam(const int oPPart);\n\n    class OP_API JointAngleEstimation\n    {\n    public:\n        static const std::shared_ptr<const TotalModel> getTotalModel();\n\n        JointAngleEstimation(const bool returnJacobian);\n\n        virtual ~JointAngleEstimation();\n\n        void initializationOnThread();\n\n        void adamFastFit(Eigen::Matrix<double, 62, 3, Eigen::RowMajor>& adamPose,\n                         Eigen::Vector3d& adamTranslation,\n                         Eigen::Matrix<double, Eigen::Dynamic, 1>& vtVec,\n                         Eigen::Matrix<double, Eigen::Dynamic, 1>& j0Vec,\n                         Eigen::VectorXd& adamFacecoeffsExp,\n                         const Array<float>& poseKeypoints3D,\n                         const Array<float>& faceKeypoints3D,\n                         const std::array<Array<float>, 2>& handKeypoints3D);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplJointAngleEstimation;\n        std::shared_ptr<ImplJointAngleEstimation> spImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(JointAngleEstimation);\n    };\n}\n\n#endif // OPENPOSE_3D_JOINT_ANGLE_ESTIMATION_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/3d/poseTriangulation.hpp",
    "content": "#ifndef OPENPOSE_3D_POSE_TRIANGULATION_HPP\n#define OPENPOSE_3D_POSE_TRIANGULATION_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API PoseTriangulation\n    {\n    public:\n        PoseTriangulation(const int minViews3d);\n\n        virtual ~PoseTriangulation();\n\n        void initializationOnThread();\n\n        Array<float> reconstructArray(\n            const std::vector<Array<float>>& keypointsVector, const std::vector<Matrix>& cameraMatrices,\n            const std::vector<Point<int>>& imageSizes) const;\n\n        std::vector<Array<float>> reconstructArray(\n            const std::vector<std::vector<Array<float>>>& keypointsVector, const std::vector<Matrix>& cameraMatrices,\n            const std::vector<Point<int>>& imageSizes) const;\n\n    private:\n        const int mMinViews3d;\n    };\n}\n\n#endif // OPENPOSE_3D_POSE_TRIANGULATION_HPP\n"
  },
  {
    "path": "include/openpose/3d/wJointAngleEstimation.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP\n#define OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/3d/jointAngleEstimation.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WJointAngleEstimation : public Worker<TDatums>\n    {\n    public:\n        explicit WJointAngleEstimation(const std::shared_ptr<JointAngleEstimation>& jointAngleEstimation);\n\n        virtual ~WJointAngleEstimation();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<JointAngleEstimation> spJointAngleEstimation;\n\n        DELETE_COPY(WJointAngleEstimation);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WJointAngleEstimation<TDatums>::WJointAngleEstimation(const std::shared_ptr<JointAngleEstimation>& jointAngleEstimation) :\n        spJointAngleEstimation{jointAngleEstimation}\n    {\n    }\n\n    template<typename TDatums>\n    WJointAngleEstimation<TDatums>::~WJointAngleEstimation()\n    {\n    }\n\n    template<typename TDatums>\n    void WJointAngleEstimation<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spJointAngleEstimation->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WJointAngleEstimation<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Input\n                auto& tDatumPtr = tDatums->at(0);\n                const auto& poseKeypoints3D = tDatumPtr->poseKeypoints3D;\n                const auto& faceKeypoints3D = tDatumPtr->faceKeypoints3D;\n                const auto& handKeypoints3D = tDatumPtr->handKeypoints3D;\n                // Running Adam model\n                spJointAngleEstimation->adamFastFit(\n                    tDatumPtr->adamPose, tDatumPtr->adamTranslation, tDatumPtr->vtVec, tDatumPtr->j0Vec,\n                    tDatumPtr->adamFaceCoeffsExp, poseKeypoints3D, faceKeypoints3D, handKeypoints3D);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WJointAngleEstimation);\n}\n\n#endif // OPENPOSE_3D_W_JOINT_ANGLE_ESTIMATION_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/3d/wPoseTriangulation.hpp",
    "content": "#ifndef OPENPOSE_3D_W_POSE_TRIANGULATION_HPP\n#define OPENPOSE_3D_W_POSE_TRIANGULATION_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/3d/poseTriangulation.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPoseTriangulation : public Worker<TDatums>\n    {\n    public:\n        explicit WPoseTriangulation(const std::shared_ptr<PoseTriangulation>& poseTriangulation);\n\n        virtual ~WPoseTriangulation();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<PoseTriangulation> spPoseTriangulation;\n\n        DELETE_COPY(WPoseTriangulation);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPoseTriangulation<TDatums>::WPoseTriangulation(const std::shared_ptr<PoseTriangulation>& poseTriangulation) :\n        spPoseTriangulation{poseTriangulation}\n    {\n    }\n\n    template<typename TDatums>\n    WPoseTriangulation<TDatums>::~WPoseTriangulation()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseTriangulation<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spPoseTriangulation->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WPoseTriangulation<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // 3-D triangulation and reconstruction\n                std::vector<Matrix> cameraMatrices;\n                std::vector<Array<float>> poseKeypointVector;\n                std::vector<Array<float>> faceKeypointVector;\n                std::vector<Array<float>> leftHandKeypointVector;\n                std::vector<Array<float>> rightHandKeypointVector;\n                std::vector<Point<int>> imageSizes;\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    poseKeypointVector.emplace_back(tDatumPtr->poseKeypoints);\n                    faceKeypointVector.emplace_back(tDatumPtr->faceKeypoints);\n                    leftHandKeypointVector.emplace_back(tDatumPtr->handKeypoints[0]);\n                    rightHandKeypointVector.emplace_back(tDatumPtr->handKeypoints[1]);\n                    cameraMatrices.emplace_back(tDatumPtr->cameraMatrix);\n                    imageSizes.emplace_back(\n                        Point<int>{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()});\n                }\n                // Pose 3-D reconstruction\n                auto poseKeypoints3Ds = spPoseTriangulation->reconstructArray(\n                    {poseKeypointVector, faceKeypointVector, leftHandKeypointVector, rightHandKeypointVector},\n                    cameraMatrices, imageSizes);\n                // Assign to all tDatums\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    tDatumPtr->poseKeypoints3D = poseKeypoints3Ds[0];\n                    tDatumPtr->faceKeypoints3D = poseKeypoints3Ds[1];\n                    tDatumPtr->handKeypoints3D[0] = poseKeypoints3Ds[2];\n                    tDatumPtr->handKeypoints3D[1] = poseKeypoints3Ds[3];\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPoseTriangulation);\n}\n\n#endif // OPENPOSE_3D_W_POSE_TRIANGULATION_HPP\n"
  },
  {
    "path": "include/openpose/calibration/cameraParameterEstimation.hpp",
    "content": "#ifndef OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP\n#define OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    /**\n     * This function estimate and saves the intrinsic parameters (K and distortion coefficients).\n     * @param gridInnerCorners The Point<int> of the board, i.e., the number of squares by width and height\n     * @param gridSquareSizeMm Floating number with the size of a square in your defined unit (point, millimeter,etc).\n     * @param flags Integer with the OpenCV flags for calibration (e.g., CALIB_RATIONAL_MODEL,\n     * CALIB_THIN_PRISM_MODEL, or CALIB_TILTED_MODEL)\n     * @param outputFilePath String with the name of the file where to write\n     */\n    OP_API void estimateAndSaveIntrinsics(\n        const Point<int>& gridInnerCorners, const float gridSquareSizeMm, const int flags,\n        const std::string& outputParameterFolder, const std::string& imageFolder, const std::string& serialNumber,\n        const bool saveImagesWithCorners = false);\n\n    OP_API void estimateAndSaveExtrinsics(\n        const std::string& parameterFolder, const std::string& imageFolder, const Point<int>& gridInnerCorners,\n        const float gridSquareSizeMm, const int index0, const int index1, const bool imagesAreUndistorted,\n        const bool combineCam0Extrinsics);\n\n    OP_API void refineAndSaveExtrinsics(\n        const std::string& parameterFolder, const std::string& imageFolder, const Point<int>& gridInnerCorners,\n        const float gridSquareSizeMm, const int numberCameras, const bool imagesAreUndistorted,\n        const bool saveImagesWithCorners = false);\n\n    OP_API void estimateAndSaveSiftFile(\n        const Point<int>& gridInnerCorners, const std::string& imageFolder, const int numberCameras,\n        const bool saveImagesWithCorners = false);\n}\n\n#endif // OPENPOSE_CALIBRATION_CAMERA_PARAMETER_ESTIMATION_HPP\n"
  },
  {
    "path": "include/openpose/calibration/headers.hpp",
    "content": "#ifndef OPENPOSE_CALIBRATION_HEADERS_HPP\n#define OPENPOSE_CALIBRATION_HEADERS_HPP\n\n// calibration module\n#include <openpose/calibration/cameraParameterEstimation.hpp>\n\n#endif // OPENPOSE_CALIBRATION_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/core/array.hpp",
    "content": "#ifndef OPENPOSE_CORE_ARRAY_HPP\n#define OPENPOSE_CORE_ARRAY_HPP\n\n#include <memory> // std::shared_ptr\n#include <vector>\n#include <openpose/core/macros.hpp>\n#include <openpose/core/matrix.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    /**\n     * Array<T>: The OpenPose Basic Raw Data Container\n     * This template class implements a multidimensional data array. It is our basic data container, analogous to\n     * Mat in OpenCV, Tensor in Torch/TensorFlow or Blob in Caffe.\n     * It wraps a Matrix and a std::shared_ptr, both of them pointing to the same raw data. I.e. they both share the\n     * same memory, so we can read and modify this data in both formats with no performance impact.\n     * Hence, it keeps high performance while adding high-level functions.\n     */\n    template<typename T>\n    class Array\n    {\n    public:\n        // ------------------------------ Constructors and Data Allocator Functions ------------------------------ //\n        /**\n         * Array constructor.\n         * Equivalent to default constructor + reset(const int size).\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         */\n        explicit Array(const int size);\n\n        /**\n         * Array constructor.\n         * Equivalent to default constructor + reset(const std::vector<int>& size = {}).\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to\n         * `new T[3*5*2]`.\n         */\n        explicit Array(const std::vector<int>& sizes = {});\n\n        /**\n         * Array constructor.\n         * Equivalent to default constructor + reset(const int size, const T value).\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         * @param value Initial value for each component of the Array.\n         */\n        Array(const int size, const T value);\n\n        /**\n         * Array constructor.\n         * Equivalent to default constructor + reset(const std::vector<int>& size, const T value).\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to:\n         * `new T[3*5*2]`.\n         * @param value Initial value for each component of the Array.\n         */\n        Array(const std::vector<int>& sizes, const T value);\n\n        /**\n         * Array constructor.\n         * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr.\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         * @param dataPtr Pointer to the memory to be used by the Array.\n         */\n        Array(const int size, T* const dataPtr);\n\n        /**\n         * Array constructor.\n         * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr.\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to:\n         * `new T[3*5*2]`.\n         * @param dataPtr Pointer to the memory to be used by the Array.\n         */\n        Array(const std::vector<int>& sizes, T* const dataPtr);\n\n        /**\n         * Array constructor.\n         * @param array Array<T> with the original data array to slice.\n         * @param index indicates the index of the array to extract.\n         * @param noCopy indicates whether to perform a copy. Copy will never go to undefined behavior, however, if\n         * noCopy == true, then:\n         *     1. It is faster, as no data copy is involved, but...\n         *     2. If the Array array goes out of scope, then the resulting Array will provoke an undefined behavior.\n         *     3. If the returned Array is modified, the information in the Array array will also be.\n         * @return Array<T> with the same dimension than array expect the first dimension being 1. E.g., if array\n         * is {p,k,m}, the resulting Array<T> is {1,k,m}.\n         */\n        Array(const Array<T>& array, const int index, const bool noCopy = false);\n\n        /**\n         * Array constructor. It manually copies the Array<T2> into the new Array<T>\n         * @param array Array<T2> with a format T2 different to the current Array type T.\n         */\n        template<typename T2>\n        Array(const Array<T2>& array) :\n            Array{array.getSize()}\n        {\n            try\n            {\n                // Copy\n                for (auto i = 0u ; i < array.getVolume() ; i++)\n                    pData[i] = T(array[i]);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        /**\n         * Copy constructor.\n         * It performs `fast copy`: For performance purpose, copying a Array<T> or Datum or cv::Mat just copies the\n         * reference, it still shares the same internal data.\n         * Modifying the copied element will modify the original one.\n         * Use clone() for a slower but real copy, similarly to cv::Mat and Array<T>.\n         * @param array Array to be copied.\n         */\n        Array<T>(const Array<T>& array);\n\n        /**\n         * Copy assignment.\n         * Similar to Array<T>(const Array<T>& array).\n         * @param array Array to be copied.\n         * @return The resulting Array.\n         */\n        Array<T>& operator=(const Array<T>& array);\n\n        /**\n         * Move constructor.\n         * It destroys the original Array to be moved.\n         * @param array Array to be moved.\n         */\n        Array<T>(Array<T>&& array);\n\n        /**\n         * Move assignment.\n         * Similar to Array<T>(Array<T>&& array).\n         * @param array Array to be moved.\n         * @return The resulting Array.\n         */\n        Array<T>& operator=(Array<T>&& array);\n\n        /**\n         * Clone function.\n         * Similar to cv::Mat::clone and Datum::clone.\n         * It performs a real but slow copy of the data, i.e., even if the copied element is modified, the original\n         * one is not.\n         * @return The resulting Array.\n         */\n        Array<T> clone() const;\n\n        /**\n         * Data allocation function.\n         * It allocates the required space for the memory (it does not initialize that memory).\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         */\n        void reset(const int size);\n\n        /**\n         * Data allocation function.\n         * Similar to reset(const int size), but it allocates a multi-dimensional array of dimensions each of the\n         * values of the argument.\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to\n         * `new T[3*5*2]`.\n         */\n        void reset(const std::vector<int>& sizes = {});\n\n        /**\n         * Data allocation function.\n         * Similar to reset(const int size), but initializing the data to the value specified by the second argument.\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         * @param value Initial value for each component of the Array.\n         */\n        void reset(const int size, const T value);\n\n        /**\n         * Data allocation function.\n         * Similar to reset(const std::vector<int>& size), but initializing the data to the value specified by the\n         * second argument.\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to\n         * `new T[3*5*2]`.\n         * @param value Initial value for each component of the Array.\n         */\n        void reset(const std::vector<int>& sizes, const T value);\n\n        /**\n         * Data allocation function.\n         * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr.\n         * @param size Integer with the number of T element to be allocated. E.g., size = 5 is internally similar to\n         * `new T[5]`.\n         * @param dataPtr Pointer to the memory to be used by the Array.\n         */\n        void reset(const int size, T* const dataPtr);\n\n        /**\n         * Data allocation function.\n         * Equivalent to default constructor, but it does not allocate memory, but rather use dataPtr.\n         * @param sizes Vector with the size of each dimension. E.g., size = {3, 5, 2} is internally similar to:\n         * `new T[3*5*2]`.\n         * @param dataPtr Pointer to the memory to be used by the Array.\n         */\n        void reset(const std::vector<int>& sizes, T* const dataPtr);\n\n        /**\n         * Data allocation function.\n         * It internally allocates memory and copies the data of the argument to the Array allocated memory.\n         * @param cvMat Matrix to be copied.\n         */\n        void setFrom(const Matrix& cvMat);\n\n        /**\n         * Data allocation function.\n         * It internally assigns all the allocated memory to the value indicated by the argument.\n         * @param value Value for each component of the Array.\n         */\n        void setTo(const T value);\n\n\n\n        // ------------------------------ Data Information Functions ------------------------------ //\n        /**\n         * Check whether memory has been allocated.\n         * @return True if no memory has been allocated, false otherwise.\n         */\n        inline bool empty() const\n        {\n            return (mVolume == 0);\n        }\n\n        /**\n         * Return a vector with the size of each dimension allocated.\n         * @return A std::vector<int> with the size of each dimension. If no memory has been allocated, it will return\n         * an empty std::vector.\n         */\n        inline std::vector<int> getSize() const\n        {\n            return mSize;\n        }\n\n        /**\n         * Return a vector with the size of the desired dimension.\n         * @param index Dimension to check its size.\n         * @return Size of the desired dimension. It will return 0 if the requested dimension is higher than the number\n         * of dimensions.\n         */\n        int getSize(const int index) const;\n\n        /**\n         * Return a string with the size of each dimension allocated.\n         * @return A std::stringwith the size of each dimension. If no memory has been allocated, it will return an\n         * empty string.\n         */\n        std::string printSize() const;\n\n        /**\n         * Return the total number of dimensions, equivalent to getSize().size().\n         * @return The number of dimensions. If no memory is allocated, it returns 0.\n         */\n        inline size_t getNumberDimensions() const\n        {\n            return mSize.size();\n        }\n\n        /**\n         * Return the total number of elements allocated, equivalent to multiply all the components from getSize().\n         * E.g., for a Array<T> of size = {2,5,3}, the volume or total number of elements is: 2x5x3 = 30.\n         * @return The total volume of the allocated data. If no memory is allocated, it returns 0.\n         */\n        inline size_t getVolume() const\n        {\n            return mVolume;\n        }\n\n        /**\n         * Similar to getVolume(), but in this case it just returns the volume between the desired dimensions.\n         * E.g., for a Array<T> of size = {2,5,3}, the volume or total number of elements for getVolume(1,2) is\n         * 5x3 = 15.\n         * @param indexA Dimension where to start.\n         * @param indexB Dimension where to stop. If indexB == -1, then it will take up to the last dimension.\n         * @return The total volume of the allocated data between the desired dimensions. If the index are out of\n         * bounds, it throws an error.\n         */\n        size_t getVolume(const int indexA, const int indexB = -1) const;\n\n        /**\n         * Return the stride or step size of the array.\n         * E.g., given and Array<T> of size 5x3, getStride() would return the following vector:\n         * {5x3sizeof(T), 3sizeof(T), sizeof(T)}.\n         */\n        std::vector<int> getStride() const;\n\n        /**\n         * Return the stride or step size of the array at the index-th dimension.\n         * E.g., given and Array<T> of size 5x3, getStride(2) would return sizeof(T).\n         */\n        int getStride(const int index) const;\n\n\n\n        // ------------------------------ Data Access Functions And Operators ------------------------------ //\n        /**\n         * Return a raw pointer to the data. Similar to: std::shared_ptr::get().\n         * Note: if you modify the pointer data, you will directly modify it in the Array<T> instance too.\n         * If you know you do not want to modify the data, then use getConstPtr() instead.\n         * @return A raw pointer to the data.\n         */\n        inline T* getPtr()\n        {\n            return pData; // spData.get()\n        }\n\n        /**\n         * Similar to getPtr(), but it forbids the data to be edited.\n         * @return A raw const pointer to the data.\n         */\n        inline const T* getConstPtr() const\n        {\n            return pData; // spData.get()\n        }\n\n        /**\n         * Similar to getConstPtr(), but it allows the data to be edited.\n         * This function is only implemented for Pybind11 usage.\n         * @return A raw pointer to the data.\n         */\n        inline T* getPseudoConstPtr() const\n        {\n            return pData; // spData.get()\n        }\n\n        /**\n         * Return a Matrix wrapper to the data. It forbids the data to be modified.\n         * OpenCV only admits unsigned char, signed char, int, float & double. If the T class is not supported by\n         * OpenCV, it will throw an error.\n         * Note: Array<T> does not return an editable Matrix because some OpenCV functions reallocate memory and it\n         * would not longer point to the Array<T> instance.\n         * If you want to perform some OpenCV operation on the Array data, you can use:\n         *     editedCvMat = array.getConstCvMat().clone();\n         *     // modify data\n         *     array.setFrom(editedCvMat)\n         * @return A const Matrix pointing to the data.\n         */\n        const Matrix& getConstCvMat() const;\n\n        /**\n         * Analogous to getConstCvMat, but in this case it returns a editable Matrix.\n         * Very important: Only allowed functions which do not provoke data reallocation.\n         * E.g., resizing functions will not work and they would provoke an undefined behavior and/or execution\n         * crashes.\n         * @return A Matrix pointing to the data.\n         */\n        Matrix& getCvMat();\n\n        /**\n         * [] operator\n         * Similar to the [] operator for raw pointer data.\n         * If debug mode is enabled, then it will check that the desired index is in the data range, and it will throw\n         * an exception otherwise (similar to the at operator).\n         * @param index The desired memory location.\n         * @return A editable reference to the data on the desired index location.\n         */\n        inline T& operator[](const int index)\n        {\n            #ifdef NDEBUG\n                return pData[index]; // spData.get()[index]\n            #else\n                return at(index);\n            #endif\n        }\n\n        /**\n         * [] operator\n         * Same functionality as operator[](const int index), but it forbids modifying the value. Otherwise, const\n         * functions would not be able to call the [] operator.\n         * @param index The desired memory location.\n         * @return A non-editable reference to the data on the desired index location.\n         */\n        inline const T& operator[](const int index) const\n        {\n            #ifdef NDEBUG\n                return pData[index]; // spData.get()[index]\n            #else\n                return at(index);\n            #endif\n        }\n\n        /**\n         * [] operator\n         * Same functionality as operator[](const int index), but it lets the user introduce the multi-dimensional\n         * index.\n         * E.g., given a (10 x 10 x 10) array, array[11] is equivalent to array[{1,1,0}]\n         * @param indexes Vector with the desired memory location.\n         * @return A editable reference to the data on the desired index location.\n         */\n        inline T& operator[](const std::vector<int>& indexes)\n        {\n            return operator[](getIndex(indexes));\n        }\n\n        /**\n         * [] operator\n         * Same functionality as operator[](const std::vector<int>& indexes), but it forbids modifying the value.\n         * Otherwise, const functions would not be able to call the [] operator.\n         * @param indexes Vector with the desired memory location.\n         * @return A non-editable reference to the data on the desired index location.\n         */\n        inline const T& operator[](const std::vector<int>& indexes) const\n        {\n            return operator[](getIndex(indexes));\n        }\n\n        /**\n         * at() function\n         * Same functionality as operator[](const int index), but it always check whether the indexes are within the\n         * data bounds. Otherwise, it will throw an error.\n         * @param index The desired memory location.\n         * @return A editable reference to the data on the desired index location.\n         */\n        inline T& at(const int index)\n        {\n            return commonAt(index);\n        }\n\n        /**\n         * at() function\n         * Same functionality as operator[](const int index) const, but it always check whether the indexes are within\n         * the data bounds. Otherwise, it will throw an error.\n         * @param index The desired memory location.\n         * @return A non-editable reference to the data on the desired index location.\n         */\n        inline const T& at(const int index) const\n        {\n            return commonAt(index);\n        }\n\n        /**\n         * at() function\n         * Same functionality as operator[](const std::vector<int>& indexes), but it always check whether the indexes\n         * are within the data bounds. Otherwise, it will throw an error.\n         * @param indexes Vector with the desired memory location.\n         * @return A editable reference to the data on the desired index location.\n         */\n        inline T& at(const std::vector<int>& indexes)\n        {\n            return at(getIndexAndCheck(indexes));\n        }\n\n        /**\n         * at() function\n         * Same functionality as operator[](const std::vector<int>& indexes) const, but it always check whether the\n         * indexes are within the data bounds. Otherwise, it will throw an error.\n         * @param indexes Vector with the desired memory location.\n         * @return A non-editable reference to the data on the desired index location.\n         */\n        inline const T& at(const std::vector<int>& indexes) const\n        {\n            return at(getIndexAndCheck(indexes));\n        }\n\n        /**\n         * It returns a string with the whole array data. Useful for debugging.\n         * The format is: values separated by a space, and a enter for each dimension. E.g.,\n         * For the Array{2, 2, 3}, it will print:\n         * Array<T>::toString():\n         * x1 x2 x3\n         * x4 x5 x6\n         *\n         * x7 x8 x9\n         * x10 x11 x12\n         * @return A string with the array values in the above format.\n         */\n        const std::string toString() const;\n\n    private:\n        std::vector<int> mSize;\n        size_t mVolume;\n        std::shared_ptr<T> spData;\n        T* pData; // pData is a wrapper of spData. Used for Pybind11 binding.\n        std::pair<bool, Matrix> mCvMatData;\n\n        /**\n         * Auxiliary function that both operator[](const std::vector<int>& indexes) and\n         * operator[](const std::vector<int>& indexes) const use.\n         * It turn the multi-dimensions indexes into the 1-dimension equivalent index.\n         * @param indexes Vector with the desired memory location.\n         * @return The equivalent 1-D index.\n         */\n        int getIndex(const std::vector<int>& indexes) const;\n\n        /**\n         * Similar to getIndex(const std::vector<int>& indexes) const, but used for at(const std::vector<int>& indexes)\n         * and at(const std::vector<int>& indexes) const.\n         * It also checks whether the index is within the allocated memory.\n         * @param indexes Vector with the desired memory location.\n         * @return The equivalent 1-D index.\n         */\n        int getIndexAndCheck(const std::vector<int>& indexes) const;\n\n        /**\n         * Auxiliary function that both at(const int index) and at(const int index) const use.\n         * @param index The desired memory location.\n         * @return A non-editable reference to the data on the desired index location.\n         */\n        T& commonAt(const int index) const;\n\n        void resetAuxiliary(const std::vector<int>& sizes, T* const dataPtr = nullptr);\n    };\n\n    // Static methods\n    OVERLOAD_C_OUT(Array)\n}\n\n#endif // OPENPOSE_CORE_ARRAY_HPP\n"
  },
  {
    "path": "include/openpose/core/arrayCpuGpu.hpp",
    "content": "#ifndef OPENPOSE_CORE_ARRAY_CPU_GPU_HPP\n#define OPENPOSE_CORE_ARRAY_CPU_GPU_HPP\n\n#include <memory> // std::shared_ptr\n#include <vector>\n#include <openpose/core/array.hpp>\n#include <openpose/core/macros.hpp>\n\nnamespace op\n{\n    /**\n     * ArrayCpuGpu<T>: Bind of caffe::Blob<T> to avoid Caffe as dependency in the headers.\n     */\n    template<typename T>\n    class ArrayCpuGpu\n    {\n    public:\n        ArrayCpuGpu();\n        /**\n         * @param caffeBlobTPtr should be a caffe::Blob<T>* element or it will provoke a core dumped. Done to\n         * avoid explicitly exposing 3rdparty libraries on the headers.\n         */\n        explicit ArrayCpuGpu(const void* caffeBlobTPtr);\n        /**\n         * Create an ArrayCpuGpu from the data in the Array element (it will automatically copy that data).\n         * @param array Array<T> where the data to be copied is.\n         * @param copyFromGpu If false (default), it will copy the data to the CPU. If true, it will copy it to the\n         * GPU memory (using CUDA copy function).\n         */\n        explicit ArrayCpuGpu(const Array<T>& array, const bool copyFromGpu);\n        explicit ArrayCpuGpu(const int num, const int channels, const int height, const int width);\n        // explicit ArrayCpuGpu(const std::vector<int>& shape);\n\n        void Reshape(const int num, const int channels, const int height, const int width);\n        void Reshape(const std::vector<int>& shape);\n        // // void Reshape(const BlobShape& shape);\n        // // void ReshapeLike(const Blob& other);\n        // void ReshapeLike(const ArrayCpuGpu& other);\n        std::string shape_string() const;\n        const std::vector<int>& shape() const;\n        int shape(const int index) const;\n        int num_axes() const;\n        int count() const;\n        int count(const int start_axis, const int end_axis) const;\n        int count(const int start_axis) const;\n\n        int CanonicalAxisIndex(const int axis_index) const;\n\n        int num() const;\n        int channels() const;\n        int height() const;\n        int width() const;\n        int LegacyShape(const int index) const;\n\n        int offset(const int n, const int c = 0, const int h = 0, const int w = 0) const;\n        // int offset(const std::vector<int>& indices) const; // Caffe warning\n\n        // // void CopyFrom(const Blob<T>& source, bool copy_diff = false, bool reshape = false);\n        // void CopyFrom(const ArrayCpuGpu<T>& source, bool copy_diff = false, bool reshape = false);\n\n        T data_at(const int n, const int c, const int h, const int w) const;\n        T diff_at(const int n, const int c, const int h, const int w) const;\n        // T data_at(const std::vector<int>& index) const; // Caffe warning\n        // T diff_at(const std::vector<int>& index) const; // Caffe warning\n\n        // const boost::shared_ptr<SyncedMemory>& data() const;\n        // const boost::shared_ptr<SyncedMemory>& diff() const;\n\n        const T* cpu_data() const;\n        void set_cpu_data(T* data);\n        const int* gpu_shape() const;\n        const T* gpu_data() const;\n        void set_gpu_data(T* data);\n        const T* cpu_diff() const;\n        const T* gpu_diff() const;\n        T* mutable_cpu_data();\n        T* mutable_gpu_data();\n        T* mutable_cpu_diff();\n        T* mutable_gpu_diff();\n        void Update();\n        // void FromProto(const BlobProto& proto, bool reshape = true);\n        // void ToProto(BlobProto* proto, bool write_diff = false) const;\n\n        T asum_data() const;\n        T asum_diff() const;\n        T sumsq_data() const;\n        T sumsq_diff() const;\n\n        void scale_data(const T scale_factor);\n        void scale_diff(const T scale_factor);\n\n        // void ShareData(const Blob& other);\n        // void ShareDiff(const Blob& other);\n\n        // bool ShapeEquals(const BlobProto& other);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplArrayCpuGpu;\n        std::shared_ptr<ImplArrayCpuGpu> spImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(ArrayCpuGpu);\n    };\n\n    // // Static methods\n    // OVERLOAD_C_OUT(ArrayCpuGpu)\n}\n\n#endif // OPENPOSE_CORE_ARRAY_CPU_GPU_HPP\n"
  },
  {
    "path": "include/openpose/core/common.hpp",
    "content": "#ifndef OPENPOSE_CORE_COMMON_HPP\n#define OPENPOSE_CORE_COMMON_HPP\n\n// Std library most used classes\n#include <array>\n#include <memory> // std::shared_ptr, std::unique_ptr\n#include <string>\n#include <vector>\n// OpenPose most used classes\n#include <openpose/core/array.hpp>\n#include <openpose/core/arrayCpuGpu.hpp>\n#include <openpose/core/macros.hpp>\n#include <openpose/core/matrix.hpp>\n#include <openpose/core/point.hpp>\n#include <openpose/core/rectangle.hpp>\n#include <openpose/core/string.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n#include <openpose/utilities/profiler.hpp>\n// Datum at the end, otherwise circular dependency with array, point & rectangle\n#include <openpose/core/datum.hpp>\n\n#endif // OPENPOSE_CORE_COMMON_HPP\n"
  },
  {
    "path": "include/openpose/core/cvMatToOpInput.hpp",
    "content": "#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP\n#define OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API CvMatToOpInput\n    {\n    public:\n        CvMatToOpInput(const PoseModel poseModel = PoseModel::BODY_25, const bool gpuResize = false);\n\n        virtual ~CvMatToOpInput();\n\n        std::vector<Array<float>> createArray(\n            const Matrix& inputData, const std::vector<double>& scaleInputToNetInputs,\n            const std::vector<Point<int>>& netInputSizes);\n\n    private:\n        const PoseModel mPoseModel;\n        const bool mGpuResize;\n        unsigned char* pInputImageCuda;\n        float* pInputImageReorderedCuda;\n        float* pOutputImageCuda;\n        unsigned long long pInputMaxSize;\n        unsigned long long pOutputMaxSize;\n    };\n}\n\n#endif // OPENPOSE_CORE_CV_MAT_TO_OP_INPUT_HPP\n"
  },
  {
    "path": "include/openpose/core/cvMatToOpOutput.hpp",
    "content": "#ifndef OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP\n#define OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API CvMatToOpOutput\n    {\n    public:\n        CvMatToOpOutput(const bool gpuResize = false);\n\n        virtual ~CvMatToOpOutput();\n\n        std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<unsigned long long>>\n            getSharedParameters();\n\n        Array<float> createArray(\n            const Matrix& inputData, const double scaleInputToOutput, const Point<int>& outputResolution);\n\n    private:\n        const bool mGpuResize;\n        unsigned char* pInputImageCuda;\n        std::shared_ptr<float*> spOutputImageCuda;\n        unsigned long long pInputMaxSize;\n        std::shared_ptr<unsigned long long> spOutputMaxSize;\n        std::shared_ptr<bool> spGpuMemoryAllocated;\n    };\n}\n\n#endif // OPENPOSE_CORE_CV_MAT_TO_OP_OUTPUT_HPP\n"
  },
  {
    "path": "include/openpose/core/datum.hpp",
    "content": "#ifndef OPENPOSE_CORE_DATUM_HPP\n#define OPENPOSE_CORE_DATUM_HPP\n\n#ifdef USE_3D_ADAM_MODEL\n    #ifdef USE_EIGEN\n        #include <Eigen/Core>\n    #endif\n#endif\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    /**\n     * Datum: The OpenPose Basic Piece of Information Between Threads\n     * Datum is one the main OpenPose classes/structs. The workers and threads share by default a\n     * std::shared_ptr<std::vector<Datum>>. It contains all the parameters that the different workers and threads need\n     * to exchange.\n     */\n    struct OP_API Datum\n    {\n        // ---------------------------------------- ID parameters ---------------------------------------- //\n        unsigned long long id; /**< Datum ID. Internally used to sort the Datums if multi-threading is used. */\n\n        unsigned long long subId; /**< Datum sub-ID. Internally used to sort the Datums if multi-threading is used. */\n\n        unsigned long long subIdMax; /**< Datum maximum sub-ID. Used to sort the Datums if multi-threading is used. */\n\n        /**\n         * Name used when saving the data to disk (e.g., `write_images` or `write_keypoint` flags in the demo).\n         */\n        std::string name;\n\n        /**\n         * Corresponding frame number.\n         * If the producer (e.g., video) starts from frame 0 and does not repeat any frame, then frameNumber should\n         * match the field id.\n         */\n        unsigned long long frameNumber;\n\n        // ------------------------------ Input image and rendered version parameters ------------------------------ //\n        /**\n         * Original image to be processed in cv::Mat uchar format.\n         * Size: (input_width x input_height) x 3 channels\n         */\n        Matrix cvInputData;\n\n        /**\n         * Original image to be processed in Array<float> format.\n         * It has been resized to the net input resolution, as well as reformatted Array<float> format to be compatible\n         * with the net.\n         * If >1 scales, each scale is right- and bottom-padded to fill the greatest resolution. The\n         * scales are sorted from bigger to smaller.\n         * Vector size: #scales\n         * Each array size: 3 x input_net_height x input_net_width\n         */\n        std::vector<Array<float>> inputNetData;\n\n        /**\n         * Rendered image in Array<float> format.\n         * It consists of a blending of the cvInputData and the pose/body part(s) heatmap/PAF(s).\n         * If rendering is disabled (e.g., `no_render_pose` flag in the demo), outputData will be empty.\n         * Size: 3 x output_net_height x output_net_width\n         */\n        Array<float> outputData;\n\n        /**\n         * Rendered image in cv::Mat uchar format.\n         * It has been resized to the desired output resolution (e.g., `resolution` flag in the demo).\n         * If outputData is empty, cvOutputData will also be empty.\n         * Size: (output_height x output_width) x 3 channels\n         */\n        Matrix cvOutputData;\n\n        /**\n         * Rendered 3D image in cv::Mat uchar format.\n         */\n        Matrix cvOutputData3D;\n\n        // ------------------------------ Resulting Array<float> data parameters ------------------------------ //\n        /**\n         * Body pose (x,y,score) locations for each person in the image.\n         * It has been resized to the desired output resolution (e.g., `resolution` flag in the demo).\n         * Size: #people x #body parts (e.g., 18 for COCO or 15 for MPI) x 3 ((x,y) coordinates + score)\n         */\n        Array<float> poseKeypoints;\n\n        /**\n         * People ID\n         * It returns a person ID for each body pose, providing temporal consistency. The ID will be the same one\n         * for a person across frames. I.e. this ID allows to keep track of the same person in time.\n         * If either person identification is disabled or poseKeypoints is empty, poseIds will also be empty.\n         * Size: #people\n         */\n        Array<long long> poseIds;\n\n        /**\n         * Body pose global confidence/score for each person in the image.\n         * It does not only consider the score of each body keypoint, but also the score of each PAF association.\n         * Optimized for COCO evaluation metric.\n         * It will highly penalyze people with missing body parts (e.g., cropped people on the borders of the image).\n         * If poseKeypoints is empty, poseScores will also be empty.\n         * Size: #people\n         */\n        Array<float> poseScores;\n\n        /**\n         * Body pose heatmaps (body parts, background and/or PAFs) for the whole image.\n         * This parameter is by default empty and disabled for performance. Each group (body parts, background and\n         * PAFs) can be individually enabled.\n         * #heatmaps = #body parts (if enabled) + 1 (if background enabled) + 2 x #PAFs (if enabled). Each PAF has 2\n         * consecutive channels, one for x- and one for y-coordinates.\n         * Order heatmaps: body parts + background (as appears in POSE_BODY_PART_MAPPING) + (x,y) channel of each PAF\n         * (sorted as appears in POSE_BODY_PART_PAIRS). See `pose/poseParameters.hpp`.\n         * The user can choose the heatmaps normalization: ranges [0, 1], [-1, 1] or [0, 255]. Check the\n         * `heatmaps_scale` flag in {OpenPose_path}/doc/advanced/demo_advanced.md for more details.\n         * Size: #heatmaps x output_net_height x output_net_width\n         */\n        Array<float> poseHeatMaps;\n\n        /**\n         * Body pose candidates for the whole image.\n         * This parameter is by default empty and disabled for performance. It can be enabled with `candidates_body`.\n         * Candidates refer to all the detected body parts, before being assembled into people. Note that the number\n         * of candidates is equal or higher than the number of body parts after being assembled into people.\n         * Size: #body parts x min(part candidates, POSE_MAX_PEOPLE) x 3 (x,y,score).\n         * Rather than vector, it should ideally be:\n         * std::array<std::vector<std::array<float,3>>, #BP> poseCandidates;\n         */\n        std::vector<std::vector<std::array<float,3>>> poseCandidates;\n\n        /**\n         * Face detection locations (x,y,width,height) for each person in the image.\n         * It is resized to cvInputData.size().\n         * Size: #people\n         */\n        std::vector<Rectangle<float>> faceRectangles;\n\n        /**\n         * Face keypoints (x,y,score) locations for each person in the image.\n         * It has been resized to the same resolution as `poseKeypoints`.\n         * Size: #people x #face parts (70) x 3 ((x,y) coordinates + score)\n         */\n        Array<float> faceKeypoints;\n\n        /**\n         * Face pose heatmaps (face parts and/or background) for the whole image.\n         * Analogous of bodyHeatMaps applied to face. However, there is no PAFs and the size is different.\n         * Size: #people x #face parts (70) x output_net_height x output_net_width\n         */\n        Array<float> faceHeatMaps;\n\n        /**\n         * Hand detection locations (x,y,width,height) for each person in the image.\n         * It is resized to cvInputData.size().\n         * Size: #people\n         */\n        std::vector<std::array<Rectangle<float>, 2>> handRectangles;\n\n        /**\n         * Hand keypoints (x,y,score) locations for each person in the image.\n         * It has been resized to the same resolution as `poseKeypoints`.\n         * handKeypoints[0] corresponds to left hands, and handKeypoints[1] to right ones.\n         * Size each Array: #people x #hand parts (21) x 3 ((x,y) coordinates + score)\n         */\n        std::array<Array<float>, 2> handKeypoints;\n\n        /**\n         * Hand pose heatmaps (hand parts and/or background) for the whole image.\n         * Analogous of faceHeatMaps applied to face.\n         * Size each Array: #people x #hand parts (21) x output_net_height x output_net_width\n         */\n        std::array<Array<float>, 2> handHeatMaps;\n\n        // ---------------------------------------- 3-D Reconstruction parameters ---------------------------------------- //\n        /**\n         * Body pose (x,y,z,score) locations for each person in the image.\n         * Size: #people x #body parts (e.g., 18 for COCO or 15 for MPI) x 4 ((x,y,z) coordinates + score)\n         */\n        Array<float> poseKeypoints3D;\n\n        /**\n         * Face keypoints (x,y,z,score) locations for each person in the image.\n         * It has been resized to the same resolution as `poseKeypoints3D`.\n         * Size: #people x #face parts (70) x 4 ((x,y,z) coordinates + score)\n         */\n        Array<float> faceKeypoints3D;\n\n        /**\n         * Hand keypoints (x,y,z,score) locations for each person in the image.\n         * It has been resized to the same resolution as `poseKeypoints3D`.\n         * handKeypoints[0] corresponds to left hands, and handKeypoints[1] to right ones.\n         * Size each Array: #people x #hand parts (21) x 4 ((x,y,z) coordinates + score)\n         */\n        std::array<Array<float>, 2> handKeypoints3D;\n\n        /**\n         * 3x4 camera matrix of the camera (equivalent to cameraIntrinsics * cameraExtrinsics).\n         */\n        Matrix cameraMatrix;\n\n        /**\n         * 3x4 extrinsic parameters of the camera.\n         */\n        Matrix cameraExtrinsics;\n\n        /**\n         * 3x3 intrinsic parameters of the camera.\n         */\n        Matrix cameraIntrinsics;\n\n        /**\n         * If it is not empty, OpenPose will not run its internal body pose estimation network and will instead use\n         * this data as the substitute of its network. The size of this element must match the size of the output of\n         * its internal network, or it will lead to core dumped (segmentation) errors. You can modify the pose\n         * estimation flags to match the dimension of both elements (e.g., `--net_resolution`, `--scale_number`, etc.).\n         */\n        Array<float> poseNetOutput;\n\n        // ---------------------------------------- Other (internal) parameters ---------------------------------------- //\n        /**\n         * Scale ratio between the input Datum::cvInputData and the net input size.\n         */\n        std::vector<double> scaleInputToNetInputs;\n\n        /**\n         * Size(s) (width x height) of the image(s) fed to the pose deep net.\n         * The size of the std::vector corresponds to the number of scales.\n         */\n        std::vector<Point<int>> netInputSizes;\n\n        /**\n         * Scale ratio between the input Datum::cvInputData and the output Datum::cvOutputData.\n         */\n        double scaleInputToOutput;\n\n        /**\n         * Size (width x height) of the image returned by the deep net.\n         */\n        Point<int> netOutputSize;\n\n        /**\n         * Scale ratio between the net output and the final output Datum::cvOutputData.\n         */\n        double scaleNetToOutput;\n\n        /**\n         * Pair with the element key id POSE_BODY_PART_MAPPING on `pose/poseParameters.hpp` and its mapped value (e.g.\n         * 1 and \"Neck\").\n         */\n        std::pair<int, std::string> elementRendered;\n\n        // 3D/Adam parameters (experimental code not meant to be publicly used)\n        #ifdef USE_3D_ADAM_MODEL\n            // Adam/Unity params\n            std::vector<double> adamPosePtr;\n            int adamPoseRows;\n            std::vector<double> adamTranslationPtr;\n            std::vector<double> vtVecPtr;\n            int vtVecRows;\n            std::vector<double> j0VecPtr;\n            int j0VecRows;\n            std::vector<double> adamFaceCoeffsExpPtr;\n            int adamFaceCoeffsExpRows;\n            #ifdef USE_EIGEN\n                // Adam/Unity params\n                Eigen::Matrix<double, 62, 3, Eigen::RowMajor> adamPose;\n                Eigen::Vector3d adamTranslation;\n                // Adam params (Jacobians)\n                Eigen::Matrix<double, Eigen::Dynamic, 1> vtVec;\n                Eigen::Matrix<double, Eigen::Dynamic, 1> j0Vec;\n                Eigen::VectorXd adamFaceCoeffsExp;\n            #endif\n        #endif\n\n\n\n\n\n        // ---------------------------------------- Functions ---------------------------------------- //\n        /**\n         * Default constructor struct.\n         * It simply initializes the struct, id is temporary set to 0 and each other variable is assigned to its\n         * default value.\n         */\n        explicit Datum();\n\n        /**\n         * Copy constructor.\n         * It performs `fast copy`: For performance purpose, copying a Datum or Array<T> or cv::Mat just copies the\n         * reference, it still shares the same internal data.\n         * Modifying the copied element will modify the original one.\n         * Use clone() for a slower but real copy, similarly to cv::Mat and Array<T>.\n         * @param datum Datum to be copied.\n         */\n        Datum(const Datum& datum);\n\n        /**\n         * Copy assignment.\n         * Similar to Datum::Datum(const Datum& datum).\n         * @param datum Datum to be copied.\n         * @return The resulting Datum.\n         */\n        Datum& operator=(const Datum& datum);\n\n        /**\n         * Move constructor.\n         * It destroys the original Datum to be moved.\n         * @param datum Datum to be moved.\n         */\n        Datum(Datum&& datum);\n\n        /**\n         * Move assignment.\n         * Similar to Datum::Datum(Datum&& datum).\n         * @param datum Datum to be moved.\n         * @return The resulting Datum.\n         */\n        Datum& operator=(Datum&& datum);\n\n        /**\n         * Destructor class.\n         * Declared virtual so that Datum can be inherited.\n         */\n        virtual ~Datum();\n\n        /**\n         * Clone function.\n         * Similar to cv::Mat::clone and Array<T>::clone.\n         * It performs a real but slow copy of the data, i.e., even if the copied element is modified, the original\n         * one is not.\n         * @return The resulting Datum.\n         */\n        Datum clone() const;\n\n\n\n\n\n        // ---------------------------------------- Comparison operators ---------------------------------------- //\n        /**\n         * Less comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator<(const Datum& datum) const\n        {\n            // return id < datum.id;\n            return id < datum.id || (id == datum.id && subId < datum.subId);\n        }\n        /**\n         * Greater comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator>(const Datum& datum) const\n        {\n            // return id > datum.id;\n            return id > datum.id || (id == datum.id && subId > datum.subId);\n        }\n        /**\n         * Less or equal comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator<=(const Datum& datum) const\n        {\n            // return id <= datum.id;\n            return id < datum.id || (id == datum.id && subId <= datum.subId);\n        }\n        /**\n         * Greater or equal comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator>=(const Datum& datum) const\n        {\n            // return id >= datum.id;\n            return id > datum.id || (id == datum.id && subId >= datum.subId);\n        }\n        /**\n         * Equal comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator==(const Datum& datum) const\n        {\n            // return id == datum.id;\n            return id == datum.id && subId == datum.subId;\n        }\n        /**\n         * Not equal comparison operator.\n         * @param datum Datum to be compared.\n         * @result Whether the instance satisfies the condition with respect to datum.\n         */\n        inline bool operator!=(const Datum& datum) const\n        {\n            // return id != datum.id;\n            return id != datum.id || subId != datum.subId;\n        }\n    };\n\n    // Defines for Datum. Added here rather than in `macros.hpp` to avoid circular dependencies\n    #define BASE_DATUM Datum\n    #define BASE_DATUMS std::vector<std::shared_ptr<BASE_DATUM>>\n    #define BASE_DATUMS_SH std::shared_ptr<BASE_DATUMS>\n    #define DEFINE_TEMPLATE_DATUM(templateName) template class OP_API templateName<BASE_DATUMS_SH>\n    #define COMPILE_TEMPLATE_DATUM(templateName) extern template class templateName<BASE_DATUMS_SH>\n}\n\n#endif // OPENPOSE_CORE_DATUM_HPP\n"
  },
  {
    "path": "include/openpose/core/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_CORE_ENUM_CLASSES_HPP\n#define OPENPOSE_CORE_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class ScaleMode : unsigned char\n    {\n        InputResolution,\n        NetOutputResolution,\n        OutputResolution,\n        ZeroToOne, // [0, 1]\n        ZeroToOneFixedAspect, // [0, 1]\n        PlusMinusOne, // [-1, 1]\n        PlusMinusOneFixedAspect, // [-1, 1]\n        UnsignedChar, // [0, 255]\n        NoScale,\n    };\n\n    enum class HeatMapType : unsigned char\n    {\n        Parts,\n        Background,\n        PAFs,\n    };\n\n    enum class RenderMode : unsigned char\n    {\n        None,\n        Auto, // It will select Gpu if CUDA version, or Cpu otherwise\n        Cpu,\n        Gpu,\n    };\n\n    enum class ElementToRender : unsigned char\n    {\n        Skeleton,\n        Background,\n        AddKeypoints,\n        AddPAFs,\n    };\n}\n\n#endif // OPENPOSE_CORE_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/core/gpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_CORE_GPU_RENDERER_HPP\n#define OPENPOSE_CORE_GPU_RENDERER_HPP\n\n#include <atomic>\n#include <tuple>\n#include <openpose/core/common.hpp>\n#include <openpose/core/renderer.hpp>\n\nnamespace op\n{\n    class OP_API GpuRenderer : public Renderer\n    {\n    public:\n        explicit GpuRenderer(\n            const float renderThreshold, const float alphaKeypoint, const float alphaHeatMap,\n            const bool blendOriginalFrame = true, const unsigned int elementToRender = 0u,\n            const unsigned int numberElementsToRender = 0u);\n\n        virtual ~GpuRenderer();\n\n        std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,\n                   std::shared_ptr<unsigned long long>, std::shared_ptr<const unsigned int>>\n                   getSharedParameters();\n\n        void setSharedParametersAndIfLast(\n            const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,\n                std::shared_ptr<unsigned long long>, std::shared_ptr<const unsigned int>>& tuple,\n            const bool isLast);\n\n        void setSharedParameters(\n            const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>,\n                std::shared_ptr<unsigned long long>>& tuple);\n\n    protected:\n        std::shared_ptr<float*> spGpuMemory;\n\n        void cpuToGpuMemoryIfNotCopiedYet(const float* const cpuMemory, const unsigned long long memoryVolume);\n\n        void gpuToCpuMemoryIfLastRenderer(float* cpuMemory, const unsigned long long memoryVolume);\n\n    private:\n        std::shared_ptr<unsigned long long> spVolume;\n        bool mIsFirstRenderer;\n        bool mIsLastRenderer;\n        std::shared_ptr<bool> spGpuMemoryAllocated;\n\n        DELETE_COPY(GpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_CORE_GPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/core/headers.hpp",
    "content": "#ifndef OPENPOSE_CORE_HEADERS_HPP\n#define OPENPOSE_CORE_HEADERS_HPP\n\n// core module\n#include <openpose/core/array.hpp>\n#include <openpose/core/arrayCpuGpu.hpp>\n#include <openpose/core/common.hpp>\n#include <openpose/core/cvMatToOpInput.hpp>\n#include <openpose/core/cvMatToOpOutput.hpp>\n#include <openpose/core/datum.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/core/gpuRenderer.hpp>\n#include <openpose/core/keepTopNPeople.hpp>\n#include <openpose/core/keypointScaler.hpp>\n#include <openpose/core/macros.hpp>\n#include <openpose/core/matrix.hpp>\n#include <openpose/core/opOutputToCvMat.hpp>\n#include <openpose/core/point.hpp>\n#include <openpose/core/rectangle.hpp>\n#include <openpose/core/renderer.hpp>\n#include <openpose/core/scaleAndSizeExtractor.hpp>\n#include <openpose/core/string.hpp>\n#include <openpose/core/verbosePrinter.hpp>\n#include <openpose/core/wCvMatToOpInput.hpp>\n#include <openpose/core/wCvMatToOpOutput.hpp>\n#include <openpose/core/wKeepTopNPeople.hpp>\n#include <openpose/core/wKeypointScaler.hpp>\n#include <openpose/core/wOpOutputToCvMat.hpp>\n#include <openpose/core/wScaleAndSizeExtractor.hpp>\n#include <openpose/core/wVerbosePrinter.hpp>\n\n#endif // OPENPOSE_CORE_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/core/keepTopNPeople.hpp",
    "content": "#ifndef OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP\n#define OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API KeepTopNPeople\n    {\n    public:\n        explicit KeepTopNPeople(const int numberPeopleMax);\n\n        virtual ~KeepTopNPeople();\n\n        Array<float> keepTopPeople(const Array<float>& peopleArrays, const Array<float>& poseScores) const;\n\n    private:\n        const int mNumberPeopleMax;\n    };\n}\n\n#endif // OPENPOSE_CORE_KEEP_TOP_N_PEOPLE_HPP\n"
  },
  {
    "path": "include/openpose/core/keypointScaler.hpp",
    "content": "#ifndef OPENPOSE_CORE_KEYPOINT_SCALER_HPP\n#define OPENPOSE_CORE_KEYPOINT_SCALER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API KeypointScaler\n    {\n    public:\n        explicit KeypointScaler(const ScaleMode scaleMode);\n\n        virtual ~KeypointScaler();\n\n        void scale(Array<float>& arrayToScale, const double scaleInputToOutput, const double scaleNetToOutput,\n                   const Point<int>& producerSize) const;\n\n        void scale(std::vector<Array<float>>& arraysToScale, const double scaleInputToOutput,\n                   const double scaleNetToOutput, const Point<int>& producerSize) const;\n\n        void scale(std::vector<std::vector<std::array<float,3>>>& poseCandidates, const double scaleInputToOutput,\n                   const double scaleNetToOutput, const Point<int>& producerSize) const;\n\n    private:\n        const ScaleMode mScaleMode;\n    };\n}\n\n#endif // OPENPOSE_CORE_KEYPOINT_SCALER_HPP\n"
  },
  {
    "path": "include/openpose/core/macros.hpp",
    "content": "#ifndef OPENPOSE_CORE_MACROS_HPP\n#define OPENPOSE_CORE_MACROS_HPP\n\n#include <chrono> // std::chrono:: functionaligy, e.g., std::chrono::milliseconds\n#include <memory> // std::shared_ptr\n#include <ostream>\n#include <string>\n#include <thread> // std::this_thread\n#include <vector>\n\n// OpenPose name and version\nconst std::string OPEN_POSE_NAME_STRING = \"OpenPose\";\nconst std::string OPEN_POSE_VERSION_STRING = \"1.7.0\";\nconst std::string OPEN_POSE_NAME_AND_VERSION = OPEN_POSE_NAME_STRING + \" \" + OPEN_POSE_VERSION_STRING;\n// #define COMMERCIAL_LICENSE\n\n#ifndef _WIN32\n    #define OP_API\n#elif defined OP_EXPORTS\n    #define OP_API __declspec(dllexport)\n#else\n    #define OP_API __declspec(dllimport)\n#endif\n\n// Disable some Windows Warnings\n#ifdef _WIN32\n    #pragma warning(disable: 4251) // 'XXX': class 'YYY' needs to have dll-interface to be used by clients of class 'ZZZ'\n#endif\n\n#define UNUSED(unusedVariable) (void)(unusedVariable)\n\n#define DELETE_COPY(className) \\\n    className(const className&) = delete; \\\n    className& operator=(const className&) = delete\n\n// Instantiate a class with all the basic types\n#define COMPILE_TEMPLATE_BASIC_TYPES_CLASS(className) COMPILE_TEMPLATE_BASIC_TYPES(className, class)\n#define COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(className) COMPILE_TEMPLATE_BASIC_TYPES(className, struct)\n#define COMPILE_TEMPLATE_BASIC_TYPES(className, classType) \\\n    template classType OP_API className<char>; \\\n    template classType OP_API className<signed char>; \\\n    template classType OP_API className<short>; \\\n    template classType OP_API className<int>; \\\n    template classType OP_API className<long>; \\\n    template classType OP_API className<long long>; \\\n    template classType OP_API className<unsigned char>; \\\n    template classType OP_API className<unsigned short>; \\\n    template classType OP_API className<unsigned int>; \\\n    template classType OP_API className<unsigned long>; \\\n    template classType OP_API className<unsigned long long>; \\\n    template classType OP_API className<float>; \\\n    template classType OP_API className<double>; \\\n    template classType OP_API className<long double>\n\n// Instantiate a class with float and double specifications\n#define COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(className) COMPILE_TEMPLATE_FLOATING_TYPES(className, class)\n#define COMPILE_TEMPLATE_FLOATING_TYPES_STRUCT(className) COMPILE_TEMPLATE_FLOATING_TYPES(className, struct)\n#define COMPILE_TEMPLATE_FLOATING_TYPES(className, classType) \\\n  char gInstantiationGuard##className; \\\n  template classType OP_API className<float>; \\\n  template classType OP_API className<double>\n\n// Instantiate a class with float and double specifications\n#define COMPILE_TEMPLATE_FLOATING_INT_TYPES_CLASS(className) COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, class)\n#define COMPILE_TEMPLATE_FLOATING_INT_TYPES_STRUCT(className) COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, struct)\n#define COMPILE_TEMPLATE_FLOATING_INT_TYPES(className, classType) \\\n  char gInstantiationGuard##className; \\\n  template classType OP_API className<int>; \\\n  template classType OP_API className<unsigned int>; \\\n  template classType OP_API className<float>; \\\n  template classType OP_API className<double>\n\n/**\n * cout operator overload calling toString() function\n * @return std::ostream containing output from toString()\n */\n#define OVERLOAD_C_OUT(className) \\\n    template<typename T> std::ostream &operator<<(std::ostream& ostream, const op::className<T>& obj) \\\n    { \\\n        ostream << obj.toString(); \\\n        return ostream; \\\n    }\n\n// PIMPL does not work if function arguments need the 3rd-party class. Alternative:\n// stackoverflow.com/questions/13978775/how-to-avoid-include-dependency-to-external-library?answertab=active#tab-top\nstruct dim3;\n\n#endif // OPENPOSE_CORE_MACROS_HPP\n"
  },
  {
    "path": "include/openpose/core/matrix.hpp",
    "content": "#ifndef OPENPOSE_CORE_MAT_HPP\n#define OPENPOSE_CORE_MAT_HPP\n\n#include <memory> // std::shared_ptr\n#include <openpose/core/macros.hpp>\n\nnamespace op\n{\n    // Convert from Matrix into cv::Mat. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // cv::Mat opMat = OP2CVMAT(cv::Mat());\n    #define OP_OP2CVMAT(opMat) \\\n        (*((cv::Mat*)((opMat).getCvMat())))\n\n    // Convert from Matrix into const cv::Mat. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // cv::Mat opMat = OP2CVCONSTMAT(cv::Mat());\n    #define OP_OP2CVCONSTMAT(opMat) \\\n        (*((cv::Mat*)((opMat).getConstCvMat())))\n\n    // Convert from cv::Mat into Matrix. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // Matrix opMat = CV2OPMAT(Matrix());\n    #define OP_CV2OPMAT(cvMat) \\\n        (op::Matrix((void*)&(cvMat)))\n\n    // Convert from cv::Mat into const Matrix. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // Matrix opMat = CV2OPCONSTMAT(Matrix());\n    #define OP_CV2OPCONSTMAT(cvMat) \\\n        (op::Matrix((const void*)&(cvMat)))\n\n    // Convert from std::vector<Matrix> into std::vector<cv::Mat>. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // std::vector<Matrix> opMats; // Assume filled\n        // OP_OP2CVVECTORMAT(cvMats, opMats);\n    #define OP_OP2CVVECTORMAT(cvMats, opMats) \\\n        std::vector<cv::Mat> cvMats; \\\n        for (auto& opMat : (opMats)) \\\n        { \\\n            const auto cvMat = OP_OP2CVCONSTMAT(opMat); \\\n            cvMats.emplace_back(cvMat); \\\n        }\n\n    // Convert from std::vector<cv::Mat> into std::vector<Matrix>. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // std::vector<cv::Mat> cvMats; // Assume filled\n        // OP_CV2OPVECTORMAT(opMats, cvMats);\n    #define OP_CV2OPVECTORMAT(opMats, cvMats) \\\n        std::vector<op::Matrix> opMats; \\\n        for (auto& cvMat : (cvMats)) \\\n        { \\\n            const auto opMat = OP_CV2OPMAT(cvMat); \\\n            opMats.emplace_back(opMat); \\\n        }\n\n    // Convert from std::vector<cv::Mat> into std::vector<Matrix>. Usage example:\n        // #include <opencv2/core/core.hpp>\n        // ...\n        // // Equivalents:\n        // OP_CV_VOID_FUNCTION(opMat, size());\n        // // and\n        // OP_OP2CVMAT(cvMat, opMat);\n        // cvMat.size();\n    #define OP_MAT_VOID_FUNCTION(opMat, function) \\\n        { \\\n            cv::Mat cvMat = OP_OP2CVMAT(cvMat, opMat); \\\n            cvMat.function; \\\n        }\n    #define OP_CONST_MAT_VOID_FUNCTION(opMat, function) \\\n        { \\\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(opMat); \\\n            cvMat.function; \\\n        }\n    #define OP_MAT_RETURN_FUNCTION(outputVariable, opMat, function) \\\n        { \\\n            cv::Mat cvMat = OP_OP2CVMAT(cvMat, opMat); \\\n            outputVariable = cvMat.function; \\\n        }\n    #define OP_CONST_MAT_RETURN_FUNCTION(outputVariable, opMat, function) \\\n        { \\\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(opMat); \\\n            outputVariable = cvMat.function; \\\n        }\n\n    /**\n     * Matrix: Bind of cv::Mat to avoid OpenCV as dependency in the headers.\n     */\n    class OP_API Matrix\n    {\n    public:\n        /**\n         * @param matrixesResized For 3-D OpenPose, if >1, it will assume the image is composed of\n         * numberImagesStackedHorizontally horizontally stacked images. It must be already resized to avoid\n         * internally allocating/removing elements of std::vector (to avoid errors if using different std DLLs)\n         * @param cvMatPtr should be a cv::Mat element or it will provoke a core dumped. Done to\n         * avoid explicitly exposing 3rdparty libraries on the headers.\n         */\n        static void splitCvMatIntoVectorMatrix(std::vector<Matrix>& matrixesResized, const void* const cvMatPtr);\n\n        Matrix();\n\n        /**\n         * @param cvMatPtr should be a cv::Mat element or it will provoke a core dumped. Done to\n         * avoid explicitly exposing 3rdparty libraries on the headers.\n         */\n        explicit Matrix(const void* cvMatPtr);\n\n        /**\n         * Analog to cv::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP)\n         */\n        explicit Matrix(const int rows, const int cols, const int type);\n\n        /**\n         * Analog to cv::Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP)\n         * Very important: This Matrix will only \"borrow\" this pointer, so the caller must make sure to maintain the\n         * memory allocated until this Matrix destructor is called and also to handle the ucharPtr memory deallocation.\n         * @param ucharPtr should be a cv::Mat::data (or analog) element or it will provoke a core dumped. Done to\n         * avoid explicitly exposing 3rdparty libraries on the headers.\n         */\n        explicit Matrix(const int rows, const int cols, const int type, void* cvMatPtr);\n\n        Matrix clone() const;\n\n        /**\n         * @return cv::Mat*.\n         */\n        void* getCvMat();\n\n        /**\n         * @return const cv::Mat*.\n         */\n        const void* getConstCvMat() const;\n\n        /**\n         * Equivalent to cv::Mat::data\n         * @return A raw pointer to the internal data of cv::Mat.\n         */\n        unsigned char* data();\n        /**\n         * Equivalent to cv::Mat::data\n         * @return A raw pointer to the internal data of cv::Mat.\n         */\n        const unsigned char* dataConst() const;\n        /**\n         * Similar to dataConst(), but it allows the data to be edited.\n         * This function is only implemented for Pybind11 usage.\n         * @return A raw pointer to the internal data of cv::Mat.\n         */\n        unsigned char* dataPseudoConst() const;\n\n        /**\n         * Equivalent to cv::Mat::eye\n         */\n        static Matrix eye(const int rows, const int cols, const int type);\n        /**\n         * Equivalent to cv::Mat::cols\n         */\n        int cols() const;\n        /**\n         * Equivalent to cv::Mat::rows\n         */\n        int rows() const;\n        /**\n         * Equivalent to cv::Mat::size[dimension]\n         */\n        int size(const int dimension) const;\n        /**\n         * Equivalent to cv::Mat::dims\n         */\n        int dims() const;\n\n        /**\n         * Equivalent to their analog cv::Mat functions\n         */\n        bool isContinuous() const;\n        bool isSubmatrix() const;\n        size_t elemSize() const;\n        size_t elemSize1() const;\n        int type() const;\n        int depth() const;\n        int channels() const;\n        size_t step1(const int i = 0) const;\n        bool empty() const;\n        size_t total() const;\n        int checkVector(const int elemChannels, const int depth = -1, const bool requireContinuous = true) const;\n\n        /**\n         * Similar to their analog cv::Mat functions\n         */\n        void setTo(const double value);\n        void copyTo(Matrix& outputMat) const;\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplMatrix;\n        std::shared_ptr<ImplMatrix> spImpl;\n    };\n}\n\n#endif // OPENPOSE_CORE_MAT_HPP\n"
  },
  {
    "path": "include/openpose/core/opOutputToCvMat.hpp",
    "content": "#ifndef OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP\n#define OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API OpOutputToCvMat\n    {\n    public:\n        OpOutputToCvMat(const bool gpuResize = false);\n\n        virtual ~OpOutputToCvMat();\n\n        void setSharedParameters(\n            const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<unsigned long long>>& tuple);\n\n        Matrix formatToCvMat(const Array<float>& outputData);\n\n    private:\n        const bool mGpuResize;\n        // Shared variables\n        std::shared_ptr<float*> spOutputImageFloatCuda;\n        std::shared_ptr<unsigned long long> spOutputMaxSize;\n        std::shared_ptr<bool> spGpuMemoryAllocated;\n        // Local variables\n        unsigned char* pOutputImageUCharCuda;\n        unsigned long long mOutputMaxSizeUChar;\n    };\n}\n\n#endif // OPENPOSE_CORE_OP_OUTPUT_TO_CV_MAT_HPP\n"
  },
  {
    "path": "include/openpose/core/point.hpp",
    "content": "#ifndef OPENPOSE_CORE_POINT_HPP\n#define OPENPOSE_CORE_POINT_HPP\n\n#include <string>\n#include <openpose/core/macros.hpp>\n\nnamespace op\n{\n    template<typename T>\n    struct Point\n    {\n        T x;\n        T y;\n\n        Point(const T x = 0, const T y = 0);\n\n        /**\n         * Copy constructor.\n         * It performs `fast copy`: For performance purpose, copying a Point<T> or Point<T> or cv::Mat just copies the\n         * reference, it still shares the same internal data.\n         * Modifying the copied element will modify the original one.\n         * Use clone() for a slower but real copy, similarly to cv::Mat and Point<T>.\n         * @param point Point to be copied.\n         */\n        Point<T>(const Point<T>& point);\n\n        /**\n         * Copy assignment.\n         * Similar to Point<T>(const Point<T>& point).\n         * @param point Point to be copied.\n         * @return The resulting Point.\n         */\n        Point<T>& operator=(const Point<T>& point);\n\n        /**\n         * Move constructor.\n         * It destroys the original Point to be moved.\n         * @param point Point to be moved.\n         */\n        Point<T>(Point<T>&& point);\n\n        /**\n         * Move assignment.\n         * Similar to Point<T>(Point<T>&& point).\n         * @param point Point to be moved.\n         * @return The resulting Point.\n         */\n        Point<T>& operator=(Point<T>&& point);\n\n        inline T area() const\n        {\n            return x * y;\n        }\n\n        /**\n         * It returns a string with the whole Point<T> data. Useful for debugging.\n         * The format is: `[x, y]`\n         * @return A string with the Point<T> values in the above format.\n         */\n        std::string toString() const;\n\n\n\n\n\n        // ------------------------------ Comparison operators ------------------------------ //\n        /**\n         * Less comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator<(const Point<T>& point) const\n        {\n            return area() < point.area();\n        }\n\n        /**\n         * Greater comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator>(const Point<T>& point) const\n        {\n            return area() > point.area();\n        }\n\n        /**\n         * Less or equal comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator<=(const Point<T>& point) const\n        {\n            return area() <= point.area();\n        }\n\n        /**\n         * Greater or equal comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator>=(const Point<T>& point) const\n        {\n            return area() >= point.area();\n        }\n\n        /**\n         * Equal comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator==(const Point<T>& point) const\n        {\n            return area() == point.area();\n        }\n\n        /**\n         * Not equal comparison operator.\n         * @param point Point<T> to be compared.\n         * @result Whether the instance satisfies the condition with respect to point.\n         */\n        inline bool operator!=(const Point<T>& point) const\n        {\n            return area() != point.area();\n        }\n\n\n\n\n\n        // ------------------------------ Basic Operators ------------------------------ //\n        Point<T>& operator+=(const Point<T>& point);\n\n        Point<T> operator+(const Point<T>& point) const;\n\n        Point<T>& operator+=(const T value);\n\n        Point<T> operator+(const T value) const;\n\n        Point<T>& operator-=(const Point<T>& point);\n\n        Point<T> operator-(const Point<T>& point) const;\n\n        Point<T>& operator-=(const T value);\n\n        Point<T> operator-(const T value) const;\n\n        Point<T>& operator*=(const T value);\n\n        Point<T> operator*(const T value) const;\n\n        Point<T>& operator/=(const T value);\n\n        Point<T> operator/(const T value) const;\n    };\n\n    // Static methods\n    OVERLOAD_C_OUT(Point)\n}\n\n#endif // OPENPOSE_CORE_POINT_HPP\n"
  },
  {
    "path": "include/openpose/core/rectangle.hpp",
    "content": "#ifndef OPENPOSE_CORE_RECTANGLE_HPP\n#define OPENPOSE_CORE_RECTANGLE_HPP\n\n#include <string>\n#include <openpose/core/macros.hpp>\n#include <openpose/core/point.hpp>\n\nnamespace op\n{\n    template<typename T>\n    struct Rectangle\n    {\n        T x;\n        T y;\n        T width;\n        T height;\n\n        Rectangle(const T x = 0, const T y = 0, const T width = 0, const T height = 0);\n\n        /**\n         * Copy constructor.\n         * It performs `fast copy`: For performance purpose, copying a Rectangle<T> or Datum or cv::Mat just copies\n         * the reference, it still shares the same internal data.\n         * Modifying the copied element will modify the original one.\n         * Use clone() for a slower but real copy, similarly to cv::Mat and Rectangle<T>.\n         * @param rectangle Rectangle to be copied.\n         */\n        Rectangle<T>(const Rectangle<T>& rectangle);\n\n        /**\n         * Copy assignment.\n         * Similar to Rectangle<T>(const Rectangle<T>& rectangle).\n         * @param rectangle Rectangle to be copied.\n         * @return The resulting Rectangle.\n         */\n        Rectangle<T>& operator=(const Rectangle<T>& rectangle);\n\n        /**\n         * Move constructor.\n         * It destroys the original Rectangle to be moved.\n         * @param rectangle Rectangle to be moved.\n         */\n        Rectangle<T>(Rectangle<T>&& rectangle);\n\n        /**\n         * Move assignment.\n         * Similar to Rectangle<T>(Rectangle<T>&& rectangle).\n         * @param rectangle Rectangle to be moved.\n         * @return The resulting Rectangle.\n         */\n        Rectangle<T>& operator=(Rectangle<T>&& rectangle);\n\n        Point<T> center() const;\n\n        inline Point<T> topLeft() const\n        {\n            return Point<T>{x, y};\n        }\n\n        Point<T> bottomRight() const;\n\n        inline T area() const\n        {\n            return width * height;\n        }\n\n        void recenter(const T newWidth, const T newHeight);\n\n        /**\n         * It returns a string with the whole Rectangle<T> data. Useful for debugging.\n         * The format is: `[x, y, width, height]`\n         * @return A string with the Rectangle<T> values in the above format.\n         */\n        std::string toString() const;\n\n        // ------------------------------ Basic Operators ------------------------------ //\n        Rectangle<T>& operator*=(const T value);\n\n        Rectangle<T> operator*(const T value) const;\n\n        Rectangle<T>& operator/=(const T value);\n\n        Rectangle<T> operator/(const T value) const;\n    };\n\n    // Static methods\n    template<typename T>\n    Rectangle<T> recenter(const Rectangle<T>& rectangle, const T newWidth, const T newHeight);\n\n    OVERLOAD_C_OUT(Rectangle)\n}\n\n#endif // OPENPOSE_CORE_RECTANGLE_HPP\n"
  },
  {
    "path": "include/openpose/core/renderer.hpp",
    "content": "#ifndef OPENPOSE_CORE_RENDERER_HPP\n#define OPENPOSE_CORE_RENDERER_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API Renderer\n    {\n    public:\n        explicit Renderer(const float renderThreshold, const float alphaKeypoint, const float alphaHeatMap,\n                          const bool blendOriginalFrame = true, const unsigned int elementToRender = 0u,\n                          const unsigned int numberElementsToRender = 0u);\n\n        virtual ~Renderer();\n\n        void increaseElementToRender(const int increment);\n\n        void setElementToRender(const int elementToRender);\n\n        void setElementToRender(const ElementToRender elementToRender);\n\n        bool getBlendOriginalFrame() const;\n\n        void setBlendOriginalFrame(const bool blendOriginalFrame);\n\n        float getAlphaKeypoint() const;\n\n        void setAlphaKeypoint(const float alphaKeypoint);\n\n        float getAlphaHeatMap() const;\n\n        void setAlphaHeatMap(const float alphaHeatMap);\n\n        bool getShowGooglyEyes() const;\n\n        void setShowGooglyEyes(const bool showGooglyEyes);\n\n    protected:\n        const float mRenderThreshold;\n        std::atomic<bool> mBlendOriginalFrame;\n        std::shared_ptr<std::atomic<unsigned int>> spElementToRender;\n        std::shared_ptr<const unsigned int> spNumberElementsToRender;\n        std::atomic<bool> mShowGooglyEyes;\n\n    private:\n        float mAlphaKeypoint;\n        float mAlphaHeatMap;\n\n        DELETE_COPY(Renderer);\n    };\n}\n\n#endif // OPENPOSE_CORE_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/core/scaleAndSizeExtractor.hpp",
    "content": "#ifndef OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP\n#define OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP\n\n#include <tuple>\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API ScaleAndSizeExtractor\n    {\n    public:\n        ScaleAndSizeExtractor(const Point<int>& netInputResolution, const float netInputResolutionDynamicBehavior,\n            const Point<int>& outputResolution, const int scaleNumber = 1, const double scaleGap = 0.25);\n\n        virtual ~ScaleAndSizeExtractor();\n\n        std::tuple<std::vector<double>, std::vector<Point<int>>, double, Point<int>> extract(\n            const Point<int>& inputResolution) const;\n\n    private:\n        const Point<int> mNetInputResolution;\n        const float mNetInputResolutionDynamicBehavior;\n        const Point<int> mOutputSize;\n        const int mScaleNumber;\n        const double mScaleGap;\n    };\n}\n\n#endif // OPENPOSE_CORE_SCALE_AND_SIZE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/core/string.hpp",
    "content": "#ifndef OPENPOSE_CORE_STRING_HPP\n#define OPENPOSE_CORE_STRING_HPP\n\n#include <memory> // std::shared_ptr\n#include <string>\n#include <openpose/core/macros.hpp>\n\nnamespace op\n{\n    /**\n     * String: Basic container for std::string to avoid std::string in the WrapperStructXXX classes. Otherwise,\n     * cryptic runtime DLL errors could occur when exporting OpenPose to other projects using different STL DLLs.\n     */\n    class OP_API String\n    {\n    public:\n        String();\n\n        /**\n         * It will force a copy of the char* of std::string to avoid DLL runtime errors. Example usages:\n         * std::string stdString = \"This is a std::string\"; \n         * String string(stdString.c_str()); \n         */\n        String(const char* charPtr);\n\n        /**\n         * It will force a copy of string\n         */\n        explicit String(const std::string& string);\n\n        const std::string& getStdString() const;\n\n        bool empty() const;\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplString;\n        std::shared_ptr<ImplString> spImpl;\n    };\n}\n\n#endif // OPENPOSE_CORE_STRING_HPP\n"
  },
  {
    "path": "include/openpose/core/verbosePrinter.hpp",
    "content": "#ifndef OPENPOSE_CORE_VERBOSE_PRINTER_HPP\n#define OPENPOSE_CORE_VERBOSE_PRINTER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API VerbosePrinter\n    {\n    public:\n        VerbosePrinter(const double verbose, const unsigned long long numberFrames);\n\n        virtual ~VerbosePrinter();\n\n        void printVerbose(const unsigned long long frameNumber) const;\n\n    private:\n        const unsigned long long mNumberFrames;\n        const std::string mNumberFramesString;\n        const double mVerbose;\n    };\n}\n\n#endif // OPENPOSE_CORE_VERBOSE_PRINTER_HPP\n"
  },
  {
    "path": "include/openpose/core/wCvMatToOpInput.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP\n#define OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/cvMatToOpInput.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WCvMatToOpInput : public Worker<TDatums>\n    {\n    public:\n        explicit WCvMatToOpInput(const std::shared_ptr<CvMatToOpInput>& cvMatToOpInput);\n\n        virtual ~WCvMatToOpInput();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<CvMatToOpInput> spCvMatToOpInput;\n\n        DELETE_COPY(WCvMatToOpInput);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WCvMatToOpInput<TDatums>::WCvMatToOpInput(const std::shared_ptr<CvMatToOpInput>& cvMatToOpInput) :\n        spCvMatToOpInput{cvMatToOpInput}\n    {\n    }\n\n    template<typename TDatums>\n    WCvMatToOpInput<TDatums>::~WCvMatToOpInput()\n    {\n    }\n\n    template<typename TDatums>\n    void WCvMatToOpInput<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WCvMatToOpInput<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // cv::Mat -> float*\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->inputNetData = spCvMatToOpInput->createArray(\n                        tDatumPtr->cvInputData, tDatumPtr->scaleInputToNetInputs, tDatumPtr->netInputSizes);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WCvMatToOpInput);\n}\n\n#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_INPUT_HPP\n"
  },
  {
    "path": "include/openpose/core/wCvMatToOpOutput.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP\n#define OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/cvMatToOpOutput.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WCvMatToOpOutput : public Worker<TDatums>\n    {\n    public:\n        explicit WCvMatToOpOutput(const std::shared_ptr<CvMatToOpOutput>& cvMatToOpOutput);\n\n        virtual ~WCvMatToOpOutput();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<CvMatToOpOutput> spCvMatToOpOutput;\n\n        DELETE_COPY(WCvMatToOpOutput);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/openCv.hpp>\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WCvMatToOpOutput<TDatums>::WCvMatToOpOutput(const std::shared_ptr<CvMatToOpOutput>& cvMatToOpOutput) :\n        spCvMatToOpOutput{cvMatToOpOutput}\n    {\n    }\n\n    template<typename TDatums>\n    WCvMatToOpOutput<TDatums>::~WCvMatToOpOutput()\n    {\n    }\n\n    template<typename TDatums>\n    void WCvMatToOpOutput<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WCvMatToOpOutput<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // cv::Mat -> float*\n                for (auto& tDatumPtr : tDatumsNoPtr)\n                    tDatumPtr->outputData = spCvMatToOpOutput->createArray(\n                        tDatumPtr->cvInputData, tDatumPtr->scaleInputToOutput, tDatumPtr->netOutputSize);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WCvMatToOpOutput);\n}\n\n#endif // OPENPOSE_CORE_W_CV_MAT_TO_OP_OUTPUT_HPP\n"
  },
  {
    "path": "include/openpose/core/wKeepTopNPeople.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP\n#define OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/keepTopNPeople.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WKeepTopNPeople : public Worker<TDatums>\n    {\n    public:\n        explicit WKeepTopNPeople(const std::shared_ptr<KeepTopNPeople>& keepTopNPeople);\n\n        virtual ~WKeepTopNPeople();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<KeepTopNPeople> spKeepTopNPeople;\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WKeepTopNPeople<TDatums>::WKeepTopNPeople(const std::shared_ptr<KeepTopNPeople>& keepTopNPeople) :\n        spKeepTopNPeople{keepTopNPeople}\n    {\n    }\n\n    template<typename TDatums>\n    WKeepTopNPeople<TDatums>::~WKeepTopNPeople()\n    {\n    }\n\n    template<typename TDatums>\n    void WKeepTopNPeople<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WKeepTopNPeople<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Rescale pose data\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    tDatumPtr->poseKeypoints = spKeepTopNPeople->keepTopPeople(\n                        tDatumPtr->poseKeypoints, tDatumPtr->poseScores);\n                    tDatumPtr->faceKeypoints = spKeepTopNPeople->keepTopPeople(\n                        tDatumPtr->faceKeypoints, tDatumPtr->poseScores);\n                    tDatumPtr->handKeypoints[0] = spKeepTopNPeople->keepTopPeople(\n                        tDatumPtr->handKeypoints[0], tDatumPtr->poseScores);\n                    tDatumPtr->handKeypoints[1] = spKeepTopNPeople->keepTopPeople(\n                        tDatumPtr->handKeypoints[1], tDatumPtr->poseScores);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WKeepTopNPeople);\n}\n\n#endif // OPENPOSE_CORE_W_KEEP_TOP_N_PEOPLE_HPP\n"
  },
  {
    "path": "include/openpose/core/wKeypointScaler.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP\n#define OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/keypointScaler.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WKeypointScaler : public Worker<TDatums>\n    {\n    public:\n        explicit WKeypointScaler(const std::shared_ptr<KeypointScaler>& keypointScaler);\n\n        virtual ~WKeypointScaler();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<KeypointScaler> spKeypointScaler;\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WKeypointScaler<TDatums>::WKeypointScaler(const std::shared_ptr<KeypointScaler>& keypointScaler) :\n        spKeypointScaler{keypointScaler}\n    {\n    }\n\n    template<typename TDatums>\n    WKeypointScaler<TDatums>::~WKeypointScaler()\n    {\n    }\n\n    template<typename TDatums>\n    void WKeypointScaler<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WKeypointScaler<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Rescale pose data\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    std::vector<Array<float>> arraysToScale{\n                        tDatumPtr->poseKeypoints, tDatumPtr->handKeypoints[0],\n                        tDatumPtr->handKeypoints[1], tDatumPtr->faceKeypoints};\n                    spKeypointScaler->scale(\n                        arraysToScale, tDatumPtr->scaleInputToOutput, tDatumPtr->scaleNetToOutput,\n                        Point<int>{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()});\n                    // Rescale part candidates\n                    spKeypointScaler->scale(\n                        tDatumPtr->poseCandidates, tDatumPtr->scaleInputToOutput, tDatumPtr->scaleNetToOutput,\n                        Point<int>{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()});\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WKeypointScaler);\n}\n\n#endif // OPENPOSE_CORE_W_KEYPOINT_SCALER_HPP\n"
  },
  {
    "path": "include/openpose/core/wOpOutputToCvMat.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP\n#define OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/opOutputToCvMat.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WOpOutputToCvMat : public Worker<TDatums>\n    {\n    public:\n        explicit WOpOutputToCvMat(const std::shared_ptr<OpOutputToCvMat>& opOutputToCvMat);\n\n        virtual ~WOpOutputToCvMat();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<OpOutputToCvMat> spOpOutputToCvMat;\n\n        DELETE_COPY(WOpOutputToCvMat);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WOpOutputToCvMat<TDatums>::WOpOutputToCvMat(const std::shared_ptr<OpOutputToCvMat>& opOutputToCvMat) :\n        spOpOutputToCvMat{opOutputToCvMat}\n    {\n    }\n\n    template<typename TDatums>\n    WOpOutputToCvMat<TDatums>::~WOpOutputToCvMat()\n    {\n    }\n\n    template<typename TDatums>\n    void WOpOutputToCvMat<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WOpOutputToCvMat<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // float* -> cv::Mat\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->cvOutputData = spOpOutputToCvMat->formatToCvMat(tDatumPtr->outputData);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WOpOutputToCvMat);\n}\n\n#endif // OPENPOSE_CORE_W_OP_OUTPUT_TO_CV_MAT_HPP\n"
  },
  {
    "path": "include/openpose/core/wScaleAndSizeExtractor.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP\n#define OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/scaleAndSizeExtractor.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WScaleAndSizeExtractor : public Worker<TDatums>\n    {\n    public:\n        explicit WScaleAndSizeExtractor(const std::shared_ptr<ScaleAndSizeExtractor>& scaleAndSizeExtractor);\n\n        virtual ~WScaleAndSizeExtractor();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<ScaleAndSizeExtractor> spScaleAndSizeExtractor;\n\n        DELETE_COPY(WScaleAndSizeExtractor);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WScaleAndSizeExtractor<TDatums>::WScaleAndSizeExtractor(\n        const std::shared_ptr<ScaleAndSizeExtractor>& scaleAndSizeExtractor) :\n        spScaleAndSizeExtractor{scaleAndSizeExtractor}\n    {\n    }\n\n    template<typename TDatums>\n    WScaleAndSizeExtractor<TDatums>::~WScaleAndSizeExtractor()\n    {\n    }\n\n    template<typename TDatums>\n    void WScaleAndSizeExtractor<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WScaleAndSizeExtractor<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // cv::Mat -> float*\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    const Point<int> inputSize{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()};\n                    std::tie(tDatumPtr->scaleInputToNetInputs, tDatumPtr->netInputSizes, tDatumPtr->scaleInputToOutput,\n                        tDatumPtr->netOutputSize) = spScaleAndSizeExtractor->extract(inputSize);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WScaleAndSizeExtractor);\n}\n\n#endif // OPENPOSE_CORE_W_SCALE_AND_SIZE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/core/wVerbosePrinter.hpp",
    "content": "#ifndef OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP\n#define OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/verbosePrinter.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WVerbosePrinter : public Worker<TDatums>\n    {\n    public:\n        explicit WVerbosePrinter(const std::shared_ptr<VerbosePrinter>& verbosePrinter);\n\n        virtual ~WVerbosePrinter();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<VerbosePrinter> spVerbosePrinter;\n\n        DELETE_COPY(WVerbosePrinter);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WVerbosePrinter<TDatums>::WVerbosePrinter(\n        const std::shared_ptr<VerbosePrinter>& verbosePrinter) :\n        spVerbosePrinter{verbosePrinter}\n    {\n    }\n\n    template<typename TDatums>\n    WVerbosePrinter<TDatums>::~WVerbosePrinter()\n    {\n    }\n\n    template<typename TDatums>\n    void WVerbosePrinter<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WVerbosePrinter<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Print verbose\n                if (checkNoNullNorEmpty(tDatums))\n                {\n                    const auto tDatumPtr = (*tDatums)[0];\n                    spVerbosePrinter->printVerbose(tDatumPtr->frameNumber);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WVerbosePrinter);\n}\n\n#endif // OPENPOSE_CORE_W_VERBOSE_PRINTER_HPP\n"
  },
  {
    "path": "include/openpose/face/faceCpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_CPU_RENDERER_HPP\n#define OPENPOSE_FACE_FACE_CPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/renderer.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/face/faceRenderer.hpp>\n\nnamespace op\n{\n    class OP_API FaceCpuRenderer : public Renderer, public FaceRenderer\n    {\n    public:\n        FaceCpuRenderer(const float renderThreshold, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,\n                        const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP);\n\n        virtual ~FaceCpuRenderer();\n\n        void renderFaceInherited(Array<float>& outputData, const Array<float>& faceKeypoints);\n\n        DELETE_COPY(FaceCpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_CPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/face/faceDetector.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_DETECTOR_HPP\n#define OPENPOSE_FACE_FACE_DETECTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API FaceDetector\n    {\n    public:\n        explicit FaceDetector(const PoseModel poseModel);\n\n        virtual ~FaceDetector();\n\n        std::vector<Rectangle<float>> detectFaces(const Array<float>& poseKeypoints) const;\n\n    private:\n        const unsigned int mNeck;\n        const unsigned int mNose;\n        const unsigned int mLEar;\n        const unsigned int mREar;\n        const unsigned int mLEye;\n        const unsigned int mREye;\n\n        DELETE_COPY(FaceDetector);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_DETECTOR_HPP\n"
  },
  {
    "path": "include/openpose/face/faceDetectorOpenCV.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP\n#define OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API FaceDetectorOpenCV\n    {\n    public:\n        explicit FaceDetectorOpenCV(const std::string& modelFolder);\n\n        virtual ~FaceDetectorOpenCV();\n\n        // No thread-save\n        std::vector<Rectangle<float>> detectFaces(const Matrix& inputData);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplFaceDetectorOpenCV;\n        std::unique_ptr<ImplFaceDetectorOpenCV> upImpl;\n\n        DELETE_COPY(FaceDetectorOpenCV);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_DETECTOR_OPENCV_HPP\n"
  },
  {
    "path": "include/openpose/face/faceExtractorCaffe.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP\n#define OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/face/faceExtractorNet.hpp>\n\nnamespace op\n{\n    /**\n     * Face keypoint extractor class for Caffe framework.\n     */\n    class OP_API FaceExtractorCaffe : public FaceExtractorNet\n    {\n    public:\n        /**\n         * Constructor of the FaceExtractor class.\n         * @param netInputSize Size at which the cropped image (where the face is located) is resized.\n         * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize.\n         */\n        FaceExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                           const std::string& modelFolder, const int gpuId,\n                           const std::vector<HeatMapType>& heatMapTypes = {},\n                           const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect,\n                           const bool enableGoogleLogging = true);\n\n        virtual ~FaceExtractorCaffe();\n\n        /**\n         * This function must be call before using any other function. It must also be called inside the thread in\n         * which the functions are going to be used.\n         */\n        void netInitializationOnThread();\n\n        /**\n         * This function extracts the face keypoints for each detected face in the image.\n         * @param faceRectangles location of the faces in the image. It is a length-variable std::vector, where\n         * each index corresponds to a different person in the image. Internally, a op::Rectangle<float>\n         * (similar to cv::Rect for floating values) with the position of that face (or 0,0,0,0 if\n         * some face is missing, e.g., if a specific person has only half of the body inside the image).\n         * @param cvInputData Original image in Mat format and BGR format.\n         */\n        void forwardPass(const std::vector<Rectangle<float>>& faceRectangles, const Matrix& inputData);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplFaceExtractorCaffe;\n        std::unique_ptr<ImplFaceExtractorCaffe> upImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(FaceExtractorCaffe);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_EXTRACTOR_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/face/faceExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_EXTRACTOR_HPP\n#define OPENPOSE_FACE_FACE_EXTRACTOR_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * Face keypoint extractor class.\n     */\n    class OP_API FaceExtractorNet\n    {\n    public:\n        /**\n         * Constructor of the FaceExtractorNet class.\n         * @param netInputSize Size at which the cropped image (where the face is located) is resized.\n         * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize.\n         */\n        explicit FaceExtractorNet(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                  const std::vector<HeatMapType>& heatMapTypes = {},\n                                  const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect);\n\n        /**\n         * Virtual destructor of the HandExtractor class.\n         * Required to allow inheritance.\n         */\n        virtual ~FaceExtractorNet();\n\n        /**\n         * This function must be call before using any other function. It must also be called inside the thread in\n         * which the functions are going to be used.\n         */\n        void initializationOnThread();\n\n        /**\n         * This function extracts the face keypoints for each detected face in the image.\n         * @param faceRectangles location of the faces in the image. It is a length-variable std::vector, where\n         * each index corresponds to a different person in the image. Internally, a op::Rectangle<float>\n         * (similar to cv::Rect for floating values) with the position of that face (or 0,0,0,0 if\n         * some face is missing, e.g., if a specific person has only half of the body inside the image).\n         * @param cvInputData Original image in Mat format and BGR format.\n         */\n        virtual void forwardPass(const std::vector<Rectangle<float>>& faceRectangles, const Matrix& inputData) = 0;\n\n        Array<float> getHeatMaps() const;\n\n        /**\n         * This function returns the face keypoins. VERY IMPORTANT: use getFaceKeypoints().clone() if the keypoints are\n         * going to be edited in a different thread.\n         * @return A Array with all the face keypoints. It follows the pose structure, i.e., the first dimension\n         * corresponds to all the people in the image, the second to each specific keypoint, and the third one to\n         * (x, y, score).\n         */\n        Array<float> getFaceKeypoints() const;\n\n        bool getEnabled() const;\n\n        void setEnabled(const bool enabled);\n\n    protected:\n        const Point<int> mNetOutputSize;\n        Array<float> mFaceImageCrop;\n        Array<float> mFaceKeypoints;\n        // HeatMaps parameters\n        Array<float> mHeatMaps;\n        const ScaleMode mHeatMapScaleMode;\n        const std::vector<HeatMapType> mHeatMapTypes;\n        // Temporarily disable it\n        std::atomic<bool> mEnabled;\n\n        virtual void netInitializationOnThread() = 0;\n\n    private:\n        // Init with thread\n        std::thread::id mThreadId;\n\n        void checkThread() const;\n\n        DELETE_COPY(FaceExtractorNet);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/face/faceGpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_GPU_RENDERER_HPP\n#define OPENPOSE_FACE_FACE_GPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/gpuRenderer.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/face/faceRenderer.hpp>\n\nnamespace op\n{\n    class OP_API FaceGpuRenderer : public GpuRenderer, public FaceRenderer\n    {\n    public:\n        FaceGpuRenderer(const float renderThreshold,\n                        const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,\n                        const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP);\n\n        virtual ~FaceGpuRenderer();\n\n        void initializationOnThread();\n\n        void renderFaceInherited(Array<float>& outputData, const Array<float>& faceKeypoints);\n\n    private:\n        float* pGpuFace; // GPU aux memory\n        float* pMaxPtr; // GPU aux memory\n        float* pMinPtr; // GPU aux memory\n        float* pScalePtr; // GPU aux memory\n\n        DELETE_COPY(FaceGpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_GPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/face/faceParameters.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_PARAMETERS_HPP\n#define OPENPOSE_FACE_FACE_PARAMETERS_HPP\n\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n\nnamespace op\n{\n    const auto FACE_MAX_FACES = POSE_MAX_PEOPLE;\n\n    const auto FACE_NUMBER_PARTS = 70u;\n    #define FACE_PAIRS_RENDER_GPU \\\n        0,1,  1,2,  2,3,  3,4,  4,5,  5,6,  6,7,  7,8,  8,9,  9,10,  10,11,  11,12,  12,13,  13,14,  14,15,  15,16,  17,18,  18,19,  19,20, \\\n        20,21,  22,23,  23,24,  24,25,  25,26,  27,28,  28,29,  29,30,  31,32,  32,33,  33,34,  34,35,  36,37,  37,38,  38,39,  39,40,  40,41, \\\n        41,36,  42,43,  43,44,  44,45,  45,46,  46,47,  47,42,  48,49,  49,50,  50,51,  51,52,  52,53,  53,54,  54,55,  55,56,  56,57,  57,58, \\\n        58,59,  59,48,  60,61,  61,62,  62,63,  63,64,  64,65,  65,66,  66,67,  67,60\n    #define FACE_SCALES_RENDER_GPU 1\n    const std::vector<unsigned int> FACE_PAIRS_RENDER {FACE_PAIRS_RENDER_GPU};\n    #define FACE_COLORS_RENDER_GPU 255.f,    255.f,    255.f\n    const std::vector<float> FACE_COLORS_RENDER{FACE_COLORS_RENDER_GPU};\n    const std::vector<float> FACE_SCALES_RENDER{FACE_SCALES_RENDER_GPU};\n\n    // Constant parameters\n    const auto FACE_CCN_DECREASE_FACTOR = 8.f;\n    const std::string FACE_PROTOTXT{\"face/pose_deploy.prototxt\"};\n    const std::string FACE_TRAINED_MODEL{\"face/pose_iter_116000.caffemodel\"};\n\n    // Rendering parameters\n    const auto FACE_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT;\n    const auto FACE_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP;\n}\n\n#endif // OPENPOSE_FACE_FACE_PARAMETERS_HPP\n"
  },
  {
    "path": "include/openpose/face/faceRenderer.hpp",
    "content": "#ifndef OPENPOSE_FACE_FACE_RENDERER_HPP\n#define OPENPOSE_FACE_FACE_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API FaceRenderer\n    {\n    public:\n        virtual ~FaceRenderer(){};\n\n        virtual void initializationOnThread(){};\n\n        void renderFace(Array<float>& outputData, const Array<float>& faceKeypoints,\n                        const float scaleInputToOutput);\n\n    private:\n        virtual void renderFaceInherited(Array<float>& outputData, const Array<float>& faceKeypoints) = 0;\n    };\n}\n\n#endif // OPENPOSE_FACE_FACE_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/face/headers.hpp",
    "content": "#ifndef OPENPOSE_FACE_HEADERS_HPP\n#define OPENPOSE_FACE_HEADERS_HPP\n\n// face module\n#include <openpose/face/faceDetector.hpp>\n#include <openpose/face/faceDetectorOpenCV.hpp>\n#include <openpose/face/faceExtractorCaffe.hpp>\n#include <openpose/face/faceExtractorNet.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/face/faceCpuRenderer.hpp>\n#include <openpose/face/faceGpuRenderer.hpp>\n#include <openpose/face/faceRenderer.hpp>\n#include <openpose/face/renderFace.hpp>\n#include <openpose/face/wFaceDetector.hpp>\n#include <openpose/face/wFaceDetectorOpenCV.hpp>\n#include <openpose/face/wFaceExtractorNet.hpp>\n#include <openpose/face/wFaceRenderer.hpp>\n\n#endif // OPENPOSE_FACE_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/face/renderFace.hpp",
    "content": "#ifndef OPENPOSE_FACE_RENDER_FACE_HPP\n#define OPENPOSE_FACE_RENDER_FACE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/face/faceParameters.hpp>\n\nnamespace op\n{\n    OP_API void renderFaceKeypointsCpu(\n        Array<float>& frameArray, const Array<float>& faceKeypoints, const float renderThreshold);\n\n    void renderFaceKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point<unsigned int>& frameSize,\n        const float* const facePtr, const int numberPeople, const float renderThreshold,\n        const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT);\n}\n\n#endif // OPENPOSE_FACE_RENDER_FACE_HPP\n"
  },
  {
    "path": "include/openpose/face/wFaceDetector.hpp",
    "content": "#ifndef OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP\n#define OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/face/faceRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFaceDetector : public Worker<TDatums>\n    {\n    public:\n        explicit WFaceDetector(const std::shared_ptr<FaceDetector>& faceDetector);\n\n        virtual ~WFaceDetector();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<FaceDetector> spFaceDetector;\n\n        DELETE_COPY(WFaceDetector);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WFaceDetector<TDatums>::WFaceDetector(const std::shared_ptr<FaceDetector>& faceDetector) :\n        spFaceDetector{faceDetector}\n    {\n    }\n\n    template<typename TDatums>\n    WFaceDetector<TDatums>::~WFaceDetector()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceDetector<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceDetector<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people face\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->faceRectangles = spFaceDetector->detectFaces(tDatumPtr->poseKeypoints);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFaceDetector);\n}\n\n#endif // OPENPOSE_FACE_W_FACE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/face/wFaceDetectorOpenCV.hpp",
    "content": "#ifndef OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP\n#define OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/face/faceRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFaceDetectorOpenCV : public Worker<TDatums>\n    {\n    public:\n        explicit WFaceDetectorOpenCV(const std::shared_ptr<FaceDetectorOpenCV>& faceDetectorOpenCV);\n\n        virtual ~WFaceDetectorOpenCV();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<FaceDetectorOpenCV> spFaceDetectorOpenCV;\n\n        DELETE_COPY(WFaceDetectorOpenCV);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WFaceDetectorOpenCV<TDatums>::WFaceDetectorOpenCV(const std::shared_ptr<FaceDetectorOpenCV>& faceDetectorOpenCV) :\n        spFaceDetectorOpenCV{faceDetectorOpenCV}\n    {\n    }\n\n    template<typename TDatums>\n    WFaceDetectorOpenCV<TDatums>::~WFaceDetectorOpenCV()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceDetectorOpenCV<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceDetectorOpenCV<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people face\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->faceRectangles = spFaceDetectorOpenCV->detectFaces(tDatumPtr->cvInputData);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFaceDetectorOpenCV);\n}\n\n#endif // OPENPOSE_FACE_W_FACE_EXTRACTOR_OPENCV_HPP\n"
  },
  {
    "path": "include/openpose/face/wFaceExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP\n#define OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/face/faceRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFaceExtractorNet : public Worker<TDatums>\n    {\n    public:\n        explicit WFaceExtractorNet(const std::shared_ptr<FaceExtractorNet>& faceExtractorNet);\n\n        virtual ~WFaceExtractorNet();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<FaceExtractorNet> spFaceExtractorNet;\n\n        DELETE_COPY(WFaceExtractorNet);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WFaceExtractorNet<TDatums>::WFaceExtractorNet(const std::shared_ptr<FaceExtractorNet>& faceExtractorNet) :\n        spFaceExtractorNet{faceExtractorNet}\n    {\n    }\n\n    template<typename TDatums>\n    WFaceExtractorNet<TDatums>::~WFaceExtractorNet()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceExtractorNet<TDatums>::initializationOnThread()\n    {\n        spFaceExtractorNet->initializationOnThread();\n    }\n\n    template<typename TDatums>\n    void WFaceExtractorNet<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Extract people face\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    spFaceExtractorNet->forwardPass(tDatumPtr->faceRectangles, tDatumPtr->cvInputData);\n                    tDatumPtr->faceHeatMaps = spFaceExtractorNet->getHeatMaps().clone();\n                    tDatumPtr->faceKeypoints = spFaceExtractorNet->getFaceKeypoints().clone();\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFaceExtractorNet);\n}\n\n#endif // OPENPOSE_FACE_W_FACE_DETECTOR_NET_HPP\n"
  },
  {
    "path": "include/openpose/face/wFaceRenderer.hpp",
    "content": "#ifndef OPENPOSE_FACE_W_FACE_RENDERER_HPP\n#define OPENPOSE_FACE_W_FACE_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/face/faceRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFaceRenderer : public Worker<TDatums>\n    {\n    public:\n        explicit WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer);\n\n        virtual ~WFaceRenderer();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<FaceRenderer> spFaceRenderer;\n\n        DELETE_COPY(WFaceRenderer);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WFaceRenderer<TDatums>::WFaceRenderer(const std::shared_ptr<FaceRenderer>& faceRenderer) :\n        spFaceRenderer{faceRenderer}\n    {\n    }\n\n    template<typename TDatums>\n    WFaceRenderer<TDatums>::~WFaceRenderer()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceRenderer<TDatums>::initializationOnThread()\n    {\n        spFaceRenderer->initializationOnThread();\n    }\n\n    template<typename TDatums>\n    void WFaceRenderer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Render people face\n                for (auto& tDatumPtr : *tDatums)\n                    spFaceRenderer->renderFace(\n                        tDatumPtr->outputData, tDatumPtr->faceKeypoints, (float)tDatumPtr->scaleInputToOutput);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFaceRenderer);\n}\n\n#endif // OPENPOSE_FACE_W_FACE_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/bvhSaver.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_FILESTREAM_BVH_SAVER_HPP\n#define OPENPOSE_FILESTREAM_BVH_SAVER_HPP\n\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/totalmodel.h>\n#endif\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API BvhSaver\n    {\n    public:\n        BvhSaver(const std::string bvhFilePath,\n                 const std::shared_ptr<const TotalModel>& totalModel = nullptr,\n                 const double fps = 30.);\n\n        virtual ~BvhSaver();\n\n        void initializationOnThread();\n\n        void updateBvh(const Eigen::Matrix<double, 62, 3, Eigen::RowMajor>& adamPose,\n                       const Eigen::Vector3d& adamTranslation,\n                       const Eigen::Matrix<double, Eigen::Dynamic, 1>& j0Vec);\n\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplBvhSaver;\n        std::shared_ptr<ImplBvhSaver> spImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(BvhSaver);\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_BVH_SAVER_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/filestream/cocoJsonSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP\n#define OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/filestream/jsonOfstream.hpp>\n\nnamespace op\n{\n    /**\n     *  The CocoJsonSaver class creates a COCO validation json file with details about the processed images. It\n     * inherits from Recorder.\n     */\n    class OP_API CocoJsonSaver\n    {\n    public:\n        /**\n         * This constructor of CocoJsonSaver extends the Recorder::Recorder(const std::string & filePathToSave)\n         * constructor.\n         * @param filePathToSave const std::string parameter with the final file path where the generated json file\n         * will be saved.\n         */\n        explicit CocoJsonSaver(\n            const std::string& filePathToSave, const PoseModel poseModel, const bool humanReadable = true,\n            const int cocoJsonVariants = 1, const CocoJsonFormat cocoJsonFormat = CocoJsonFormat::Body,\n            const int cocoJsonVariant = 0);\n\n        virtual ~CocoJsonSaver();\n\n        void record(\n            const Array<float>& poseKeypoints, const Array<float>& poseScores, const std::string& imageName,\n            const unsigned long long frameNumber);\n\n    private:\n        const PoseModel mPoseModel;\n        const int mCocoJsonVariant;\n        std::vector<std::tuple<JsonOfstream, CocoJsonFormat, bool>> mJsonOfstreams;\n\n        DELETE_COPY(CocoJsonSaver);\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_POSE_JSON_COCO_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP\n#define OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class DataFormat : unsigned char\n    {\n        Json,\n        Xml,\n        Yaml,\n        Yml,\n    };\n\n    enum class CocoJsonFormat : unsigned char\n    {\n        Body,\n        Hand21,\n        Hand42,\n        Face,\n        Foot,\n        Car,\n        Size,\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/filestream/fileSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_DATA_SAVER_HPP\n#define OPENPOSE_FILESTREAM_DATA_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/utilities/string.hpp>\n\nnamespace op\n{\n    class OP_API FileSaver\n    {\n    protected:\n        explicit FileSaver(const std::string& directoryPath);\n\n        virtual ~FileSaver();\n\n        std::string getNextFileName(const unsigned long long index) const;\n\n        std::string getNextFileName(const std::string& fileNameNoExtension) const;\n\n    private:\n        const std::string mDirectoryPath;\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_DATA_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/fileStream.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_FILE_STREAM_HPP\n#define OPENPOSE_FILESTREAM_FILE_STREAM_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/utilities/openCv.hpp>\n\nnamespace op\n{\n    OP_API std::string dataFormatToString(const DataFormat dataFormat);\n\n    OP_API DataFormat stringToDataFormat(const std::string& dataFormat);\n\n    // Save custom float format\n    // Example to read it in Python, assuming a (18 x 300 x 500) size Array\n    // x = np.fromfile(heatMapFullPath, dtype=np.float32)\n    // assert x[0] == 3 # First parameter saves the number of dimensions (18x300x500 = 3 dimensions)\n    // shape_x = x[1:1+int(x[0])]\n    // assert len(shape_x[0]) == 3 # Number of dimensions\n    // assert shape_x[0] == 18 # Size of the first dimension\n    // assert shape_x[1] == 300 # Size of the second dimension\n    // assert shape_x[2] == 500 # Size of the third dimension\n    // arrayData = x[1+int(round(x[0])):]\n    OP_API void saveFloatArray(const Array<float>& array, const std::string& fullFilePath);\n\n    // Save/load json, xml, yaml, yml\n    OP_API void saveData(\n        const std::vector<Matrix>& opMats, const std::vector<std::string>& cvMatNames,\n        const std::string& fileNameNoExtension, const DataFormat dataFormat);\n\n    OP_API void saveData(\n        const Matrix& opMat, const std::string cvMatName, const std::string& fileNameNoExtension,\n        const DataFormat dataFormat);\n\n    OP_API std::vector<Matrix> loadData(\n        const std::vector<std::string>& cvMatNames, const std::string& fileNameNoExtension,\n        const DataFormat dataFormat);\n\n    OP_API Matrix loadData(\n        const std::string& cvMatName, const std::string& fileNameNoExtension, const DataFormat dataFormat);\n\n    // Json - Saving as *.json not available in OpenCV versions < 3.0, this function is a quick fix\n    OP_API void savePeopleJson(\n        const Array<float>& keypoints, const std::vector<std::vector<std::array<float,3>>>& candidates,\n        const std::string& keypointName, const std::string& fileName, const bool humanReadable);\n\n    // It will save a bunch of Array<float> elements\n    OP_API void savePeopleJson(\n        const std::vector<std::pair<Array<float>, std::string>>& keypointVector,\n        const std::vector<std::vector<std::array<float,3>>>& candidates, const std::string& fileName,\n        const bool humanReadable);\n\n    // Save/load image\n    OP_API void saveImage(\n        const Matrix& matrix, const std::string& fullFilePath,\n        const std::vector<int>& openCvCompressionParams\n            = {getCvImwriteJpegQuality(), 100, getCvImwritePngCompression(), 9});\n\n    OP_API Matrix loadImage(const std::string& fullFilePath, const int openCvFlags = getCvLoadImageAnydepth());\n\n    OP_API std::vector<std::array<Rectangle<float>, 2>> loadHandDetectorTxt(const std::string& txtFilePath);\n}\n\n#endif // OPENPOSE_FILESTREAM_FILE_STREAM_HPP\n"
  },
  {
    "path": "include/openpose/filestream/headers.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_HEADERS_HPP\n#define OPENPOSE_FILESTREAM_HEADERS_HPP\n\n// fileStream module\n#include <openpose/filestream/bvhSaver.hpp>\n#include <openpose/filestream/cocoJsonSaver.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/filestream/fileSaver.hpp>\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/filestream/heatMapSaver.hpp>\n#include <openpose/filestream/imageSaver.hpp>\n#include <openpose/filestream/jsonOfstream.hpp>\n#include <openpose/filestream/keypointSaver.hpp>\n#include <openpose/filestream/peopleJsonSaver.hpp>\n#include <openpose/filestream/udpSender.hpp>\n#include <openpose/filestream/videoSaver.hpp>\n#include <openpose/filestream/wBvhSaver.hpp>\n#include <openpose/filestream/wCocoJsonSaver.hpp>\n#include <openpose/filestream/wFaceSaver.hpp>\n#include <openpose/filestream/wHandSaver.hpp>\n#include <openpose/filestream/wImageSaver.hpp>\n#include <openpose/filestream/wHeatMapSaver.hpp>\n#include <openpose/filestream/wPeopleJsonSaver.hpp>\n#include <openpose/filestream/wPoseSaver.hpp>\n#include <openpose/filestream/wUdpSender.hpp>\n#include <openpose/filestream/wVideoSaver.hpp>\n#include <openpose/filestream/wVideoSaver3D.hpp>\n\n#endif // OPENPOSE_FILESTREAM_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/filestream/heatMapSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP\n#define OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/fileSaver.hpp>\n\nnamespace op\n{\n    class OP_API HeatMapSaver : public FileSaver\n    {\n    public:\n        HeatMapSaver(const std::string& directoryPath, const std::string& imageFormat);\n\n        virtual ~HeatMapSaver();\n\n        void saveHeatMaps(const std::vector<Array<float>>& heatMaps, const std::string& fileName) const;\n\n    private:\n        const std::string mImageFormat;\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_HEAT_MAP_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/imageSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP\n#define OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/fileSaver.hpp>\n\nnamespace op\n{\n    class OP_API ImageSaver : public FileSaver\n    {\n    public:\n        ImageSaver(const std::string& directoryPath, const std::string& imageFormat);\n\n        virtual ~ImageSaver();\n\n        void saveImages(const Matrix& cvOutputData, const std::string& fileName) const;\n\n        void saveImages(const std::vector<Matrix>& matOutputDatas, const std::string& fileName) const;\n\n    private:\n        const std::string mImageFormat;\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_IMAGE_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/jsonOfstream.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP\n#define OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP\n\n#include <fstream> // std::ofstream\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API JsonOfstream\n    {\n    public:\n        explicit JsonOfstream(const std::string& filePath, const bool humanReadable = true);\n\n        /**\n         * Move constructor.\n         * It destroys the original JsonOfstream to be moved.\n         * @param array JsonOfstream to be moved.\n         */\n        JsonOfstream(JsonOfstream&& jsonOfstream);\n\n        /**\n         * Move assignment.\n         * Similar to JsonOfstream(JsonOfstream&& jsonOfstream).\n         * @param array JsonOfstream to be moved.\n         * @return The resulting JsonOfstream.\n         */\n        JsonOfstream& operator=(JsonOfstream&& jsonOfstream);\n\n        virtual ~JsonOfstream();\n\n        void objectOpen();\n\n        void objectClose();\n\n        void arrayOpen();\n\n        void arrayClose();\n\n        void version(const std::string& version);\n\n        void key(const std::string& string);\n\n        template <typename T>\n        inline void plainText(const T& value)\n        {\n            *upOfstream << value;\n        }\n\n        inline void comma()\n        {\n            *upOfstream << \",\";\n        }\n\n        void enter();\n\n    private:\n        bool mHumanReadable;\n        long long mBracesCounter;\n        long long mBracketsCounter;\n        std::unique_ptr<std::ofstream> upOfstream; // std::unique_ptr to solve std::move issue in GCC < 5\n\n        DELETE_COPY(JsonOfstream);\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_JSON_OFSTREAM_HPP\n"
  },
  {
    "path": "include/openpose/filestream/keypointSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP\n#define OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/filestream/fileSaver.hpp>\n\nnamespace op\n{\n    class OP_API KeypointSaver : public FileSaver\n    {\n    public:\n        KeypointSaver(const std::string& directoryPath, const DataFormat format);\n\n        virtual ~KeypointSaver();\n\n        void saveKeypoints(const std::vector<Array<float>>& keypointVector, const std::string& fileName,\n                           const std::string& keypointName) const;\n\n    private:\n        const DataFormat mFormat;\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_KEYPOINT_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/peopleJsonSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP\n#define OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/fileSaver.hpp>\n\nnamespace op\n{\n    class OP_API PeopleJsonSaver : public FileSaver\n    {\n    public:\n        PeopleJsonSaver(const std::string& directoryPath);\n\n        virtual ~PeopleJsonSaver();\n\n        void save(\n            const std::vector<std::pair<Array<float>, std::string>>& keypointVector,\n            const std::vector<std::vector<std::array<float,3>>>& candidates, const std::string& fileName,\n            const bool humanReadable = true) const;\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_PEOPLE_JSON_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/udpSender.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_UDP_SENDER_HPP\n#define OPENPOSE_FILESTREAM_UDP_SENDER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API UdpSender\n    {\n    public:\n        UdpSender(const std::string& udpHost, const std::string& udpPort);\n\n        virtual ~UdpSender();\n\n        void sendJointAngles(const double* const adamPosePtr, const int adamPoseRows,\n                             const double* const adamTranslationPtr,\n                             const double* const adamFaceCoeffsExpPtr, const int faceCoeffRows);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplUdpSender;\n        std::shared_ptr<ImplUdpSender> spImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(UdpSender);\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_UDP_SENDER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/videoSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP\n#define OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API VideoSaver\n    {\n    public:\n        VideoSaver(\n            const std::string& videoSaverPath, const int cvFourcc, const double fps,\n            const std::string& addAudioFromThisVideo = \"\");\n\n        virtual ~VideoSaver();\n\n        bool isOpened();\n\n        void write(const Matrix& matToSave);\n\n        void write(const std::vector<Matrix>& matsToSave);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplVideoSaver;\n        std::unique_ptr<ImplVideoSaver> upImpl;\n\n        DELETE_COPY(VideoSaver);\n    };\n}\n\n#endif // OPENPOSE_FILESTREAM_VIDEO_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wBvhSaver.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/bvhSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WBvhSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WBvhSaver(const std::shared_ptr<BvhSaver>& bvhSaver);\n\n        virtual ~WBvhSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<BvhSaver> spBvhSaver;\n\n        DELETE_COPY(WBvhSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WBvhSaver<TDatums>::WBvhSaver(const std::shared_ptr<BvhSaver>& bvhSaver) :\n        spBvhSaver{bvhSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WBvhSaver<TDatums>::~WBvhSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WBvhSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WBvhSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Record BVH file\n                const auto& tDatumPtr = (*tDatums)[0];\n                if (!tDatumPtr->poseKeypoints3D.empty())\n                    spBvhSaver->updateBvh(tDatumPtr->adamPose, tDatumPtr->adamTranslation, tDatumPtr->j0Vec);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WBvhSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_BVH_SAVER_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/filestream/wCocoJsonSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/cocoJsonSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WCocoJsonSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WCocoJsonSaver(const std::shared_ptr<CocoJsonSaver>& cocoJsonSaver);\n\n        virtual ~WCocoJsonSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<CocoJsonSaver> spCocoJsonSaver;\n\n        DELETE_COPY(WCocoJsonSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WCocoJsonSaver<TDatums>::WCocoJsonSaver(const std::shared_ptr<CocoJsonSaver>& cocoJsonSaver) :\n        spCocoJsonSaver{cocoJsonSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WCocoJsonSaver<TDatums>::~WCocoJsonSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WCocoJsonSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WCocoJsonSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Check tDatums->size() == 1\n                if (tDatums->size() > 1)\n                    error(\"Function only ready for tDatums->size() == 1\", __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                const auto& tDatumPtr = tDatums->at(0);\n                // Record json in COCO format\n                spCocoJsonSaver->record(\n                    tDatumPtr->poseKeypoints, tDatumPtr->poseScores, tDatumPtr->name, tDatumPtr->frameNumber);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WCocoJsonSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_COCO_JSON_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wFaceSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/filestream/keypointSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFaceSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WFaceSaver(const std::shared_ptr<KeypointSaver>& keypointSaver);\n\n        virtual ~WFaceSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<KeypointSaver> spKeypointSaver;\n\n        DELETE_COPY(WFaceSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WFaceSaver<TDatums>::WFaceSaver(const std::shared_ptr<KeypointSaver>& keypointSaver) :\n        spKeypointSaver{keypointSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WFaceSaver<TDatums>::~WFaceSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WFaceSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record people face keypoint data\n                std::vector<Array<float>> keypointVector(tDatumsNoPtr.size());\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    keypointVector[i] = tDatumsNoPtr[i]->faceKeypoints;\n                const auto fileName = (!tDatumsNoPtr[0]->name.empty()\n                    ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id));\n                spKeypointSaver->saveKeypoints(keypointVector, fileName, \"face\");\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFaceSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_FACE_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wHandSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/filestream/keypointSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WHandSaver(const std::shared_ptr<KeypointSaver>& keypointSaver);\n\n        virtual ~WHandSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<KeypointSaver> spKeypointSaver;\n\n        DELETE_COPY(WHandSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandSaver<TDatums>::WHandSaver(const std::shared_ptr<KeypointSaver>& keypointSaver) :\n        spKeypointSaver{keypointSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WHandSaver<TDatums>::~WHandSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record people hand keypoint data\n                const auto fileName = (!tDatumsNoPtr[0]->name.empty()\n                    ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id));\n                std::vector<Array<float>> keypointVector(tDatumsNoPtr.size());\n                // Left hand\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    keypointVector[i] = tDatumsNoPtr[i]->handKeypoints[0];\n                spKeypointSaver->saveKeypoints(keypointVector, fileName, \"hand_left\");\n                // Right hand\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    keypointVector[i] = tDatumsNoPtr[i]->handKeypoints[1];\n                spKeypointSaver->saveKeypoints(keypointVector, fileName, \"hand_right\");\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_HAND_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wHeatMapSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/heatMapSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHeatMapSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WHeatMapSaver(const std::shared_ptr<HeatMapSaver>& heatMapSaver);\n\n        virtual ~WHeatMapSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<HeatMapSaver> spHeatMapSaver;\n\n        DELETE_COPY(WHeatMapSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHeatMapSaver<TDatums>::WHeatMapSaver(const std::shared_ptr<HeatMapSaver>& heatMapSaver) :\n        spHeatMapSaver{heatMapSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WHeatMapSaver<TDatums>::~WHeatMapSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WHeatMapSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHeatMapSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record pose heatmap image(s) on disk\n                std::vector<Array<float>> poseHeatMaps(tDatumsNoPtr.size());\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    poseHeatMaps[i] = tDatumsNoPtr[i]->poseHeatMaps;\n                const auto fileName = (!tDatumsNoPtr[0]->name.empty()\n                    ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id)) + \"_pose_heatmaps\";\n                spHeatMapSaver->saveHeatMaps(poseHeatMaps, fileName);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey,\n                                                          __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHeatMapSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_HEAT_MAP_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wImageSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/imageSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WImageSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WImageSaver(const std::shared_ptr<ImageSaver>& imageSaver);\n\n        virtual ~WImageSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<ImageSaver> spImageSaver;\n\n        DELETE_COPY(WImageSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WImageSaver<TDatums>::WImageSaver(const std::shared_ptr<ImageSaver>& imageSaver) :\n        spImageSaver{imageSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WImageSaver<TDatums>::~WImageSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WImageSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WImageSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record image(s) on disk\n                std::vector<Matrix> opOutputDatas(tDatumsNoPtr.size());\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    opOutputDatas[i] = tDatumsNoPtr[i]->cvOutputData;\n                const auto fileName = (!tDatumsNoPtr[0]->name.empty()\n                    ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id));\n                spImageSaver->saveImages(opOutputDatas, fileName);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WImageSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_IMAGE_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wPeopleJsonSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/peopleJsonSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPeopleJsonSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WPeopleJsonSaver(const std::shared_ptr<PeopleJsonSaver>& peopleJsonSaver);\n\n        virtual ~WPeopleJsonSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<PeopleJsonSaver> spPeopleJsonSaver;\n\n        DELETE_COPY(WPeopleJsonSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPeopleJsonSaver<TDatums>::WPeopleJsonSaver(const std::shared_ptr<PeopleJsonSaver>& peopleJsonSaver) :\n        spPeopleJsonSaver{peopleJsonSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WPeopleJsonSaver<TDatums>::~WPeopleJsonSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WPeopleJsonSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WPeopleJsonSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Save body/face/hand keypoints to JSON file\n                const auto& tDatumFirstPtr = (*tDatums)[0];\n                const auto baseFileName = (!tDatumFirstPtr->name.empty() ? tDatumFirstPtr->name\n                                            : std::to_string(tDatumFirstPtr->id)) + \"_keypoints\";\n                const bool humanReadable = false;\n                for (auto i = 0u ; i < tDatums->size() ; i++)\n                {\n                    const auto& tDatumPtr = (*tDatums)[i];\n                    // const auto fileName = baseFileName;\n                    const auto fileName = baseFileName + (i != 0 ? \"_\" + std::to_string(i) : \"\");\n\n                    // Pose IDs from long long to float\n                    Array<float> poseIds{tDatumPtr->poseIds};\n\n                    const std::vector<std::pair<Array<float>, std::string>> keypointVector{\n                        // Pose IDs\n                        std::make_pair(poseIds, \"person_id\"),\n                        // 2D\n                        std::make_pair(tDatumPtr->poseKeypoints, \"pose_keypoints_2d\"),\n                        std::make_pair(tDatumPtr->faceKeypoints, \"face_keypoints_2d\"),\n                        std::make_pair(tDatumPtr->handKeypoints[0], \"hand_left_keypoints_2d\"),\n                        std::make_pair(tDatumPtr->handKeypoints[1], \"hand_right_keypoints_2d\"),\n                        // 3D\n                        std::make_pair(tDatumPtr->poseKeypoints3D, \"pose_keypoints_3d\"),\n                        std::make_pair(tDatumPtr->faceKeypoints3D, \"face_keypoints_3d\"),\n                        std::make_pair(tDatumPtr->handKeypoints3D[0], \"hand_left_keypoints_3d\"),\n                        std::make_pair(tDatumPtr->handKeypoints3D[1], \"hand_right_keypoints_3d\")\n                    };\n                    // Save keypoints\n                    spPeopleJsonSaver->save(\n                        keypointVector, tDatumPtr->poseCandidates, fileName, humanReadable);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPeopleJsonSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_PEOPLE_JSON_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wPoseSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/filestream/keypointSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPoseSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WPoseSaver(const std::shared_ptr<KeypointSaver>& keypointSaver);\n\n        virtual ~WPoseSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<KeypointSaver> spKeypointSaver;\n\n        DELETE_COPY(WPoseSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPoseSaver<TDatums>::WPoseSaver(const std::shared_ptr<KeypointSaver>& keypointSaver) :\n        spKeypointSaver{keypointSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WPoseSaver<TDatums>::~WPoseSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record people pose keypoint data\n                std::vector<Array<float>> keypointVector(tDatumsNoPtr.size());\n                for (auto i = 0u; i < tDatumsNoPtr.size(); i++)\n                    keypointVector[i] = tDatumsNoPtr[i]->poseKeypoints;\n                const auto fileName = (!tDatumsNoPtr[0]->name.empty()\n                    ? tDatumsNoPtr[0]->name : std::to_string(tDatumsNoPtr[0]->id));\n                spKeypointSaver->saveKeypoints(keypointVector, fileName, \"pose\");\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPoseSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_POSE_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wUdpSender.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP\n#define OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/udpSender.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WUdpSender : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WUdpSender(const std::shared_ptr<UdpSender>& udpSender);\n\n        virtual ~WUdpSender();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        const std::shared_ptr<UdpSender> spUdpSender;\n\n        DELETE_COPY(WUdpSender);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WUdpSender<TDatums>::WUdpSender(const std::shared_ptr<UdpSender>& udpSender) :\n        spUdpSender{udpSender}\n    {\n    }\n\n    template<typename TDatums>\n    WUdpSender<TDatums>::~WUdpSender()\n    {\n    }\n\n    template<typename TDatums>\n    void WUdpSender<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WUdpSender<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Send though UDP communication\n#ifdef USE_3D_ADAM_MODEL\n                const auto& tDatumPtr = (*tDatums)[0];\n                if (!tDatumPtr->poseKeypoints3D.empty())\n                {\n                    const auto& adamPose = tDatumPtr->adamPose; // Eigen::Matrix<double, 62, 3, Eigen::RowMajor>\n                    const auto& adamTranslation = tDatumPtr->adamTranslation; // Eigen::Vector3d(3, 1)\n                    const auto adamFaceCoeffsExp = tDatumPtr->adamFaceCoeffsExp; // Eigen::VectorXd resized to (200, 1)\n                    //const float mouth_open = tDatumPtr->mouthOpening; // tDatumPtr->mouth_open;\n                    //const float leye_open = tDatumPtr->rightEyeOpening; // tDatumPtr->leye_open;\n                    //const float reye_open = tDatumPtr->leftEyeOpening; // tDatumPtr->reye_open;\n                    //const float dist_root_foot = Datum.distanceRootFoot; // tDatumPtr->dist_root_foot;\n                    // m_adam_t:\n                    //     1. Total translation (centimeters) of the root in camera/global coordinate representation.\n                    // m_adam_pose:\n                    //     1. First row is global rotation, in AngleAxis representation. Radians (not degrees!)\n                    //     2. Rest are joint-angles in Euler-Angle representation. Degrees.\n                    spUdpSender->sendJointAngles(\n                        adamPose.data(), adamPose.rows(), adamTranslation.data(), adamFaceCoeffsExp.data(),\n                        adamFaceCoeffsExp.rows());\n                }\n#endif\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WUdpSender);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_UDP_SENDER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wVideoSaver.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP\n#define OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/videoSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WVideoSaver : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WVideoSaver(const std::shared_ptr<VideoSaver>& videoSaver);\n\n        virtual ~WVideoSaver();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<VideoSaver> spVideoSaver;\n\n        DELETE_COPY(WVideoSaver);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WVideoSaver<TDatums>::WVideoSaver(const std::shared_ptr<VideoSaver>& videoSaver) :\n        spVideoSaver{videoSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WVideoSaver<TDatums>::~WVideoSaver()\n    {\n    }\n\n    template<typename TDatums>\n    void WVideoSaver<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WVideoSaver<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record video(s)\n                std::vector<Matrix> opOutputDatas(tDatumsNoPtr.size());\n                for (auto i = 0u ; i < opOutputDatas.size() ; i++)\n                    opOutputDatas[i] = tDatumsNoPtr[i]->cvOutputData;\n                spVideoSaver->write(opOutputDatas);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WVideoSaver);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_VIDEO_SAVER_HPP\n"
  },
  {
    "path": "include/openpose/filestream/wVideoSaver3D.hpp",
    "content": "#ifndef OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP\n#define OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/videoSaver.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WVideoSaver3D : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WVideoSaver3D(const std::shared_ptr<VideoSaver>& videoSaver);\n\n        virtual ~WVideoSaver3D();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<VideoSaver> spVideoSaver;\n\n        DELETE_COPY(WVideoSaver3D);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WVideoSaver3D<TDatums>::WVideoSaver3D(const std::shared_ptr<VideoSaver>& videoSaver) :\n        spVideoSaver{videoSaver}\n    {\n    }\n\n    template<typename TDatums>\n    WVideoSaver3D<TDatums>::~WVideoSaver3D()\n    {\n    }\n\n    template<typename TDatums>\n    void WVideoSaver3D<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WVideoSaver3D<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // Record video(s)\n                if (!tDatumsNoPtr.empty())\n                    spVideoSaver->write(tDatumsNoPtr[0]->cvOutputData3D);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WVideoSaver3D);\n}\n\n#endif // OPENPOSE_FILESTREAM_W_VIDEO_SAVER_3D_HPP\n"
  },
  {
    "path": "include/openpose/flags.hpp",
    "content": "#ifndef OPENPOSE_FLAGS_HPP\n#define OPENPOSE_FLAGS_HPP\n\n// Note: This class is not included within the basic OpenPose `headers.hpp` and must be explicitly included. In\n// addition, Google Flags library must also be linked to the resulting binary or library. OpenPose library does\n// not force to use Google Flags, but the OpenPose examples do so.\n\n// GFlags: DEFINE_bool, _int32, _int64, _uint64, _double, _string\n#include <gflags/gflags.h>\n// Allow Google Flags in Ubuntu 14\n#ifndef GFLAGS_GFLAGS_H_\n    namespace gflags = google;\n#endif\n\n// See all the available parameter options with the `--help` flag. E.g., `build/examples/openpose/openpose.bin --help`\n// Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose\n// executable. E.g., for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`.\n// Debugging/Other\nDEFINE_int32(logging_level,             3,              \"The logging level. Integer in the range [0, 255]. 0 will output any opLog() message,\"\n                                                        \" while 255 will not output any. Current OpenPose library messages are in the range 0-4:\"\n                                                        \" 1 for low priority messages and 4 for important ones.\");\nDEFINE_bool(disable_multi_thread,       false,          \"It would slightly reduce the frame rate in order to highly reduce the lag. Mainly useful\"\n                                                        \" for 1) Cases where it is needed a low latency (e.g., webcam in real-time scenarios with\"\n                                                        \" low-range GPU devices); and 2) Debugging OpenPose when it is crashing to locate the\"\n                                                        \" error.\");\nDEFINE_int32(profile_speed,             1000,           \"If PROFILER_ENABLED was set in CMake or Makefile.config files, OpenPose will show some\"\n                                                        \" runtime statistics at this frame number.\");\n#ifndef OPENPOSE_FLAGS_DISABLE_POSE\n#ifndef OPENPOSE_FLAGS_DISABLE_PRODUCER\n// Producer\nDEFINE_int32(camera,                    -1,             \"The camera index for cv::VideoCapture. Integer in the range [0, 9]. Select a negative\"\n                                                        \" number (by default), to auto-detect and open the first available camera.\");\nDEFINE_string(camera_resolution,        \"-1x-1\",        \"Set the camera resolution (either `--camera` or `--flir_camera`). `-1x-1` will use the\"\n                                                        \" default 1280x720 for `--camera`, or the maximum flir camera resolution available for\"\n                                                        \" `--flir_camera`\");\nDEFINE_string(video,                    \"\",             \"Use a video file instead of the camera. Use `examples/media/video.avi` for our default\"\n                                                        \" example video.\");\nDEFINE_string(image_dir,                \"\",             \"Process a directory of images. Use `examples/media/` for our default example folder with 20\"\n                                                        \" images. Read all standard formats (jpg, png, bmp, etc.).\");\nDEFINE_bool(flir_camera,                false,          \"Whether to use FLIR (Point-Grey) stereo camera.\");\nDEFINE_int32(flir_camera_index,         -1,             \"Select -1 (default) to run on all detected flir cameras at once. Otherwise, select the flir\"\n                                                        \" camera index to run, where 0 corresponds to the detected flir camera with the lowest\"\n                                                        \" serial number, and `n` to the `n`-th lowest serial number camera.\");\nDEFINE_string(ip_camera,                \"\",             \"String with the IP camera URL. It supports protocols like RTSP and HTTP.\");\nDEFINE_uint64(frame_first,              0,              \"Start on desired frame number. Indexes are 0-based, i.e., the first frame has index 0.\");\nDEFINE_uint64(frame_step,               1,              \"Step or gap between processed frames. E.g., `--frame_step 5` would read and process frames\"\n                                                        \" 0, 5, 10, etc..\");\nDEFINE_uint64(frame_last,               -1,             \"Finish on desired frame number. Select -1 to disable. Indexes are 0-based, e.g., if set to\"\n                                                        \" 10, it will process 11 frames (0-10).\");\nDEFINE_bool(frame_flip,                 false,          \"Flip/mirror each frame (e.g., for real time webcam demonstrations).\");\nDEFINE_int32(frame_rotate,              0,              \"Rotate each frame, 4 possible values: 0, 90, 180, 270.\");\nDEFINE_bool(frames_repeat,              false,          \"Repeat frames when finished.\");\nDEFINE_bool(process_real_time,          false,          \"Enable to keep the original source frame rate (e.g., for video). If the processing time is\"\n                                                        \" too long, it will skip frames. If it is too fast, it will slow it down.\");\nDEFINE_string(camera_parameter_path,    \"models/cameraParameters/flir/\", \"String with the folder where the camera parameters are located. If there\"\n                                                        \" is only 1 XML file (for single video, webcam, or images from the same camera), you must\"\n                                                        \" specify the whole XML file path (ending in .xml).\");\nDEFINE_bool(frame_undistort,            false,          \"If false (default), it will not undistort the image, if true, it will undistortionate them\"\n                                                        \" based on the camera parameters found in `camera_parameter_path`\");\n#endif // OPENPOSE_FLAGS_DISABLE_PRODUCER\n// OpenPose\nDEFINE_string(model_folder,             \"models/\",      \"Folder path (absolute or relative) where the models (pose, face, ...) are located.\");\nDEFINE_string(prototxt_path,            \"\",             \"The combination `--model_folder` + `--prototxt_path` represents the whole path to the\"\n                                                        \" prototxt file. If empty, it will use the default OpenPose ProtoTxt file.\");\nDEFINE_string(caffemodel_path,          \"\",             \"The combination `--model_folder` + `--caffemodel_path` represents the whole path to the\"\n                                                        \" caffemodel file. If empty, it will use the default OpenPose CaffeModel file.\");\nDEFINE_string(output_resolution,        \"-1x-1\",        \"The image resolution (display and output). Use \\\"-1x-1\\\" to force the program to use the\"\n                                                        \" input image resolution.\");\nDEFINE_int32(num_gpu,                   -1,             \"The number of GPU devices to use. If negative, it will use all the available GPUs in your\"\n                                                        \" machine.\");\nDEFINE_int32(num_gpu_start,             0,              \"GPU device start number.\");\nDEFINE_int32(keypoint_scale,            0,              \"Scaling of the (x,y) coordinates of the final pose data array, i.e., the scale of the (x,y)\"\n                                                        \" coordinates that will be saved with the `write_json` & `write_keypoint` flags.\"\n                                                        \" Select `0` to scale it to the original source resolution; `1`to scale it to the net output\"\n                                                        \" size (set with `net_resolution`); `2` to scale it to the final output size (set with\"\n                                                        \" `resolution`); `3` to scale it in the range [0,1], where (0,0) would be the top-left\"\n                                                        \" corner of the image, and (1,1) the bottom-right one; and 4 for range [-1,1], where\"\n                                                        \" (-1,-1) would be the top-left corner of the image, and (1,1) the bottom-right one. Non\"\n                                                        \" related with `scale_number` and `scale_gap`.\");\nDEFINE_int32(number_people_max,         -1,             \"This parameter will limit the maximum number of people detected, by keeping the people with\"\n                                                        \" top scores. The score is based in person area over the image, body part score, as well as\"\n                                                        \" joint score (between each pair of connected body parts). Useful if you know the exact\"\n                                                        \" number of people in the scene, so it can remove false positives (if all the people have\"\n                                                        \" been detected. However, it might also include false negatives by removing very small or\"\n                                                        \" highly occluded people. -1 will keep them all.\");\nDEFINE_bool(maximize_positives,         false,          \"It reduces the thresholds to accept a person candidate. It highly increases both false and\"\n                                                        \" true positives. I.e., it maximizes average recall but could harm average precision.\");\nDEFINE_double(fps_max,                  -1.,            \"Maximum processing frame rate. By default (-1), OpenPose will process frames as fast as\"\n                                                        \" possible. Example usage: If OpenPose is displaying images too quickly, this can reduce\"\n                                                        \" the speed so the user can analyze better each frame from the GUI.\");\n// OpenPose Body Pose\nDEFINE_int32(body,                      1,              \"Select 0 to disable body keypoint detection (e.g., for faster but less accurate face\"\n                                                        \" keypoint detection, custom hand detector, etc.), 1 (default) for body keypoint\"\n                                                        \" estimation, and 2 to disable its internal body pose estimation network but still\"\n                                                        \" still run the greedy association parsing algorithm\");\nDEFINE_string(model_pose,               \"BODY_25\",      \"Model to be used. E.g., `BODY_25` (fastest for CUDA version, most accurate, and includes\"\n                                                        \" foot keypoints), `COCO` (18 keypoints), `MPI` (15 keypoints, least accurate model but\"\n                                                        \" fastest on CPU), `MPI_4_layers` (15 keypoints, even faster but less accurate).\");\nDEFINE_string(net_resolution,           \"-1x368\",       \"Multiples of 16. If it is increased, the accuracy potentially increases. If it is\"\n                                                        \" decreased, the speed increases. For maximum speed-accuracy balance, it should keep the\"\n                                                        \" closest aspect ratio possible to the images or videos to be processed. Using `-1` in\"\n                                                        \" any of the dimensions, OP will choose the optimal aspect ratio depending on the user's\"\n                                                        \" input value. E.g., the default `-1x368` is equivalent to `656x368` in 16:9 resolutions,\"\n                                                        \" e.g., full HD (1980x1080) and HD (1280x720) resolutions.\");\nDEFINE_double(net_resolution_dynamic,   1.,             \"This flag only applies to images or custom inputs (not to video or webcam). If it is zero\"\n                                                        \" or a negative value, it means that using `-1` in `net_resolution` will behave as explained\"\n                                                        \" in its description. Otherwise, and to avoid out of memory errors, the `-1` in\"\n                                                        \" `net_resolution` will clip to this value times the default 16/9 aspect ratio value (which\"\n                                                        \" is 656 width for a 368 height). E.g., `net_resolution_dynamic 10 net_resolution -1x368`\"\n                                                        \" will clip to 6560x368 (10 x 656). Recommended 1 for small GPUs (to avoid out of memory\"\n                                                        \" errors but maximize speed) and 0 for big GPUs (for maximum accuracy and speed).\");\nDEFINE_int32(scale_number,              1,              \"Number of scales to average.\");\nDEFINE_double(scale_gap,                0.25,           \"Scale gap between scales. No effect unless scale_number > 1. Initial scale is always 1.\"\n                                                        \" If you want to change the initial scale, you actually want to multiply the\"\n                                                        \" `net_resolution` by your desired initial scale.\");\n// OpenPose Body Pose Heatmaps and Part Candidates\nDEFINE_bool(heatmaps_add_parts,         false,          \"If true, it will fill op::Datum::poseHeatMaps array with the body part heatmaps, and\"\n                                                        \" analogously face & hand heatmaps to op::Datum::faceHeatMaps & op::Datum::handHeatMaps.\"\n                                                        \" If more than one `add_heatmaps_X` flag is enabled, it will place then in sequential\"\n                                                        \" memory order: body parts + bkg + PAFs. It will follow the order on\"\n                                                        \" POSE_BODY_PART_MAPPING in `src/openpose/pose/poseParameters.cpp`. Program speed will\"\n                                                        \" considerably decrease. Not required for OpenPose, enable it only if you intend to\"\n                                                        \" explicitly use this information later.\");\nDEFINE_bool(heatmaps_add_bkg,           false,          \"Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to\"\n                                                        \" background.\");\nDEFINE_bool(heatmaps_add_PAFs,          false,          \"Same functionality as `add_heatmaps_parts`, but adding the PAFs.\");\nDEFINE_int32(heatmaps_scale,            2,              \"Set 0 to scale op::Datum::poseHeatMaps in the range [-1,1], 1 for [0,1]; 2 for integer\"\n                                                        \" rounded [0,255]; and 3 for no scaling.\");\nDEFINE_bool(part_candidates,            false,          \"Also enable `write_json` in order to save this information. If true, it will fill the\"\n                                                        \" op::Datum::poseCandidates array with the body part candidates. Candidates refer to all\"\n                                                        \" the detected body parts, before being assembled into people. Note that the number of\"\n                                                        \" candidates is equal or higher than the number of final body parts (i.e., after being\"\n                                                        \" assembled into people). The empty body parts are filled with 0s. Program speed will\"\n                                                        \" slightly decrease. Not required for OpenPose, enable it only if you intend to explicitly\"\n                                                        \" use this information.\");\nDEFINE_double(upsampling_ratio,         0.,             \"Upsampling ratio between the `net_resolution` and the output net results. A value less\"\n                                                        \" or equal than 0 (default) will use the network default value (recommended).\");\n// OpenPose Face\nDEFINE_bool(face,                       false,          \"Enables face keypoint detection. It will share some parameters from the body pose, e.g.\"\n                                                        \" `model_folder`. Note that this will considerable slow down the performance and increase\"\n                                                        \" the required GPU memory. In addition, the greater number of people on the image, the\"\n                                                        \" slower OpenPose will be.\");\nDEFINE_int32(face_detector,             0,              \"Kind of face rectangle detector. Select 0 (default) to select OpenPose body detector (most\"\n                                                        \" accurate one and fastest one if body is enabled), 1 to select OpenCV face detector (not\"\n                                                        \" implemented for hands), 2 to indicate that it will be provided by the user, or 3 to\"\n                                                        \" also apply hand tracking (only for hand). Hand tracking might improve hand keypoint\"\n                                                        \" detection for webcam (if the frame rate is high enough, i.e., >7 FPS per GPU) and video.\"\n                                                        \" This is not person ID tracking, it simply looks for hands in positions at which hands were\"\n                                                        \" located in previous frames, but it does not guarantee the same person ID among frames.\");\nDEFINE_string(face_net_resolution,      \"368x368\",      \"Multiples of 16 and squared. Analogous to `net_resolution` but applied to the face keypoint\"\n                                                        \" detector. 320x320 usually works fine while giving a substantial speed up when multiple\"\n                                                        \" faces on the image.\");\n// OpenPose Hand\nDEFINE_bool(hand,                       false,          \"Enables hand keypoint detection. It will share some parameters from the body pose, e.g.\"\n                                                        \" `model_folder`. Analogously to `--face`, it will also slow down the performance, increase\"\n                                                        \" the required GPU memory and its speed depends on the number of people.\");\nDEFINE_int32(hand_detector,             0,              \"Kind of hand rectangle detector. Analogous to `--face_detector`.\");\nDEFINE_string(hand_net_resolution,      \"368x368\",      \"Multiples of 16 and squared. Analogous to `net_resolution` but applied to the hand keypoint\"\n                                                        \" detector.\");\nDEFINE_int32(hand_scale_number,         1,              \"Analogous to `scale_number` but applied to the hand keypoint detector. Our best results\"\n                                                        \" were found with `hand_scale_number` = 6 and `hand_scale_range` = 0.4.\");\nDEFINE_double(hand_scale_range,         0.4,            \"Analogous purpose than `scale_gap` but applied to the hand keypoint detector. Total range\"\n                                                        \" between smallest and biggest scale. The scales will be centered in ratio 1. E.g., if\"\n                                                        \" scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2.\");\n// OpenPose 3-D Reconstruction\nDEFINE_bool(3d,                         false,          \"Running OpenPose 3-D reconstruction demo: 1) Reading from a stereo camera system.\"\n                                                        \" 2) Performing 3-D reconstruction from the multiple views. 3) Displaying 3-D reconstruction\"\n                                                        \" results. Note that it will only display 1 person. If multiple people is present, it will\"\n                                                        \" fail.\");\nDEFINE_int32(3d_min_views,              -1,             \"Minimum number of views required to reconstruct each keypoint. By default (-1), it will\"\n                                                        \" require max(2, min(4, #cameras-1)) cameras to see the keypoint in order to reconstruct\"\n                                                        \" it.\");\nDEFINE_int32(3d_views,                  -1,             \"Complementary option for `--image_dir` or `--video`. OpenPose will read as many images per\"\n                                                        \" iteration, allowing tasks such as stereo camera processing (`--3d`). Note that\"\n                                                        \" `--camera_parameter_path` must be set. OpenPose must find as many `xml` files in the\"\n                                                        \" parameter folder as this number indicates.\");\n// Extra algorithms\nDEFINE_bool(identification,             false,          \"Experimental, not available yet. Whether to enable people identification across frames.\");\nDEFINE_int32(tracking,                  -1,             \"Experimental, not available yet. Whether to enable people tracking across frames. The\"\n                                                        \" value indicates the number of frames where tracking is run between each OpenPose keypoint\"\n                                                        \" detection. Select -1 (default) to disable it or 0 to run simultaneously OpenPose keypoint\"\n                                                        \" detector and tracking for potentially higher accuracy than only OpenPose.\");\nDEFINE_int32(ik_threads,                0,              \"Experimental, not available yet. Whether to enable inverse kinematics (IK) from 3-D\"\n                                                        \" keypoints to obtain 3-D joint angles. By default (0 threads), it is disabled. Increasing\"\n                                                        \" the number of threads will increase the speed but also the global system latency.\");\n// OpenPose Rendering\nDEFINE_int32(part_to_show,              0,              \"Prediction channel to visualize: 0 (default) for all the body parts, 1 for the background\"\n                                                        \" heat map, 2 for the superposition of heatmaps, 3 for the superposition of PAFs,\"\n                                                        \" 4-(4+#keypoints) for each body part heat map, the following ones for each body part pair\"\n                                                        \" PAF.\");\nDEFINE_bool(disable_blending,           false,          \"If enabled, it will render the results (keypoint skeletons or heatmaps) on a black\"\n                                                        \" background, instead of being rendered into the original image. Related: `part_to_show`,\"\n                                                        \" `alpha_pose`, and `alpha_pose`.\");\n// OpenPose Rendering Pose\nDEFINE_double(render_threshold,         0.05,           \"Only estimated keypoints whose score confidences are higher than this threshold will be\"\n                                                        \" rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in\"\n                                                        \" the saved results. Generally, a high threshold (> 0.5) will only render very clear body\"\n                                                        \" parts; while small thresholds (~0.1) will also output guessed and occluded keypoints,\"\n                                                        \" but also more false positives (i.e., wrong detections).\");\nDEFINE_int32(render_pose,               -1,             \"Set to 0 for no rendering, 1 for CPU rendering (slightly faster), and 2 for GPU rendering\"\n                                                        \" (slower but greater functionality, e.g., `alpha_X` flags). If -1, it will pick CPU if\"\n                                                        \" CPU_ONLY is enabled, or GPU if CUDA is enabled. If rendering is enabled, it will render\"\n                                                        \" both `outputData` and `cvOutputData` with the original image and desired body part to be\"\n                                                        \" shown (i.e., keypoints, heat maps or PAFs).\");\nDEFINE_double(alpha_pose,               0.6,            \"Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will\"\n                                                        \" hide it. Only valid for GPU rendering.\");\nDEFINE_double(alpha_heatmap,            0.7,            \"Blending factor (range 0-1) between heatmap and original frame. 1 will only show the\"\n                                                        \" heatmap, 0 will only show the frame. Only valid for GPU rendering.\");\n// OpenPose Rendering Face\nDEFINE_double(face_render_threshold,    0.4,            \"Analogous to `render_threshold`, but applied to the face keypoints.\");\nDEFINE_int32(face_render,               -1,             \"Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same\"\n                                                        \" configuration that `render_pose` is using.\");\nDEFINE_double(face_alpha_pose,          0.6,            \"Analogous to `alpha_pose` but applied to face.\");\nDEFINE_double(face_alpha_heatmap,       0.7,            \"Analogous to `alpha_heatmap` but applied to face.\");\n// OpenPose Rendering Hand\nDEFINE_double(hand_render_threshold,    0.2,            \"Analogous to `render_threshold`, but applied to the hand keypoints.\");\nDEFINE_int32(hand_render,               -1,             \"Analogous to `render_pose` but applied to the hand. Extra option: -1 to use the same\"\n                                                        \" configuration that `render_pose` is using.\");\nDEFINE_double(hand_alpha_pose,          0.6,            \"Analogous to `alpha_pose` but applied to hand.\");\nDEFINE_double(hand_alpha_heatmap,       0.7,            \"Analogous to `alpha_heatmap` but applied to hand.\");\n#ifndef OPENPOSE_FLAGS_DISABLE_DISPLAY\n// Display\nDEFINE_bool(fullscreen,                 false,          \"Run in full-screen mode (press f during runtime to toggle).\");\nDEFINE_bool(no_gui_verbose,             false,          \"Do not write text on output images on GUI (e.g., number of current frame and people). It\"\n                                                        \" does not affect the pose rendering.\");\nDEFINE_int32(display,                   -1,             \"Display mode: -1 for automatic selection; 0 for no display (useful if there is no X server\"\n                                                        \" and/or to slightly speed up the processing if visual output is not required); 2 for 2-D\"\n                                                        \" display; 3 for 3-D display (if `--3d` enabled); and 1 for both 2-D and 3-D display.\");\n#endif // OPENPOSE_FLAGS_DISABLE_DISPLAY\n// Command Line Interface Verbose\nDEFINE_double(cli_verbose,              -1.f,           \"If -1, it will be disabled (default). If it is a positive integer number, it will print on\"\n                                                        \" the command line every `verbose` frames. If number in the range (0,1), it will print the\"\n                                                        \" progress every `verbose` times the total of frames.\");\n// Result Saving\nDEFINE_string(write_images,             \"\",             \"Directory to write rendered frames in `write_images_format` image format.\");\nDEFINE_string(write_images_format,      \"png\",          \"File extension and format for `write_images`, e.g., png, jpg or bmp. Check the OpenCV\"\n                                                        \" function cv::imwrite for all compatible extensions.\");\nDEFINE_string(write_video,              \"\",             \"Full file path to write rendered frames in motion JPEG video format. It might fail if the\"\n                                                        \" final path does not finish in `.avi`. It internally uses cv::VideoWriter. Flag\"\n                                                        \" `write_video_fps` controls FPS. Alternatively, the video extension can be `.mp4`,\"\n                                                        \" resulting in a file with a much smaller size and allowing `--write_video_with_audio`.\"\n                                                        \" However, that would require: 1) Ubuntu or Mac system, 2) FFmpeg library installed\"\n                                                        \" (`sudo apt-get install ffmpeg`), 3) the creation temporarily of a folder with the same\"\n                                                        \" file path than the final video (without the extension) to storage the intermediate frames\"\n                                                        \" that will later be used to generate the final MP4 video.\");\nDEFINE_double(write_video_fps,          -1.,            \"Frame rate for the recorded video. By default, it will try to get the input frames producer\"\n                                                        \" frame rate (e.g., input video or webcam frame rate). If the input frames producer does not\"\n                                                        \" have a set FPS (e.g., image_dir or webcam if OpenCV not compiled with its support), set\"\n                                                        \" this value accordingly (e.g., to the frame rate displayed by the OpenPose GUI).\");\nDEFINE_bool(write_video_with_audio,     false,          \"If the input is video and the output is so too, it will save the video with audio. It\"\n                                                        \" requires the output video file path finishing in `.mp4` format (see `write_video` for\"\n                                                        \" details).\");\nDEFINE_string(write_video_3d,           \"\",             \"Analogous to `--write_video`, but applied to the 3D output.\");\nDEFINE_string(write_video_adam,         \"\",             \"Experimental, not available yet. Analogous to `--write_video`, but applied to Adam model.\");\nDEFINE_string(write_json,               \"\",             \"Directory to write OpenPose output in JSON format. It includes body, hand, and face pose\"\n                                                        \" keypoints (2-D and 3-D), as well as pose candidates (if `--part_candidates` enabled).\");\nDEFINE_string(write_coco_json,          \"\",             \"Full file path to write people pose data with JSON COCO validation format. If foot, face,\"\n                                                        \" hands, etc. JSON is also desired (`--write_coco_json_variants`), they are saved with\"\n                                                        \" different file name suffix.\");\nDEFINE_int32(write_coco_json_variants,  1,              \"Add 1 for body, add 2 for foot, 4 for face, and/or 8 for hands. Use 0 to use all the\"\n                                                        \" possible candidates. E.g., 7 would mean body+foot+face COCO JSON.\");\nDEFINE_int32(write_coco_json_variant,   0,              \"Currently, this option is experimental and only makes effect on car JSON generation. It\"\n                                                        \" selects the COCO variant for cocoJsonSaver.\");\nDEFINE_string(write_heatmaps,           \"\",             \"Directory to write body pose heatmaps in PNG format. At least 1 `add_heatmaps_X` flag\"\n                                                        \" must be enabled.\");\nDEFINE_string(write_heatmaps_format,    \"png\",          \"File extension and format for `write_heatmaps`, analogous to `write_images_format`.\"\n                                                        \" For lossless compression, recommended `png` for integer `heatmaps_scale` and `float` for\"\n                                                        \" floating values. See `doc/02_output.md` for more details.\");\nDEFINE_string(write_keypoint,           \"\",             \"(Deprecated, use `write_json`) Directory to write the people pose keypoint data. Set format\"\n                                                        \" with `write_keypoint_format`.\");\nDEFINE_string(write_keypoint_format,    \"yml\",          \"(Deprecated, use `write_json`) File extension and format for `write_keypoint`: json, xml,\"\n                                                        \" yaml & yml. Json not available for OpenCV < 3.0, use `write_json` instead.\");\n// Result Saving - Extra Algorithms\nDEFINE_string(write_bvh,                \"\",             \"Experimental, not available yet. E.g., `~/Desktop/mocapResult.bvh`.\");\n// UDP Communication\nDEFINE_string(udp_host,                 \"\",             \"Experimental, not available yet. IP for UDP communication. E.g., `192.168.0.1`.\");\nDEFINE_string(udp_port,                 \"8051\",         \"Experimental, not available yet. Port number for UDP communication.\");\n#endif // OPENPOSE_FLAGS_DISABLE_POSE\n\n#endif // OPENPOSE_FLAGS_HPP\n"
  },
  {
    "path": "include/openpose/gpu/cuda.hpp",
    "content": "#ifndef OPENPOSE_GPU_CUDA_HPP\n#define OPENPOSE_GPU_CUDA_HPP\n\n#include <utility> // std::pair\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    const auto CUDA_NUM_THREADS = 512u;\n\n    OP_API void cudaCheck(const int line = -1, const std::string& function = \"\", const std::string& file = \"\");\n\n    OP_API int getCudaGpuNumber();\n\n    inline unsigned int getNumberCudaBlocks(\n        const unsigned int totalRequired, const unsigned int numberCudaThreads = CUDA_NUM_THREADS)\n    {\n        return (totalRequired + numberCudaThreads - 1) / numberCudaThreads;\n    }\n\n    OP_API void getNumberCudaThreadsAndBlocks(\n        dim3& numberCudaThreads, dim3& numberCudaBlocks, const Point<unsigned int>& frameSize);\n\n    template <typename T>\n    void reorderAndNormalize(\n        T* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels);\n\n    template <typename T>\n    void uCharImageCast(unsigned char* targetPtr, const T* const srcPtr, const int volume);\n}\n\n#endif // OPENPOSE_GPU_CUDA_HPP\n"
  },
  {
    "path": "include/openpose/gpu/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_GPU_ENUM_CLASSES_HPP\n#define OPENPOSE_GPU_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class GpuMode : unsigned char\n    {\n        Cuda = 0,\n        OpenCL = 1,\n        NoGpu = 2,\n        Size,\n    };\n}\n\n#endif // OPENPOSE_GPU_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/gpu/gpu.hpp",
    "content": "#ifndef OPENPOSE_GPU_GPU_HPP\n#define OPENPOSE_GPU_GPU_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gpu/enumClasses.hpp>\n\nnamespace op\n{\n    OP_API int getGpuNumber();\n\n    OP_API GpuMode getGpuMode();\n}\n\n#endif // OPENPOSE_GPU_GPU_HPP\n"
  },
  {
    "path": "include/openpose/gpu/headers.hpp",
    "content": "#ifndef OPENPOSE_GPU_HEADERS_HPP\n#define OPENPOSE_GPU_HEADERS_HPP\n\n// gpu module\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/gpu/enumClasses.hpp>\n#include <openpose/gpu/gpu.hpp>\n\n#endif // OPENPOSE_GPU_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/gui/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_GUI_ENUM_CLASSES_HPP\n#define OPENPOSE_GUI_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    /**\n    * GUI display modes.\n     * An enum class with the different output screen options. E.g., 2-D, 3-D, all, none.\n     */\n    enum class DisplayMode : unsigned short\n    {\n        NoDisplay,  /**< No display. */\n        DisplayAll, /**< All (2-D and 3-D/Adam) displays */\n        Display2D,  /**< Only 2-D display. */\n        Display3D,  /**< Only 3-D display. */\n        DisplayAdam /**< Only Adam display. */\n    };\n\n    /**\n     * Full screen modes.\n     * An enum class with the different full screen mode options, i.e., full screen or windored.\n     */\n    enum class FullScreenMode : bool\n    {\n        FullScreen, /**< Full screen mode. */\n        Windowed,   /**< Windowed mode, depending on the frame output size. */\n    };\n}\n\n#endif // OPENPOSE_GUI_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/gui/frameDisplayer.hpp",
    "content": "#ifndef OPENPOSE_GUI_FRAMES_DISPLAY_HPP\n#define OPENPOSE_GUI_FRAMES_DISPLAY_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     *  The FrameDisplayer class is the one presenting visually the processed frame to the user.\n     */\n    class OP_API FrameDisplayer\n    {\n    public:\n        /**\n         * Constructor of the FrameDisplayer class.\n         * @param windowedName const std::string value with the opencv resulting display name. Showed at the top-left\n         * part of the window.\n         * @param initialWindowedSize const Point<int> with the initial window output resolution (width and height).\n         * @param fullScreen bool from which the FrameDisplayer::FullScreenMode property mFullScreenMode will be set,\n         * i.e., specifying the type of initial display (it can be changed later).\n         */\n        FrameDisplayer(const std::string& windowedName = OPEN_POSE_NAME_AND_VERSION,\n                       const Point<int>& initialWindowedSize = Point<int>{}, const bool fullScreen = false);\n\n        virtual ~FrameDisplayer();\n\n        // Due to OpenCV visualization issues (all visualization functions must be in the same thread)\n        void initializationOnThread();\n\n        /**\n         * This function set the new FrameDisplayer::FullScreenMode (e.g., full screen).\n         * @param fullScreenMode New FrameDisplayer::FullScreenMode state.\n         */\n        void setFullScreenMode(const FullScreenMode fullScreenMode);\n\n        /**\n         * This function switch between full screen and windowed modes (e.g., when double-click on video players or\n         * Ctrt+Enter are presed).\n         */\n        void switchFullScreenMode();\n\n        /**\n         * This function displays an image on the display.\n         * @param frame Mat image to display.\n         * @param waitKeyValue int value that specifies the argument parameter for cv::waitKey (see OpenCV\n         * documentation for more information). Special cases: select -1\n         * not to use cv::waitKey or 0 for cv::waitKey(0). OpenCV doc:\n         * http://docs.opencv.org/2.4/modules/highgui/doc/user_interface.html?highlight=waitkey\n         */\n        void displayFrame(const Matrix& frame, const int waitKeyValue = -1);\n\n        /**\n         * Analogous to the previous displayFrame, but first it horizontally concatenates all the frames\n         */\n        void displayFrame(const std::vector<Matrix>& frames, const int waitKeyValue = -1);\n\n    private:\n        const std::string mWindowName;\n        Point<int> mWindowedSize;\n        FullScreenMode mFullScreenMode;\n    };\n}\n\n#endif // OPENPOSE_GUI_FRAMES_DISPLAY_HPP\n"
  },
  {
    "path": "include/openpose/gui/gui.hpp",
    "content": "#ifndef OPENPOSE_GUI_GUI_HPP\n#define OPENPOSE_GUI_GUI_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/core/renderer.hpp>\n#include <openpose/gui/frameDisplayer.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n#include <openpose/face/faceExtractorNet.hpp>\n#include <openpose/hand/handExtractorNet.hpp>\n\nnamespace op\n{\n    class OP_API Gui\n    {\n    public:\n        Gui(const Point<int>& outputSize, const bool fullScreen,\n            const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n            const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr = nullptr,\n            const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets = {},\n            const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets = {},\n            const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets = {},\n            const std::vector<std::shared_ptr<Renderer>>& renderers = {},\n            const DisplayMode displayMode = DisplayMode::Display2D);\n\n        virtual ~Gui();\n\n        virtual void initializationOnThread();\n\n        void setImage(const Matrix& cvMatOutput);\n\n        void setImage(const std::vector<Matrix>& cvMatOutputs);\n\n        virtual void update();\n\n    protected:\n        std::shared_ptr<std::atomic<bool>> spIsRunning;\n        DisplayMode mDisplayMode;\n        DisplayMode mDisplayModeOriginal;\n\n    private:\n        // Frames display\n        FrameDisplayer mFrameDisplayer;\n        // Other variables\n        std::vector<std::shared_ptr<PoseExtractorNet>> mPoseExtractorNets;\n        std::vector<std::shared_ptr<FaceExtractorNet>> mFaceExtractorNets;\n        std::vector<std::shared_ptr<HandExtractorNet>> mHandExtractorNets;\n        std::vector<std::shared_ptr<Renderer>> mRenderers;\n        std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>> spVideoSeek;\n    };\n}\n\n#endif // OPENPOSE_GUI_GUI_HPP\n"
  },
  {
    "path": "include/openpose/gui/gui3D.hpp",
    "content": "﻿#ifndef OPENPOSE_GUI_GUI_3D_HPP\n#define OPENPOSE_GUI_GUI_3D_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/enumClasses.hpp>\n#include <openpose/gui/gui.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    class OP_API Gui3D : public Gui\n    {\n    public:\n        Gui3D(const Point<int>& outputSize, const bool fullScreen,\n              const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n              const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr = nullptr,\n              const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets = {},\n              const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets = {},\n              const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets = {},\n              const std::vector<std::shared_ptr<Renderer>>& renderers = {},\n              const PoseModel poseModel = PoseModel::BODY_25,\n              const DisplayMode displayMode = DisplayMode::DisplayAll,\n              const bool copyGlToCvMat = false);\n\n        virtual ~Gui3D();\n\n        virtual void initializationOnThread();\n\n        void setKeypoints(const Array<float>& poseKeypoints3D, const Array<float>& faceKeypoints3D,\n                          const Array<float>& leftHandKeypoints3D, const Array<float>& rightHandKeypoints3D);\n\n        virtual void update();\n\n        virtual Matrix readCvMat();\n\n    private:\n        const bool mCopyGlToCvMat;\n    };\n}\n\n#endif // OPENPOSE_GUI_GUI_3D_HPP\n"
  },
  {
    "path": "include/openpose/gui/guiAdam.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_GUI_GUI_ADAM_HPP\n#define OPENPOSE_GUI_GUI_ADAM_HPP\n\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/totalmodel.h>\n#endif\n#include <openpose/core/common.hpp>\n#include <openpose/gui/enumClasses.hpp>\n#include <openpose/gui/gui.hpp>\n\nnamespace op\n{\n    // This worker will do 3-D rendering\n    class OP_API GuiAdam : public Gui\n    {\n    public:\n        GuiAdam(const Point<int>& outputSize, const bool fullScreen,\n                const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n                const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr = nullptr,\n                const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets = {},\n                const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets = {},\n                const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets = {},\n                const std::vector<std::shared_ptr<Renderer>>& renderers = {},\n                const DisplayMode displayMode = DisplayMode::DisplayAll,\n                const std::shared_ptr<const TotalModel>& totalModel = nullptr,\n                const std::string& adamRenderedVideoPath = \"\");\n\n        virtual ~GuiAdam();\n\n        virtual void initializationOnThread();\n\n        void generateMesh(const Array<float>& poseKeypoints3D, const Array<float>& faceKeypoints3D,\n                          const std::array<Array<float>, 2>& handKeypoints3D,\n                          const double* const adamPosePtr,\n                          const double* const adamTranslationPtr,\n                          const double* const vtVecPtr, const int vtVecRows,\n                          const double* const j0VecPtr, const int j0VecRows,\n                          const double* const adamFaceCoeffsExpPtr);\n\n        virtual void update();\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplGuiAdam;\n        std::shared_ptr<ImplGuiAdam> spImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(GuiAdam);\n    };\n}\n\n#endif // OPENPOSE_GUI_GUI_ADAM_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/gui/guiInfoAdder.hpp",
    "content": "#ifndef OPENPOSE_GUI_ADD_GUI_INFO_HPP\n#define OPENPOSE_GUI_ADD_GUI_INFO_HPP\n\n#include <queue>\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API GuiInfoAdder\n    {\n    public:\n        GuiInfoAdder(const int numberGpus, const bool guiEnabled = false);\n\n        virtual ~GuiInfoAdder();\n\n        void addInfo(Matrix& outputData, const int numberPeople, const unsigned long long id,\n                     const std::string& elementRenderedName, const unsigned long long frameNumber,\n                     const Array<long long>& poseIds = Array<long long>{},\n                     const Array<float>& poseKeypoints = Array<float>{});\n\n    private:\n        // Const variables\n        const int mNumberGpus;\n        const bool mGuiEnabled;\n        // Other variables\n        std::queue<std::chrono::high_resolution_clock::time_point> mFpsQueue;\n        double mFps;\n        unsigned int mFpsCounter;\n        std::string mLastElementRenderedName;\n        int mLastElementRenderedCounter;\n        unsigned long long mLastId;\n    };\n}\n\n#endif // OPENPOSE_GUI_ADD_GUI_INFO_HPP\n"
  },
  {
    "path": "include/openpose/gui/headers.hpp",
    "content": "#ifndef OPENPOSE_GUI_HEADERS_HPP\n#define OPENPOSE_GUI_HEADERS_HPP\n\n// gui module\n#include <openpose/gui/enumClasses.hpp>\n#include <openpose/gui/frameDisplayer.hpp>\n#include <openpose/gui/gui.hpp>\n#include <openpose/gui/guiAdam.hpp>\n#include <openpose/gui/gui3D.hpp>\n#include <openpose/gui/guiInfoAdder.hpp>\n#include <openpose/gui/wGui.hpp>\n#include <openpose/gui/wGuiAdam.hpp>\n#include <openpose/gui/wGui3D.hpp>\n#include <openpose/gui/wGuiInfoAdder.hpp>\n\n#endif // OPENPOSE_GUI_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/gui/wGui.hpp",
    "content": "#ifndef OPENPOSE_GUI_W_GUI_HPP\n#define OPENPOSE_GUI_W_GUI_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/gui.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WGui : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WGui(const std::shared_ptr<Gui>& gui);\n\n        virtual ~WGui();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<Gui> spGui;\n\n        DELETE_COPY(WGui);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WGui<TDatums>::WGui(const std::shared_ptr<Gui>& gui) :\n        spGui{gui}\n    {\n    }\n\n    template<typename TDatums>\n    WGui<TDatums>::~WGui()\n    {\n    }\n\n    template<typename TDatums>\n    void WGui<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spGui->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WGui<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            // tDatums might be empty but we still wanna update the GUI\n            if (tDatums != nullptr)\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Update cvMat\n                if (!tDatums->empty())\n                {\n                    std::vector<Matrix> cvOutputDatas;\n                    for (auto& tDatumPtr : *tDatums)\n                        cvOutputDatas.emplace_back(tDatumPtr->cvOutputData);\n                    spGui->setImage(cvOutputDatas);\n                }\n                // Refresh/update GUI\n                spGui->update();\n                // Profiling speed\n                if (!tDatums->empty())\n                {\n                    Profiler::timerEnd(profilerKey);\n                    Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WGui);\n}\n\n#endif // OPENPOSE_GUI_W_GUI_HPP\n"
  },
  {
    "path": "include/openpose/gui/wGui3D.hpp",
    "content": "#ifndef OPENPOSE_GUI_W_GUI_3D_HPP\n#define OPENPOSE_GUI_W_GUI_3D_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/gui3D.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    // This worker will do 3-D rendering\n    template<typename TDatums>\n    class WGui3D : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WGui3D(const std::shared_ptr<Gui3D>& gui3D);\n\n        virtual ~WGui3D();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<Gui3D> spGui3D;\n\n        DELETE_COPY(WGui3D);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WGui3D<TDatums>::WGui3D(const std::shared_ptr<Gui3D>& gui3D) :\n        spGui3D{gui3D}\n    {\n    }\n\n    template<typename TDatums>\n    WGui3D<TDatums>::~WGui3D()\n    {\n    }\n\n    template<typename TDatums>\n    void WGui3D<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spGui3D->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WGui3D<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            // tDatums might be empty but we still wanna update the GUI\n            if (tDatums != nullptr)\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Update cvMat & keypoints\n                if (!tDatums->empty())\n                {\n                    // Update cvMat\n                    std::vector<Matrix> cvOutputDatas;\n                    for (auto& tDatumPtr : *tDatums)\n                        cvOutputDatas.emplace_back(tDatumPtr->cvOutputData);\n                    spGui3D->setImage(cvOutputDatas);\n                    // Update keypoints\n                    auto& tDatumPtr = (*tDatums)[0];\n                    spGui3D->setKeypoints(\n                        tDatumPtr->poseKeypoints3D, tDatumPtr->faceKeypoints3D, tDatumPtr->handKeypoints3D[0],\n                        tDatumPtr->handKeypoints3D[1]);\n                }\n                // Refresh/update GUI\n                spGui3D->update();\n                // Read OpenCV mat equivalent\n                if (!tDatums->empty())\n                {\n                    auto& tDatumPtr = (*tDatums)[0];\n                    tDatumPtr->cvOutputData3D = spGui3D->readCvMat();\n                }\n                // Profiling speed\n                if (!tDatums->empty())\n                {\n                    Profiler::timerEnd(profilerKey);\n                    Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WGui3D);\n}\n\n#endif // OPENPOSE_GUI_W_GUI_3D_HPP\n"
  },
  {
    "path": "include/openpose/gui/wGuiAdam.hpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#ifndef OPENPOSE_GUI_W_GUI_ADAM_HPP\n#define OPENPOSE_GUI_W_GUI_ADAM_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/guiAdam.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WGuiAdam : public WorkerConsumer<TDatums>\n    {\n    public:\n        explicit WGuiAdam(const std::shared_ptr<GuiAdam>& guiAdam);\n\n        virtual ~WGuiAdam();\n\n        void initializationOnThread();\n\n        void workConsumer(const TDatums& tDatums);\n\n    private:\n        std::shared_ptr<GuiAdam> spGuiAdam;\n\n        DELETE_COPY(WGuiAdam);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WGuiAdam<TDatums>::WGuiAdam(const std::shared_ptr<GuiAdam>& guiAdam) :\n        spGuiAdam{guiAdam}\n    {\n    }\n\n    template<typename TDatums>\n    WGuiAdam<TDatums>::~WGuiAdam()\n    {\n    }\n\n    template<typename TDatums>\n    void WGuiAdam<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spGuiAdam->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WGuiAdam<TDatums>::workConsumer(const TDatums& tDatums)\n    {\n        try\n        {\n            // tDatums might be empty but we still wanna update the GUI\n            if (tDatums != nullptr)\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Update cvMat & keypoints\n                if (!tDatums->empty())\n                {\n                    // Update cvMat\n                    std::vector<Mat> cvOutputDatas;\n                    for (auto& tDatum : *tDatums)\n                        cvOutputDatas.emplace_back(tDatumPtr->cvOutputData);\n                    spGuiAdam->setImage(cvOutputDatas);\n                    // Update keypoints\n                    const auto& tDatumPtr = (*tDatums)[0];\n                    if (!tDatumPtr->poseKeypoints3D.empty())\n                        spGuiAdam->generateMesh(\n                            tDatumPtr->poseKeypoints3D, tDatumPtr->faceKeypoints3D, tDatumPtr->handKeypoints3D,\n                            tDatumPtr->adamPose.data(), tDatumPtr->adamTranslation.data(), tDatumPtr->vtVec.data(),\n                            tDatumPtr->vtVec.rows(), tDatumPtr->j0Vec.data(), tDatumPtr->j0Vec.rows(),\n                            tDatumPtr->adamFaceCoeffsExp.data());\n                }\n                // Refresh/update GUI\n                spGuiAdam->update();\n                // Profiling speed\n                if (!tDatums->empty())\n                {\n                    Profiler::timerEnd(profilerKey);\n                    Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WGuiAdam);\n}\n\n#endif // OPENPOSE_GUI_W_GUI_ADAM_HPP\n#endif\n"
  },
  {
    "path": "include/openpose/gui/wGuiInfoAdder.hpp",
    "content": "#ifndef OPENPOSE_GUI_W_ADD_GUI_INFO_HPP\n#define OPENPOSE_GUI_W_ADD_GUI_INFO_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/guiInfoAdder.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WGuiInfoAdder : public Worker<TDatums>\n    {\n    public:\n        explicit WGuiInfoAdder(const std::shared_ptr<GuiInfoAdder>& guiInfoAdder);\n\n        virtual ~WGuiInfoAdder();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<GuiInfoAdder> spGuiInfoAdder;\n\n        DELETE_COPY(WGuiInfoAdder);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WGuiInfoAdder<TDatums>::WGuiInfoAdder(const std::shared_ptr<GuiInfoAdder>& guiInfoAdder) :\n        spGuiInfoAdder{guiInfoAdder}\n    {\n    }\n\n    template<typename TDatums>\n    WGuiInfoAdder<TDatums>::~WGuiInfoAdder()\n    {\n    }\n\n    template<typename TDatums>\n    void WGuiInfoAdder<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WGuiInfoAdder<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Add GUI components to frame\n                for (auto& tDatumPtr : *tDatums)\n                    spGuiInfoAdder->addInfo(\n                        tDatumPtr->cvOutputData,\n                        std::max(tDatumPtr->poseKeypoints.getSize(0), tDatumPtr->faceKeypoints.getSize(0)),\n                        tDatumPtr->id, tDatumPtr->elementRendered.second, tDatumPtr->frameNumber,\n                        tDatumPtr->poseIds, tDatumPtr->poseKeypoints);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WGuiInfoAdder);\n}\n\n#endif // OPENPOSE_GUI_W_ADD_GUI_INFO_HPP\n"
  },
  {
    "path": "include/openpose/hand/handCpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_CPU_RENDERER_HPP\n#define OPENPOSE_HAND_HAND_CPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/renderer.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/hand/handRenderer.hpp>\n\nnamespace op\n{\n    class OP_API HandCpuRenderer : public Renderer, public HandRenderer\n    {\n    public:\n        HandCpuRenderer(const float renderThreshold, const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT,\n                        const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP);\n\n        virtual ~HandCpuRenderer();\n\n        void renderHandInherited(Array<float>& outputData, const std::array<Array<float>, 2>& handKeypoints);\n\n        DELETE_COPY(HandCpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_CPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/hand/handDetector.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_DETECTOR_HPP\n#define OPENPOSE_HAND_HAND_DETECTOR_HPP\n\n#include <mutex>\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    // Note: This class is thread-safe, so several GPUs can be running hands and using `updateTracker`, and updateTracker will keep the latest known\n    // tracking\n    class OP_API HandDetector\n    {\n    public:\n        explicit HandDetector(const PoseModel poseModel);\n\n        virtual ~HandDetector();\n\n        std::vector<std::array<Rectangle<float>, 2>> detectHands(const Array<float>& poseKeypoints) const;\n\n        std::vector<std::array<Rectangle<float>, 2>> trackHands(const Array<float>& poseKeypoints);\n\n        void updateTracker(const std::array<Array<float>, 2>& handKeypoints, const unsigned long long id);\n\n    private:\n        enum class PosePart : unsigned int\n        {\n            LWrist = 0,\n            LElbow,\n            LShoulder,\n            RWrist,\n            RElbow,\n            RShoulder,\n            Size,\n        };\n\n        const std::array<unsigned int, (int)PosePart::Size> mPoseIndexes;\n        std::vector<std::array<Point<float>, (int)PosePart::Size>> mPoseTrack;\n        std::vector<Rectangle<float>> mHandLeftPrevious;\n        std::vector<Rectangle<float>> mHandRightPrevious;\n        unsigned long long mCurrentId;\n        std::mutex mMutex;\n\n        std::array<unsigned int, (int)PosePart::Size> getPoseKeypoints(const PoseModel poseModel,\n                                                                       const std::array<std::string, (int)PosePart::Size>& poseStrings) const;\n\n        DELETE_COPY(HandDetector);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_DETECTOR_HPP\n"
  },
  {
    "path": "include/openpose/hand/handDetectorFromTxt.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP\n#define OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API HandDetectorFromTxt\n    {\n    public:\n        explicit HandDetectorFromTxt(const std::string& txtDirectoryPath);\n\n        virtual ~HandDetectorFromTxt();\n\n        std::vector<std::array<Rectangle<float>, 2>> detectHands();\n\n    private:\n        const std::string mTxtDirectoryPath;\n        const std::vector<std::string> mFilePaths;\n        long long mFrameNameCounter;\n\n        DELETE_COPY(HandDetectorFromTxt);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_DETECTOR_FROM_TXT_HPP\n"
  },
  {
    "path": "include/openpose/hand/handExtractorCaffe.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP\n#define OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/hand/handExtractorNet.hpp>\n\nnamespace op\n{\n    /**\n     * Hand keypoint extractor class for Caffe framework.\n     */\n    class OP_API HandExtractorCaffe : public HandExtractorNet\n    {\n    public:\n        /**\n         * Constructor of the HandExtractorCaffe class.\n         * @param netInputSize Size at which the cropped image (where the hand is located) is resized.\n         * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize.\n         * @param modelFolder Folder where the models are located.\n         * @param gpuId The GPU index (0-based) which the deep net will use.\n         * @param numberScales Number of scales to run. The more scales, the slower it will be but possibly also more\n         * accurate.\n         * @param rangeScales The range between the smaller and bigger scale.\n         */\n        HandExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                           const std::string& modelFolder, const int gpuId,\n                           const int numberScales = 1, const float rangeScales = 0.4f,\n                           const std::vector<HeatMapType>& heatMapTypes = {},\n                           const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect,\n                           const bool enableGoogleLogging = true);\n\n        /**\n         * Virtual destructor of the HandExtractor class.\n         * Required to allow inheritance.\n         */\n        virtual ~HandExtractorCaffe();\n\n        /**\n         * This function must be call before using any other function. It must also be called inside the thread in\n         * which the functions are going to be used.\n         */\n        void netInitializationOnThread();\n\n        /**\n         * This function extracts the hand keypoints for each detected hand in the image.\n         * @param handRectangles location of the hands in the image. It is a length-variable std::vector, where\n         * each index corresponds to a different person in the image. Internally the std::vector, a std::array of 2\n         * elements: index 0 and 1 for left and right hand respectively. Inside each array element, a\n         * op::Rectangle<float> (similar to cv::Rect for floating values) with the position of that hand (or 0,0,0,0 if\n         * some hand is missing, e.g., if a specific person has only half of the body inside the image).\n         * @param inputData Original image in Mat format and BGR format.\n         */\n        void forwardPass(const std::vector<std::array<Rectangle<float>, 2>> handRectangles, const Matrix& inputData);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplHandExtractorCaffe;\n        std::unique_ptr<ImplHandExtractorCaffe> upImpl;\n\n        Array<float> getHeatMapsFromLastPass() const;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(HandExtractorCaffe);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_EXTRACTOR_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/hand/handExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_EXTRACTOR_HPP\n#define OPENPOSE_HAND_HAND_EXTRACTOR_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * Hand keypoint extractor class.\n     */\n    class OP_API HandExtractorNet\n    {\n    public:\n        /**\n         * Constructor of the HandExtractorNet class.\n         * @param netInputSize Size at which the cropped image (where the hand is located) is resized.\n         * @param netOutputSize Size of the final results. At the moment, it must be equal than netOutputSize.\n         * @param numberScales Number of scales to run. The more scales, the slower it will be but possibly also more\n         * accurate.\n         * @param rangeScales The range between the smaller and bigger scale.\n         */\n        explicit HandExtractorNet(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                  const int numberScales = 1, const float rangeScales = 0.4f,\n                                  const std::vector<HeatMapType>& heatMapTypes = {},\n                                  const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect);\n\n        /**\n         * Virtual destructor of the HandExtractorNet class.\n         * Required to allow inheritance.\n         */\n        virtual ~HandExtractorNet();\n\n        /**\n         * This function must be call before using any other function. It must also be called inside the thread in\n         * which the functions are going to be used.\n         */\n        void initializationOnThread();\n\n        /**\n         * This function extracts the hand keypoints for each detected hand in the image.\n         * @param handRectangles location of the hands in the image. It is a length-variable std::vector, where\n         * each index corresponds to a different person in the image. Internally the std::vector, a std::array of 2\n         * elements: index 0 and 1 for left and right hand respectively. Inside each array element, a\n         * op::Rectangle<float> (similar to cv::Rect for floating values) with the position of that hand (or 0,0,0,0 if\n         * some hand is missing, e.g., if a specific person has only half of the body inside the image).\n         * @param cvInputData Original image in Mat format and BGR format.\n         */\n        virtual void forwardPass(const std::vector<std::array<Rectangle<float>, 2>> handRectangles,\n                                 const Matrix& cvInputData) = 0;\n\n        std::array<Array<float>, 2> getHeatMaps() const;\n\n        /**\n         * This function returns the hand keypoins. VERY IMPORTANT: use getHandKeypoints().clone() if the keypoints are\n         * going to be edited in a different thread.\n         * @return A std::array with all the left hand keypoints (index 0) and all the right ones (index 1). Each\n         * Array<float> follows the pose structure, i.e., the first dimension corresponds to all the people in the\n         * image, the second to each specific keypoint, and the third one to (x, y, score).\n         */\n        std::array<Array<float>, 2> getHandKeypoints() const;\n\n        bool getEnabled() const;\n\n        void setEnabled(const bool enabled);\n\n    protected:\n        const std::pair<int, float> mMultiScaleNumberAndRange;\n        const Point<int> mNetOutputSize;\n        Array<float> mHandImageCrop;\n        std::array<Array<float>, 2> mHandKeypoints;\n        // HeatMaps parameters\n        const ScaleMode mHeatMapScaleMode;\n        const std::vector<HeatMapType> mHeatMapTypes;\n        std::array<Array<float>, 2> mHeatMaps;\n        // Temporarily disable it\n        std::atomic<bool> mEnabled;\n\n        virtual void netInitializationOnThread() = 0;\n\n    private:\n        // Init with thread\n        std::thread::id mThreadId;\n\n        void checkThread() const;\n\n        DELETE_COPY(HandExtractorNet);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/hand/handGpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_GPU_RENDERER_HPP\n#define OPENPOSE_HAND_HAND_GPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/gpuRenderer.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/hand/handRenderer.hpp>\n\nnamespace op\n{\n    class OP_API HandGpuRenderer : public GpuRenderer, public HandRenderer\n    {\n    public:\n        HandGpuRenderer(const float renderThreshold,\n                        const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT,\n                        const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP);\n\n        virtual ~HandGpuRenderer();\n\n        void initializationOnThread();\n\n        void renderHandInherited(Array<float>& outputData, const std::array<Array<float>, 2>& handKeypoints);\n\n    private:\n        float* pGpuHand; // GPU aux memory\n        float* pMaxPtr; // GPU aux memory\n        float* pMinPtr; // GPU aux memory\n        float* pScalePtr; // GPU aux memory\n\n        DELETE_COPY(HandGpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_GPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/hand/handParameters.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_PARAMETERS_HPP\n#define OPENPOSE_HAND_HAND_PARAMETERS_HPP\n\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n\nnamespace op\n{\n    const auto HAND_MAX_HANDS = 2*POSE_MAX_PEOPLE;\n\n    const auto HAND_NUMBER_PARTS = 21u;\n    #define HAND_PAIRS_RENDER_GPU \\\n        0,1,  1,2,  2,3,  3,4,  0,5,  5,6,  6,7,  7,8,  0,9,  9,10,  10,11,  11,12,  0,13,  13,14,  14,15,  15,16,  0,17,  17,18,  18,19,  19,20\n    #define HAND_SCALES_RENDER_GPU 1\n    const std::vector<unsigned int> HAND_PAIRS_RENDER {HAND_PAIRS_RENDER_GPU};\n    #define HAND_COLORS_RENDER_GPU \\\n        100.f,  100.f,  100.f, \\\n        100.f,    0.f,    0.f, \\\n        150.f,    0.f,    0.f, \\\n        200.f,    0.f,    0.f, \\\n        255.f,    0.f,    0.f, \\\n        100.f,  100.f,    0.f, \\\n        150.f,  150.f,    0.f, \\\n        200.f,  200.f,    0.f, \\\n        255.f,  255.f,    0.f, \\\n          0.f,  100.f,   50.f, \\\n          0.f,  150.f,   75.f, \\\n          0.f,  200.f,  100.f, \\\n          0.f,  255.f,  125.f, \\\n          0.f,   50.f,  100.f, \\\n          0.f,   75.f,  150.f, \\\n          0.f,  100.f,  200.f, \\\n          0.f,  125.f,  255.f, \\\n        100.f,    0.f,  100.f, \\\n        150.f,    0.f,  150.f, \\\n        200.f,    0.f,  200.f, \\\n        255.f,    0.f,  255.f\n    const std::vector<float> HAND_COLORS_RENDER{HAND_COLORS_RENDER_GPU};\n    const std::vector<float> HAND_SCALES_RENDER{HAND_SCALES_RENDER_GPU};\n\n\n    // Constant parameters\n    const auto HAND_CCN_DECREASE_FACTOR = 8.f;\n    const std::string HAND_PROTOTXT{\"hand/pose_deploy.prototxt\"};\n    const std::string HAND_TRAINED_MODEL{\"hand/pose_iter_102000.caffemodel\"};\n\n    // Rendering parameters\n    const auto HAND_DEFAULT_ALPHA_KEYPOINT = POSE_DEFAULT_ALPHA_KEYPOINT;\n    const auto HAND_DEFAULT_ALPHA_HEAT_MAP = POSE_DEFAULT_ALPHA_HEAT_MAP;\n}\n\n#endif // OPENPOSE_HAND_HAND_PARAMETERS_HPP\n"
  },
  {
    "path": "include/openpose/hand/handRenderer.hpp",
    "content": "#ifndef OPENPOSE_HAND_HAND_RENDERER_HPP\n#define OPENPOSE_HAND_HAND_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API HandRenderer\n    {\n    public:\n        virtual ~HandRenderer(){};\n\n        virtual void initializationOnThread(){};\n\n        void renderHand(Array<float>& outputData, const std::array<Array<float>, 2>& handKeypoints,\n                        const float scaleInputToOutput);\n\n    private:\n        virtual void renderHandInherited(Array<float>& outputData,\n                                         const std::array<Array<float>, 2>& handKeypoints) = 0;\n    };\n}\n\n#endif // OPENPOSE_HAND_HAND_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/hand/headers.hpp",
    "content": "#ifndef OPENPOSE_HAND_HEADERS_HPP\n#define OPENPOSE_HAND_HEADERS_HPP\n\n// hand module\n#include <openpose/hand/handDetector.hpp>\n#include <openpose/hand/handDetectorFromTxt.hpp>\n#include <openpose/hand/handExtractorCaffe.hpp>\n#include <openpose/hand/handExtractorNet.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/hand/handCpuRenderer.hpp>\n#include <openpose/hand/handGpuRenderer.hpp>\n#include <openpose/hand/handRenderer.hpp>\n#include <openpose/hand/renderHand.hpp>\n#include <openpose/hand/wHandDetector.hpp>\n#include <openpose/hand/wHandDetectorFromTxt.hpp>\n#include <openpose/hand/wHandDetectorTracking.hpp>\n#include <openpose/hand/wHandDetectorUpdate.hpp>\n#include <openpose/hand/wHandExtractorNet.hpp>\n#include <openpose/hand/wHandRenderer.hpp>\n\n#endif // OPENPOSE_HAND_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/hand/renderHand.hpp",
    "content": "#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP\n#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handParameters.hpp>\n\nnamespace op\n{\n    OP_API void renderHandKeypointsCpu(\n        Array<float>& frameArray, const std::array<Array<float>, 2>& handKeypoints, const float renderThreshold);\n\n    void renderHandKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point<unsigned int>& frameSize,\n        const float* const handsPtr, const int numberHands, const float renderThreshold,\n        const float alphaColorToAdd = HAND_DEFAULT_ALPHA_KEYPOINT);\n}\n\n#endif // OPENPOSE_HAND_GPU_HAND_RENDER_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandDetector.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_HPP\n#define OPENPOSE_HAND_W_HAND_DETECTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handDetector.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandDetector : public Worker<TDatums>\n    {\n    public:\n        explicit WHandDetector(const std::shared_ptr<HandDetector>& handDetector);\n\n        virtual ~WHandDetector();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandDetector> spHandDetector;\n\n        DELETE_COPY(WHandDetector);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandDetector<TDatums>::WHandDetector(const std::shared_ptr<HandDetector>& handDetector) :\n        spHandDetector{handDetector}\n    {\n    }\n\n    template<typename TDatums>\n    WHandDetector<TDatums>::~WHandDetector()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetector<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetector<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people hand\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->handRectangles = spHandDetector->detectHands(tDatumPtr->poseKeypoints);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandDetector);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_DETECTOR_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandDetectorFromTxt.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP\n#define OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handDetectorFromTxt.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandDetectorFromTxt : public Worker<TDatums>\n    {\n    public:\n        explicit WHandDetectorFromTxt(const std::shared_ptr<HandDetectorFromTxt>& handDetectorFromTxt);\n\n        virtual ~WHandDetectorFromTxt();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandDetectorFromTxt> spHandDetectorFromTxt;\n\n        DELETE_COPY(WHandDetectorFromTxt);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandDetectorFromTxt<TDatums>::WHandDetectorFromTxt(const std::shared_ptr<HandDetectorFromTxt>& handDetectorFromTxt) :\n        spHandDetectorFromTxt{handDetectorFromTxt}\n    {\n    }\n\n    template<typename TDatums>\n    WHandDetectorFromTxt<TDatums>::~WHandDetectorFromTxt()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorFromTxt<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorFromTxt<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people hand\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->handRectangles = spHandDetectorFromTxt->detectHands();\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandDetectorFromTxt);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_DETECTOR_FROM_JSON_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandDetectorTracking.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP\n#define OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandDetectorTracking : public Worker<TDatums>\n    {\n    public:\n        explicit WHandDetectorTracking(const std::shared_ptr<HandDetector>& handDetector);\n\n        virtual ~WHandDetectorTracking();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandDetector> spHandDetector;\n\n        DELETE_COPY(WHandDetectorTracking);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandDetectorTracking<TDatums>::WHandDetectorTracking(const std::shared_ptr<HandDetector>& handDetector) :\n        spHandDetector{handDetector}\n    {\n    }\n\n    template<typename TDatums>\n    WHandDetectorTracking<TDatums>::~WHandDetectorTracking()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorTracking<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorTracking<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people hand\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->handRectangles = spHandDetector->trackHands(tDatumPtr->poseKeypoints);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandDetectorTracking);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_DETECTOR_TRACKING_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandDetectorUpdate.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP\n#define OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandDetectorUpdate : public Worker<TDatums>\n    {\n    public:\n        explicit WHandDetectorUpdate(const std::shared_ptr<HandDetector>& handDetector);\n\n        virtual ~WHandDetectorUpdate();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandDetector> spHandDetector;\n\n        DELETE_COPY(WHandDetectorUpdate);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandDetectorUpdate<TDatums>::WHandDetectorUpdate(const std::shared_ptr<HandDetector>& handDetector) :\n        spHandDetector{handDetector}\n    {\n    }\n\n    template<typename TDatums>\n    WHandDetectorUpdate<TDatums>::~WHandDetectorUpdate()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorUpdate<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandDetectorUpdate<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Detect people hand\n                for (auto& tDatumPtr : *tDatums)\n                    spHandDetector->updateTracker(tDatumPtr->handKeypoints, tDatumPtr->id);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandDetectorUpdate);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_DETECTOR_UPDATE_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP\n#define OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandExtractorNet : public Worker<TDatums>\n    {\n    public:\n        explicit WHandExtractorNet(const std::shared_ptr<HandExtractorNet>& handExtractorNet);\n\n        virtual ~WHandExtractorNet();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandExtractorNet> spHandExtractorNet;\n\n        DELETE_COPY(WHandExtractorNet);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandExtractorNet<TDatums>::WHandExtractorNet(const std::shared_ptr<HandExtractorNet>& handExtractorNet) :\n        spHandExtractorNet{handExtractorNet}\n    {\n    }\n\n    template<typename TDatums>\n    WHandExtractorNet<TDatums>::~WHandExtractorNet()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandExtractorNet<TDatums>::initializationOnThread()\n    {\n        spHandExtractorNet->initializationOnThread();\n    }\n\n    template<typename TDatums>\n    void WHandExtractorNet<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Extract people hands\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    spHandExtractorNet->forwardPass(tDatumPtr->handRectangles, tDatumPtr->cvInputData);\n                    for (auto hand = 0 ; hand < 2 ; hand++)\n                    {\n                        tDatumPtr->handHeatMaps[hand] = spHandExtractorNet->getHeatMaps()[hand].clone();\n                        tDatumPtr->handKeypoints[hand] = spHandExtractorNet->getHandKeypoints()[hand].clone();\n                    }\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandExtractorNet);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_EXTRACTOR_NET_HPP\n"
  },
  {
    "path": "include/openpose/hand/wHandRenderer.hpp",
    "content": "#ifndef OPENPOSE_HAND_W_HAND_RENDERER_HPP\n#define OPENPOSE_HAND_W_HAND_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/hand/handRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WHandRenderer : public Worker<TDatums>\n    {\n    public:\n        explicit WHandRenderer(const std::shared_ptr<HandRenderer>& handRenderer);\n\n        virtual ~WHandRenderer();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<HandRenderer> spHandRenderer;\n\n        DELETE_COPY(WHandRenderer);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WHandRenderer<TDatums>::WHandRenderer(const std::shared_ptr<HandRenderer>& handRenderer) :\n        spHandRenderer{handRenderer}\n    {\n    }\n\n    template<typename TDatums>\n    WHandRenderer<TDatums>::~WHandRenderer()\n    {\n    }\n\n    template<typename TDatums>\n    void WHandRenderer<TDatums>::initializationOnThread()\n    {\n        spHandRenderer->initializationOnThread();\n    }\n\n    template<typename TDatums>\n    void WHandRenderer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Render people hands\n                for (auto& tDatumPtr : *tDatums)\n                    spHandRenderer->renderHand(\n                        tDatumPtr->outputData, tDatumPtr->handKeypoints, (float)tDatumPtr->scaleInputToOutput);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WHandRenderer);\n}\n\n#endif // OPENPOSE_HAND_W_HAND_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/headers.hpp",
    "content": "#ifndef OPENPOSE_HEADERS_HPP\n#define OPENPOSE_HEADERS_HPP\n\n// 3d module\n#include <openpose/3d/headers.hpp>\n\n// calibration module\n#include <openpose/calibration/headers.hpp>\n\n// core module\n#include <openpose/core/headers.hpp>\n\n// face module\n#include <openpose/face/headers.hpp>\n\n// filestream module\n#include <openpose/filestream/headers.hpp>\n\n// gui module\n#include <openpose/gui/headers.hpp>\n\n// hand module\n#include <openpose/hand/headers.hpp>\n\n// net module\n#include <openpose/net/headers.hpp>\n\n// pose module\n#include <openpose/pose/headers.hpp>\n\n// producer module\n#include <openpose/producer/headers.hpp>\n\n// threading module\n#include <openpose/thread/headers.hpp>\n\n// tracking module\n#include <openpose/tracking/headers.hpp>\n\n// unity module\n#include <openpose/unity/headers.hpp>\n\n// utilities module\n#include <openpose/utilities/headers.hpp>\n\n// wrapper module\n#include <openpose/wrapper/headers.hpp>\n\n#endif // OPENPOSE_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/net/bodyPartConnectorBase.hpp",
    "content": "#ifndef OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP\n#define OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void connectBodyPartsCpu(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor = 1.f, const bool maximizePositives = false);\n\n    // Windows: Cuda functions do not include OP_API\n    template <typename T>\n    void connectBodyPartsGpu(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor, const bool maximizePositives, Array<T> pairScoresCpu, T* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const T* const peaksGpuPtr);\n\n    template <typename T>\n    void connectBodyPartsOcl(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor = 1.f, const bool maximizePositives = false,\n        Array<T> pairScoresCpu = Array<T>{}, T* pairScoresGpuPtr = nullptr,\n        const unsigned int* const bodyPartPairsGpuPtr = nullptr, const unsigned int* const mapIdxGpuPtr = nullptr,\n        const T* const peaksGpuPtr = nullptr, const int gpuID = 0);\n\n    // Private functions used by the 2 above functions\n    template <typename T>\n    std::vector<std::pair<std::vector<int>, T>> createPeopleVector(\n        const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize,\n        const int maxPeaks, const T interThreshold, const T interMinAboveThreshold,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs, const T defaultNmsThreshold,\n        const Array<T>& precomputedPAFs = Array<T>());\n\n    template <typename T>\n    void removePeopleBelowThresholdsAndFillFaces(\n        std::vector<int>& validSubsetIndexes, int& numberPeople,\n        std::vector<std::pair<std::vector<int>, T>>& subsets, const unsigned int numberBodyParts,\n        const int minSubsetCnt, const T minSubsetScore, const bool maximizePositives, const T* const peaksPtr);\n\n    template <typename T>\n    void peopleVectorToPeopleArray(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T scaleFactor,\n        const std::vector<std::pair<std::vector<int>, T>>& subsets, const std::vector<int>& validSubsetIndexes,\n        const T* const peaksPtr, const int numberPeople, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs);\n\n    template <typename T>\n    std::vector<std::tuple<T, T, int, int, int>> pafPtrIntoVector(\n        const Array<T>& pairScores, const T* const peaksPtr, const int maxPeaks,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyPartPairs);\n\n    template <typename T>\n    std::vector<std::pair<std::vector<int>, T>> pafVectorIntoPeopleVector(\n        const std::vector<std::tuple<T, T, int, int, int>>& pairScores, const T* const peaksPtr, const int maxPeaks,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyParts);\n}\n\n#endif // OPENPOSE_POSE_BODY_PARTS_CONNECTOR_HPP\n"
  },
  {
    "path": "include/openpose/net/bodyPartConnectorCaffe.hpp",
    "content": "#ifndef OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP\n#define OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep\n    // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the\n    // Caffe code.\n    template <typename T>\n    class BodyPartConnectorCaffe\n    {\n    public:\n        explicit BodyPartConnectorCaffe();\n\n        virtual ~BodyPartConnectorCaffe();\n\n        virtual void Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const int gpuID = 0);\n\n        virtual inline const char* type() const { return \"BodyPartConnector\"; }\n\n        void setPoseModel(const PoseModel poseModel);\n\n        void setMaximizePositives(const bool maximizePositives);\n\n        void setDefaultNmsThreshold(const T defaultNmsThreshold);\n\n        void setInterMinAboveThreshold(const T interMinAboveThreshold);\n\n        void setInterThreshold(const T interThreshold);\n\n        void setMinSubsetCnt(const int minSubsetCnt);\n\n        void setMinSubsetScore(const T minSubsetScore);\n\n        void setScaleNetToOutput(const T scaleNetToOutput);\n\n        virtual void Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints,\n                             Array<T>& poseScores);\n\n        virtual void Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints,\n                                 Array<T>& poseScores);\n\n        virtual void Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints,\n                                 Array<T>& poseScores);\n\n        virtual void Forward_ocl(const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints,\n                                 Array<T>& poseScores);\n\n        virtual void Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n        virtual void Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n    private:\n        PoseModel mPoseModel;\n        bool mMaximizePositives;\n        T mDefaultNmsThreshold;\n        T mInterMinAboveThreshold;\n        T mInterThreshold;\n        int mMinSubsetCnt;\n        T mMinSubsetScore;\n        T mScaleNetToOutput;\n        std::array<int, 4> mHeatMapsSize;\n        std::array<int, 4> mPeaksSize;\n        std::array<int, 4> mTopSize;\n        // GPU auxiliary\n        unsigned int* pBodyPartPairsGpuPtr;\n        unsigned int* pMapIdxGpuPtr;\n        Array<T> mFinalOutputCpu;\n        T* pFinalOutputGpuPtr;\n        int mGpuID;\n\n        DELETE_COPY(BodyPartConnectorCaffe);\n    };\n}\n\n#endif // OPENPOSE_POSE_BODY_PART_CONNECTOR_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/net/headers.hpp",
    "content": "#ifndef OPENPOSE_NET_HEADERS_HPP\n#define OPENPOSE_NET_HEADERS_HPP\n\n// net module\n#include <openpose/net/bodyPartConnectorBase.hpp>\n#include <openpose/net/bodyPartConnectorCaffe.hpp>\n#include <openpose/net/maximumBase.hpp>\n#include <openpose/net/maximumCaffe.hpp>\n#include <openpose/net/net.hpp>\n#include <openpose/net/netCaffe.hpp>\n#include <openpose/net/netOpenCv.hpp>\n#include <openpose/net/nmsBase.hpp>\n#include <openpose/net/nmsCaffe.hpp>\n#include <openpose/net/resizeAndMergeBase.hpp>\n#include <openpose/net/resizeAndMergeCaffe.hpp>\n\n#endif // OPENPOSE_NET_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/net/maximumBase.hpp",
    "content": "#ifndef OPENPOSE_NET_MAXIMUM_BASE_HPP\n#define OPENPOSE_NET_MAXIMUM_BASE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void maximumCpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize,\n                    const std::array<int, 4>& sourceSize);\n\n    // Windows: Cuda functions do not include OP_API\n    template <typename T>\n    void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize,\n                    const std::array<int, 4>& sourceSize);\n}\n\n#endif // OPENPOSE_NET_MAXIMUM_BASE_HPP\n"
  },
  {
    "path": "include/openpose/net/maximumCaffe.hpp",
    "content": "#ifndef OPENPOSE_NET_MAXIMUM_CAFFE_HPP\n#define OPENPOSE_NET_MAXIMUM_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep\n    // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the\n    // Caffe code.\n    template <typename T>\n    class MaximumCaffe\n    {\n    public:\n        explicit MaximumCaffe();\n\n        virtual ~MaximumCaffe();\n\n        virtual void LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual inline const char* type() const { return \"Maximum\"; }\n\n        virtual void Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n        virtual void Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n    private:\n        std::array<int, 4> mBottomSize;\n        std::array<int, 4> mTopSize;\n    };\n}\n\n#endif // OPENPOSE_NET_MAXIMUM_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/net/net.hpp",
    "content": "#ifndef OPENPOSE_NET_NET_HPP\n#define OPENPOSE_NET_NET_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API Net\n    {\n    public:\n        virtual ~Net(){}\n\n        virtual void initializationOnThread() = 0;\n\n        virtual void forwardPass(const Array<float>& inputData) const = 0;\n\n        virtual std::shared_ptr<ArrayCpuGpu<float>> getOutputBlobArray() const = 0;\n    };\n}\n\n#endif // OPENPOSE_NET_NET_HPP\n"
  },
  {
    "path": "include/openpose/net/netCaffe.hpp",
    "content": "#ifndef OPENPOSE_NET_NET_CAFFE_HPP\n#define OPENPOSE_NET_NET_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/net/net.hpp>\n\nnamespace op\n{\n    class OP_API NetCaffe : public Net\n    {\n    public:\n        NetCaffe(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId = 0,\n                 const bool enableGoogleLogging = true, const std::string& lastBlobName = \"net_output\");\n\n        virtual ~NetCaffe();\n\n        void initializationOnThread();\n\n        void forwardPass(const Array<float>& inputNetData) const;\n\n        std::shared_ptr<ArrayCpuGpu<float>> getOutputBlobArray() const;\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplNetCaffe;\n        std::unique_ptr<ImplNetCaffe> upImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(NetCaffe);\n    };\n}\n\n#endif // OPENPOSE_NET_NET_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/net/netOpenCv.hpp",
    "content": "#ifndef OPENPOSE_NET_NET_OPEN_CV_HPP\n#define OPENPOSE_NET_NET_OPEN_CV_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/net/net.hpp>\n\nnamespace op\n{\n    class OP_API NetOpenCv : public Net\n    {\n    public:\n        NetOpenCv(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId = 0);\n\n        virtual ~NetOpenCv();\n\n        void initializationOnThread();\n\n        void forwardPass(const Array<float>& inputNetData) const;\n\n        std::shared_ptr<ArrayCpuGpu<float>> getOutputBlobArray() const;\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplNetOpenCv;\n        std::unique_ptr<ImplNetOpenCv> upImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(NetOpenCv);\n    };\n}\n\n#endif // OPENPOSE_NET_NET_OPEN_CV_HPP\n"
  },
  {
    "path": "include/openpose/net/nmsBase.hpp",
    "content": "#ifndef OPENPOSE_NET_NMS_BASE_HPP\n#define OPENPOSE_NET_NMS_BASE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void nmsCpu(\n      T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array<int, 4>& targetSize,\n      const std::array<int, 4>& sourceSize, const Point<T>& offset);\n\n    // Windows: Cuda functions do not include OP_API\n    template <typename T>\n    void nmsGpu(\n      T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold, const std::array<int, 4>& targetSize,\n      const std::array<int, 4>& sourceSize, const Point<T>& offset);\n\n    // Windows: OpenCL functions do not include OP_API\n    template <typename T>\n    void nmsOcl(\n      T* targetPtr, uint8_t* kernelGpuPtr, uint8_t* kernelCpuPtr, const T* const sourcePtr, const T threshold, const std::array<int, 4>& targetSize,\n      const std::array<int, 4>& sourceSize, const Point<T>& offset, const int gpuID = 0);\n}\n\n#endif // OPENPOSE_NET_NMS_BASE_HPP\n"
  },
  {
    "path": "include/openpose/net/nmsCaffe.hpp",
    "content": "#ifndef OPENPOSE_NET_NMS_CAFFE_HPP\n#define OPENPOSE_NET_NMS_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep\n    // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the\n    // Caffe code.\n    template <typename T>\n    class NmsCaffe\n    {\n    public:\n        explicit NmsCaffe();\n\n        virtual ~NmsCaffe();\n\n        virtual void LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top,\n                             const int maxPeaks, const int outputChannels = -1, const int gpuID = 0);\n\n        virtual inline const char* type() const { return \"Nms\"; }\n\n        void setThreshold(const T threshold);\n\n        // Empirically gives better results (copied from Matlab original code)\n        void setOffset(const Point<T>& offset);\n\n        virtual void Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_ocl(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n        virtual void Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n    private:\n        T mThreshold;\n        Point<T> mOffset;\n        int mGpuID;\n\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplNmsCaffe;\n        std::unique_ptr<ImplNmsCaffe> upImpl;\n\n        // PIMP requires DELETE_COPY & destructor, or extra code\n        // http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html\n        DELETE_COPY(NmsCaffe);\n    };\n}\n\n#endif // OPENPOSE_NET_NMS_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/net/resizeAndMergeBase.hpp",
    "content": "#ifndef OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP\n#define OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void resizeAndMergeCpu(\n        T* targetPtr, const std::vector<const T*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<T>& scaleInputToNetInputs = {1.f});\n\n    // Windows: Cuda functions do not include OP_API\n    template <typename T>\n    void resizeAndMergeGpu(\n        T* targetPtr, const std::vector<const T*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<T>& scaleInputToNetInputs = {1.f});\n\n    // Windows: OpenCL functions do not include OP_API\n    template <typename T>\n    void resizeAndMergeOcl(\n        T* targetPtr, const std::vector<const T*>& sourcePtrs, std::vector<T*>& sourceTempPtrs,\n        const std::array<int, 4>& targetSize, const std::vector<std::array<int, 4>>& sourceSizes,\n        const std::vector<T>& scaleInputToNetInputs = {1.f}, const int gpuID = 0);\n\n    // Functions for cvMatToOpInput/cvMatToOpOutput\n    template <typename T>\n    void resizeAndPadRbgGpu(\n        T* targetPtr, const T* const srcPtr, const int sourceWidth, const int sourceHeight,\n        const int targetWidth, const int targetHeight, const T scaleFactor);\n\n    template <typename T>\n    void resizeAndPadRbgGpu(\n        T* targetPtr, const unsigned char* const srcPtr, const int sourceWidth, const int sourceHeight,\n        const int targetWidth, const int targetHeight, const T scaleFactor);\n}\n#endif // OPENPOSE_NET_RESIZE_AND_MERGE_BASE_HPP\n"
  },
  {
    "path": "include/openpose/net/resizeAndMergeCaffe.hpp",
    "content": "#ifndef OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP\n#define OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    // It mostly follows the Caffe::layer implementation, so Caffe users can easily use it. However, in order to keep\n    // the compatibility with any generic Caffe version, we keep this 'layer' inside our library rather than in the\n    // Caffe code.\n    template <typename T>\n    class ResizeAndMergeCaffe\n    {\n    public:\n        explicit ResizeAndMergeCaffe();\n\n        virtual ~ResizeAndMergeCaffe();\n\n        virtual void LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top,\n                             const T netFactor, const T scaleFactor, const bool mergeFirstDimension = true,\n                             const int gpuID = 0);\n\n        virtual inline const char* type() const { return \"ResizeAndMerge\"; }\n\n        void setScaleRatios(const std::vector<T>& scaleRatios);\n\n        virtual void Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Forward_ocl(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top);\n\n        virtual void Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n        virtual void Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                  const std::vector<ArrayCpuGpu<T>*>& bottom);\n\n    private:\n        std::vector<T*> mTempGPUData;\n        std::vector<T> mScaleRatios;\n        std::vector<std::array<int, 4>> mBottomSizes;\n        std::array<int, 4> mTopSize;\n        int mGpuID;\n\n        DELETE_COPY(ResizeAndMergeCaffe);\n    };\n}\n\n#endif // OPENPOSE_NET_RESIZE_AND_MERGE_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/pose/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_POSE_ENUM_CLASSES_HPP\n#define OPENPOSE_POSE_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    /**\n     * An enum class in which all the possible type of pose estimation models are included.\n     */\n    enum class PoseModel : unsigned char\n    {\n        /**\n         * COCO + 6 foot keypoints + neck + lower abs model, with 25+1 components (see poseParameters.hpp for details).\n         */\n        BODY_25 = 0,\n        COCO_18,        /**< COCO model + neck, with 18+1 components (see poseParameters.hpp for details). */\n        MPI_15,         /**< MPI model, with 15+1 components (see poseParameters.hpp for details). */\n        MPI_15_4,       /**< Variation of the MPI model, reduced number of CNN stages to 4: faster but less accurate.*/\n        BODY_19,        /**< Experimental. Do not use. */\n        BODY_19_X2,     /**< Experimental. Do not use. */\n        BODY_19N,       /**< Experimental. Do not use. */\n        BODY_25E,       /**< Experimental. Do not use. */\n        CAR_12,         /**< Experimental. Do not use. */\n        BODY_25D,       /**< Experimental. Do not use. */\n        BODY_23,        /**< Experimental. Do not use. */\n        CAR_22,         /**< Experimental. Do not use. */\n        BODY_19E,       /**< Experimental. Do not use. */\n        BODY_25B,       /**< Experimental. Do not use. */\n        BODY_135,       /**< Experimental. Do not use. */\n        Size,\n    };\n\n    enum class PoseProperty : unsigned char\n    {\n        NMSThreshold = 0,\n        ConnectInterMinAboveThreshold,\n        ConnectInterThreshold,\n        ConnectMinSubsetCnt,\n        ConnectMinSubsetScore,\n        Size,\n    };\n}\n\n#endif // OPENPOSE_POSE_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/pose/headers.hpp",
    "content": "#ifndef OPENPOSE_POSE_HEADERS_HPP\n#define OPENPOSE_POSE_HEADERS_HPP\n\n// pose module\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseCpuRenderer.hpp>\n#include <openpose/pose/poseExtractor.hpp>\n#include <openpose/pose/poseExtractorCaffe.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n#include <openpose/pose/poseGpuRenderer.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/pose/poseRenderer.hpp>\n#include <openpose/pose/renderPose.hpp>\n#include <openpose/pose/wPoseExtractor.hpp>\n#include <openpose/pose/wPoseExtractorNet.hpp>\n#include <openpose/pose/wPoseRenderer.hpp>\n\n#endif // OPENPOSE_POSE_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseCpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_CPU_RENDERER_HPP\n#define OPENPOSE_POSE_POSE_CPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/renderer.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/pose/poseRenderer.hpp>\n\nnamespace op\n{\n    class OP_API PoseCpuRenderer : public Renderer, public PoseRenderer\n    {\n    public:\n        PoseCpuRenderer(\n            const PoseModel poseModel, const float renderThreshold, const bool blendOriginalFrame = true,\n            const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT,\n            const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u);\n\n        virtual ~PoseCpuRenderer();\n\n        std::pair<int, std::string> renderPose(\n            Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleInputToOutput,\n            const float scaleNetToOutput = -1.f);\n\n    private:\n        DELETE_COPY(PoseCpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_CPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseExtractor.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_HPP\n#define OPENPOSE_POSE_POSE_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/core/keepTopNPeople.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n#include <openpose/tracking/personIdExtractor.hpp>\n#include <openpose/tracking/personTracker.hpp>\n\nnamespace op\n{\n    class OP_API PoseExtractor\n    {\n    public:\n        PoseExtractor(const std::shared_ptr<PoseExtractorNet>& poseExtractorNet,\n                      const std::shared_ptr<KeepTopNPeople>& keepTopNPeople = nullptr,\n                      const std::shared_ptr<PersonIdExtractor>& personIdExtractor = nullptr,\n                      const std::shared_ptr<std::vector<std::shared_ptr<PersonTracker>>>& personTracker = {},\n                      const int numberPeopleMax = -1, const int tracking = -1);\n\n        virtual ~PoseExtractor();\n\n        void initializationOnThread();\n\n        void forwardPass(const std::vector<Array<float>>& inputNetData,\n                         const Point<int>& inputDataSize,\n                         const std::vector<double>& scaleRatios,\n                         const Array<float>& poseNetOutput = Array<float>{},\n                         const long long frameId = -1ll);\n\n        // PoseExtractorNet functions\n        Array<float> getHeatMapsCopy() const;\n\n        std::vector<std::vector<std::array<float, 3>>> getCandidatesCopy() const;\n\n        Array<float> getPoseKeypoints() const;\n\n        Array<float> getPoseScores() const;\n\n        float getScaleNetToOutput() const;\n\n        // KeepTopNPeople functions\n        void keepTopPeople(Array<float>& poseKeypoints, const Array<float>& poseScores) const;\n\n        // PersonIdExtractor functions\n        // Not thread-safe\n        Array<long long> extractIds(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                    const unsigned long long imageIndex = 0ull);\n\n        // Same than extractIds but thread-safe\n        Array<long long> extractIdsLockThread(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                              const unsigned long long imageIndex,\n                                              const long long frameId);\n\n        // PersonTracker functions\n        void track(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                   const Matrix& cvMatInput, const unsigned long long imageViewIndex = 0ull);\n\n        void trackLockThread(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                             const Matrix& cvMatInput,\n                             const unsigned long long imageViewIndex,\n                             const long long frameId);\n\n    private:\n        const int mNumberPeopleMax;\n        const int mTracking;\n        const std::shared_ptr<PoseExtractorNet> spPoseExtractorNet;\n        const std::shared_ptr<KeepTopNPeople> spKeepTopNPeople;\n        const std::shared_ptr<PersonIdExtractor> spPersonIdExtractor;\n        const std::shared_ptr<std::vector<std::shared_ptr<PersonTracker>>> spPersonTrackers;\n\n        DELETE_COPY(PoseExtractor);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseExtractorCaffe.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP\n#define OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/net/bodyPartConnectorCaffe.hpp>\n#include <openpose/net/maximumCaffe.hpp>\n#include <openpose/net/netCaffe.hpp>\n#include <openpose/net/netOpenCv.hpp>\n#include <openpose/net/nmsCaffe.hpp>\n#include <openpose/net/resizeAndMergeCaffe.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n\nnamespace op\n{\n    class OP_API PoseExtractorCaffe : public PoseExtractorNet\n    {\n    public:\n        PoseExtractorCaffe(\n            const PoseModel poseModel, const std::string& modelFolder, const int gpuId,\n            const std::vector<HeatMapType>& heatMapTypes = {},\n            const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect,\n            const bool addPartCandidates = false, const bool maximizePositives = false,\n            const std::string& protoTxtPath = \"\", const std::string& caffeModelPath = \"\",\n            const float upsamplingRatio = 0.f, const bool enableNet = true,\n            const bool enableGoogleLogging = true);\n\n        virtual ~PoseExtractorCaffe();\n\n        virtual void netInitializationOnThread();\n\n        /**\n         * @param poseNetOutput If it is not empty, OpenPose will not run its internal body pose estimation network\n         * and will instead use this data as the substitute of its network. The size of this element must match the\n         * size of the output of its internal network, or it will lead to core dumped (segmentation) errors. You can\n         * modify the pose estimation flags to match the dimension of both elements (e.g., `--net_resolution`,\n         * `--scale_number`, etc.).\n         */\n        virtual void forwardPass(\n            const std::vector<Array<float>>& inputNetData, const Point<int>& inputDataSize,\n            const std::vector<double>& scaleInputToNetInputs = {1.f},\n            const Array<float>& poseNetOutput = Array<float>{});\n\n        const float* getCandidatesCpuConstPtr() const;\n\n        const float* getCandidatesGpuConstPtr() const;\n\n        const float* getHeatMapCpuConstPtr() const;\n\n        const float* getHeatMapGpuConstPtr() const;\n\n        std::vector<int> getHeatMapSize() const;\n\n        const float* getPoseGpuConstPtr() const;\n\n    private:\n        // Used when increasing spNets\n        const PoseModel mPoseModel;\n        const int mGpuId;\n        const std::string mModelFolder;\n        const std::string mProtoTxtPath;\n        const std::string mCaffeModelPath;\n        const float mUpsamplingRatio;\n        const bool mEnableNet;\n        const bool mEnableGoogleLogging;\n        // General parameters\n        std::vector<std::shared_ptr<Net>> spNets;\n        std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;\n        std::shared_ptr<NmsCaffe<float>> spNmsCaffe;\n        std::shared_ptr<BodyPartConnectorCaffe<float>> spBodyPartConnectorCaffe;\n        std::shared_ptr<MaximumCaffe<float>> spMaximumCaffe;\n        std::vector<std::vector<int>> mNetInput4DSizes;\n        // Init with thread\n        std::vector<std::shared_ptr<ArrayCpuGpu<float>>> spCaffeNetOutputBlobs;\n        std::shared_ptr<ArrayCpuGpu<float>> spHeatMapsBlob;\n        std::shared_ptr<ArrayCpuGpu<float>> spPeaksBlob;\n        std::shared_ptr<ArrayCpuGpu<float>> spMaximumPeaksBlob;\n\n        DELETE_COPY(PoseExtractorCaffe);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_EXTRACTOR_CAFFE_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP\n#define OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/pose/poseParameters.hpp>\n\nnamespace op\n{\n    class OP_API PoseExtractorNet\n    {\n    public:\n        PoseExtractorNet(const PoseModel poseModel,\n                         const std::vector<HeatMapType>& heatMapTypes = {},\n                         const ScaleMode heatMapScaleMode = ScaleMode::ZeroToOneFixedAspect,\n                         const bool addPartCandidates = false,\n                         const bool maximizePositives = false);\n\n        virtual ~PoseExtractorNet();\n\n        void initializationOnThread();\n\n        virtual void forwardPass(\n            const std::vector<Array<float>>& inputNetData, const Point<int>& inputDataSize,\n            const std::vector<double>& scaleRatios = {1.f}, const Array<float>& poseNetOutput = Array<float>{}) = 0;\n\n        virtual const float* getCandidatesCpuConstPtr() const = 0;\n\n        virtual const float* getCandidatesGpuConstPtr() const = 0;\n\n        virtual const float* getHeatMapCpuConstPtr() const = 0;\n\n        virtual const float* getHeatMapGpuConstPtr() const = 0;\n\n        virtual std::vector<int> getHeatMapSize() const = 0;\n\n        Array<float> getHeatMapsCopy() const;\n\n        std::vector<std::vector<std::array<float,3>>> getCandidatesCopy() const;\n\n        virtual const float* getPoseGpuConstPtr() const = 0;\n\n        Array<float> getPoseKeypoints() const;\n\n        Array<float> getPoseScores() const;\n\n        float getScaleNetToOutput() const;\n\n        double get(const PoseProperty property) const;\n\n        void set(const PoseProperty property, const double value);\n\n        void increase(const PoseProperty property, const double value);\n\n        void clear();\n\n    protected:\n        const PoseModel mPoseModel;\n        Point<int> mNetOutputSize;\n        Array<float> mPoseKeypoints;\n        Array<float> mPoseScores;\n        float mScaleNetToOutput;\n\n        void checkThread() const;\n\n        virtual void netInitializationOnThread() = 0;\n\n    private:\n        const std::vector<HeatMapType> mHeatMapTypes;\n        const ScaleMode mHeatMapScaleMode;\n        const bool mAddPartCandidates;\n        std::array<std::atomic<double>, (int)PoseProperty::Size> mProperties;\n        std::thread::id mThreadId;\n\n        DELETE_COPY(PoseExtractorNet);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_EXTRACTOR_NET_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseGpuRenderer.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_GPU_RENDERER_HPP\n#define OPENPOSE_POSE_POSE_GPU_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/gpuRenderer.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/pose/poseRenderer.hpp>\n\nnamespace op\n{\n    class OP_API PoseGpuRenderer : public GpuRenderer, public PoseRenderer\n    {\n    public:\n        PoseGpuRenderer(\n            const PoseModel poseModel, const std::shared_ptr<PoseExtractorNet>& poseExtractorNet,\n            const float renderThreshold, const bool blendOriginalFrame = true,\n            const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT,\n            const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u);\n\n        virtual ~PoseGpuRenderer();\n\n        void initializationOnThread();\n\n        std::pair<int, std::string> renderPose(Array<float>& outputData, const Array<float>& poseKeypoints,\n                                               const float scaleInputToOutput,\n                                               const float scaleNetToOutput = -1.f);\n\n    private:\n        const std::shared_ptr<PoseExtractorNet> spPoseExtractorNet;\n        // Init with thread\n        float* pGpuPose; // GPU aux memory\n        float* pMaxPtr; // GPU aux memory\n        float* pMinPtr; // GPU aux memory\n        float* pScalePtr; // GPU aux memory\n\n        DELETE_COPY(PoseGpuRenderer);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_GPU_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseParameters.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_PARAMETERS_HPP\n#define OPENPOSE_POSE_POSE_PARAMETERS_HPP\n\n#include <map>\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    // Constant Global Parameters\n    // For OpenCL-NMS in Ubuntu, (POSE_MAX_PEOPLE+1)*3(x,y,score) must be divisible by 32. Easy fix:\n    // POSE_MAX_PEOPLE = 32n - 1\n    // For OpenCL-NMS in Windows, it must be by 64, so 64n - 1\n    const auto POSE_MAX_PEOPLE = 127u;\n\n    // Model functions\n    OP_API const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel);\n    OP_API const std::string& getPoseProtoTxt(const PoseModel poseModel);\n    OP_API const std::string& getPoseTrainedModel(const PoseModel poseModel);\n    OP_API unsigned int getPoseNumberBodyParts(const PoseModel poseModel);\n    OP_API const std::vector<unsigned int>& getPosePartPairs(const PoseModel poseModel);\n    OP_API const std::vector<unsigned int>& getPoseMapIndex(const PoseModel poseModel);\n    OP_API unsigned int getPoseMaxPeaks();\n    OP_API float getPoseNetDecreaseFactor(const PoseModel poseModel);\n    OP_API unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string);\n    OP_API unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings);\n\n    // Default NSM and body connector parameters\n    OP_API float getPoseDefaultNmsThreshold(const PoseModel poseModel, const bool maximizePositives = false);\n    OP_API float getPoseDefaultConnectInterMinAboveThreshold(const bool maximizePositives = false);\n    OP_API float getPoseDefaultConnectInterThreshold(const PoseModel poseModel, const bool maximizePositives = false);\n    OP_API unsigned int getPoseDefaultMinSubsetCnt(const bool maximizePositives = false);\n    OP_API float getPoseDefaultConnectMinSubsetScore(const bool maximizePositives = false);\n    OP_API bool addBkgChannel(const PoseModel poseModel);\n}\n\n#endif // OPENPOSE_POSE_POSE_PARAMETERS_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseParametersRender.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP\n#define OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    // Rendering parameters\n    const auto POSE_DEFAULT_ALPHA_KEYPOINT = 0.6f;\n    const auto POSE_DEFAULT_ALPHA_HEAT_MAP = 0.7f;\n\n    // Model-Dependent Parameters\n    // CUDA-code Model-Dependent Parameters must be defined with #define\n    // BODY_25\n    #define POSE_BODY_25_PAIRS_RENDER_GPU \\\n        1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   14,19,19,20,14,21, 11,22,22,23,11,24\n    #define POSE_BODY_25_SCALES_RENDER_GPU 1\n    #define POSE_BODY_25_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        170.f,   255.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n         85.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f\n    // COCO\n    #define POSE_COCO_PAIRS_RENDER_GPU \\\n        1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   1,8,   8,9,   9,10,  1,11,  11,12, 12,13,  1,0,   0,14, 14,16,  0,15, 15,17\n    #define POSE_COCO_SCALES_RENDER_GPU 1\n    #define POSE_COCO_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        170.f,   255.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n         85.f,     0.f,   255.f\n    // MPI\n    // MPI colors chosen such that they are closed to COCO colors\n    #define POSE_MPI_PAIRS_RENDER_GPU \\\n        0,1,   1,2,   2,3,   3,4,   1,5,   5,6,   6,7,   1,14,  14,8,  8,9,  9,10,  14,11, 11,12, 12,13\n    #define POSE_MPI_SCALES_RENDER_GPU 1\n    #define POSE_MPI_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        170.f,   255.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n         43.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,     0.f,   255.f\n    // BODY_19\n    #define POSE_BODY_19_PAIRS_RENDER_GPU \\\n        1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18\n    #define POSE_BODY_19_SCALES_RENDER_GPU 1\n    #define POSE_BODY_19_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        170.f,   255.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n         85.f,     0.f,   255.f\n    // BODY_23\n    #define POSE_BODY_23_PAIRS_RENDER_GPU \\\n        1,7, 4,10, 0,1,   0,4,   1,2,   2,3,   4,5,   5,6,   7,8,  8,9, 10,11, 11,12,  0,13, 13,15,  0,14, 14,16,   12,17,17,18,12,19, 9,20,20,21,9,22\n    #define POSE_BODY_23_SCALES_RENDER_GPU 1\n    #define POSE_BODY_23_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        170.f,   255.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n         85.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f\n    // BODY_25B\n    #define POSE_BODY_25B_PAIRS_RENDER_GPU \\\n        0,1, 0,2, 1,3, 2,4,   5,7, 6,8,   7,9, 8,10,   5,11, 6,12,   11,13, 12,14,   13,15, 14,16, \\\n        15,19, 19,20, 15,21,   16,22, 22,23, 16,24,   5,17, \\\n        6,17,   17,18,   11,12\n    #define POSE_BODY_25B_SCALES_RENDER_GPU 1\n    #define POSE_BODY_25B_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n         85.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n        170.f,   255.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f\n    // BODY_135\n    // Hand color selection\n    // http://www.perbang.dk/rgbgradient/\n    // 1. Main color\n    //     - Each finger of the right hand: 11 steps from FF0000 to FF0001 and pick last 5 from HSV gradient.\n    //     - Each finger of the left hand: 21 steps from FF0000 to FF0001, choosing 4 among first 6 (HSV grad.),\n    //       and then green.\n    //     Note: Choosing first 5 from 11 steps was giving 2 very close greens\n    // 2. Gradient color from wrist to finger tips\n    //     - Inside each finger: 5 steps from main color to 000000, and selecting first 4 from RGB gradient.\n    //     Note: Used HSV gradient for red finger.\n    const auto H135 = 25;\n    const auto F135 = H135 + 40;\n        // 15,19, 19,20, 15,21,   16,22, 22,23, 16,24,   5,17,\n        // 6,17,   17,18,   11,12,\n    #define POSE_BODY_135_PAIRS_RENDER_GPU \\\n        0,1, 0,2, 1,3, 2,4,   5,7, 6,8,   7,9, 8,10,   5,11, 6,12,   11,13, 12,14,   13,15, 14,16, \\\n        15,19, 19,20, 15,21,   16,22, 22,23, 16,24,   5,6,   17,18,   11,12, \\\n        \\\n        9,H135+0, H135+0,H135+1, H135+1,H135+2, H135+2,H135+3,           9,H135+4, H135+4,H135+5, H135+5,H135+6, H135+6,H135+7, \\\n        9,H135+8, H135+8,H135+9, H135+9,H135+10, H135+10,H135+11,        9,H135+12, H135+12,H135+13, H135+13,H135+14, H135+14,H135+15, \\\n        9,H135+16, H135+16,H135+17, H135+17,H135+18, H135+18,H135+19, \\\n        \\\n        10,H135+20, H135+20,H135+21, H135+21,H135+22, H135+22,H135+23,   10,H135+24, H135+24,H135+25, H135+25,H135+26, H135+26,H135+27, \\\n        10,H135+28, H135+28,H135+29, H135+29,H135+30, H135+30,H135+31,   10,H135+32, H135+32,H135+33, H135+33,H135+34, H135+34,H135+35, \\\n        10,H135+36, H135+36,H135+37, H135+37,H135+38, H135+38,H135+39, \\\n        \\\n        F135+0,F135+1,    F135+1,F135+2,    F135+2,F135+3,    F135+3,F135+4,    F135+4,F135+5,    F135+5,F135+6,    F135+6,F135+7,    F135+7,F135+8,    F135+8,F135+9,    F135+9,F135+10,   F135+10,F135+11,  F135+11,F135+12,  F135+12,F135+13,  F135+13,F135+14,  F135+14,F135+15,  F135+15,F135+16,  F135+17,F135+18,  F135+18,F135+19,  F135+19,F135+20, \\\n        F135+20,F135+21,  F135+22,F135+23,  F135+23,F135+24,  F135+24,F135+25,  F135+25,F135+26,  F135+27,F135+28,  F135+28,F135+29,  F135+29,F135+30,  F135+31,F135+32,  F135+32,F135+33,  F135+33,F135+34,  F135+34,F135+35,  F135+36,F135+37,  F135+37,F135+38,  F135+38,F135+39,  F135+39,F135+40,  F135+40,F135+41, \\\n        F135+41,F135+36,  F135+42,F135+43,  F135+43,F135+44,  F135+44,F135+45,  F135+45,F135+46,  F135+46,F135+47,  F135+47,F135+42,  F135+48,F135+49,  F135+49,F135+50,  F135+50,F135+51,  F135+51,F135+52,  F135+52,F135+53,  F135+53,F135+54,  F135+54,F135+55,  F135+55,F135+56,  F135+56,F135+57,  F135+57,F135+58, \\\n        F135+58,F135+59,  F135+59,F135+48,  F135+60,F135+61,  F135+61,F135+62,  F135+62,F135+63,  F135+63,F135+64,  F135+64,F135+65,  F135+65,F135+66,  F135+66,F135+67,  F135+67,F135+60\n    // Disabled really noisy values\n    #define POSE_BODY_135_SCALES_RENDER_GPU \\\n        1.f,1.f,1.f,1.f,1.f, 1.f,1.f,1.f,1.f,1.f, 1.f,1.f,1.f,1.f,1.f, 1.f,1.f, \\\n        0.00f,0.00f, \\\n        1.f,1.f,1.f,1.f,1.f,1.f, \\\n        0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, \\\n        0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, 0.60f,0.60f,0.60f,0.60f,0.60f, \\\n        0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \\\n        0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \\\n        0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f, \\\n        0.45f,0.45f,0.45f,0.45f,0.45f, 0.45f,0.45f,0.45f,0.45f,0.45f\n        // First 0.45f row:\n        // 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.00f,0.00f,0.00f, 0.00f,0.00f,0.45f,0.45f,0.45f,\n    #define POSE_BODY_135_COLORS_RENDER_GPU \\\n        255.f,     0.f,    85.f, \\\n        170.f,     0.f,   255.f, \\\n        255.f,     0.f,   170.f, \\\n         85.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n        170.f,   255.f,     0.f, \\\n        255.f,    85.f,     0.f, \\\n         85.f,   255.f,     0.f, \\\n        255.f,   170.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n          0.f,   170.f,   255.f, \\\n          0.f,   255.f,    85.f, \\\n          0.f,    85.f,   255.f, \\\n          0.f,   255.f,   170.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n        \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n          0.f,   255.f,   255.f, \\\n        \\\n        255.f,    0.f,    0.f, \\\n        191.f,   47.f,   47.f, \\\n        127.f,   63.f,   63.f, \\\n         63.f,   47.f,   47.f, \\\n        255.f,   76.f,    0.f, \\\n        191.f,   57.f,    0.f, \\\n        127.f,   38.f,    0.f, \\\n         63.f,   19.f,    0.f, \\\n        255.f,  152.f,    0.f, \\\n        191.f,  114.f,    0.f, \\\n        127.f,   76.f,    0.f, \\\n         63.f,   38.f,    0.f, \\\n        255.f,  255.f,    0.f, \\\n        191.f,  191.f,    0.f, \\\n        127.f,  127.f,    0.f, \\\n         63.f,   63.f,    0.f, \\\n          0.f,  255.f,    0.f, \\\n          0.f,  191.f,    0.f, \\\n          0.f,  127.f,    0.f, \\\n          0.f,   63.f,    0.f, \\\n        \\\n        255.f,    0.f,  153.f, \\\n        191.f,    0.f,  114.f, \\\n        127.f,    0.f,   76.f, \\\n         63.f,    0.f,   38.f, \\\n        203.f,    0.f,  255.f, \\\n        152.f,    0.f,  191.f, \\\n        101.f,    0.f,  127.f, \\\n         50.f,    0.f,   63.f, \\\n         50.f,    0.f,  255.f, \\\n         37.f,    0.f,  191.f, \\\n         25.f,    0.f,  127.f, \\\n         12.f,    0.f,   63.f, \\\n          0.f,  102.f,  255.f, \\\n          0.f,   76.f,  191.f, \\\n          0.f,   51.f,  127.f, \\\n          0.f,   25.f,   63.f, \\\n          0.f,  255.f,  255.f, \\\n          0.f,  191.f,  191.f, \\\n          0.f,  127.f,  127.f, \\\n          0.f,   63.f,   63.f, \\\n        \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f, \\\n        255.f,   255.f,   255.f\n\n    // CAR_12\n    #define POSE_CAR_12_PAIRS_RENDER_GPU \\\n        4,5,   4,6,   4,0,   0,2,   4,8,   8,10,   5,7,   5,1,   1,3,  5,9, 9,11,     0,1, 8,9,     2,3, 6,7, 10,11,     6,2,7,3, 6,10,7,11\n        // 4,5,   4,6,   4,0,   0,2,   4,8,   8,10,   5,7,   5,1,   1,3,  5,9, 9,11\n    #define POSE_CAR_12_SCALES_RENDER_GPU 0.5\n    #define POSE_CAR_12_COLORS_RENDER_GPU \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        255.f,   255.f,     0.f, \\\n        \\\n        255.f,     0.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,    75.f,    75.f, \\\n        255.f,    75.f,    75.f, \\\n        \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f, \\\n        255.f,     0.f,   255.f\n\n    // CAR_22\n    #define POSE_CAR_22_PAIRS_RENDER_GPU \\\n            0,1,1,3,3,2,2,0,   6,7,7,16,16,17,17,6,   12,13,13,14,14,15,15,12,   6,8,7,8,6,9,7,9,6,4,7,5,   12,11,13,10, \\\n            16,18,17,18,16,19,17,19,   6,21,7,20\n    #define POSE_CAR_22_SCALES_RENDER_GPU 0.625\n    #define POSE_CAR_22_COLORS_RENDER_GPU \\\n        255.f,   128.f,   128.f, \\\n        255.f,     0.f,     0.f, \\\n         64.f,     0.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n        \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        \\\n          0.f,     0.f,    64.f, \\\n        128.f,   128.f,   255.f, \\\n        \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        \\\n         64.f,     0.f,     0.f, \\\n        255.f,   128.f,   128.f, \\\n        255.f,     0.f,     0.f, \\\n        255.f,     0.f,     0.f, \\\n        \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,   255.f, \\\n        \\\n          0.f,   255.f,     0.f, \\\n          0.f,   255.f,     0.f, \\\n        \\\n          0.f,     0.f,   255.f, \\\n          0.f,     0.f,    64.f\n\n    // Rendering functions\n    OP_API const std::vector<float>& getPoseScales(const PoseModel poseModel);\n    OP_API const std::vector<float>& getPoseColors(const PoseModel poseModel);\n    OP_API const std::vector<unsigned int>& getPoseBodyPartPairsRender(const PoseModel poseModel);\n    OP_API unsigned int getNumberElementsToRender(const PoseModel poseModel);\n}\n\n#endif // OPENPOSE_POSE_POSE_PARAMETERS_RENDER_HPP\n"
  },
  {
    "path": "include/openpose/pose/poseRenderer.hpp",
    "content": "#ifndef OPENPOSE_POSE_POSE_RENDERER_HPP\n#define OPENPOSE_POSE_POSE_RENDERER_HPP\n\n#include <map>\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n\nnamespace op\n{\n    class OP_API PoseRenderer\n    {\n    public:\n        PoseRenderer(const PoseModel poseModel);\n\n        virtual ~PoseRenderer();\n\n        virtual void initializationOnThread(){};\n\n        virtual std::pair<int, std::string> renderPose(\n            Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleInputToOutput,\n            const float scaleNetToOutput = -1.f) = 0;\n\n    protected:\n        const PoseModel mPoseModel;\n        const std::map<unsigned int, std::string> mPartIndexToName;\n\n    private:\n\n        DELETE_COPY(PoseRenderer);\n    };\n}\n\n#endif // OPENPOSE_POSE_POSE_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/pose/renderPose.hpp",
    "content": "#ifndef OPENPOSE_POSE_RENDER_POSE_HPP\n#define OPENPOSE_POSE_RENDER_POSE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n\nnamespace op\n{\n    OP_API void renderPoseKeypointsCpu(\n        Array<float>& frameArray, const Array<float>& poseKeypoints, const PoseModel poseModel,\n        const float renderThreshold, const bool blendOriginalFrame = true);\n\n    void renderPoseKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const PoseModel poseModel,\n        const int numberPeople, const Point<unsigned int>& frameSize, const float* const posePtr,\n        const float renderThreshold, const bool googlyEyes = false, const bool blendOriginalFrame = true,\n        const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT);\n\n    void renderPoseHeatMapGpu(\n        float* frame, const Point<unsigned int>& frameSize, const float* const heatMapPtr, const Point<int>& heatMapSize,\n        const float scaleToKeepRatio, const unsigned int part,\n        const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);\n\n    void renderPoseHeatMapsGpu(\n        float* frame, const PoseModel poseModel, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio,\n        const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);\n\n    void renderPosePAFGpu(\n        float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part,\n        const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);\n\n    void renderPosePAFsGpu(\n        float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio,\n        const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);\n\n    void renderPoseDistanceGpu(\n        float* framePtr, const Point<unsigned int>& frameSize, const float* const heatMapPtr, const Point<int>& heatMapSize,\n        const float scaleToKeepRatio, const unsigned int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP);\n}\n\n#endif // OPENPOSE_POSE_RENDER_POSE_HPP\n"
  },
  {
    "path": "include/openpose/pose/wPoseExtractor.hpp",
    "content": "#ifndef OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP\n#define OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/poseExtractor.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPoseExtractor : public Worker<TDatums>\n    {\n    public:\n        explicit WPoseExtractor(const std::shared_ptr<PoseExtractor>& poseExtractorSharedPtr);\n\n        virtual ~WPoseExtractor();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<PoseExtractor> spPoseExtractor;\n\n        DELETE_COPY(WPoseExtractor);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPoseExtractor<TDatums>::WPoseExtractor(const std::shared_ptr<PoseExtractor>& poseExtractorSharedPtr) :\n        spPoseExtractor{poseExtractorSharedPtr}\n    {\n    }\n\n    template<typename TDatums>\n    WPoseExtractor<TDatums>::~WPoseExtractor()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseExtractor<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spPoseExtractor->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WPoseExtractor<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Extract people pose\n                for (auto i = 0u ; i < tDatums->size() ; i++)\n                // for (auto& tDatum : *tDatums)\n                {\n                    auto& tDatumPtr = (*tDatums)[i];\n                    // OpenPose net forward pass\n                    spPoseExtractor->forwardPass(\n                        tDatumPtr->inputNetData, Point<int>{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()},\n                        tDatumPtr->scaleInputToNetInputs, tDatumPtr->poseNetOutput, tDatumPtr->id);\n                    // OpenPose keypoint detector\n                    tDatumPtr->poseCandidates = spPoseExtractor->getCandidatesCopy();\n                    tDatumPtr->poseHeatMaps = spPoseExtractor->getHeatMapsCopy();\n                    tDatumPtr->poseKeypoints = spPoseExtractor->getPoseKeypoints().clone();\n                    tDatumPtr->poseScores = spPoseExtractor->getPoseScores().clone();\n                    tDatumPtr->scaleNetToOutput = spPoseExtractor->getScaleNetToOutput();\n                    // Keep desired top N people\n                    spPoseExtractor->keepTopPeople(tDatumPtr->poseKeypoints, tDatumPtr->poseScores);\n                    // ID extractor (experimental)\n                    tDatumPtr->poseIds = spPoseExtractor->extractIdsLockThread(\n                        tDatumPtr->poseKeypoints, tDatumPtr->cvInputData, i, tDatumPtr->id);\n                    // Tracking (experimental)\n                    spPoseExtractor->trackLockThread(\n                        tDatumPtr->poseKeypoints, tDatumPtr->poseIds, tDatumPtr->cvInputData, i, tDatumPtr->id);\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPoseExtractor);\n}\n\n#endif // OPENPOSE_POSE_W_POSE_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/pose/wPoseExtractorNet.hpp",
    "content": "#ifndef OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP\n#define OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/poseExtractorNet.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPoseExtractorNet : public Worker<TDatums>\n    {\n    public:\n        explicit WPoseExtractorNet(const std::shared_ptr<PoseExtractorNet>& poseExtractorSharedPtr);\n\n        virtual ~WPoseExtractorNet();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<PoseExtractorNet> spPoseExtractorNet;\n\n        DELETE_COPY(WPoseExtractorNet);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPoseExtractorNet<TDatums>::WPoseExtractorNet(const std::shared_ptr<PoseExtractorNet>& poseExtractorSharedPtr) :\n        spPoseExtractorNet{poseExtractorSharedPtr}\n    {\n    }\n\n    template<typename TDatums>\n    WPoseExtractorNet<TDatums>::~WPoseExtractorNet()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseExtractorNet<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spPoseExtractorNet->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WPoseExtractorNet<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Extract people pose\n                for (auto& tDatumPtr : *tDatums)\n                {\n                    spPoseExtractorNet->forwardPass(\n                        tDatumPtr->inputNetData, Point<int>{tDatumPtr->cvInputData.cols(), tDatumPtr->cvInputData.rows()},\n                        tDatumPtr->scaleInputToNetInputs, tDatumPtr->poseNetOutput);\n                    tDatumPtr->poseCandidates = spPoseExtractorNet->getCandidatesCopy();\n                    tDatumPtr->poseHeatMaps = spPoseExtractorNet->getHeatMapsCopy();\n                    tDatumPtr->poseKeypoints = spPoseExtractorNet->getPoseKeypoints().clone();\n                    tDatumPtr->poseScores = spPoseExtractorNet->getPoseScores().clone();\n                    tDatumPtr->scaleNetToOutput = spPoseExtractorNet->getScaleNetToOutput();\n                }\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPoseExtractorNet);\n}\n\n#endif // OPENPOSE_POSE_W_POSE_EXTRACTOR_NET_HPP\n"
  },
  {
    "path": "include/openpose/pose/wPoseRenderer.hpp",
    "content": "#ifndef OPENPOSE_POSE_W_POSE_RENDERER_HPP\n#define OPENPOSE_POSE_W_POSE_RENDERER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/pose/poseRenderer.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPoseRenderer : public Worker<TDatums>\n    {\n    public:\n        explicit WPoseRenderer(const std::shared_ptr<PoseRenderer>& poseRendererSharedPtr);\n\n        virtual ~WPoseRenderer();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<PoseRenderer> spPoseRenderer;\n\n        DELETE_COPY(WPoseRenderer);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPoseRenderer<TDatums>::WPoseRenderer(const std::shared_ptr<PoseRenderer>& poseRendererSharedPtr) :\n        spPoseRenderer{poseRendererSharedPtr}\n    {\n    }\n\n    template<typename TDatums>\n    WPoseRenderer<TDatums>::~WPoseRenderer()\n    {\n    }\n\n    template<typename TDatums>\n    void WPoseRenderer<TDatums>::initializationOnThread()\n    {\n        try\n        {\n            spPoseRenderer->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WPoseRenderer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Render people pose\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->elementRendered = spPoseRenderer->renderPose(\n                        tDatumPtr->outputData, tDatumPtr->poseKeypoints, (float)tDatumPtr->scaleInputToOutput,\n                        (float)tDatumPtr->scaleNetToOutput);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPoseRenderer);\n}\n\n#endif // OPENPOSE_POSE_W_POSE_RENDERER_HPP\n"
  },
  {
    "path": "include/openpose/producer/datumProducer.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP\n#define OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP\n\n#include <atomic>\n#include <limits> // std::numeric_limits\n#include <openpose/core/common.hpp>\n#include <openpose/core/datum.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/producer/producer.hpp>\n\nnamespace op\n{\n    template<typename TDatum>\n    class DatumProducer\n    {\n    public:\n        explicit DatumProducer(\n            const std::shared_ptr<Producer>& producerSharedPtr,\n            const unsigned long long frameFirst = 0, const unsigned long long frameStep = 1,\n            const unsigned long long frameLast = std::numeric_limits<unsigned long long>::max(),\n            const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr = nullptr);\n\n        virtual ~DatumProducer();\n\n        std::pair<bool, std::shared_ptr<std::vector<std::shared_ptr<TDatum>>>> checkIfRunningAndGetDatum();\n\n    private:\n        const unsigned long long mNumberFramesToProcess;\n        std::shared_ptr<Producer> spProducer;\n        unsigned long long mGlobalCounter;\n        unsigned long long mFrameStep;\n        unsigned int mNumberConsecutiveEmptyFrames;\n        std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>> spVideoSeek;\n\n        void checkIfTooManyConsecutiveEmptyFrames(\n            unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame) const;\n\n        DELETE_COPY(DatumProducer);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/producer/datumProducer.hpp>\n#include <openpose/utilities/openCv.hpp>\nnamespace op\n{\n    // Auxiliary functions for DatumProducer in order to 1) Reduce compiling time and 2) Remove OpenCV deps.\n    OP_API void datumProducerConstructor(\n        const std::shared_ptr<Producer>& producerSharedPtr, const unsigned long long frameFirst,\n        const unsigned long long frameStep, const unsigned long long frameLast);\n    OP_API void datumProducerConstructorTooManyConsecutiveEmptyFrames(\n            unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame);\n    OP_API bool datumProducerConstructorRunningAndGetDatumIsDatumProducerRunning(\n        const std::shared_ptr<Producer>& producerSharedPtr, const unsigned long long numberFramesToProcess,\n        const unsigned long long globalCounter);\n    OP_API void datumProducerConstructorRunningAndGetDatumApplyPlayerControls(\n        const std::shared_ptr<Producer>& producerSharedPtr,\n        const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr);\n    OP_API unsigned long long datumProducerConstructorRunningAndGetNextFrameNumber(\n        const std::shared_ptr<Producer>& producerSharedPtr);\n    OP_API void datumProducerConstructorRunningAndGetDatumFrameIntegrity(Matrix& matrix);\n\n    template<typename TDatum>\n    DatumProducer<TDatum>::DatumProducer(\n        const std::shared_ptr<Producer>& producerSharedPtr,\n        const unsigned long long frameFirst, const unsigned long long frameStep,\n        const unsigned long long frameLast,\n        const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr) :\n        mNumberFramesToProcess{(frameLast != std::numeric_limits<unsigned long long>::max()\n                                ? frameLast - frameFirst : frameLast)},\n        spProducer{producerSharedPtr},\n        mGlobalCounter{0ll},\n        mFrameStep{frameStep},\n        mNumberConsecutiveEmptyFrames{0u},\n        spVideoSeek{videoSeekSharedPtr}\n    {\n        try\n        {\n            datumProducerConstructor(producerSharedPtr, frameFirst, frameStep, frameLast);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum>\n    DatumProducer<TDatum>::~DatumProducer()\n    {\n    }\n\n    template<typename TDatum>\n    std::pair<bool, std::shared_ptr<std::vector<std::shared_ptr<TDatum>>>> DatumProducer<TDatum>::checkIfRunningAndGetDatum()\n    {\n        try\n        {\n            // If producer released -> it sends an empty Matrix + a datumProducerRunning signal\n            const bool datumProducerRunning = datumProducerConstructorRunningAndGetDatumIsDatumProducerRunning(\n                spProducer, mNumberFramesToProcess, mGlobalCounter);\n            // If device is open\n            auto datums = std::make_shared<std::vector<std::shared_ptr<TDatum>>>();\n            if (datumProducerRunning)\n            {\n                // Fast forward/backward - Seek to specific frame index desired\n                datumProducerConstructorRunningAndGetDatumApplyPlayerControls(spProducer, spVideoSeek);\n                // Get Matrix vector\n                std::string nextFrameName = spProducer->getNextFrameName();\n                const unsigned long long nextFrameNumber = datumProducerConstructorRunningAndGetNextFrameNumber(\n                    spProducer);\n                const std::vector<Matrix> matrices = spProducer->getFrames();\n                // Check frames are not empty\n                checkIfTooManyConsecutiveEmptyFrames(\n                    mNumberConsecutiveEmptyFrames, matrices.empty() || matrices[0].empty());\n                if (!matrices.empty())\n                {\n                    // Get camera parameters\n                    const std::vector<Matrix> cameraMatrices = spProducer->getCameraMatrices();\n                    const std::vector<Matrix> cameraExtrinsics = spProducer->getCameraExtrinsics();\n                    const std::vector<Matrix> cameraIntrinsics = spProducer->getCameraIntrinsics();\n                    // Resize datum\n                    datums->resize(matrices.size());\n                    // Datum cannot be assigned before resize()\n                    auto& datumPtr = (*datums)[0];\n                    datumPtr = std::make_shared<TDatum>();\n                    // Filling first element\n                    std::swap(datumPtr->name, nextFrameName);\n                    datumPtr->frameNumber = nextFrameNumber;\n                    datumPtr->cvInputData = matrices[0];\n                    datumProducerConstructorRunningAndGetDatumFrameIntegrity(datumPtr->cvInputData);\n                    if (!cameraMatrices.empty())\n                    {\n                        datumPtr->cameraMatrix = cameraMatrices[0];\n                        datumPtr->cameraExtrinsics = cameraExtrinsics[0];\n                        datumPtr->cameraIntrinsics = cameraIntrinsics[0];\n                    }\n                    // Initially, cvOutputData = cvInputData. No performance hit (both cv::Mat share raw memory)\n                    datumPtr->cvOutputData = datumPtr->cvInputData;\n                    // Resize if it's stereo-system\n                    if (datums->size() > 1)\n                    {\n                        // Stereo-system: Assign all Matrices\n                        for (auto i = 1u ; i < datums->size() ; i++)\n                        {\n                            auto& datumIPtr = (*datums)[i];\n                            datumIPtr = std::make_shared<TDatum>();\n                            datumIPtr->name = datumPtr->name;\n                            datumIPtr->frameNumber = datumPtr->frameNumber;\n                            datumIPtr->cvInputData = matrices[i];\n                            datumProducerConstructorRunningAndGetDatumFrameIntegrity(datumPtr->cvInputData);\n                            datumIPtr->cvOutputData = datumIPtr->cvInputData;\n                            if (cameraMatrices.size() > i)\n                            {\n                                datumIPtr->cameraMatrix = cameraMatrices[i];\n                                datumIPtr->cameraExtrinsics = cameraExtrinsics[i];\n                                datumIPtr->cameraIntrinsics = cameraIntrinsics[i];\n                            }\n                        }\n                    }\n                    // Check producer is running\n                    if ((*datums)[0]->cvInputData.empty())\n                        datums = nullptr;\n                    // Increase counter if successful image\n                    if (datums != nullptr)\n                        mGlobalCounter += mFrameStep;\n                }\n            }\n            // Return result\n            return std::make_pair(datumProducerRunning, datums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(false, std::make_shared<std::vector<std::shared_ptr<TDatum>>>());\n        }\n    }\n\n    template<typename TDatum>\n    void DatumProducer<TDatum>::checkIfTooManyConsecutiveEmptyFrames(\n        unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame) const\n    {\n        datumProducerConstructorTooManyConsecutiveEmptyFrames(\n            numberConsecutiveEmptyFrames, emptyFrame);\n    }\n\n    extern template class DatumProducer<BASE_DATUM>;\n}\n\n\n#endif // OPENPOSE_PRODUCER_DATUM_PRODUCER_HPP\n"
  },
  {
    "path": "include/openpose/producer/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_ENUM_CLASSES_HPP\n#define OPENPOSE_PRODUCER_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class ProducerFpsMode : bool\n    {\n        /** The frames will be extracted at the original source fps (frames might be skipped or repeated). */\n        OriginalFps,\n        /** The frames will be extracted when the software retrieves them (frames will not be skipped or repeated). */\n        RetrievalFps,\n    };\n\n    enum class ProducerProperty : unsigned char\n    {\n        AutoRepeat = 0,\n        Flip,\n        Rotation,\n        FrameStep,\n        NumberViews,\n        Size,\n    };\n\n    /**\n     * Type of producers\n     * An enum class in which all the possible type of Producer are included. In order to add a new Producer,\n     * include its name in this enum and add a new 'else if' statement inside ProducerFactory::createProducer().\n     */\n    enum class ProducerType : unsigned char\n    {\n        /** Stereo FLIR (Point-Grey) camera reader. Based on Spinnaker SDK. */\n        FlirCamera,\n        /** An image directory reader. It is able to read images on a folder with a interface similar to the OpenCV\n         * cv::VideoCapture.\n         */\n        ImageDirectory,\n        /** An IP camera frames extractor, extending the functionality of cv::VideoCapture. */\n        IPCamera,\n        /** A video frames extractor, extending the functionality of cv::VideoCapture. */\n        Video,\n        /** A webcam frames extractor, extending the functionality of cv::VideoCapture. */\n        Webcam,\n        /** No type defined. Default state when no specific Producer has been picked yet. */\n        None,\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/producer/flirReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_FLIR_READER_HPP\n#define OPENPOSE_PRODUCER_FLIR_READER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/producer/producer.hpp>\n#include <openpose/producer/spinnakerWrapper.hpp>\n\nnamespace op\n{\n    /**\n     * FlirReader is an abstract class to extract frames from a FLIR stereo-camera system. Its interface imitates the\n     * cv::VideoCapture class, so it can be used quite similarly to the cv::VideoCapture class. Thus,\n     * it is quite similar to VideoReader and WebcamReader.\n     */\n    class OP_API FlirReader : public Producer\n    {\n    public:\n        /**\n         * Constructor of FlirReader. It opens all the available FLIR cameras\n         */\n        explicit FlirReader(const std::string& cameraParametersPath, const Point<int>& cameraResolution,\n                            const bool undistortImage = true, const int cameraIndex = -1);\n\n        virtual ~FlirReader();\n\n        std::vector<Matrix> getCameraMatrices();\n\n        std::vector<Matrix> getCameraExtrinsics();\n\n        std::vector<Matrix> getCameraIntrinsics();\n\n        std::string getNextFrameName();\n\n        bool isOpened() const;\n\n        void release();\n\n        double get(const int capProperty);\n\n        void set(const int capProperty, const double value);\n\n    private:\n        SpinnakerWrapper mSpinnakerWrapper;\n        Point<int> mResolution;\n        unsigned long long mFrameNameCounter;\n\n        Matrix getRawFrame();\n\n        std::vector<Matrix> getRawFrames();\n\n        DELETE_COPY(FlirReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_FLIR_READER_HPP\n"
  },
  {
    "path": "include/openpose/producer/headers.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_HEADERS_HPP\n#define OPENPOSE_PRODUCER_HEADERS_HPP\n\n// producer module\n#include <openpose/producer/datumProducer.hpp>\n#include <openpose/producer/enumClasses.hpp>\n#include <openpose/producer/flirReader.hpp>\n#include <openpose/producer/imageDirectoryReader.hpp>\n#include <openpose/producer/ipCameraReader.hpp>\n#include <openpose/producer/producer.hpp>\n#include <openpose/producer/spinnakerWrapper.hpp>\n#include <openpose/producer/videoCaptureReader.hpp>\n#include <openpose/producer/videoReader.hpp>\n#include <openpose/producer/webcamReader.hpp>\n#include <openpose/producer/wDatumProducer.hpp>\n\n#endif // OPENPOSE_PRODUCER_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/producer/imageDirectoryReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP\n#define OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/producer/producer.hpp>\n\nnamespace op\n{\n    /**\n     * ImageDirectoryReader is an abstract class to extract frames from a image directory. Its interface imitates the\n     * cv::VideoCapture class, so it can be used quite similarly to the cv::VideoCapture class. Thus,\n     * it is quite similar to VideoReader and WebcamReader.\n     */\n    class OP_API ImageDirectoryReader : public Producer\n    {\n    public:\n        /**\n         * Constructor of ImageDirectoryReader. It sets the image directory path from which the images will be loaded\n         * and generates a std::vector<std::string> with the list of images on that directory.\n         * @param imageDirectoryPath const std::string parameter with the folder path containing the images.\n         * @param cameraParameterPath const std::string parameter with the folder path containing the camera\n         * parameters (only required if imageDirectorystereo > 1).\n         * @param numberViews const int parameter with the number of images per iteration (>1 would represent\n         * stereo processing).\n         */\n        explicit ImageDirectoryReader(\n            const std::string& imageDirectoryPath, const std::string& cameraParameterPath = \"\",\n            const bool undistortImage = false, const int numberViews = -1);\n\n        virtual ~ImageDirectoryReader();\n\n        std::string getNextFrameName();\n\n        inline bool isOpened() const\n        {\n            return (mFrameNameCounter >= 0);\n        }\n\n        inline void release()\n        {\n            mFrameNameCounter = {-1ll};\n        }\n\n        double get(const int capProperty);\n\n        void set(const int capProperty, const double value);\n\n    private:\n        const std::string mImageDirectoryPath;\n        const std::vector<std::string> mFilePaths;\n        Point<int> mResolution;\n        long long mFrameNameCounter;\n\n        Matrix getRawFrame();\n\n        std::vector<Matrix> getRawFrames();\n\n        DELETE_COPY(ImageDirectoryReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_IMAGE_DIRECTORY_READER_HPP\n"
  },
  {
    "path": "include/openpose/producer/ipCameraReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP\n#define OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/producer/videoCaptureReader.hpp>\n\nnamespace op\n{\n    /**\n     * IpCameraReader is a wrapper of the cv::VideoCapture class for IP camera streaming.\n     */\n    class OP_API IpCameraReader : public VideoCaptureReader\n    {\n    public:\n        /**\n         * Constructor of IpCameraReader. It opens the IP camera as a wrapper of cv::VideoCapture.\n         * @param cameraPath const std::string parameter with the full camera IP link.\n         */\n        explicit IpCameraReader(const std::string& cameraPath, const std::string& cameraParameterPath = \"\",\n                                const bool undistortImage = false);\n\n        virtual ~IpCameraReader();\n\n        std::string getNextFrameName();\n\n        inline bool isOpened() const\n        {\n            return VideoCaptureReader::isOpened();\n        }\n\n        inline double get(const int capProperty)\n        {\n            return VideoCaptureReader::get(capProperty);\n        }\n\n        inline void set(const int capProperty, const double value)\n        {\n            VideoCaptureReader::set(capProperty, value);\n        }\n\n    private:\n        const std::string mPathName;\n\n        Matrix getRawFrame();\n\n        std::vector<Matrix> getRawFrames();\n\n        DELETE_COPY(IpCameraReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_IP_CAMERA_READER_HPP\n"
  },
  {
    "path": "include/openpose/producer/producer.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_PRODUCER_HPP\n#define OPENPOSE_PRODUCER_PRODUCER_HPP\n\n#include <openpose/3d/cameraParameterReader.hpp>\n#include <openpose/core/common.hpp>\n#include <openpose/producer/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * Producer is an abstract class to extract frames from a source (image directory, video file,\n     * webcam stream, etc.). It has the basic and common functions (e.g., getFrame, release & isOpened).\n     */\n    class OP_API Producer\n    {\n    public:\n        /**\n         * Constructor of Producer.\n         */\n        explicit Producer(const ProducerType type, const std::string& cameraParameterPath, const bool undistortImage,\n                          const int mNumberViews);\n\n        /**\n         * Destructor of Producer. It is virtual so that any children class can implement\n         * its own destructor.\n         */\n        virtual ~Producer();\n\n        /**\n         * Main function of Producer, it retrieves and returns a new frame from the frames producer.\n         * @return Mat with the new frame.\n         */\n        Matrix getFrame();\n\n        /**\n         * Analogous to getFrame, but it could return > 1 frame.\n         * @return std::vector<Mat> with the new frame(s).\n         */\n        std::vector<Matrix> getFrames();\n\n        /**\n         * It retrieves and returns the camera matrixes from the frames producer.\n         * Virtual class because FlirReader implements their own.\n         * @return std::vector<Mat> with the camera matrices.\n         */\n        virtual std::vector<Matrix> getCameraMatrices();\n\n        /**\n         * It retrieves and returns the camera extrinsic parameters from the frames producer.\n         * Virtual class because FlirReader implements their own.\n         * @return std::vector<Mat> with the camera extrinsic parameters.\n         */\n        virtual std::vector<Matrix> getCameraExtrinsics();\n\n        /**\n         * It retrieves and returns the camera intrinsic parameters from the frames producer.\n         * Virtual class because FlirReader implements their own.\n         * @return std::vector<Mat> with the camera intrinsic parameters.\n         */\n        virtual std::vector<Matrix> getCameraIntrinsics();\n\n        /**\n         * This function returns a unique frame name (e.g., the frame number for video, the\n         * frame counter for webcam, the image name for image directory reader, etc.).\n         * @return std::string with an unique frame name.\n         */\n        virtual std::string getNextFrameName() = 0;\n\n        /**\n         * This function sets whether the producer must keep the original fps frame rate or extract the frames as quick\n         * as possible.\n         * @param fpsMode ProducerFpsMode parameter specifying the new value.\n         */\n        void setProducerFpsMode(const ProducerFpsMode fpsMode);\n\n        /**\n         * This function returns the type of producer (video, webcam, ...).\n         * @return ProducerType with the kind of producer.\n         */\n        inline ProducerType getType()\n        {\n            return mType;\n        }\n\n        /**\n         * This function returns whether the Producer instance is still opened and able\n         * to retrieve more frames.\n         * @return bool indicating whether the Producer is opened.\n         */\n        virtual bool isOpened() const = 0;\n\n        /**\n         * This function releases and closes the Producer. After it is called, no more frames\n         * can be retrieved from Producer::getFrames.\n         */\n        virtual void release() = 0;\n\n        /**\n         * This function is a wrapper of cv::VideoCapture::get. It allows getting different properties\n         * of the Producer (fps, width, height, etc.). See the OpenCV documentation for all the\n         * available properties.\n         * @param capProperty int indicating the property to be modified.\n         * @return double returning the property value.\n         */\n        virtual double get(const int capProperty) = 0;\n\n        /**\n         * This function is a wrapper of cv::VideoCapture::set. It allows setting different properties\n         * of the Producer (fps, width, height, etc.). See the OpenCV documentation for all the\n         * available properties.\n         * @param capProperty int indicating the property to be modified.\n         * @param value double indicating the new value to be assigned.\n         */\n        virtual void set(const int capProperty, const double value) = 0;\n\n        /**\n         * Extra attributes that VideoCapture::get/set do not contain.\n         * @param property ProducerProperty indicating the property to be modified.\n         */\n        double get(const ProducerProperty property);\n\n        /**\n         * Extra attributes that VideoCapture::get/set do not contain.\n         * @param property ProducerProperty indicating the property to be modified.\n         * @param value double indicating the new value to be assigned.\n         */\n        void set(const ProducerProperty property, const double value);\n\n    protected:\n        /**\n         * Protected function which checks that the frames keeps their integry (some OpenCV versions\n         * might return corrupted frames within a video or webcam with a size different to the\n         * standard resolution). If the frame is corrupted, it is set to an empty Mat.\n         * @param frame Mat with the frame matrix to be checked and modified.\n         */\n        void checkFrameIntegrity(Matrix& frame);\n\n        /**\n         * Protected function which checks that the frame producer has ended. If so, if resets\n         * or releases the producer according to mRepeatWhenFinished.\n         */\n        void ifEndedResetOrRelease();\n\n        /**\n         * Protected function which forces the producer to get frames at the rate of get(CV_CAP_PROP_FPS).\n         */\n        void keepDesiredFrameRate();\n\n        /**\n         * Function to be defined by its children class. It retrieves and returns a new frame from the frames producer.\n         * @return Mat with the new frame.\n         */\n        virtual Matrix getRawFrame() = 0;\n\n        /**\n         * Function to be defined by its children class. It retrieves and returns a new frame from the frames producer.\n         * It is equivalent to getRawFrame when more than 1 image can be returned.\n         * @return std::vector<Mat> with the new frames.\n         */\n        virtual std::vector<Matrix> getRawFrames() = 0;\n\n    private:\n        const ProducerType mType;\n        ProducerFpsMode mProducerFpsMode;\n        std::array<double, (int)ProducerProperty::Size> mProperties;\n        unsigned int mNumberEmptyFrames;\n        // For ProducerFpsMode::OriginalFps\n        bool mTrackingFps;\n        unsigned long long mFirstFrameTrackingFps;\n        unsigned long long mNumberFramesTrackingFps;\n        unsigned int mNumberSetPositionTrackingFps;\n        std::chrono::high_resolution_clock::time_point mClockTrackingFps;\n        // Camera parameters\n        CameraParameterReader mCameraParameterReader;\n\n        DELETE_COPY(Producer);\n    };\n\n    /**\n     * This function returns the desired producer given the input parameters.\n     */\n    OP_API std::shared_ptr<Producer> createProducer(\n        const ProducerType producerType = ProducerType::None, const std::string& producerString = \"\",\n        const Point<int>& cameraResolution = Point<int>{-1,-1},\n        const std::string& cameraParameterPath = \"models/cameraParameters/\", const bool undistortImage = true,\n        const int numberViews = -1);\n}\n\n#endif // OPENPOSE_PRODUCER_PRODUCER_HPP\n"
  },
  {
    "path": "include/openpose/producer/spinnakerWrapper.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP\n#define OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    /**\n     * SpinnakerWrapper is a subclass of SpinnakerWrapper. It decouples the final interface (meant to imitates\n     * cv::VideoCapture) from the Spinnaker SDK wrapper.\n     */\n    class OP_API SpinnakerWrapper\n    {\n    public:\n        /**\n         * Constructor of SpinnakerWrapper. It opens all the available FLIR cameras\n         * cameraIndex = -1 means that all cameras are taken\n         */\n        explicit SpinnakerWrapper(const std::string& cameraParameterPath, const Point<int>& cameraResolution,\n                                  const bool undistortImage, const int cameraIndex = -1);\n\n        virtual ~SpinnakerWrapper();\n\n        std::vector<Matrix> getRawFrames();\n\n        /**\n         * Note: The camera parameters are only read if undistortImage is true. This should be changed to add a\n         * new bool flag in the constructor, e.g., readCameraParameters\n         */\n        std::vector<Matrix> getCameraMatrices() const;\n\n        std::vector<Matrix> getCameraExtrinsics() const;\n\n        std::vector<Matrix> getCameraIntrinsics() const;\n\n        Point<int> getResolution() const;\n\n        bool isOpened() const;\n\n        void release();\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplSpinnakerWrapper;\n        std::shared_ptr<ImplSpinnakerWrapper> upImpl;\n\n        DELETE_COPY(SpinnakerWrapper);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_SPINNAKER_WRAPPER_HPP\n"
  },
  {
    "path": "include/openpose/producer/videoCaptureReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP\n#define OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/producer/producer.hpp>\n\nnamespace op\n{\n    /**\n     *  VideoCaptureReader is an abstract class to extract frames from a cv::VideoCapture source (video file,\n     * webcam stream, etc.). It has the basic and common functions of the cv::VideoCapture class (e.g., get, set, etc.).\n     */\n    class OP_API VideoCaptureReader : public Producer\n    {\n    public:\n        /**\n         * This constructor of VideoCaptureReader wraps cv::VideoCapture(const int).\n         * @param index const int indicating the cv::VideoCapture constructor int argument, in the range [0, 9].\n         */\n        explicit VideoCaptureReader(const int index, const bool throwExceptionIfNoOpened,\n                                    const std::string& cameraParameterPath, const bool undistortImage,\n                                    const int numberViews);\n\n        /**\n         * This constructor of VideoCaptureReader wraps cv::VideoCapture(const std::string).\n         * @param path const std::string indicating the cv::VideoCapture constructor string argument.\n         * @param producerType const std::string indicating whether the frame source is an IP camera or video.\n         */\n        explicit VideoCaptureReader(const std::string& path, const ProducerType producerType,\n                                    const std::string& cameraParameterPath, const bool undistortImage,\n                                    const int numberViews);\n\n        /**\n         * Destructor of VideoCaptureReader. It releases the cv::VideoCapture member. It is virtual so that\n         * any children class can implement its own destructor.\n         */\n        virtual ~VideoCaptureReader();\n\n        virtual std::string getNextFrameName() = 0;\n\n        virtual bool isOpened() const;\n\n        void release();\n\n        virtual double get(const int capProperty) = 0;\n\n        virtual void set(const int capProperty, const double value) = 0;\n\n    protected:\n        virtual Matrix getRawFrame() = 0;\n\n        virtual std::vector<Matrix> getRawFrames() = 0;\n\n        void resetWebcam(const int index, const bool throwExceptionIfNoOpened);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplVideoCaptureReader;\n        std::unique_ptr<ImplVideoCaptureReader> upImpl;\n\n        DELETE_COPY(VideoCaptureReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_VIDEO_CAPTURE_READER_HPP\n"
  },
  {
    "path": "include/openpose/producer/videoReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_VIDEO_READER_HPP\n#define OPENPOSE_PRODUCER_VIDEO_READER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/producer/videoCaptureReader.hpp>\n\nnamespace op\n{\n    /**\n     * VideoReader is a wrapper of the cv::VideoCapture class for video. It allows controlling a video (e.g., extracting\n     * frames, setting resolution & fps, etc).\n     */\n    class OP_API VideoReader : public VideoCaptureReader\n    {\n    public:\n        /**\n         * Constructor of VideoReader. It opens the video as a wrapper of cv::VideoCapture. It includes a flag to\n         * indicate whether the video should be repeated once it is completely read.\n         * @param videoPath const std::string parameter with the full video path location.\n         * @param cameraParameterPath const std::string parameter with the folder path containing the camera\n         * parameters (only required if imageDirectorystereo > 1).\n         * @param numberViews const int parameter with the number of images per iteration (>1 would represent\n         * stereo processing).\n         */\n        explicit VideoReader(\n            const std::string& videoPath, const std::string& cameraParameterPath = \"\",\n            const bool undistortImage = false, const int numberViews = -1);\n\n        virtual ~VideoReader();\n\n        std::string getNextFrameName();\n\n        inline bool isOpened() const\n        {\n            return VideoCaptureReader::isOpened();\n        }\n\n        double get(const int capProperty);\n\n        void set(const int capProperty, const double value);\n\n    private:\n        const std::string mPathName;\n\n        Matrix getRawFrame();\n\n        std::vector<Matrix> getRawFrames();\n\n        DELETE_COPY(VideoReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_VIDEO_READER_HPP\n"
  },
  {
    "path": "include/openpose/producer/wDatumProducer.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP\n#define OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP\n\n#include <limits> // std::numeric_limits\n#include <queue> // std::queue\n#include <openpose/core/common.hpp>\n#include <openpose/producer/datumProducer.hpp>\n#include <openpose/thread/workerProducer.hpp>\n\nnamespace op\n{\n    template<typename TDatum>\n    class WDatumProducer : public WorkerProducer<std::shared_ptr<std::vector<std::shared_ptr<TDatum>>>>\n    {\n    public:\n        explicit WDatumProducer(const std::shared_ptr<DatumProducer<TDatum>>& datumProducer);\n\n        virtual ~WDatumProducer();\n\n        void initializationOnThread();\n\n        std::shared_ptr<std::vector<std::shared_ptr<TDatum>>> workProducer();\n\n    private:\n        std::shared_ptr<DatumProducer<TDatum>> spDatumProducer;\n        std::queue<std::shared_ptr<std::vector<std::shared_ptr<TDatum>>>> mQueuedElements;\n\n        DELETE_COPY(WDatumProducer);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/core/datum.hpp>\nnamespace op\n{\n    template<typename TDatum>\n    WDatumProducer<TDatum>::WDatumProducer(\n        const std::shared_ptr<DatumProducer<TDatum>>& datumProducer) :\n        spDatumProducer{datumProducer}\n    {\n    }\n\n    template<typename TDatum>\n    WDatumProducer<TDatum>::~WDatumProducer()\n    {\n    }\n\n\n    template<typename TDatum>\n    void WDatumProducer<TDatum>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatum>\n    std::shared_ptr<std::vector<std::shared_ptr<TDatum>>> WDatumProducer<TDatum>::workProducer()\n    {\n        try\n        {\n            // Debugging log\n            opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Profiling speed\n            const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n            // Create and fill final shared pointer\n            std::shared_ptr<std::vector<std::shared_ptr<TDatum>>> tDatums;\n            // Producer\n            if (mQueuedElements.empty())\n            {\n                bool isRunning;\n                std::tie(isRunning, tDatums) = spDatumProducer->checkIfRunningAndGetDatum();\n                // Stop Worker if producer finished\n                if (!isRunning)\n                    this->stop();\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Equivalent to WQueueSplitter\n            // Queued elements - Multiple views --> Split views into different shared pointers\n            if (tDatums != nullptr && tDatums->size() > 1)\n            {\n                // Add tDatums to mQueuedElements\n                for (auto i = 0u ; i < tDatums->size() ; i++)\n                {\n                    auto& tDatumPtr = (*tDatums)[i];\n                    tDatumPtr->subId = i;\n                    tDatumPtr->subIdMax = tDatums->size()-1;\n                    mQueuedElements.emplace(\n                        std::make_shared<std::vector<std::shared_ptr<TDatum>>>(\n                            std::vector<std::shared_ptr<TDatum>>{tDatumPtr}));\n                }\n            }\n            // Queued elements - Multiple views --> Return oldest view\n            if (!mQueuedElements.empty())\n            {\n                tDatums = mQueuedElements.front();\n                mQueuedElements.pop();\n            }\n            // Return result\n            return tDatums;\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    extern template class WDatumProducer<BASE_DATUM>;\n}\n\n#endif // OPENPOSE_PRODUCER_W_DATUM_PRODUCER_HPP\n"
  },
  {
    "path": "include/openpose/producer/webcamReader.hpp",
    "content": "#ifndef OPENPOSE_PRODUCER_WEBCAM_READER_HPP\n#define OPENPOSE_PRODUCER_WEBCAM_READER_HPP\n\n#include <atomic>\n#include <mutex>\n#include <openpose/core/common.hpp>\n#include <openpose/producer/videoCaptureReader.hpp>\n\nnamespace op\n{\n    /**\n     *  WebcamReader is a wrapper of the cv::VideoCapture class for webcam. It allows controlling a video (extracting\n     * frames, setting resolution & fps, seeking to a particular frame, etc).\n     */\n    class OP_API WebcamReader : public VideoCaptureReader\n    {\n    public:\n        /**\n         * Constructor of WebcamReader. It opens the webcam as a wrapper of cv::VideoCapture. It includes an argument\n         * to indicate the desired resolution.\n         * @param webcamIndex const int indicating the camera source (see the OpenCV documentation about\n         * cv::VideoCapture for more details), in the range [0, 9].\n         * @param webcamResolution const Point<int> parameter which specifies the desired camera resolution.\n         * @param throwExceptionIfNoOpened Bool parameter which specifies whether to throw an exception if the camera\n         * cannot be opened.\n         */\n        explicit WebcamReader(const int webcamIndex = 0, const Point<int>& webcamResolution = Point<int>{},\n                              const bool throwExceptionIfNoOpened = true, const std::string& cameraParameterPath = \"\",\n                              const bool undistortImage = false);\n\n        virtual ~WebcamReader();\n\n        std::string getNextFrameName();\n\n        bool isOpened() const;\n\n        double get(const int capProperty);\n\n        void set(const int capProperty, const double value);\n\n    private:\n        const int mIndex;\n        const bool mWebcamStarted;\n        long long mFrameNameCounter;\n        bool mThreadOpened;\n        Matrix mBuffer;\n        std::mutex mBufferMutex;\n        std::atomic<bool> mCloseThread;\n        std::thread mThread;\n        // Detect camera unplugged\n        double mLastNorm;\n        std::atomic<int> mDisconnectedCounter;\n        Point<int> mResolution;\n\n        Matrix getRawFrame();\n\n        std::vector<Matrix> getRawFrames();\n\n        void bufferingThread();\n\n        bool reset();\n\n        DELETE_COPY(WebcamReader);\n    };\n}\n\n#endif // OPENPOSE_PRODUCER_WEBCAM_READER_HPP\n"
  },
  {
    "path": "include/openpose/thread/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_THREAD_ENUM_CLASSES_HPP\n#define OPENPOSE_THREAD_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    /**\n     * ThreadManager synchronization mode.\n     */\n    enum class ThreadManagerMode : unsigned char\n    {\n        /**\n         * First and last queues of ThreadManager will be given to the user, so he must push elements to the first queue and retrieve\n         * them from the last one after being processed.\n         * Recommended for prototyping environments (easier to test but more error-prone and potentially slower in performance).\n         */\n        Asynchronous,\n        AsynchronousIn,     /**< Similar to Asynchronous, but only the input (first) queue is given to the user. */\n        AsynchronousOut,    /**< Similar to Asynchronous, but only the output (last) queue is given to the user. */\n        /**\n         * Everything will run inside the ThreadManager.\n         * Recommended for production environments (more difficult to set up but faster in performance and less error-prone).\n         */\n        Synchronous,\n    };\n}\n\n#endif // OPENPOSE_THREAD_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/thread/headers.hpp",
    "content": "#ifndef OPENPOSE_THREAD_HEADERS_HPP\n#define OPENPOSE_THREAD_HEADERS_HPP\n\n// thread module\n#include <openpose/thread/enumClasses.hpp>\n#include <openpose/thread/priorityQueue.hpp>\n#include <openpose/thread/queue.hpp>\n#include <openpose/thread/queueBase.hpp>\n#include <openpose/thread/subThread.hpp>\n#include <openpose/thread/subThreadNoQueue.hpp>\n#include <openpose/thread/subThreadQueueIn.hpp>\n#include <openpose/thread/subThreadQueueInOut.hpp>\n#include <openpose/thread/subThreadQueueOut.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/threadManager.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/thread/workerProducer.hpp>\n#include <openpose/thread/workerConsumer.hpp>\n#include <openpose/thread/wFpsMax.hpp>\n#include <openpose/thread/wIdGenerator.hpp>\n#include <openpose/thread/wQueueAssembler.hpp>\n#include <openpose/thread/wQueueOrderer.hpp>\n\n#endif // OPENPOSE_THREAD_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/thread/priorityQueue.hpp",
    "content": "#ifndef OPENPOSE_THREAD_PRIORITY_QUEUE_HPP\n#define OPENPOSE_THREAD_PRIORITY_QUEUE_HPP\n\n#include <queue> // std::priority_queue\n#include <openpose/core/common.hpp>\n#include <openpose/thread/queueBase.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TQueue = std::priority_queue<TDatums, std::vector<TDatums>, std::greater<TDatums>>>\n    class PriorityQueue : public QueueBase<TDatums, TQueue>\n    {\n    public:\n        explicit PriorityQueue(const long long maxSize = 256);\n\n        virtual ~PriorityQueue();\n\n        TDatums front() const;\n\n    private:\n        bool pop(TDatums& tDatums);\n\n        DELETE_COPY(PriorityQueue);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <type_traits> // std::is_same\nnamespace op\n{\n    template<typename TDatums, typename TQueue>\n    PriorityQueue<TDatums, TQueue>::PriorityQueue(const long long maxSize) :\n        QueueBase<TDatums, TQueue>{maxSize}\n    {\n        // Check TDatums = underlying value type of TQueue\n        typedef typename TQueue::value_type underlyingValueType;\n        static_assert(std::is_same<TDatums, underlyingValueType>::value,\n                      \"Error: The type of the queue must be the same as the type of the container\");\n    }\n\n    template<typename TDatums, typename TQueue>\n    PriorityQueue<TDatums, TQueue>::~PriorityQueue()\n    {\n    }\n\n    template<typename TDatums, typename TQueue>\n    TDatums PriorityQueue<TDatums, TQueue>::front() const\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{this->mMutex};\n            return this->mTQueue.top();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return TDatums{};\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool PriorityQueue<TDatums, TQueue>::pop(TDatums& tDatums)\n    {\n        try\n        {\n            if (this->mPopIsStopped || this->mTQueue.empty())\n                return false;\n\n            tDatums = {std::move(this->mTQueue.top())};\n            this->mTQueue.pop();\n            this->mConditionVariable.notify_one();\n            return true;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(PriorityQueue);\n}\n\n#endif // OPENPOSE_THREAD_PRIORITY_QUEUE_HPP\n"
  },
  {
    "path": "include/openpose/thread/queue.hpp",
    "content": "#ifndef OPENPOSE_THREAD_QUEUE_HPP\n#define OPENPOSE_THREAD_QUEUE_HPP\n\n#include <queue> // std::queue\n#include <openpose/core/common.hpp>\n#include <openpose/thread/queueBase.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TQueue = std::queue<TDatums>>\n    class Queue : public QueueBase<TDatums, TQueue>\n    {\n    public:\n        explicit Queue(const long long maxSize);\n\n        virtual ~Queue();\n\n        TDatums front() const;\n\n    private:\n        bool pop(TDatums& tDatums);\n\n        DELETE_COPY(Queue);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <type_traits> // std::is_same\nnamespace op\n{\n    template<typename TDatums, typename TQueue>\n    Queue<TDatums, TQueue>::Queue(const long long maxSize) :\n        QueueBase<TDatums, TQueue>{maxSize}\n    {\n        // Check TDatums = underlying value type of TQueue\n        typedef typename TQueue::value_type underlyingValueType;\n        static_assert(std::is_same<TDatums, underlyingValueType>::value,\n                      \"Error: The type of the queue must be the same as the type of the container\");\n    }\n\n    template<typename TDatums, typename TQueue>\n    Queue<TDatums, TQueue>::~Queue()\n    {\n    }\n\n    template<typename TDatums, typename TQueue>\n    TDatums Queue<TDatums, TQueue>::front() const\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{this->mMutex};\n            return this->mTQueue.front();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return TDatums{};\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool Queue<TDatums, TQueue>::pop(TDatums& tDatums)\n    {\n        try\n        {\n            if (this->mPopIsStopped || this->mTQueue.empty())\n                return false;\n\n            tDatums = {std::move(this->mTQueue.front())};\n            this->mTQueue.pop();\n            this->mConditionVariable.notify_one();\n            return true;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(Queue);\n}\n\n#endif // OPENPOSE_THREAD_QUEUE_HPP\n"
  },
  {
    "path": "include/openpose/thread/queueBase.hpp",
    "content": "#ifndef OPENPOSE_THREAD_QUEUE_BASE_HPP\n#define OPENPOSE_THREAD_QUEUE_BASE_HPP\n\n#include <condition_variable>\n#include <mutex>\n#include <queue> // std::queue & std::priority_queue\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TQueue>\n    class QueueBase\n    {\n    public:\n        explicit QueueBase(const long long maxSize = -1);\n\n        virtual ~QueueBase();\n\n        bool forceEmplace(TDatums& tDatums);\n\n        bool tryEmplace(TDatums& tDatums);\n\n        bool waitAndEmplace(TDatums& tDatums);\n\n        bool forcePush(const TDatums& tDatums);\n\n        bool tryPush(const TDatums& tDatums);\n\n        bool waitAndPush(const TDatums& tDatums);\n\n        bool tryPop(TDatums& tDatums);\n\n        bool tryPop();\n\n        bool waitAndPop(TDatums& tDatums);\n\n        bool waitAndPop();\n\n        bool empty() const;\n\n        void stop();\n\n        void stopPusher();\n\n        void addPopper();\n\n        void addPusher();\n\n        bool isRunning() const;\n\n        bool isFull() const;\n\n        size_t size() const;\n\n        void clear();\n\n        virtual TDatums front() const = 0;\n\n    protected:\n        mutable std::mutex mMutex;\n        long long mPoppers;\n        long long mPushers;\n        long long mMaxPoppersPushers;\n        bool mPopIsStopped;\n        bool mPushIsStopped;\n        std::condition_variable mConditionVariable;\n        TQueue mTQueue;\n\n        virtual bool pop(TDatums& tDatums) = 0;\n\n        unsigned long long getMaxSize() const;\n\n    private:\n        const long long mMaxSize;\n\n        bool emplace(TDatums& tDatums);\n\n        bool push(const TDatums& tDatums);\n\n        bool pop();\n\n        void updateMaxPoppersPushers();\n\n        DELETE_COPY(QueueBase);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/core/datum.hpp>\n#include <openpose/utilities/fastMath.hpp>\nnamespace op\n{\n    template<typename TDatums, typename TQueue>\n    QueueBase<TDatums, TQueue>::QueueBase(const long long maxSize) :\n        mPoppers{0ll},\n        mPushers{0ll},\n        mPopIsStopped{false},\n        mPushIsStopped{false},\n        mMaxSize{maxSize}\n    {\n    }\n\n    // Virtual destructor\n    template<typename TDatums, typename TQueue>\n    QueueBase<TDatums, TQueue>::~QueueBase()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            stop();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::forceEmplace(TDatums& tDatums)\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            if (mTQueue.size() >= getMaxSize())\n                mTQueue.pop();\n            return emplace(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::tryEmplace(TDatums& tDatums)\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            if (mTQueue.size() >= getMaxSize())\n                return false;\n            return emplace(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::waitAndEmplace(TDatums& tDatums)\n    {\n        try\n        {\n            std::unique_lock<std::mutex> lock{mMutex};\n            mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; });\n            return emplace(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::forcePush(const TDatums& tDatums)\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            if (mTQueue.size() >= getMaxSize())\n                mTQueue.pop();\n            return push(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::tryPush(const TDatums& tDatums)\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            if (mTQueue.size() >= getMaxSize())\n                return false;\n            return push(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::waitAndPush(const TDatums& tDatums)\n    {\n        try\n        {\n            std::unique_lock<std::mutex> lock{mMutex};\n            mConditionVariable.wait(lock, [this]{return mTQueue.size() < getMaxSize() || mPushIsStopped; });\n            return push(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::tryPop(TDatums& tDatums)\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            return pop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::tryPop()\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            return pop();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::waitAndPop(TDatums& tDatums)\n    {\n        try\n        {\n            std::unique_lock<std::mutex> lock{mMutex};\n            mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; });\n            return pop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::waitAndPop()\n    {\n        try\n        {\n            std::unique_lock<std::mutex> lock{mMutex};\n            mConditionVariable.wait(lock, [this]{return !mTQueue.empty() || mPopIsStopped; });\n            return pop();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::empty() const\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            return mTQueue.empty();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::stop()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const std::lock_guard<std::mutex> lock{mMutex};\n            mPopIsStopped = {true};\n            mPushIsStopped = {true};\n            while (!mTQueue.empty())\n                mTQueue.pop();\n            mConditionVariable.notify_all();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::stopPusher()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const std::lock_guard<std::mutex> lock{mMutex};\n            mPushers--;\n            if (mPushers == 0)\n            {\n                mPushIsStopped = {true};\n                if (mTQueue.empty())\n                    mPopIsStopped = {true};\n                mConditionVariable.notify_all();\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::addPopper()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const std::lock_guard<std::mutex> lock{mMutex};\n            mPoppers++;\n            updateMaxPoppersPushers();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::addPusher()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const std::lock_guard<std::mutex> lock{mMutex};\n            mPushers++;\n            updateMaxPoppersPushers();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::isRunning() const\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            return !(mPushIsStopped && (mPopIsStopped || mTQueue.empty()));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return true;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::isFull() const\n    {\n        try\n        {\n            // No mutex required because the size() and getMaxSize() are already thread-safe\n            return size() == getMaxSize();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    size_t QueueBase<TDatums, TQueue>::size() const\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            return mTQueue.size();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::clear()\n    {\n        try\n        {\n            const std::lock_guard<std::mutex> lock{mMutex};\n            while (!mTQueue.empty())\n                mTQueue.pop();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    unsigned long long QueueBase<TDatums, TQueue>::getMaxSize() const\n    {\n        try\n        {\n            return (mMaxSize > 0 ? mMaxSize : fastMax(1ll, mMaxPoppersPushers));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::emplace(TDatums& tDatums)\n    {\n        try\n        {\n            if (mPushIsStopped)\n                return false;\n\n            mTQueue.emplace(tDatums);\n            mConditionVariable.notify_all();\n            return true;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::push(const TDatums& tDatums)\n    {\n        try\n        {\n            if (mPushIsStopped)\n                return false;\n\n            mTQueue.push(tDatums);\n            mConditionVariable.notify_all();\n            return true;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    bool QueueBase<TDatums, TQueue>::pop()\n    {\n        try\n        {\n            if (mPopIsStopped || mTQueue.empty())\n                return false;\n\n            mTQueue.pop();\n            mConditionVariable.notify_all();\n            return true;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TQueue>\n    void QueueBase<TDatums, TQueue>::updateMaxPoppersPushers()\n    {\n        try\n        {\n            mMaxPoppersPushers = fastMax(mPoppers, mPushers);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    extern template class QueueBase<BASE_DATUMS_SH, std::queue<BASE_DATUMS_SH>>;\n    extern template class QueueBase<\n        BASE_DATUMS_SH,\n        std::priority_queue<BASE_DATUMS_SH, std::vector<BASE_DATUMS_SH>,\n        std::greater<BASE_DATUMS_SH>>>;\n}\n\n#endif // OPENPOSE_THREAD_QUEUE_BASE_HPP\n"
  },
  {
    "path": "include/openpose/thread/subThread.hpp",
    "content": "#ifndef OPENPOSE_THREAD_SUB_THREAD_HPP\n#define OPENPOSE_THREAD_SUB_THREAD_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>>\n    class SubThread\n    {\n    public:\n        explicit SubThread(const std::vector<TWorker>& tWorkers);\n\n        // Destructor\n        virtual ~SubThread();\n\n        void initializationOnThread();\n\n        virtual bool work() = 0;\n\n    protected:\n        inline size_t getTWorkersSize() const\n        {\n            return mTWorkers.size();\n        }\n\n        bool workTWorkers(TDatums& tDatums, const bool inputIsRunning);\n\n    private:\n        std::vector<TWorker> mTWorkers;\n\n        DELETE_COPY(SubThread);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker>\n    SubThread<TDatums, TWorker>::SubThread(const std::vector<TWorker>& tWorkers) :\n        mTWorkers{tWorkers}\n    {\n    }\n\n    template<typename TDatums, typename TWorker>\n    SubThread<TDatums, TWorker>::~SubThread()\n    {\n    }\n\n    template<typename TDatums, typename TWorker>\n    bool SubThread<TDatums, TWorker>::workTWorkers(TDatums& tDatums, const bool inputIsRunning)\n    {\n        try\n        {\n            // If !inputIsRunning -> try to close TWorkers\n            if (!inputIsRunning)\n            {\n                for (auto& tWorkers : mTWorkers)\n                {\n                    tWorkers->tryStop();\n                    if (tWorkers->isRunning())\n                        break;\n                }\n            }\n\n            // If (at least) last TWorker still working -> make TWorkers work\n            if ((*mTWorkers.crbegin())->isRunning())\n            {\n                // Iterate over all workers and check whether some of them stopped\n                auto allRunning = true;\n                auto lastOneStopped = false;\n                for (auto& worker : mTWorkers)\n                {\n                    if (lastOneStopped)\n                        worker->tryStop();\n\n                    if (!worker->checkAndWork(tDatums))\n                    {\n                        allRunning = false;\n                        lastOneStopped = true;\n                    }\n                    else\n                        lastOneStopped = false;\n                }\n\n                if (allRunning)\n                    return true;\n                else\n                {\n                    // If last one still running -> try to stop workers\n                    // If last one stopped -> return false\n                    auto lastRunning = (*mTWorkers.crbegin())->isRunning();\n                    if (lastRunning)\n                    {\n                        // Check last one that stopped\n                        auto lastIndexNotRunning = 0ull;\n                        for (auto i = mTWorkers.size() - 1 ; i > 0 ; i--)\n                        {\n                            if (!mTWorkers[i]->checkAndWork(tDatums))\n                            {\n                                lastIndexNotRunning = i;\n                                break;\n                            }\n                        }\n\n                        // Stop workers before last index stopped\n                        for (auto i = 0ull; i < lastIndexNotRunning ; i++)\n                            mTWorkers[i]->stop();\n\n                        // Try stopping workers after last index stopped\n                        lastRunning = false;\n                        for (auto i = lastIndexNotRunning+1; i < mTWorkers.size() ; i++)\n                        {\n                            mTWorkers[i]->tryStop();\n                            if (mTWorkers[i]->isRunning())\n                            {\n                                lastRunning = true;\n                                break;\n                            }\n                        }\n                    }\n                    return lastRunning;\n                }\n            }\n            else\n                return false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void SubThread<TDatums, TWorker>::initializationOnThread()\n    {\n        try\n        {\n            for (auto& tWorker : mTWorkers)\n                tWorker->initializationOnThreadNoException();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(SubThread);\n}\n\n#endif // OPENPOSE_THREAD_SUB_THREAD_HPP\n"
  },
  {
    "path": "include/openpose/thread/subThreadNoQueue.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP\n#define OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>>\n    class SubThreadNoQueue : public SubThread<TDatums, TWorker>\n    {\n    public:\n        explicit SubThreadNoQueue(const std::vector<TWorker>& tWorkers);\n\n        virtual ~SubThreadNoQueue();\n\n        bool work();\n\n        DELETE_COPY(SubThreadNoQueue);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker>\n    SubThreadNoQueue<TDatums, TWorker>::SubThreadNoQueue(const std::vector<TWorker>& tWorkers) :\n        SubThread<TDatums, TWorker>{tWorkers}\n    {\n    }\n\n    template<typename TDatums, typename TWorker>\n    SubThreadNoQueue<TDatums, TWorker>::~SubThreadNoQueue()\n    {\n    }\n\n    template<typename TDatums, typename TWorker>\n    bool SubThreadNoQueue<TDatums, TWorker>::work()\n    {\n        try\n        {\n            TDatums tDatums;\n            return this->workTWorkers(tDatums, true);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(SubThreadNoQueue);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_NO_QUEUE_HPP\n"
  },
  {
    "path": "include/openpose/thread/subThreadQueueIn.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP\n#define OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/queue.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>, typename TQueue = Queue<TDatums>>\n    class SubThreadQueueIn : public SubThread<TDatums, TWorker>\n    {\n    public:\n        SubThreadQueueIn(const std::vector<TWorker>& tWorkers, const std::shared_ptr<TQueue>& tQueueIn);\n\n        virtual ~SubThreadQueueIn();\n\n        bool work();\n\n    private:\n        std::shared_ptr<TQueue> spTQueueIn;\n\n        DELETE_COPY(SubThreadQueueIn);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueIn<TDatums, TWorker, TQueue>::SubThreadQueueIn(const std::vector<TWorker>& tWorkers,\n                                                                 const std::shared_ptr<TQueue>& tQueueIn) :\n        SubThread<TDatums, TWorker>{tWorkers},\n        spTQueueIn{tQueueIn}\n    {\n        // spTQueueIn->addPopper();\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueIn<TDatums, TWorker, TQueue>::~SubThreadQueueIn()\n    {\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool SubThreadQueueIn<TDatums, TWorker, TQueue>::work()\n    {\n        try\n        {\n            // Pop TDatums\n            if (spTQueueIn->empty())\n                std::this_thread::sleep_for(std::chrono::microseconds{100});\n            TDatums tDatums;\n            bool queueIsRunning = spTQueueIn->tryPop(tDatums);\n            // Check queue not empty\n            if (!queueIsRunning)\n                queueIsRunning = spTQueueIn->isRunning();\n            // Process TDatums\n            const auto workersAreRunning = this->workTWorkers(tDatums, queueIsRunning);\n            // Close queue input if all workers closed\n            if (!workersAreRunning)\n                spTQueueIn->stop();\n            return workersAreRunning;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            spTQueueIn->stop();\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(SubThreadQueueIn);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_QUEUE_IN_HPP\n"
  },
  {
    "path": "include/openpose/thread/subThreadQueueInOut.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP\n#define OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/queue.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>, typename TQueue = Queue<TDatums>>\n    class SubThreadQueueInOut : public SubThread<TDatums, TWorker>\n    {\n    public:\n        SubThreadQueueInOut(const std::vector<TWorker>& tWorkers, const std::shared_ptr<TQueue>& tQueueIn,\n                            const std::shared_ptr<TQueue>& tQueueOut);\n\n        virtual ~SubThreadQueueInOut();\n\n        bool work();\n\n    private:\n        std::shared_ptr<TQueue> spTQueueIn;\n        std::shared_ptr<TQueue> spTQueueOut;\n\n        DELETE_COPY(SubThreadQueueInOut);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueInOut<TDatums, TWorker, TQueue>::SubThreadQueueInOut(const std::vector<TWorker>& tWorkers,\n                                                                       const std::shared_ptr<TQueue>& tQueueIn,\n                                                                       const std::shared_ptr<TQueue>& tQueueOut) :\n        SubThread<TDatums, TWorker>{tWorkers},\n        spTQueueIn{tQueueIn},\n        spTQueueOut{tQueueOut}\n    {\n        // spTQueueIn->addPopper();\n        spTQueueOut->addPusher();\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueInOut<TDatums, TWorker, TQueue>::~SubThreadQueueInOut()\n    {\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool SubThreadQueueInOut<TDatums, TWorker, TQueue>::work()\n    {\n        try\n        {\n            // If output queue is closed -> close input queue\n            if (!spTQueueOut->isRunning())\n            {\n                spTQueueIn->stop();\n                return false;\n            }\n            // If output queue running -> normal operation\n            else\n            {\n                // Don't work until next queue is not full\n                // This reduces latency to half\n                if (!spTQueueOut->isFull())\n                {\n                    // Pop TDatums\n                    if (spTQueueIn->empty())\n                        std::this_thread::sleep_for(std::chrono::microseconds{100});\n                    TDatums tDatums;\n                    bool workersAreRunning = spTQueueIn->tryPop(tDatums);\n                    // Check queue not stopped\n                    if (!workersAreRunning)\n                        workersAreRunning = spTQueueIn->isRunning();\n                    // Process TDatums\n                    workersAreRunning = this->workTWorkers(tDatums, workersAreRunning);\n                    // Push/emplace tDatums if successfully processed\n                    if (workersAreRunning)\n                    {\n                        if (tDatums != nullptr)\n                            spTQueueOut->waitAndEmplace(tDatums);\n                    }\n                    // Close both queues otherwise\n                    else\n                    {\n                        spTQueueIn->stop();\n                        spTQueueOut->stopPusher();\n                    }\n                    return workersAreRunning;\n                }\n                else\n                {\n                    std::this_thread::sleep_for(std::chrono::microseconds{100});\n                    return true;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            spTQueueIn->stop();\n            spTQueueOut->stop();\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(SubThreadQueueInOut);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_QUEUE_IN_OUT_HPP\n"
  },
  {
    "path": "include/openpose/thread/subThreadQueueOut.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP\n#define OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/queue.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>, typename TQueue = Queue<TDatums>>\n    class SubThreadQueueOut : public SubThread<TDatums, TWorker>\n    {\n    public:\n        SubThreadQueueOut(const std::vector<TWorker>& tWorkers, const std::shared_ptr<TQueue>& tQueueOut);\n\n        virtual ~SubThreadQueueOut();\n\n        bool work();\n\n    private:\n        std::shared_ptr<TQueue> spTQueueOut;\n\n        DELETE_COPY(SubThreadQueueOut);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueOut<TDatums, TWorker, TQueue>::SubThreadQueueOut(const std::vector<TWorker>& tWorkers,\n                   const std::shared_ptr<TQueue>& tQueueOut) :\n        SubThread<TDatums, TWorker>{tWorkers},\n        spTQueueOut{tQueueOut}\n    {\n        spTQueueOut->addPusher();\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    SubThreadQueueOut<TDatums, TWorker, TQueue>::~SubThreadQueueOut()\n    {\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool SubThreadQueueOut<TDatums, TWorker, TQueue>::work()\n    {\n        try\n        {\n            // If output queue is closed -> close input queue\n            if (!spTQueueOut->isRunning())\n                return false;\n            else\n            {\n                // Don't work until next queue is not full\n                // This reduces latency to half\n                if (!spTQueueOut->isFull())\n                {\n                    // Process TDatums\n                    TDatums tDatums;\n                    const auto workersAreRunning = this->workTWorkers(tDatums, true);\n                    // Push/emplace tDatums if successfully processed\n                    if (workersAreRunning)\n                    {\n                        if (tDatums != nullptr)\n                            spTQueueOut->waitAndEmplace(tDatums);\n                    }\n                    // Close queue otherwise\n                    else\n                        spTQueueOut->stopPusher();\n                    return workersAreRunning;\n                }\n                else\n                {\n                    std::this_thread::sleep_for(std::chrono::microseconds{100});\n                    return true;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            spTQueueOut->stop();\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(SubThreadQueueOut);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_QUEUE_OUT_HPP\n"
  },
  {
    "path": "include/openpose/thread/thread.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_HPP\n#define OPENPOSE_THREAD_THREAD_HPP\n\n#include <atomic>\n#include <openpose/core/common.hpp>\n#include <openpose/thread/subThread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>>\n    class Thread\n    {\n    public:\n        explicit Thread(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr = nullptr);\n\n        // Move constructor\n        Thread(Thread&& t);\n\n        // Move assignment\n        Thread& operator=(Thread&& t);\n\n        // Destructor\n        virtual ~Thread();\n\n        void add(const std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>& subThreads);\n\n        void add(const std::shared_ptr<SubThread<TDatums, TWorker>>& subThread);\n\n        void exec(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr);\n\n        void startInThread();\n\n        void stopAndJoin();\n\n        inline bool isRunning() const\n        {\n            return *spIsRunning;\n        }\n\n    private:\n        std::shared_ptr<std::atomic<bool>> spIsRunning;\n        std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>> mSubThreads;\n        std::thread mThread;\n\n        void initializationOnThread();\n\n        void threadFunction();\n\n        void stop();\n\n        void join();\n\n        DELETE_COPY(Thread);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums, typename TWorker>\n    Thread<TDatums, TWorker>::Thread(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr) :\n        spIsRunning{(isRunningSharedPtr != nullptr ? isRunningSharedPtr : std::make_shared<std::atomic<bool>>(false))}\n    {\n    }\n\n    template<typename TDatums, typename TWorker>\n    Thread<TDatums, TWorker>::Thread(Thread<TDatums, TWorker>&& t) :\n        spIsRunning{std::make_shared<std::atomic<bool>>(t.spIsRunning->load())}\n    {\n        std::swap(mSubThreads, t.mSubThreads);\n        std::swap(mThread, t.mThread);\n    }\n\n    template<typename TDatums, typename TWorker>\n    Thread<TDatums, TWorker>& Thread<TDatums, TWorker>::operator=(Thread<TDatums, TWorker>&& t)\n    {\n        std::swap(mSubThreads, t.mSubThreads);\n        std::swap(mThread, t.mThread);\n        spIsRunning = {std::make_shared<std::atomic<bool>>(t.spIsRunning->load())};\n        return *this;\n    }\n\n    template<typename TDatums, typename TWorker>\n    Thread<TDatums, TWorker>::~Thread()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            stopAndJoin();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::add(const std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>& subThreads)\n    {\n        for (const auto& subThread : subThreads)\n            mSubThreads.emplace_back(subThread);\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::add(const std::shared_ptr<SubThread<TDatums, TWorker>>& subThread)\n    {\n        add(std::vector<std::shared_ptr<SubThread<TDatums, TWorker>>>{subThread});\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::exec(const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr)\n    {\n        try\n        {\n            stopAndJoin();\n            spIsRunning = isRunningSharedPtr;\n            *spIsRunning = true;\n            threadFunction();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::startInThread()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            stopAndJoin();\n            *spIsRunning = true;\n            mThread = {std::thread{&Thread::threadFunction, this}};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::stopAndJoin()\n    {\n        try\n        {\n            stop();\n            join();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::initializationOnThread()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            for (auto& subThread : mSubThreads)\n                subThread->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::threadFunction()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            initializationOnThread();\n\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            while (isRunning())\n            {\n                bool allSubThreadsClosed = true;\n                for (auto& subThread : mSubThreads)\n                    allSubThreadsClosed &= !subThread->work();\n\n                if (allSubThreadsClosed)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    stop();\n                    break;\n                }\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::stop()\n    {\n        try\n        {\n            *spIsRunning = false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker>\n    void Thread<TDatums, TWorker>::join()\n    {\n        try\n        {\n            if (mThread.joinable())\n                mThread.join();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(Thread);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_HPP\n"
  },
  {
    "path": "include/openpose/thread/threadManager.hpp",
    "content": "#ifndef OPENPOSE_THREAD_THREAD_MANAGER_HPP\n#define OPENPOSE_THREAD_THREAD_MANAGER_HPP\n\n#include <atomic>\n#include <set> // std::multiset\n#include <tuple>\n#include <openpose/core/common.hpp>\n#include <openpose/thread/enumClasses.hpp>\n#include <openpose/thread/queue.hpp>\n#include <openpose/thread/thread.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums, typename TWorker = std::shared_ptr<Worker<TDatums>>, typename TQueue = Queue<TDatums>>\n    class ThreadManager\n    {\n    public:\n        // Completely customizable case\n        explicit ThreadManager(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous);\n\n        virtual ~ThreadManager();\n\n        /**\n         * It sets the maximum number of elements in the queue.\n         * For maximum speed, set to a very large number, but the trade-off would be:\n         *  - Latency will hugely increase.\n         *  - The program might go out of RAM memory (so the computer might freeze).\n         * For minimum latency while keeping an optimal speed, set to -1, that will automatically\n         * detect the ideal number based on how many elements are connected to that queue.\n         * @param defaultMaxSizeQueues long long element with the maximum number of elements on the queue.\n         */\n        void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues = -1);\n\n        void add(const unsigned long long threadId, const std::vector<TWorker>& tWorkers,\n                 const unsigned long long queueInId, const unsigned long long queueOutId);\n\n        void add(const unsigned long long threadId, const TWorker& tWorker, const unsigned long long queueInId,\n                 const unsigned long long queueOutId);\n\n        void reset();\n\n        void exec();\n\n        void start();\n\n        void stop();\n\n        inline std::shared_ptr<std::atomic<bool>> getIsRunningSharedPtr()\n        {\n            return spIsRunning;\n        }\n\n        inline bool isRunning() const\n        {\n            return *spIsRunning;\n        }\n\n        bool tryEmplace(TDatums& tDatums);\n\n        bool waitAndEmplace(TDatums& tDatums);\n\n        bool tryPush(const TDatums& tDatums);\n\n        bool waitAndPush(const TDatums& tDatums);\n\n        bool tryPop(TDatums& tDatums);\n\n        bool waitAndPop(TDatums& tDatums);\n\n    private:\n        const ThreadManagerMode mThreadManagerMode;\n        std::shared_ptr<std::atomic<bool>> spIsRunning;\n        long long mDefaultMaxSizeQueues;\n        std::multiset<std::tuple<unsigned long long, std::vector<TWorker>, unsigned long long, unsigned long long>> mThreadWorkerQueues;\n        std::vector<std::shared_ptr<Thread<TDatums, TWorker>>> mThreads;\n        std::vector<std::shared_ptr<TQueue>> mTQueues;\n\n        void add(const std::vector<std::tuple<unsigned long long, std::vector<TWorker>, unsigned long long, unsigned long long>>& threadWorkerQueues);\n\n        void add(const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long, unsigned long long>>& threadWorkerQueues);\n\n        void multisetToThreads();\n\n        void checkAndCreateEmptyThreads();\n\n        void checkAndCreateQueues();\n\n        DELETE_COPY(ThreadManager);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <utility> // std::pair\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/thread/subThread.hpp>\n#include <openpose/thread/subThreadNoQueue.hpp>\n#include <openpose/thread/subThreadQueueIn.hpp>\n#include <openpose/thread/subThreadQueueInOut.hpp>\n#include <openpose/thread/subThreadQueueOut.hpp>\nnamespace op\n{\n    template<typename TDatums, typename TWorker, typename TQueue>\n    ThreadManager<TDatums, TWorker, TQueue>::ThreadManager(const ThreadManagerMode threadManagerMode) :\n        mThreadManagerMode{threadManagerMode},\n        spIsRunning{std::make_shared<std::atomic<bool>>(false)},\n        mDefaultMaxSizeQueues{-1ll}\n    {\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    ThreadManager<TDatums, TWorker, TQueue>::~ThreadManager()\n    {\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues)\n    {\n        try\n        {\n            mDefaultMaxSizeQueues = {defaultMaxSizeQueues};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::add(const unsigned long long threadId,\n                                                      const std::vector<TWorker>& tWorkers,\n                                                      const unsigned long long queueInId,\n                                                      const unsigned long long queueOutId)\n    {\n        try\n        {\n            add({std::make_tuple(threadId, tWorkers, queueInId, queueOutId)});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::add(const unsigned long long threadId,\n                                                      const TWorker& tWorker,\n                                                      const unsigned long long queueInId,\n                                                      const unsigned long long queueOutId)\n    {\n        try\n        {\n            add({std::make_tuple(threadId, std::vector<TWorker>{tWorker}, queueInId, queueOutId)});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::reset()\n    {\n        try\n        {\n            mThreadWorkerQueues.clear();\n            mThreads.clear();\n            mTQueues.clear();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::exec()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Set threads\n            multisetToThreads();\n            if (!mThreads.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Start threads\n                for (auto i = 0u; i < mThreads.size() - 1; i++)\n                    mThreads.at(i)->startInThread();\n                (*mThreads.rbegin())->exec(spIsRunning);\n                // Stop threads - It will arrive here when the exec() command has finished\n                stop();\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::start()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Set threads\n            multisetToThreads();\n            // Start threads\n            for (auto& thread : mThreads)\n                thread->startInThread();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::stop()\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            for (auto& tQueue : mTQueues)\n                tQueue->stop();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            *spIsRunning = false;\n            for (auto& thread : mThreads)\n                thread->stopAndJoin();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            checkWorkerErrors();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::tryEmplace(TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return mTQueues[0]->tryEmplace(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::waitAndEmplace(TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return mTQueues[0]->waitAndEmplace(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::tryPush(const TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return mTQueues[0]->tryPush(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::waitAndPush(const TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return mTQueues[0]->waitAndPush(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::tryPop(TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousOut)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return (*mTQueues.rbegin())->tryPop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    bool ThreadManager<TDatums, TWorker, TQueue>::waitAndPop(TDatums& tDatums)\n    {\n        try\n        {\n            if (mThreadManagerMode != ThreadManagerMode::Asynchronous\n                && mThreadManagerMode != ThreadManagerMode::AsynchronousOut)\n                error(\"Not available for this ThreadManagerMode.\", __LINE__, __FUNCTION__, __FILE__);\n            if (mTQueues.empty())\n                error(\"ThreadManager already stopped or not started yet.\", __LINE__, __FUNCTION__, __FILE__);\n            return (*mTQueues.rbegin())->waitAndPop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, std::vector<TWorker>,\n                                                                                   unsigned long long, unsigned long long>>& threadWorkerQueues)\n    {\n        try\n        {\n            for (const auto& threadWorkerQueue : threadWorkerQueues)\n                mThreadWorkerQueues.insert(threadWorkerQueue);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::add(const std::vector<std::tuple<unsigned long long, TWorker, unsigned long long,\n                                                                                   unsigned long long>>& threadWorkerQueues)\n    {\n        try\n        {\n            for (const auto& threadWorkerQueue : threadWorkerQueues)\n                add({std::make_tuple(std::get<0>(threadWorkerQueue),\n                                     std::vector<TWorker>{std::get<1>(threadWorkerQueue)},\n                                     std::get<2>(threadWorkerQueue),\n                                     std::get<3>(threadWorkerQueue))});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::multisetToThreads()\n    {\n        try\n        {\n            if (!mThreadWorkerQueues.empty())\n            {\n                // This avoids extra std::cout if errors occur on different threads\n                setMainThread();\n\n                // Check threads\n                checkAndCreateEmptyThreads();\n\n                // Check and create queues\n                checkAndCreateQueues();\n\n                // Data\n                const auto maxQueueIdSynchronous = mTQueues.size()+1;\n\n                // Set up threads\n                for (const auto& threadWorkerQueue : mThreadWorkerQueues)\n                {\n                    auto& thread = mThreads[std::get<0>(threadWorkerQueue)];\n                    const auto& tWorkers = std::get<1>(threadWorkerQueue);\n                    const auto queueIn = std::get<2>(threadWorkerQueue);\n                    const auto queueOut = std::get<3>(threadWorkerQueue);\n                    std::shared_ptr<SubThread<TDatums, TWorker>> subThread;\n                    // If AsynchronousIn -> queue indexes are OK\n                    if (mThreadManagerMode == ThreadManagerMode::Asynchronous\n                        || mThreadManagerMode == ThreadManagerMode::AsynchronousIn)\n                    {\n                        if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn\n                            && queueOut == mTQueues.size())\n                            subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(\n                                tWorkers, mTQueues.at(queueIn))};\n                        else\n                            subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(\n                                tWorkers, mTQueues.at(queueIn), mTQueues.at(queueOut))};\n                    }\n                    // If !AsynchronousIn -> queue indexes - 1\n                    else if (queueOut != maxQueueIdSynchronous\n                        || mThreadManagerMode == ThreadManagerMode::AsynchronousOut)\n                    {\n                        // Queue in + out\n                        if (queueIn != 0)\n                            subThread = {std::make_shared<SubThreadQueueInOut<TDatums, TWorker, TQueue>>(\n                                tWorkers, mTQueues.at(queueIn-1), mTQueues.at(queueOut-1))};\n                        // Case queue out (first TWorker(s))\n                        else\n                            subThread = {std::make_shared<SubThreadQueueOut<TDatums, TWorker, TQueue>>(\n                                tWorkers, mTQueues.at(queueOut-1))};\n                    }\n                    // Case queue in (last TWorker(s))\n                    else if (queueIn != 0) // && queueOut == maxQueueIdSynchronous\n                        subThread = {std::make_shared<SubThreadQueueIn<TDatums, TWorker, TQueue>>(\n                            tWorkers, mTQueues.at(queueIn-1))};\n                    // Case no queue\n                    else // if (queueIn == 0 && queueOut == maxQueueIdSynchronous)\n                        subThread = {std::make_shared<SubThreadNoQueue<TDatums, TWorker>>(tWorkers)};\n                    thread->add(subThread);\n                }\n            }\n            else\n                error(\"Empty, no TWorker(s) added.\", __LINE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::checkAndCreateEmptyThreads()\n    {\n        try\n        {\n            // Check all thread ids from 0-maxThreadId are present\n            const auto maxThreadId = std::get<0>(*mThreadWorkerQueues.crbegin());\n            auto previousThreadId = std::get<0>(*mThreadWorkerQueues.cbegin());\n            for (const auto& threadWorkerQueue : mThreadWorkerQueues)\n            {\n                const auto currentThreadId = std::get<0>(threadWorkerQueue);\n                if (currentThreadId - previousThreadId > 1)\n                    error(\"Missing thread id \" + std::to_string(currentThreadId) + \" of \"\n                          + std::to_string(maxThreadId) + \".\", __LINE__, __FUNCTION__, __FILE__);\n                previousThreadId = currentThreadId;\n            }\n\n            // Create Threads\n            // #threads = maxThreadId+1\n            mThreads.resize(maxThreadId);\n            for (auto& thread : mThreads)\n                thread = std::make_shared<Thread<TDatums, TWorker>>();\n            mThreads.emplace_back(std::make_shared<Thread<TDatums, TWorker>>(spIsRunning));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums, typename TWorker, typename TQueue>\n    void ThreadManager<TDatums, TWorker, TQueue>::checkAndCreateQueues()\n    {\n        try\n        {\n            if (!mThreadWorkerQueues.empty())\n            {\n                // Get max queue id to get queue size\n                auto maxQueueId = std::get<3>(*mThreadWorkerQueues.cbegin());\n                for (const auto& threadWorkerQueue : mThreadWorkerQueues)\n                    maxQueueId = fastMax(\n                        maxQueueId, fastMax(std::get<2>(threadWorkerQueue), std::get<3>(threadWorkerQueue)));\n\n                // Check each queue id has at least a worker that uses it as input and another one as output.\n                // Special cases:\n                std::vector<std::pair<bool, bool>> usedQueueIds(maxQueueId+1, {false, false});\n                for (const auto& threadWorkerQueue : mThreadWorkerQueues)\n                {\n                    usedQueueIds.at(std::get<2>(threadWorkerQueue)).first = true;\n                    usedQueueIds.at(std::get<3>(threadWorkerQueue)).second = true;\n                }\n                // Id 0 must only needs a worker using it as input.\n                usedQueueIds.begin()->second = true;\n                // Id maxQueueId only needs a worker using it as output.\n                usedQueueIds.rbegin()->first = true;\n                // Error if missing queue id\n                for (auto i = 0ull ; i < usedQueueIds.size() ; i++)\n                {\n                    if (!usedQueueIds[i].first)\n                        error(\"Missing queue id \" + std::to_string(i) + \" (of \"\n                              + std::to_string(maxQueueId) + \") as input.\", __LINE__, __FUNCTION__, __FILE__);\n                    if (!usedQueueIds[i].second)\n                        error(\"Missing queue id \" + std::to_string(i) + \" (of \"\n                              + std::to_string(maxQueueId) + \") as output.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n\n                // Create Queues\n                if (mThreadManagerMode == ThreadManagerMode::Asynchronous)\n                    mTQueues.resize(maxQueueId+1);   // First and last one are queues\n                else if (mThreadManagerMode == ThreadManagerMode::Synchronous)\n                    mTQueues.resize(maxQueueId-1);   // First and last one are not actually queues\n                else if (mThreadManagerMode == ThreadManagerMode::AsynchronousIn\n                         || mThreadManagerMode == ThreadManagerMode::AsynchronousOut)\n                    mTQueues.resize(maxQueueId);   // First or last one is queue\n                else\n                    error(\"Unknown ThreadManagerMode\", __LINE__, __FUNCTION__, __FILE__);\n                for (auto& tQueue : mTQueues)\n                    tQueue = std::make_shared<TQueue>(mDefaultMaxSizeQueues);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(ThreadManager);\n}\n\n#endif // OPENPOSE_THREAD_THREAD_MANAGER_HPP\n"
  },
  {
    "path": "include/openpose/thread/wFpsMax.hpp",
    "content": "#ifndef OPENPOSE_THREAD_W_FPS_MAX_HPP\n#define OPENPOSE_THREAD_W_FPS_MAX_HPP\n\n#include <thread>\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WFpsMax : public Worker<TDatums>\n    {\n    public:\n        explicit WFpsMax(const double fpsMax);\n\n        virtual ~WFpsMax();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        const unsigned long long mNanosecondsToSleep;\n\n        DELETE_COPY(WFpsMax);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    WFpsMax<TDatums>::WFpsMax(const double fpsMax) :\n        mNanosecondsToSleep{uLongLongRound(1e9/fpsMax)}\n    {\n    }\n\n    template<typename TDatums>\n    WFpsMax<TDatums>::~WFpsMax()\n    {\n    }\n\n    template<typename TDatums>\n    void WFpsMax<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WFpsMax<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            // Debugging log\n            opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Profiling speed\n            const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n            // tDatums not used --> Avoid warning\n            UNUSED(tDatums);\n            // Sleep the desired time\n            std::this_thread::sleep_for(std::chrono::nanoseconds{mNanosecondsToSleep});\n            // Profiling speed\n            Profiler::timerEnd(profilerKey);\n            Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n            // Debugging log\n            opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WFpsMax);\n}\n\n#endif // OPENPOSE_THREAD_W_FPS_MAX_HPP\n"
  },
  {
    "path": "include/openpose/thread/wIdGenerator.hpp",
    "content": "#ifndef OPENPOSE_THREAD_W_ID_GENERATOR_HPP\n#define OPENPOSE_THREAD_W_ID_GENERATOR_HPP\n\n#include <queue> // std::priority_queue\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/utilities/pointerContainer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WIdGenerator : public Worker<TDatums>\n    {\n    public:\n        explicit WIdGenerator();\n\n        virtual ~WIdGenerator();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        unsigned long long mGlobalCounter;\n\n        DELETE_COPY(WIdGenerator);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WIdGenerator<TDatums>::WIdGenerator() :\n        mGlobalCounter{0ull}\n    {\n    }\n\n    template<typename TDatums>\n    WIdGenerator<TDatums>::~WIdGenerator()\n    {\n    }\n\n    template<typename TDatums>\n    void WIdGenerator<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WIdGenerator<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Add ID\n                for (auto& tDatumPtr : *tDatums)\n                    // To avoid overwriting ID if e.g., custom input has already filled it\n                    if (tDatumPtr->id == std::numeric_limits<unsigned long long>::max())\n                        tDatumPtr->id = mGlobalCounter;\n                // Increase ID\n                const auto& tDatumPtr = (*tDatums)[0];\n                if (tDatumPtr->subId == tDatumPtr->subIdMax)\n                    mGlobalCounter++;\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WIdGenerator);\n}\n\n#endif // OPENPOSE_THREAD_W_ID_GENERATOR_HPP\n"
  },
  {
    "path": "include/openpose/thread/wQueueAssembler.hpp",
    "content": "#ifndef OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP\n#define OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP\n\n#include <queue> // std::queue\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/utilities/pointerContainer.hpp>\n\nnamespace op\n{\n    // Note: The goal of WQueueAssembler and WQueueSplitter (integrated in wDatumProducer) is to reduce the latency\n    // of OpenPose. E.g., if 4 cameras in stereo mode, without this, OpenPose would have to process all 4 cameras\n    // with the same GPU. In this way, this work is parallelized over GPUs (1 view for each).\n    // Pros: Latency highly recuded, same speed\n    // Cons: Requires these extra 2 classes and proper threads for them\n    template<typename TDatums>\n    class WQueueAssembler : public Worker<std::shared_ptr<TDatums>>\n    {\n    public:\n        explicit WQueueAssembler();\n\n        virtual ~WQueueAssembler();\n\n        void initializationOnThread();\n\n        void work(std::shared_ptr<TDatums>& tDatums);\n\n    private:\n        std::shared_ptr<TDatums> mNextTDatums;\n\n        DELETE_COPY(WQueueAssembler);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    WQueueAssembler<TDatums>::WQueueAssembler()\n    {\n    }\n\n    template<typename TDatums>\n    WQueueAssembler<TDatums>::~WQueueAssembler()\n    {\n    }\n\n    template<typename TDatums>\n    void WQueueAssembler<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WQueueAssembler<TDatums>::work(std::shared_ptr<TDatums>& tDatums)\n    {\n        try\n        {\n            // Profiling speed\n            const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n            // Input TDatums -> enqueue it\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Sanity check\n                if (tDatums->size() > 1)\n                    error(\"This function assumes that WQueueSplitter (inside WDatumProducer)\"\n                          \" was applied in the first place, i.e., that there is only 1 element\"\n                          \" per TDatums (size = \" + std::to_string(tDatums->size()) + \").\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                auto tDatumPtr = (*tDatums)[0];\n                // Single view --> Return\n                if (tDatumPtr->subIdMax == 0)\n                    return;\n                // Multiple view --> Merge views into different TDatums (1st frame)\n                if (mNextTDatums == nullptr)\n                    mNextTDatums = std::make_shared<TDatums>();\n                // Multiple view --> Merge views into different TDatums\n                mNextTDatums->emplace_back(tDatumPtr);\n                // Last view - Return frame\n                if (mNextTDatums->back()->subId == mNextTDatums->back()->subIdMax)\n                {\n                    tDatums = mNextTDatums;\n                    mNextTDatums = nullptr;\n                    // Profiling speed\n                    Profiler::timerEnd(profilerKey);\n                    Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                    // Debugging log\n                    opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Non-last view - Return nothing\n                else\n                    tDatums = nullptr;\n            }\n            // Sleep if no new tDatums to either pop or push\n            else\n                std::this_thread::sleep_for(std::chrono::milliseconds{1});\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    extern template class WQueueAssembler<BASE_DATUMS>;\n}\n\n#endif // OPENPOSE_THREAD_W_QUEUE_ASSEMBLER_HPP\n"
  },
  {
    "path": "include/openpose/thread/wQueueOrderer.hpp",
    "content": "#ifndef OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP\n#define OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP\n\n#include <queue> // std::priority_queue\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/utilities/pointerContainer.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WQueueOrderer : public Worker<TDatums>\n    {\n    public:\n        explicit WQueueOrderer(const unsigned int maxBufferSize = 64u);\n\n        virtual ~WQueueOrderer();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n        void tryStop();\n\n    private:\n        const unsigned int mMaxBufferSize;\n        bool mStopWhenEmpty;\n        unsigned long long mNextExpectedId;\n        unsigned long long mNextExpectedSubId;\n        std::priority_queue<TDatums, std::vector<TDatums>, PointerContainerGreater<TDatums>> mPriorityQueueBuffer;\n\n        DELETE_COPY(WQueueOrderer);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    WQueueOrderer<TDatums>::WQueueOrderer(const unsigned int maxBufferSize) :\n        mMaxBufferSize{maxBufferSize},\n        mStopWhenEmpty{false},\n        mNextExpectedId{0},\n        mNextExpectedSubId{0}\n    {\n    }\n\n    template<typename TDatums>\n    WQueueOrderer<TDatums>::~WQueueOrderer()\n    {\n    }\n\n    template<typename TDatums>\n    void WQueueOrderer<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WQueueOrderer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            // Profiling speed\n            const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n            bool profileSpeed = (tDatums != nullptr);\n            // Input TDatum -> enqueue or return it back\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // T* to T\n                auto& tDatumsNoPtr = *tDatums;\n                // tDatums is the next expected, update counter\n                if (tDatumsNoPtr[0]->id == mNextExpectedId && tDatumsNoPtr[0]->subId == mNextExpectedSubId)\n                {\n                    // If single-view\n                    if (tDatumsNoPtr[0]->subIdMax == 0)\n                        mNextExpectedId++;\n                    // If muilti-view system\n                    else\n                    {\n                        mNextExpectedSubId++;\n                        if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax)\n                        {\n                            mNextExpectedSubId = 0;\n                            mNextExpectedId++;\n                        }\n                    }\n                }\n                // Else push it to our buffered queue\n                else\n                {\n                    // Enqueue current tDatums\n                    mPriorityQueueBuffer.emplace(tDatums);\n                    tDatums = nullptr;\n                    // Else if buffer full -> remove one tDatums\n                    if (mPriorityQueueBuffer.size() > mMaxBufferSize)\n                    {\n                        tDatums = mPriorityQueueBuffer.top();\n                        mPriorityQueueBuffer.pop();\n                    }\n                }\n            }\n            // If input TDatum enqueued -> check if previously enqueued next desired frame and pop it\n            if (!checkNoNullNorEmpty(tDatums))\n            {\n                // Retrieve frame if next is desired frame or if we want to stop this worker\n                if (!mPriorityQueueBuffer.empty()\n                    && (mStopWhenEmpty ||\n                        ((*mPriorityQueueBuffer.top())[0]->id == mNextExpectedId\n                          && (*mPriorityQueueBuffer.top())[0]->subId == mNextExpectedSubId)))\n                {\n                    tDatums = { mPriorityQueueBuffer.top() };\n                    mPriorityQueueBuffer.pop();\n                }\n            }\n            // If TDatum ready to be returned -> updated next expected id\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                const auto& tDatumsNoPtr = *tDatums;\n                // If single-view\n                if (tDatumsNoPtr[0]->subIdMax == 0)\n                    mNextExpectedId = tDatumsNoPtr[0]->id + 1;\n                // If muilti-view system\n                else\n                {\n                    mNextExpectedSubId = tDatumsNoPtr[0]->subId + 1;\n                    if (mNextExpectedSubId > tDatumsNoPtr[0]->subIdMax)\n                    {\n                        mNextExpectedSubId = 0;\n                        mNextExpectedId = tDatumsNoPtr[0]->id + 1;\n                    }\n                }\n            }\n            // Sleep if no new tDatums to either pop or push\n            if (!checkNoNullNorEmpty(tDatums) && mPriorityQueueBuffer.size() < mMaxBufferSize / 2u)\n                std::this_thread::sleep_for(std::chrono::milliseconds{1});\n            // If TDatum popped and/or pushed\n            if (profileSpeed || tDatums != nullptr)\n            {\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    void WQueueOrderer<TDatums>::tryStop()\n    {\n        try\n        {\n            // Close if all frames were retrieved from the queue\n            if (mPriorityQueueBuffer.empty())\n                this->stop();\n            mStopWhenEmpty = true;\n\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WQueueOrderer);\n}\n\n#endif // OPENPOSE_THREAD_W_QUEUE_ORDERER_HPP\n"
  },
  {
    "path": "include/openpose/thread/worker.hpp",
    "content": "#ifndef OPENPOSE_THREAD_WORKER_HPP\n#define OPENPOSE_THREAD_WORKER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class Worker\n    {\n    public:\n        Worker();\n\n        virtual ~Worker();\n\n        void initializationOnThreadNoException();\n\n        bool checkAndWork(TDatums& tDatums);\n\n        inline bool isRunning() const\n        {\n            return mIsRunning;\n        }\n\n        inline void stop()\n        {\n            mIsRunning = false;\n        }\n\n        // Virtual in case some function needs special stopping (e.g., buffers might not stop immediately and need a\n        // few iterations)\n        inline virtual void tryStop()\n        {\n            stop();\n        }\n\n    protected:\n        virtual void initializationOnThread() = 0;\n\n        virtual void work(TDatums& tDatums) = 0;\n\n    private:\n        bool mIsRunning;\n\n        DELETE_COPY(Worker);\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    Worker<TDatums>::Worker() :\n        mIsRunning{true}\n    {\n    }\n\n    template<typename TDatums>\n    Worker<TDatums>::~Worker()\n    {\n    }\n\n    template<typename TDatums>\n    void Worker<TDatums>::initializationOnThreadNoException()\n    {\n        try\n        {\n            this->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatums>\n    bool Worker<TDatums>::checkAndWork(TDatums& tDatums)\n    {\n        try\n        {\n            if (mIsRunning)\n                work(tDatums);\n            return mIsRunning;\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(Worker);\n}\n\n#endif // OPENPOSE_THREAD_WORKER_HPP\n"
  },
  {
    "path": "include/openpose/thread/workerConsumer.hpp",
    "content": "#ifndef OPENPOSE_THREAD_WORKER_CONSUMER_HPP\n#define OPENPOSE_THREAD_WORKER_CONSUMER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WorkerConsumer : public Worker<TDatums>\n    {\n    public:\n        virtual ~WorkerConsumer();\n\n        void work(TDatums& tDatums);\n\n    protected:\n        virtual void workConsumer(const TDatums& tDatums) = 0;\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    WorkerConsumer<TDatums>::~WorkerConsumer()\n    {\n    }\n\n    template<typename TDatums>\n    void WorkerConsumer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            workConsumer(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WorkerConsumer);\n}\n\n#endif // OPENPOSE_THREAD_WORKER_CONSUMER_HPP\n"
  },
  {
    "path": "include/openpose/thread/workerProducer.hpp",
    "content": "#ifndef OPENPOSE_THREAD_WORKER_PRODUCER_HPP\n#define OPENPOSE_THREAD_WORKER_PRODUCER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WorkerProducer : public Worker<TDatums>\n    {\n    public:\n        virtual ~WorkerProducer();\n\n        void work(TDatums& tDatums);\n\n    protected:\n        virtual TDatums workProducer() = 0;\n    };\n}\n\n\n\n\n\n// Implementation\nnamespace op\n{\n    template<typename TDatums>\n    WorkerProducer<TDatums>::~WorkerProducer()\n    {\n    }\n\n    template<typename TDatums>\n    void WorkerProducer<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            tDatums = std::move(workProducer());\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            errorWorker(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WorkerProducer);\n}\n\n#endif // OPENPOSE_THREAD_WORKER_PRODUCER_HPP\n"
  },
  {
    "path": "include/openpose/tracking/headers.hpp",
    "content": "#ifndef OPENPOSE_TRACKING_HEADERS_HPP\n#define OPENPOSE_TRACKING_HEADERS_HPP\n\n// tracking module\n#include <openpose/tracking/personIdExtractor.hpp>\n#include <openpose/tracking/personTracker.hpp>\n#include <openpose/tracking/wPersonIdExtractor.hpp>\n\n#endif // OPENPOSE_TRACKING_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/tracking/personIdExtractor.hpp",
    "content": "#ifndef OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP\n#define OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API PersonIdExtractor\n    {\n    public:\n        PersonIdExtractor(const float confidenceThreshold = 0.1f, const float inlierRatioThreshold = 0.5f,\n                          const float distanceThreshold = 30.f, const int numberFramesToDeletePerson = 10);\n\n        virtual ~PersonIdExtractor();\n\n        Array<long long> extractIds(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                    const unsigned long long imageViewIndex = 0ull);\n\n        Array<long long> extractIdsLockThread(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                              const unsigned long long imageViewIndex,\n                                              const long long frameId);\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplPersonIdExtractor;\n        std::shared_ptr<ImplPersonIdExtractor> spImpl;\n\n        DELETE_COPY(PersonIdExtractor);\n    };\n}\n\n#endif // OPENPOSE_TRACKING_PERSON_ID_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/tracking/personTracker.hpp",
    "content": "#ifndef OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP\n#define OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    class OP_API PersonTracker\n    {\n    public:\n        PersonTracker(const bool mergeResults, const int levels = 3, const int patchSize = 31,\n                      const float confidenceThreshold = 0.05f, const bool trackVelocity = false,\n                      const bool scaleVarying = false, const float rescale = 640);\n\n        virtual ~PersonTracker();\n\n        void track(Array<float>& poseKeypoints, Array<long long>& poseIds, const Matrix& cvMatInput);\n\n        void trackLockThread(Array<float>& poseKeypoints, Array<long long>& poseIds, const Matrix& cvMatInput,\n                             const long long frameId);\n\n        bool getMergeResults() const;\n\n    private:\n        // PIMPL idiom\n        // http://www.cppsamples.com/common-tasks/pimpl.html\n        struct ImplPersonTracker;\n        std::shared_ptr<ImplPersonTracker> spImpl;\n\n        DELETE_COPY(PersonTracker);\n    };\n}\n\n#endif // OPENPOSE_OPENPOSE_PRIVATE_TRACKING_PERSON_TRACKER_HPP\n"
  },
  {
    "path": "include/openpose/tracking/wPersonIdExtractor.hpp",
    "content": "#ifndef OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP\n#define OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/worker.hpp>\n#include <openpose/tracking/personIdExtractor.hpp>\n\nnamespace op\n{\n    template<typename TDatums>\n    class WPersonIdExtractor : public Worker<TDatums>\n    {\n    public:\n        explicit WPersonIdExtractor(const std::shared_ptr<PersonIdExtractor>& personIdExtractor);\n\n        virtual ~WPersonIdExtractor();\n\n        void initializationOnThread();\n\n        void work(TDatums& tDatums);\n\n    private:\n        std::shared_ptr<PersonIdExtractor> spPersonIdExtractor;\n\n        DELETE_COPY(WPersonIdExtractor);\n    };\n}\n\n\n\n\n\n// Implementation\n#include <openpose/utilities/pointerContainer.hpp>\nnamespace op\n{\n    template<typename TDatums>\n    WPersonIdExtractor<TDatums>::WPersonIdExtractor(const std::shared_ptr<PersonIdExtractor>& personIdExtractor) :\n        spPersonIdExtractor{personIdExtractor}\n    {\n    }\n\n    template<typename TDatums>\n    WPersonIdExtractor<TDatums>::~WPersonIdExtractor()\n    {\n    }\n\n    template<typename TDatums>\n    void WPersonIdExtractor<TDatums>::initializationOnThread()\n    {\n    }\n\n    template<typename TDatums>\n    void WPersonIdExtractor<TDatums>::work(TDatums& tDatums)\n    {\n        try\n        {\n            if (checkNoNullNorEmpty(tDatums))\n            {\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Profiling speed\n                const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n                // Render people pose\n                for (auto& tDatumPtr : *tDatums)\n                    tDatumPtr->poseIds = spPersonIdExtractor->extractIds(\n                        tDatumPtr->poseKeypoints, tDatumPtr->cvInputData);\n                // Profiling speed\n                Profiler::timerEnd(profilerKey);\n                Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__);\n                // Debugging log\n                opLogIfDebug(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            this->stop();\n            tDatums = nullptr;\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_DATUM(WPersonIdExtractor);\n}\n\n#endif // OPENPOSE_TRACKING_W_PERSON_ID_EXTRACTOR_HPP\n"
  },
  {
    "path": "include/openpose/unity/headers.hpp",
    "content": "#ifndef OPENPOSE_UNITY_HEADERS_HPP\n#define OPENPOSE_UNITY_HEADERS_HPP\n\n// unity module\n#include <openpose/unity/unityBinding.hpp>\n\n#endif // OPENPOSE_UNITY_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/unity/unityBinding.hpp",
    "content": "// Temporarily, all the code is located in\n// src/openpose/unity/unityBinding.cpp\n// TODO: Move functionality from unityBinding.cpp to this class\n"
  },
  {
    "path": "include/openpose/utilities/check.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_CHECK_HPP\n#define OPENPOSE_UTILITIES_CHECK_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    // CHECK, CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, and CHECK_GT\n    template<typename T>\n    void checkBool(\n        const bool condition, const T& message = \"\", const int line = -1, const std::string& function = \"\",\n        const std::string& file = \"\")\n    {\n        if (!condition)\n            error(\"Check failed: \" + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkEqual(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA != conditionB)\n            error(\"CheckE failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkNotEqual(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA == conditionB)\n            error(\"CheckNE failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkLessOrEqual(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA > conditionB)\n            error(\"CheckLE failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkLessThan(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA >= conditionB)\n            error(\"CheckLT failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkGreaterOrEqual(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA < conditionB)\n            error(\"CheckGE failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n\n    template<typename T, typename T1, typename T2>\n    void checkGreaterThan(\n        const T1& conditionA, const T2& conditionB, const T& message = \"\", const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        if (conditionA <= conditionB)\n            error(\"CheckGT failed (\" + tToString(conditionA) + \" vs. \" + tToString(conditionB) + \"): \"\n                  + tToString(message), line, function, file);\n    }\n}\n\n#endif // OPENPOSE_UTILITIES_CHECK_HPP\n"
  },
  {
    "path": "include/openpose/utilities/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_ENUM_CLASSES_HPP\n#define OPENPOSE_UTILITIES_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class ErrorMode : unsigned char\n    {\n        StdRuntimeError,\n        FileLogging,\n        StdCerr,\n        All,\n    };\n\n    enum class LogMode : unsigned char\n    {\n        FileLogging,\n        StdCout,\n        All,\n    };\n\n    enum class Priority : unsigned char\n    {\n        None = 0,\n        Low = 1,\n        Normal = 2,\n        High = 3,\n        Max = 4,\n        NoOutput = 255,\n    };\n\n    enum class Extensions : unsigned char\n    {\n        Images, // jpg, png, ...\n        Size\n    };\n}\n\n#endif // OPENPOSE_UTILITIES_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/utilities/errorAndLog.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP\n#define OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP\n\n#include <sstream> // std::stringstream\n#include <string>\n#include <vector>\n#include <openpose/core/macros.hpp>\n#include <openpose/utilities/enumClasses.hpp>\n\nnamespace op\n{\n    OP_API void setMainThread();\n\n    OP_API std::string getThreadId();\n\n    OP_API bool getIfInMainThreadOrEmpty();\n\n    OP_API bool getIfNotInMainThreadOrEmpty();\n\n    template<typename T>\n    std::string tToString(const T& message)\n    {\n        // Message -> ostringstream\n        std::ostringstream oss;\n        oss << message;\n        // ostringstream -> std::string\n        return oss.str();\n    }\n\n    /**\n     * Differences between different kind of errors:\n     *  - error() is a normal error in the code.\n     *  - errorWorker() is an error that occurred on a thread. Therefore, the machine will stop the threads, go back\n     *    to the main thread, and then throw the error.\n     *  - errorDestructor() is an error that occurred on a destructor. Exception on destructors provokes core dumped,\n     *    so we simply output an error message via std::cerr.\n     */\n\n    // Error management - How to use:\n        // error(message, __LINE__, __FUNCTION__, __FILE__);\n    OP_API void error(\n        const std::string& message, const int line = -1, const std::string& function = \"\",\n        const std::string& file = \"\");\n\n    template<typename T>\n    inline void error(\n        const T& message, const int line = -1, const std::string& function = \"\", const std::string& file = \"\")\n    {\n        error(tToString(message), line, function, file);\n    }\n\n    // Worker error management\n    OP_API void checkWorkerErrors();\n\n    OP_API void errorWorker(\n        const std::string& message, const int line = -1, const std::string& function = \"\",\n        const std::string& file = \"\");\n\n    template<typename T>\n    inline void errorWorker(\n        const T& message, const int line = -1, const std::string& function = \"\", const std::string& file = \"\")\n    {\n        errorWorker(tToString(message), line, function, file);\n    }\n\n    // Destructor error management\n    OP_API void errorDestructor(\n        const std::string& message, const int line = -1, const std::string& function = \"\",\n        const std::string& file = \"\");\n\n    template<typename T>\n    inline void errorDestructor(\n        const T& message, const int line = -1, const std::string& function = \"\", const std::string& file = \"\")\n    {\n        errorDestructor(tToString(message), line, function, file);\n    }\n\n    // Printing info - How to use:\n        // It will print info if desiredPriority >= sPriorityThreshold\n        // opLog(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__);\n    OP_API void opLog(\n        const std::string& message, const Priority priority = Priority::Max, const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\");\n\n    template<typename T>\n    inline void opLog(\n        const T& message, const Priority priority = Priority::Max, const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        opLog(tToString(message), priority, line, function, file);\n    }\n\n    // If only desired on debug mode (no computational cost at all on release mode):\n        // It will print info if desiredPriority >= sPriorityThreshold\n        // opLogIfDebug(message, desiredPriority, __LINE__, __FUNCTION__, __FILE__);\n    template<typename T>\n    inline void opLogIfDebug(\n        const T& message, const Priority priority = Priority::Max, const int line = -1,\n        const std::string& function = \"\", const std::string& file = \"\")\n    {\n        #ifndef NDEBUG\n            opLog(message, priority, line, function, file);\n        #else\n            UNUSED(message);\n            UNUSED(priority);\n            UNUSED(line);\n            UNUSED(function);\n            UNUSED(file);\n        #endif\n    }\n\n    // This class is thread-safe\n    namespace ConfigureError\n    {\n        OP_API std::vector<ErrorMode> getErrorModes();\n\n        OP_API void setErrorModes(const std::vector<ErrorMode>& errorModes);\n    }\n\n    // This class is not fully thread-safe\n    namespace ConfigureLog\n    {\n        OP_API Priority getPriorityThreshold();\n\n        OP_API const std::vector<LogMode>& getLogModes();\n\n        // This function is not thread-safe. It must be run at the beginning\n        OP_API void setPriorityThreshold(const Priority priorityThreshold);\n\n        // This function is not thread-safe. It must be run at the beginning\n        OP_API void setLogModes(const std::vector<LogMode>& loggingModes);\n    }\n}\n\n#endif // OPENPOSE_UTILITIES_ERROR_AND_LOG_HPP\n"
  },
  {
    "path": "include/openpose/utilities/fastMath.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_MATH_HPP\n#define OPENPOSE_UTILITIES_MATH_HPP\n\nnamespace op\n{\n    // Use op::round/max/min for basic types (int, char, long, float, double, etc). Never with classes!\n    // `std::` alternatives uses 'const T&' instead of 'const T' as argument.\n    // E.g., std::round is really slow (~300 ms vs ~10 ms when I individually apply it to each element of a whole\n    // image array\n\n    // VERY IMPORTANT: These fast functions does NOT work for negative integer numbers.\n    // E.g., positiveIntRound(-180.f) = -179.\n\n    // Round functions\n    // Signed\n    template<typename T>\n    inline char positiveCharRound(const T a)\n    {\n        return char(a+0.5f);\n    }\n\n    template<typename T>\n    inline signed char positiveSCharRound(const T a)\n    {\n        return (signed char)(a+0.5f);\n    }\n\n    template<typename T>\n    inline int positiveIntRound(const T a)\n    {\n        return int(a+0.5f);\n    }\n\n    template<typename T>\n    inline long positiveLongRound(const T a)\n    {\n        return long(a+0.5f);\n    }\n\n    template<typename T>\n    inline long long positiveLongLongRound(const T a)\n    {\n        return (long long)(a+0.5f);\n    }\n\n    // Unsigned\n    template<typename T>\n    inline unsigned char uCharRound(const T a)\n    {\n        return (unsigned char)(a+0.5f);\n    }\n\n    template<typename T>\n    inline unsigned int uIntRound(const T a)\n    {\n        return (unsigned int)(a+0.5f);\n    }\n\n    template<typename T>\n    inline unsigned long ulongRound(const T a)\n    {\n        return (unsigned long)(a+0.5f);\n    }\n\n    template<typename T>\n    inline unsigned long long uLongLongRound(const T a)\n    {\n        return (unsigned long long)(a+0.5f);\n    }\n\n    // Max/min functions\n    template<typename T>\n    inline T fastMax(const T a, const T b)\n    {\n        return (a > b ? a : b);\n    }\n\n    template<typename T>\n    inline T fastMin(const T a, const T b)\n    {\n        return (a < b ? a : b);\n    }\n\n    template<class T>\n    inline T fastTruncate(T value, T min = 0, T max = 1)\n    {\n        return fastMin(max, fastMax(min, value));\n    }\n}\n\n#endif // OPENPOSE_UTILITIES_MATH_HPP\n"
  },
  {
    "path": "include/openpose/utilities/fileSystem.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_FILE_SYSTEM_HPP\n#define OPENPOSE_UTILITIES_FILE_SYSTEM_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    OP_API void makeDirectory(const std::string& directoryPath);\n\n    OP_API bool existDirectory(const std::string& directoryPath);\n\n    OP_API bool existFile(const std::string& filePath);\n\n    /**\n     * This function makes sure that the directoryPathString is properly formatted. I.e., it\n     * changes all '\\' by '/', and it makes sure that the string finishes with '/'.\n     * @param directoryPathString std::string with the directory path to be formatted.\n     * @return std::string with the formatted directory path.\n     */\n    OP_API std::string formatAsDirectory(const std::string& directoryPathString);\n\n    /**\n     * This function extracts the file name and extension from a full path.\n     * @param fullPath std::string with the full path.\n     * @return std::string with the file name with extension.\n     */\n    OP_API std::string getFileNameAndExtension(const std::string& fullPath);\n\n    /**\n     * This function extracts the file name (without extension) from a full path.\n     * @param fullPath std::string with the full path.\n     * @return std::string with the file name without extension.\n     */\n    OP_API std::string getFileNameNoExtension(const std::string& fullPath);\n\n    /**\n     * This function extracts the extension from a full path.\n     * E.g., if fullPath is `/media/document.txt`, output will be `txt`\n     * @param fullPath std::string with the full path.\n     * @return std::string with the file extension.\n     */\n    OP_API std::string getFileExtension(const std::string& fullPath);\n\n    /**\n     * This function extracts the full file path without its extension from a full file path.\n     * @param fullPath std::string with the full path.\n     * @return std::string with the full file path without extension.\n     */\n    OP_API std::string getFullFilePathNoExtension(const std::string& fullPath);\n\n    /**\n     * This function extracts the full file path of the folder where it is contained.\n     * @param fullPath std::string with the full path.\n     * @return std::string with the full file path of the folder.\n     */\n    OP_API std::string getFileParentFolderPath(const std::string& fullPath);\n\n    /**\n     * This function extracts all the files in a directory path with the desired\n     * extensions. If no extensions is specified, then all the file names are returned.\n     * @param directoryPath std::string with the directory path.\n     * @param extensions std::vector<std::string> with the extensions of the desired files.\n     * @return std::vector<std::string> with the existing file names.\n     */\n    OP_API std::vector<std::string> getFilesOnDirectory(\n        const std::string& directoryPath, const std::vector<std::string>& extensions = {});\n\n    /**\n     * Analogous to getFilesOnDirectory(const std::string& directoryPath, const std::vector<std::string>& extensions)\n     * for 1 specific extension.\n     * @param directoryPath std::string with the directory path.\n     * @param extension std::string with the extension of the desired files.\n     * @return std::vector<std::string> with the existing file names.\n     */\n    OP_API std::vector<std::string> getFilesOnDirectory(\n        const std::string& directoryPath, const std::string& extension);\n\n    /**\n     * This function extracts all the files in a directory path with the desired\n     * group of extensions (e.g., Extensions::Images).\n     * @param directoryPath std::string with the directory path.\n     * @param extensions Extensions with the kind of extensions desired (e.g., Extensions:Images).\n     * @return std::vector<std::string> with the existing file names.\n     */\n    OP_API std::vector<std::string> getFilesOnDirectory(\n        const std::string& directoryPath, const Extensions extensions);\n\n    OP_API std::string removeSpecialsCharacters(const std::string& stringToVariate);\n\n    OP_API void removeAllOcurrencesOfSubString(std::string& stringToModify, const std::string& substring);\n\n    OP_API void replaceAll(std::string& stringText, const char charToChange, const char charToAdd);\n}\n\n#endif // OPENPOSE_UTILITIES_FILE_SYSTEM_HPP\n"
  },
  {
    "path": "include/openpose/utilities/flagsToOpenPose.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP\n#define OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/gui/enumClasses.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/producer/enumClasses.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n\nnamespace op\n{\n    OP_API PoseMode flagsToPoseMode(const int poseModeInt);\n\n    OP_API PoseModel flagsToPoseModel(const String& poseModeString);\n\n    OP_API ScaleMode flagsToScaleMode(const int keypointScaleMode);\n\n    OP_API ScaleMode flagsToHeatMapScaleMode(const int heatMapScaleMode);\n\n    OP_API Detector flagsToDetector(const int detector);\n\n    // Determine type of frame source\n    OP_API ProducerType flagsToProducerType(\n        const String& imageDirectory, const String& videoPath, const String& ipCameraPath,\n        const int webcamIndex, const bool flirCamera);\n\n    OP_API std::pair<ProducerType, String> flagsToProducer(\n        const String& imageDirectory, const String& videoPath, const String& ipCameraPath = String(\"\"),\n        const int webcamIndex = -1, const bool flirCamera = false, const int flirCameraIndex = -1);\n\n    OP_API std::vector<HeatMapType> flagsToHeatMaps(\n        const bool heatMapsAddParts = false, const bool heatMapsAddBkg = false,\n        const bool heatMapsAddPAFs = false);\n\n    OP_API RenderMode flagsToRenderMode(\n        const int renderFlag, const bool gpuBuggy = false, const int renderPoseFlag = -2);\n\n    OP_API DisplayMode flagsToDisplayMode(const int display, const bool enabled3d);\n\n    /**\n     * E.g., const Point<int> netInputSize = flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\n     * E.g., const Point<int> resolution = flagsToPoint(resolutionString, \"1280x720\");\n     */\n    OP_API Point<int> flagsToPoint(const String& pointString, const String& pointExample);\n}\n\n#endif // OPENPOSE_UTILITIES_FLAGS_TO_OPEN_POSE_HPP\n"
  },
  {
    "path": "include/openpose/utilities/headers.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_HEADERS_HPP\n#define OPENPOSE_UTILITIES_HEADERS_HPP\n\n// utilities module\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/enumClasses.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/flagsToOpenPose.hpp>\n#include <openpose/utilities/keypoint.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose/utilities/pointerContainer.hpp>\n#include <openpose/utilities/profiler.hpp>\n#include <openpose/utilities/standard.hpp>\n#include <openpose/utilities/string.hpp>\n\n#endif // OPENPOSE_UTILITIES_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/utilities/keypoint.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_KEYPOINT_HPP\n#define OPENPOSE_UTILITIES_KEYPOINT_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template <typename T>\n    T getDistance(const Array<T>& keypoints, const int person, const int elementA, const int elementB);\n\n    template <typename T>\n    void averageKeypoints(Array<T>& keypointsA, const Array<T>& keypointsB, const int personA);\n\n    template <typename T>\n    void scaleKeypoints(Array<T>& keypoints, const T scale);\n\n    template <typename T>\n    void scaleKeypoints2d(Array<T>& keypoints, const T scaleX, const T scaleY);\n\n    template <typename T>\n    void scaleKeypoints2d(Array<T>& keypoints, const T scaleX, const T scaleY, const T offsetX, const T offsetY);\n\n    template <typename T>\n    void renderKeypointsCpu(\n        Array<T>& frameArray, const Array<T>& keypoints, const std::vector<unsigned int>& pairs,\n        const std::vector<T> colors, const T thicknessCircleRatio, const T thicknessLineRatioWRTCircle,\n        const std::vector<T>& poseScales, const T threshold);\n\n    template <typename T>\n    Rectangle<T> getKeypointsRectangle(\n        const Array<T>& keypoints, const int person, const T threshold, const int firstIndex = 0,\n        const int lastIndex = -1);\n\n    template <typename T>\n    T getAverageScore(const Array<T>& keypoints, const int person);\n\n    template <typename T>\n    T getKeypointsArea(const Array<T>& keypoints, const int person, const T threshold);\n\n    template <typename T>\n    int getBiggestPerson(const Array<T>& keypoints, const T threshold);\n\n    template <typename T>\n    int getNonZeroKeypoints(const Array<T>& keypoints, const int person, const T threshold);\n\n    template <typename T>\n    T getDistanceAverage(const Array<T>& keypoints, const int personA, const int personB, const T threshold);\n\n    template <typename T>\n    T getDistanceAverage(\n        const Array<T>& keypointsA, const int personA, const Array<T>& keypointsB, const int personB,\n        const T threshold);\n\n    /**\n     * Creates and Array<T> with a specific person.\n     * @param keypoints Array<T> with the original data array to slice.\n     * @param person indicates the index of the array to extract.\n     * @param noCopy indicates whether to perform a copy. Copy will never go to undefined behavior, however, if\n     * noCopy == true, then:\n     *     1. It is faster, as no data copy is involved, but...\n     *     2. If the Array keypoints goes out of scope, then the resulting Array will provoke an undefined behavior.\n     *     3. If the returned Array is modified, the information in the Array keypoints will also be.\n     * @return Array<T> with the same dimension than keypoints expect the first dimension being 1. E.g., if keypoints\n     * is {p,k,m}, the resulting Array<T> is {1,k,m}.\n     */\n    template <typename T>\n    Array<T> getKeypointsPerson(const Array<T>& keypoints, const int person, const bool noCopy = false);\n\n    template <typename T>\n    float getKeypointsRoi(const Array<T>& keypoints, const int personA, const int personB, const T threshold);\n\n    template <typename T>\n    float getKeypointsRoi(\n        const Array<T>& keypointsA, const int personA, const Array<T>& keypointsB, const int personB,\n        const T threshold);\n\n    template <typename T>\n    float getKeypointsRoi(\n        const Rectangle<T>& rectangleA, const Rectangle<T>& rectangleB);\n}\n\n#endif // OPENPOSE_UTILITIES_KEYPOINT_HPP\n"
  },
  {
    "path": "include/openpose/utilities/openCv.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_OPEN_CV_HPP\n#define OPENPOSE_UTILITIES_OPEN_CV_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    OP_API void unrollArrayToUCharCvMat(Matrix& matResult, const Array<float>& array);\n\n    OP_API void uCharCvMatToFloatPtr(float* floatPtrImage, const Matrix& matImage, const int normalize);\n\n    OP_API double resizeGetScaleFactor(const Point<int>& initialSize, const Point<int>& targetSize);\n\n    OP_API void keepRoiInside(Rectangle<int>& roi, const int imageWidth, const int imageHeight);\n\n    OP_API void transpose(Matrix& matrix);\n\n    /**\n     * It performs rotation and flipping over the desired Mat.\n     * @param cvMat Mat with the frame matrix to be rotated and/or flipped.\n     * @param rotationAngle How much the cvMat element should be rotated. 0 would mean no rotation.\n     * @param flipFrame Whether to flip the cvMat element. Set to false to disable it.\n     */\n    OP_API void rotateAndFlipFrame(Matrix& frame, const double rotationAngle, const bool flipFrame = false);\n\n    /**\n     * Wrapper of CV_CAP_PROP_FRAME_COUNT to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvCapPropFrameCount();\n\n    /**\n     * Wrapper of CV_CAP_PROP_FRAME_FPS to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvCapPropFrameFps();\n\n    /**\n     * Wrapper of CV_CAP_PROP_FRAME_WIDTH to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvCapPropFrameWidth();\n\n    /**\n     * Wrapper of CV_CAP_PROP_FRAME_HEIGHT to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvCapPropFrameHeight();\n\n    /**\n     * Wrapper of CV_FOURCC to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvFourcc(const char c1, const char c2, const char c3, const char c4);\n\n    /**\n     * Wrapper of CV_IMWRITE_JPEG_QUALITY to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvImwriteJpegQuality();\n\n    /**\n     * Wrapper of CV_IMWRITE_PNG_COMPRESSION to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvImwritePngCompression();\n\n    /**\n     * Wrapper of CV_LOAD_IMAGE_ANYDEPTH to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvLoadImageAnydepth();\n\n    /**\n     * Wrapper of CV_LOAD_IMAGE_GRAYSCALE to avoid leaving OpenCV dependencies on headers.\n     */\n    OP_API int getCvLoadImageGrayScale();\n}\n\n#endif // OPENPOSE_UTILITIES_OPEN_CV_HPP\n"
  },
  {
    "path": "include/openpose/utilities/pointerContainer.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP\n#define OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP\n\nnamespace op\n{\n    template<typename TPointerContainer>\n    inline bool checkNoNullNorEmpty(const TPointerContainer& tPointerContainer)\n    {\n        return (tPointerContainer != nullptr && tPointerContainer->size() > 0);\n    }\n\n    template<typename TDatumsSP>\n    class PointerContainerGreater\n    {\n    public:\n        bool operator() (const TDatumsSP& a, const TDatumsSP& b)\n        {\n            if (!b || b->empty())\n                return true;\n            else if (!a || a->empty())\n                return false;\n            else\n                return *(*a)[0] > *(*b)[0];\n        }\n    };\n\n    template<typename TDatumsSP>\n    class PointerContainerLess\n    {\n    public:\n        bool operator() (const TDatumsSP& a, const TDatumsSP& b)\n        {\n            if (!b || b->empty())\n                return false;\n            else if (!a || a->empty())\n                return true;\n            else\n                return *(*a)[0] < *(*b)[0];\n        }\n    };\n}\n\n#endif // OPENPOSE_UTILITIES_POINTER_CONTAINER_HPP\n"
  },
  {
    "path": "include/openpose/utilities/profiler.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_PROFILER_HPP\n#define OPENPOSE_UTILITIES_PROFILER_HPP\n\n#include <chrono>\n#include <string>\n#include <openpose/core/macros.hpp>\n#include <openpose/utilities/enumClasses.hpp>\n\nnamespace op\n{\n    // The following functions provides basic functions to measure time. Usage example:\n    //     const auto timerInit = getTimerInit();\n    //         // [Some code in here]\n    //     const auto timeSeconds = getTimeSeconds(timerInit);\n    //     const printTime(timeSeconds, \"Function X took \", \" seconds.\");\n    OP_API std::chrono::time_point<std::chrono::high_resolution_clock> getTimerInit();\n\n    OP_API double getTimeSeconds(const std::chrono::time_point<std::chrono::high_resolution_clock>& timerInit);\n\n    OP_API void printTime(\n        const std::chrono::time_point<std::chrono::high_resolution_clock>& timerInit, const std::string& firstMessage,\n        const std::string& secondMessage, const Priority priority);\n\n    // The following functions will run REPS times and average the final time in seconds. Usage example:\n    //     const auto REPS = 1000;\n    //     double time = 0.;\n    //     OP_PROFILE_INIT(REPS);\n    //         // [Some code in here]\n    //     OP_PROFILE_END(time, 1e3, REPS); // Time in msec. 1 = sec, 1e3 = msec, 1e6 = usec, 1e9 = nsec, etc.\n    //     opLog(\"Function X took \" + std::to_string(time) + \" milliseconds.\");\n    #define OP_PROFILE_INIT(REPS) \\\n    { \\\n        const auto timerInit = getTimerInit(); \\\n        for (auto rep = 0 ; rep < (REPS) ; ++rep) \\\n        {\n    #define OP_PROFILE_END(finalTime, factor, REPS) \\\n        } \\\n        (finalTime) = (factor)/(float)(REPS)*getTimeSeconds(timerInit); \\\n    }\n\n    // The following functions will run REPS times, wait for the kernels to finish, and then average the final time\n    // in seconds. Usage example:\n    //     const auto REPS = 1000;\n    //     double time = 0.;\n    //     OP_CUDA_PROFILE_INIT(REPS);\n    //         // [Some code with CUDA calls in here]\n    //     OP_CUDA_PROFILE_END(time, 1e3, REPS); // Time in msec. 1 = sec, 1e3 = msec, 1e6 = usec, 1e9 = nsec, etc.\n    //     opLog(\"Function X took \" + std::to_string(time) + \" milliseconds.\");\n    // Analogous to OP_PROFILE_INIT, but also waits for CUDA kernels to finish their asynchronous operations\n    // It requires: #include <cuda_runtime.h>\n    #define OP_CUDA_PROFILE_INIT(REPS) \\\n    { \\\n        cudaDeviceSynchronize(); \\\n        const auto timerInit = getTimerInit(); \\\n        for (auto rep = 0 ; rep < (REPS) ; ++rep) \\\n        {\n    // Analogous to OP_PROFILE_END, but also waits for CUDA kernels to finish their asynchronous operations\n    // It requires: #include <cuda_runtime.h>\n    #define OP_CUDA_PROFILE_END(finalTime, factor, REPS) \\\n        } \\\n        cudaDeviceSynchronize(); \\\n        (finalTime) = (factor)/(float)(REPS)*getTimeSeconds(timerInit); \\\n        cudaCheck(__LINE__, __FUNCTION__, __FILE__); \\\n    }\n\n    // Enable PROFILER_ENABLED on Makefile.config or CMake in order to use this function. Otherwise nothing will be outputted.\n    // How to use - example:\n    // For GPU - It can only be applied in the main.cpp file:\n        // Profiler::profileGpuMemory(__LINE__, __FUNCTION__, __FILE__);\n    // For time:\n        // // ... inside continuous loop ...\n        // const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n        // // functions to do...\n        // Profiler::timerEnd(profilerKey);\n        // Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, NUMBER_ITERATIONS);\n    class OP_API Profiler\n    {\n    public:\n        static unsigned long long DEFAULT_X;\n\n        // Non-thread safe, it must be performed at the beginning of the code before any parallelization occurs\n        static void setDefaultX(const unsigned long long defaultX);\n\n        static const std::string timerInit(const int line, const std::string& function, const std::string& file);\n\n        static void timerEnd(const std::string& key);\n\n        static void printAveragedTimeMsOnIterationX(\n            const std::string& key, const int line, const std::string& function, const std::string& file,\n            const unsigned long long x = DEFAULT_X);\n\n        static void printAveragedTimeMsEveryXIterations(\n            const std::string& key, const int line, const std::string& function, const std::string& file,\n            const unsigned long long x = DEFAULT_X);\n\n        static void profileGpuMemory(const int line, const std::string& function, const std::string& file);\n    };\n}\n\n#endif // OPENPOSE_UTILITIES_PROFILER_HPP\n"
  },
  {
    "path": "include/openpose/utilities/standard.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_STANDARD_HPP\n#define OPENPOSE_UTILITIES_STANDARD_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    template <typename T>\n    bool vectorsAreEqual(const std::vector<T>& vectorA, const std::vector<T>& vectorB)\n    {\n        try\n        {\n            if (vectorA.size() != vectorB.size())\n                return false;\n            else\n            {\n                for (auto i = 0u ; i < vectorA.size() ; i++)\n                    if (vectorA[i] != vectorB[i])\n                        return false;\n                return true;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    /**\n     * std::vector<T> concatenator.\n     * Auxiliary function that concatenate std::vectors of any class type T.\n     * It assumes basic copy (ideal for smart pointers, pointers, etc.), so note that the copy still shares the same\n     * internal data. It will not work for element that cannot be copied.\n     * @param vectorA First std::shared_ptr<T> element to be concatenated.\n     * @param vectorB Second std::shared_ptr<T> element to be concatenated.\n     * @return Concatenated std::vector<T> of both vectorA and vectorB.\n     */\n    template <typename T>\n    std::vector<T> mergeVectors(const std::vector<T>& vectorA, const std::vector<T>& vectorB)\n    {\n        try\n        {\n            auto vectorToReturn(vectorA);\n            for (auto& tElement : vectorB)\n                vectorToReturn.emplace_back(tElement);\n            return vectorToReturn;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<T>{};\n        }\n    }\n}\n\n#endif // OPENPOSE_UTILITIES_STANDARD_HPP\n"
  },
  {
    "path": "include/openpose/utilities/string.hpp",
    "content": "#ifndef OPENPOSE_UTILITIES_STRING_HPP\n#define OPENPOSE_UTILITIES_STRING_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    OP_API unsigned long long getLastNumber(const std::string& string);\n\n    /**\n     * This template function turns an integer number into a fixed-length std::string.\n     * @param number T integer corresponding to the integer to be formatted.\n     * @param stringLength unsigned long long indicating the final length. If 0, the\n     * final length is the original number length.\n     * @return std::string with the formatted value.\n     */\n    template<typename T>\n    std::string toFixedLengthString(const T number, const unsigned long long stringLength = 0);\n\n    OP_API std::vector<std::string> splitString(const std::string& stringToSplit, const std::string& delimiter);\n\n    OP_API std::string toLower(const std::string& string);\n\n    OP_API std::string toUpper(const std::string& string);\n\n    OP_API std::string remove0sFromString(const std::string& string);\n\n    OP_API std::string getFirstNumberOnString(const std::string& string);\n}\n\n#endif // OPENPOSE_UTILITIES_STRING_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/enumClasses.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_ENUM_CLASSES_HPP\n#define OPENPOSE_WRAPPER_ENUM_CLASSES_HPP\n\nnamespace op\n{\n    enum class PoseMode : unsigned char\n    {\n        Disabled = 0,\n        Enabled,\n        NoNetwork,\n        Size,\n    };\n\n    enum class Detector : unsigned char\n    {\n        Body = 0,\n        OpenCV,\n        Provided,\n        BodyWithTracking,\n        Size,\n    };\n\n    enum class WorkerType : unsigned char\n    {\n        Input = 0,\n        PreProcessing,\n        PostProcessing,\n        Output,\n        Size,\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_ENUM_CLASSES_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/headers.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_HEADERS_HPP\n#define OPENPOSE_WRAPPER_HEADERS_HPP\n\n// wrapper module\n#include <openpose/wrapper/enumClasses.hpp>\n#include <openpose/wrapper/wrapper.hpp>\n#include <openpose/wrapper/wrapperAuxiliary.hpp>\n#include <openpose/wrapper/wrapperStructFace.hpp>\n#include <openpose/wrapper/wrapperStructGui.hpp>\n#include <openpose/wrapper/wrapperStructHand.hpp>\n#include <openpose/wrapper/wrapperStructInput.hpp>\n#include <openpose/wrapper/wrapperStructOutput.hpp>\n#include <openpose/wrapper/wrapperStructPose.hpp>\n\n#endif // OPENPOSE_WRAPPER_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapper.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/thread/headers.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n#include <openpose/wrapper/wrapperStructExtra.hpp>\n#include <openpose/wrapper/wrapperStructFace.hpp>\n#include <openpose/wrapper/wrapperStructGui.hpp>\n#include <openpose/wrapper/wrapperStructHand.hpp>\n#include <openpose/wrapper/wrapperStructInput.hpp>\n#include <openpose/wrapper/wrapperStructOutput.hpp>\n#include <openpose/wrapper/wrapperStructPose.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperT: OpenPose all-in-one wrapper template class. Simplified into Wrapper for WrapperT<std::vector<Datum>>\n     * WrapperT allows the user to set up the input (video, webcam, custom input, etc.), pose, face and/or hands\n     * estimation and rendering, and output (integrated small GUI, custom output, etc.).\n     *\n     * This function can be used in 2 ways:\n     *     - Synchronous mode: call the full constructor with your desired input and output workers.\n     *     - Asynchronous mode: call the empty constructor WrapperT() + use the emplace and pop functions to push the\n     *       original frames and retrieve the processed ones.\n     *     - Mix of them:\n     *         - Synchronous input + asynchronous output: call the constructor WrapperT(ThreadManagerMode::Synchronous,\n     *           workersInput, {}, true)\n     *         - Asynchronous input + synchronous output: call the constructor\n     *           WrapperT(ThreadManagerMode::Synchronous, nullptr, workersOutput, irrelevantBoolean, true)\n     */\n    template<typename TDatum = BASE_DATUM,\n             typename TDatums = std::vector<std::shared_ptr<TDatum>>,\n             typename TDatumsSP = std::shared_ptr<TDatums>,\n             typename TWorker = std::shared_ptr<Worker<TDatumsSP>>>\n    class WrapperT\n    {\n    public:\n        /**\n         * Constructor.\n         * @param threadManagerMode Thread synchronization mode. If set to ThreadManagerMode::Synchronous, everything\n         * will run inside the WrapperT. If ThreadManagerMode::Synchronous(In/Out), then input (frames producer) and/or\n         * output (GUI, writing results, etc.) will be controlled outside the WrapperT class by the user. See\n         * ThreadManagerMode for a detailed explanation of when to use each one.\n         */\n        explicit WrapperT(const ThreadManagerMode threadManagerMode = ThreadManagerMode::Synchronous);\n\n        /**\n         * Destructor.\n         * It automatically frees resources.\n         */\n        virtual ~WrapperT();\n\n        /**\n         * Disable multi-threading.\n         * Useful for debugging and logging, all the Workers will run in the same thread.\n         * Note that workerOnNewThread (argument for setWorker function) will not make any effect.\n         */\n        void disableMultiThreading();\n\n        /**\n         * Add an user-defined extra Worker for a desired task (input, output, ...).\n         * @param workerType WorkerType to configure (e.g., Input, PreProcessing, PostProcessing, Output).\n         * @param worker TWorker to be added.\n         * @param workerOnNewThread Whether to add this TWorker on a new thread (if it is computationally demanding) or\n         * simply reuse existing threads (for light functions). Set to true if the performance time is unknown.\n         */\n        void setWorker(const WorkerType workerType, const TWorker& worker, const bool workerOnNewThread = true);\n\n        /**\n         * It configures the pose parameters. Do not call for default values.\n         */\n        void configure(const WrapperStructPose& wrapperStructPose);\n\n        /**\n         * Analogous to configure(WrapperStructPose) but applied to face (WrapperStructFace)\n         */\n        void configure(const WrapperStructFace& wrapperStructFace);\n\n        /**\n         * Analogous to configure() but applied to hand (WrapperStructHand)\n         */\n        void configure(const WrapperStructHand& wrapperStructHand);\n\n        /**\n         * Analogous to configure() but applied to the extra options (WrapperStructExtra)\n         */\n        void configure(const WrapperStructExtra& wrapperStructExtra);\n\n        /**\n         * Analogous to configure() but applied to the input (WrapperStructInput)\n         */\n        void configure(const WrapperStructInput& wrapperStructInput);\n\n        /**\n         * Analogous to configure() but applied to the output (WrapperStructOutput)\n         */\n        void configure(const WrapperStructOutput& wrapperStructOutput);\n\n        /**\n         * Analogous to configure() but applied to the GUI (WrapperStructGui)\n         */\n        void configure(const WrapperStructGui& wrapperStructGui);\n\n        /**\n         * Function to start multi-threading.\n         * Similar to start(), but exec() blocks the thread that calls the function (it saves 1 thread). Use exec()\n         * instead of start() if the calling thread will otherwise be waiting for the WrapperT to end.\n         */\n        void exec();\n\n        /**\n         * Function to start multi-threading.\n         * Similar to exec(), but start() does not block the thread that calls the function. It just opens new threads,\n         * so it lets the user perform other tasks meanwhile on the calling thread.\n         * VERY IMPORTANT NOTE: if the GUI is selected and OpenCV is compiled with Qt support, this option will not\n         * work. Qt needs the main thread to plot visual results, so the final GUI (which uses OpenCV) would return an\n         * exception similar to: `QMetaMethod::invoke: Unable to invoke methods with return values in queued\n         * connections`. Use exec() in that case.\n         */\n        void start();\n\n        /**\n         * Function to stop multi-threading.\n         * It can be called internally or externally.\n         */\n        void stop();\n\n        /**\n         * Whether the WrapperT is running.\n         * It will return true after exec() or start() and before stop(), and false otherwise.\n         * @return Boolean specifying whether the WrapperT is running.\n         */\n        bool isRunning() const;\n\n        /**\n         * It sets the maximum number of elements in the queue.\n         * For maximum speed, set to a very large number, but the trade-off would be:\n         *  - Latency will hugely increase.\n         *  - The program might go out of RAM memory (so the computer might freeze).\n         * For minimum latency while keeping an optimal speed, set to -1, that will automatically\n         * detect the ideal number based on how many elements are connected to that queue.\n         * @param defaultMaxSizeQueues long long element with the maximum number of elements on the queue.\n         */\n        void setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues = -1);\n\n        /**\n         * Emplace (move) an element on the first (input) queue.\n         * Only valid if ThreadManagerMode::Asynchronous or ThreadManagerMode::AsynchronousIn.\n         * If the input queue is full or the WrapperT was stopped, it will return false and not emplace it.\n         * @param tDatums TDatumsSP element to be emplaced.\n         * @return Boolean specifying whether the tDatums could be emplaced.\n         */\n        bool tryEmplace(TDatumsSP& tDatums);\n\n        /**\n         * Emplace (move) an element on the first (input) queue.\n         * Similar to tryEmplace.\n         * However, if the input queue is full, it will wait until it can emplace it.\n         * If the WrapperT class is stopped before adding the element, it will return false and not emplace it.\n         * @param tDatums TDatumsSP element to be emplaced.\n         * @return Boolean specifying whether the tDatums could be emplaced.\n         */\n        bool waitAndEmplace(TDatumsSP& tDatums);\n\n        /**\n         * Similar to waitAndEmplace(const TDatumsSP& tDatums), but it takes a Matrix as input.\n         * @param matrix Matrix with the image to be processed.\n         * @return Boolean specifying whether the tDatums could be emplaced.\n         */\n        bool waitAndEmplace(Matrix& matrix);\n\n        /**\n         * Push (copy) an element on the first (input) queue.\n         * Same as tryEmplace, but it copies the data instead of moving it.\n         * @param tDatums TDatumsSP element to be pushed.\n         * @return Boolean specifying whether the tDatums could be pushed.\n         */\n        bool tryPush(const TDatumsSP& tDatums);\n\n        /**\n         * Push (copy) an element on the first (input) queue.\n         * Same as waitAndEmplace, but it copies the data instead of moving it.\n         * @param tDatums TDatumsSP element to be pushed.\n         * @return Boolean specifying whether the tDatums could be pushed.\n         */\n        bool waitAndPush(const TDatumsSP& tDatums);\n\n        /**\n         * Similar to waitAndPush(const TDatumsSP& tDatums), but it takes a Matrix as input.\n         * @param matrix Matrix with the image to be processed.\n         * @return Boolean specifying whether the tDatums could be pushed.\n         */\n        bool waitAndPush(const Matrix& matrix);\n\n        /**\n         * Pop (retrieve) an element from the last (output) queue.\n         * Only valid if ThreadManagerMode::Asynchronous or ThreadManagerMode::AsynchronousOut.\n         * If the output queue is empty or the WrapperT was stopped, it will return false and not retrieve it.\n         * @param tDatums TDatumsSP element where the retrieved element will be placed.\n         * @return Boolean specifying whether the tDatums could be retrieved.\n         */\n        bool tryPop(TDatumsSP& tDatums);\n\n        /**\n         * Pop (retrieve) an element from the last (output) queue.\n         * Similar to tryPop.\n         * However, if the output queue is empty, it will wait until it can pop an element.\n         * If the WrapperT class is stopped before popping the element, it will return false and not retrieve it.\n         * @param tDatums TDatumsSP element where the retrieved element will be placed.\n         * @return Boolean specifying whether the tDatums could be retrieved.\n         */\n        bool waitAndPop(TDatumsSP& tDatums);\n\n        /**\n         * Runs both waitAndEmplace and waitAndPop.\n         * @param tDatums TDatumsSP element where the retrieved element will be placed.\n         * @return Boolean specifying whether the tDatums could be retrieved.\n         */\n        bool emplaceAndPop(TDatumsSP& tDatums);\n\n        /**\n         * Similar to emplaceAndPop(TDatumsSP& tDatums), but it takes a Matrix as input.\n         * @param matrix Matrix with the image to be processed.\n         * @return TDatumsSP element where the processed information will be placed.\n         */\n        TDatumsSP emplaceAndPop(const Matrix& matrix);\n\n    private:\n        const ThreadManagerMode mThreadManagerMode;\n        ThreadManager<TDatumsSP> mThreadManager;\n        bool mMultiThreadEnabled;\n        // Configuration\n        WrapperStructPose mWrapperStructPose;\n        WrapperStructFace mWrapperStructFace;\n        WrapperStructHand mWrapperStructHand;\n        WrapperStructExtra mWrapperStructExtra;\n        WrapperStructInput mWrapperStructInput;\n        WrapperStructOutput mWrapperStructOutput;\n        WrapperStructGui mWrapperStructGui;\n        // User configurable workers\n        std::array<bool, int(WorkerType::Size)> mUserWsOnNewThread;\n        std::array<std::vector<TWorker>, int(WorkerType::Size)> mUserWs;\n\n        DELETE_COPY(WrapperT);\n    };\n\n    // Type\n    typedef WrapperT<BASE_DATUM> Wrapper;\n}\n\n\n\n\n\n// Implementation\n#include <openpose/wrapper/wrapperAuxiliary.hpp>\nnamespace op\n{\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::WrapperT(const ThreadManagerMode threadManagerMode) :\n        mThreadManagerMode{threadManagerMode},\n        mThreadManager{threadManagerMode},\n        mMultiThreadEnabled{true}\n    {\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::~WrapperT()\n    {\n        try\n        {\n            stop();\n            // Reset mThreadManager\n            mThreadManager.reset();\n            // Reset user workers\n            for (auto& userW : mUserWs)\n                userW.clear();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::disableMultiThreading()\n    {\n        try\n        {\n            mMultiThreadEnabled = false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::setWorker(\n        const WorkerType workerType, const TWorker& worker, const bool workerOnNewThread)\n    {\n        try\n        {\n            // Sanity check\n            if (worker == nullptr)\n                error(\"Your worker is a nullptr.\", __LINE__, __FILE__, __FUNCTION__);\n            // Add worker\n            mUserWs[int(workerType)].clear();\n            mUserWs[int(workerType)].emplace_back(worker);\n            mUserWsOnNewThread[int(workerType)] = workerOnNewThread;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructPose& wrapperStructPose)\n    {\n        try\n        {\n            mWrapperStructPose = wrapperStructPose;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructFace& wrapperStructFace)\n    {\n        try\n        {\n            mWrapperStructFace = wrapperStructFace;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructHand& wrapperStructHand)\n    {\n        try\n        {\n            mWrapperStructHand = wrapperStructHand;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructExtra& wrapperStructExtra)\n    {\n        try\n        {\n            mWrapperStructExtra = wrapperStructExtra;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructInput& wrapperStructInput)\n    {\n        try\n        {\n            mWrapperStructInput = wrapperStructInput;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructOutput& wrapperStructOutput)\n    {\n        try\n        {\n            mWrapperStructOutput = wrapperStructOutput;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::configure(const WrapperStructGui& wrapperStructGui)\n    {\n        try\n        {\n            mWrapperStructGui = wrapperStructGui;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::exec()\n    {\n        try\n        {\n            configureThreadManager<TDatum, TDatums, TDatumsSP, TWorker>(\n                mThreadManager, mMultiThreadEnabled, mThreadManagerMode, mWrapperStructPose, mWrapperStructFace,\n                mWrapperStructHand, mWrapperStructExtra, mWrapperStructInput, mWrapperStructOutput, mWrapperStructGui,\n                mUserWs, mUserWsOnNewThread);\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            mThreadManager.exec();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::start()\n    {\n        try\n        {\n            configureThreadManager<TDatum, TDatums, TDatumsSP, TWorker>(\n                mThreadManager, mMultiThreadEnabled, mThreadManagerMode, mWrapperStructPose, mWrapperStructFace,\n                mWrapperStructHand, mWrapperStructExtra, mWrapperStructInput, mWrapperStructOutput, mWrapperStructGui,\n                mUserWs, mUserWsOnNewThread);\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            mThreadManager.start();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::stop()\n    {\n        try\n        {\n            mThreadManager.stop();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::isRunning() const\n    {\n        try\n        {\n            return mThreadManager.isRunning();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::setDefaultMaxSizeQueues(const long long defaultMaxSizeQueues)\n    {\n        try\n        {\n            mThreadManager.setDefaultMaxSizeQueues(defaultMaxSizeQueues);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::tryEmplace(TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Input)].empty())\n                error(\"Emplace cannot be called if an input worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // tryEmplace for 1 camera\n            if (tDatums->size() < 2)\n            {\n                return mThreadManager.tryEmplace(tDatums);\n            }\n            // tryEmplace for multiview\n            else\n            {\n                bool successfulEmplace = true;\n                for (auto datumIndex = 0u; datumIndex < tDatums->size(); ++datumIndex)\n                {\n                    auto tDatumsSingle = std::make_shared<TDatums>(TDatums({ tDatums->at(datumIndex) }));\n                    if (!tryEmplace(tDatumsSingle))\n                    {\n                        successfulEmplace = false;\n                        break;\n                    }\n                }\n                return successfulEmplace;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::waitAndEmplace(TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Input)].empty())\n                error(\"Emplace cannot be called if an input worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // waitAndEmplace for 1 camera\n            if (tDatums->size() < 2)\n            {\n                return mThreadManager.waitAndEmplace(tDatums);\n            }\n            // waitAndEmplace for multiview\n            else\n            {\n                bool successfulEmplace = true;\n                for (auto datumIndex = 0u ; datumIndex < tDatums->size() ; ++datumIndex)\n                {\n                    auto tDatumsSingle = std::make_shared<TDatums>(TDatums({tDatums->at(datumIndex)}));\n                    if (!waitAndEmplace(tDatumsSingle))\n                    {\n                        successfulEmplace = false;\n                        opLog(\"Waiting to emplace for multi-camera failed.\",\n                            Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                        break;\n                    }\n                }\n                return successfulEmplace;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::waitAndEmplace(Matrix& matrix)\n    {\n        try\n        {\n            // Create new datum\n            auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<TDatum>>>();\n            datumsPtr->emplace_back();\n            auto& tDatumPtr = datumsPtr->at(0);\n            tDatumPtr = std::make_shared<TDatum>();\n            // Fill datum\n            std::swap(tDatumPtr->cvInputData, matrix);\n            // Return result\n            return waitAndEmplace(datumsPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::tryPush(const TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Input)].empty())\n                error(\"Push cannot be called if an input worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            return mThreadManager.tryPush(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::waitAndPush(const TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Input)].empty())\n                error(\"Push cannot be called if an input worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            return mThreadManager.waitAndPush(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::waitAndPush(const Matrix& matrix)\n    {\n        try\n        {\n            // Create new datum\n            auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<TDatum>>>();\n            datumsPtr->emplace_back();\n            auto& tDatumPtr = datumsPtr->at(0);\n            tDatumPtr = std::make_shared<TDatum>();\n            // Fill datum\n            tDatumPtr->cvInputData = matrix.clone();\n            // Return result\n            return waitAndEmplace(datumsPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::tryPop(TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Output)].empty())\n                error(\"Pop cannot be called if an output worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            return mThreadManager.tryPop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::waitAndPop(TDatumsSP& tDatums)\n    {\n        try\n        {\n            if (!mUserWs[int(WorkerType::Output)].empty())\n                error(\"Pop cannot be called if an output worker was already selected.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            return mThreadManager.waitAndPop(tDatums);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    bool WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::emplaceAndPop(TDatumsSP& tDatums)\n    {\n        try\n        {\n            // Run waitAndEmplace + waitAndPop\n            if (waitAndEmplace(tDatums))\n                return waitAndPop(tDatums);\n            return false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    TDatumsSP WrapperT<TDatum, TDatums, TDatumsSP, TWorker>::emplaceAndPop(const Matrix& matrix)\n    {\n        try\n        {\n            // Create new datum\n            auto datumsPtr = std::make_shared<std::vector<std::shared_ptr<TDatum>>>();\n            datumsPtr->emplace_back();\n            auto& tDatumPtr = datumsPtr->at(0);\n            tDatumPtr = std::make_shared<TDatum>();\n            // Fill datum\n            tDatumPtr->cvInputData = matrix;\n            // Emplace and pop\n            emplaceAndPop(datumsPtr);\n            // Return result\n            return datumsPtr;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return TDatumsSP{};\n        }\n    }\n\n    extern template class WrapperT<BASE_DATUM>;\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperAuxiliary.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP\n\n#include <openpose/thread/headers.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n#include <openpose/wrapper/wrapperStructExtra.hpp>\n#include <openpose/wrapper/wrapperStructFace.hpp>\n#include <openpose/wrapper/wrapperStructGui.hpp>\n#include <openpose/wrapper/wrapperStructHand.hpp>\n#include <openpose/wrapper/wrapperStructInput.hpp>\n#include <openpose/wrapper/wrapperStructOutput.hpp>\n#include <openpose/wrapper/wrapperStructPose.hpp>\n\nnamespace op\n{\n    /**\n     * It checks that no wrong/contradictory flags are enabled for Wrapper(T)\n     * @param wrapperStructPose\n     * @param wrapperStructFace\n     * @param wrapperStructHand\n     * @param wrapperStructExtra\n     * @param wrapperStructInput\n     * @param wrapperStructOutput\n     * @param renderOutput\n     * @param userOutputWsEmpty\n     * @param producerSharedPtr\n     * @param threadManagerMode\n     */\n    OP_API void wrapperConfigureSanityChecks(\n        WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace,\n        const WrapperStructHand& wrapperStructHand, const WrapperStructExtra& wrapperStructExtra,\n        const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput,\n        const WrapperStructGui& wrapperStructGui, const bool renderOutput, const bool userInputAndPreprocessingWsEmpty,\n        const bool userOutputWsEmpty, const std::shared_ptr<Producer>& producerSharedPtr,\n        const ThreadManagerMode threadManagerMode);\n\n    /**\n     * Thread ID increase (private internal function).\n     * If multi-threading mode, it increases the thread ID.\n     * If single-threading mode (for debugging), it does not modify it.\n     * Note that mThreadId must be re-initialized to 0 before starting a new Wrapper(T) configuration.\n     * @param threadId unsigned long long element with the current thread id value. I will be edited to the next\n     * `desired thread id number.\n     */\n    OP_API void threadIdPP(unsigned long long& threadId, const bool multiThreadEnabled);\n\n    /**\n     * Set ThreadManager from TWorkers (private internal function).\n     * After any configure() has been called, the TWorkers are initialized. This function resets the ThreadManager\n     * and adds them.\n     * Common code for start() and exec().\n     */\n    template<typename TDatum,\n             typename TDatums = std::vector<std::shared_ptr<TDatum>>,\n             typename TDatumsSP = std::shared_ptr<TDatums>,\n             typename TWorker = std::shared_ptr<Worker<TDatumsSP>>>\n    void configureThreadManager(\n        ThreadManager<TDatumsSP>& threadManager, const bool multiThreadEnabled,\n        const ThreadManagerMode threadManagerMode, const WrapperStructPose& wrapperStructPose,\n        const WrapperStructFace& wrapperStructFace, const WrapperStructHand& wrapperStructHand,\n        const WrapperStructExtra& wrapperStructExtra, const WrapperStructInput& wrapperStructInput,\n        const WrapperStructOutput& wrapperStructOutput, const WrapperStructGui& wrapperStructGui,\n        const std::array<std::vector<TWorker>, int(WorkerType::Size)>& userWs,\n        const std::array<bool, int(WorkerType::Size)>& userWsOnNewThread);\n\n    /**\n     * It fills camera parameters and splits the cvMat depending on how many camera parameter matrices are found.\n     * For example usage, check `examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.cpp`\n     */\n    template<typename TDatum,\n             typename TDatums = std::vector<std::shared_ptr<TDatum>>,\n             typename TDatumsSP = std::shared_ptr<TDatums>>\n    void createMultiviewTDatum(\n        TDatumsSP& tDatumsSP, unsigned long long& frameCounter,\n        const CameraParameterReader& cameraParameterReader, const void* const cvMatPtr);\n}\n\n\n\n\n\n// Implementation\n#include <openpose/3d/headers.hpp>\n#include <openpose/core/headers.hpp>\n#include <openpose/face/headers.hpp>\n#include <openpose/filestream/headers.hpp>\n#include <openpose/gpu/gpu.hpp>\n#include <openpose/gui/headers.hpp>\n#include <openpose/hand/headers.hpp>\n#include <openpose/pose/headers.hpp>\n#include <openpose/producer/headers.hpp>\n#include <openpose/tracking/headers.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/standard.hpp>\nnamespace op\n{\n    template<typename TDatum, typename TDatums, typename TDatumsSP, typename TWorker>\n    void configureThreadManager(\n        ThreadManager<TDatumsSP>& threadManager, const bool multiThreadEnabledTemp,\n        const ThreadManagerMode threadManagerMode, const WrapperStructPose& wrapperStructPoseTemp,\n        const WrapperStructFace& wrapperStructFace, const WrapperStructHand& wrapperStructHand,\n        const WrapperStructExtra& wrapperStructExtra, const WrapperStructInput& wrapperStructInput,\n        const WrapperStructOutput& wrapperStructOutput, const WrapperStructGui& wrapperStructGui,\n        const std::array<std::vector<TWorker>, int(WorkerType::Size)>& userWs,\n        const std::array<bool, int(WorkerType::Size)>& userWsOnNewThread)\n    {\n        try\n        {\n            opLog(\"Running configureThreadManager...\", Priority::Normal);\n\n            // Create producer\n            auto producerSharedPtr = createProducer(\n                wrapperStructInput.producerType, wrapperStructInput.producerString.getStdString(),\n                wrapperStructInput.cameraResolution, wrapperStructInput.cameraParameterPath.getStdString(),\n                wrapperStructInput.undistortImage, wrapperStructInput.numberViews);\n\n            // Editable arguments\n            auto wrapperStructPose = wrapperStructPoseTemp;\n            auto multiThreadEnabled = multiThreadEnabledTemp;\n\n            // User custom workers\n            const auto& userInputWs = userWs[int(WorkerType::Input)];\n            const auto& userPreProcessingWs = userWs[int(WorkerType::PreProcessing)];\n            const auto& userPostProcessingWs = userWs[int(WorkerType::PostProcessing)];\n            const auto& userOutputWs = userWs[int(WorkerType::Output)];\n            const auto userInputWsOnNewThread = userWsOnNewThread[int(WorkerType::Input)];\n            const auto userPreProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PreProcessing)];\n            const auto userPostProcessingWsOnNewThread = userWsOnNewThread[int(WorkerType::PostProcessing)];\n            const auto userOutputWsOnNewThread = userWsOnNewThread[int(WorkerType::Output)];\n\n            // Video seek\n            const auto spVideoSeek = std::make_shared<std::pair<std::atomic<bool>, std::atomic<int>>>();\n            // It cannot be directly included in the constructor (compiler error for copying std::atomic)\n            spVideoSeek->first = false;\n            spVideoSeek->second = 0;\n\n            // Required parameters\n            const auto gpuMode = getGpuMode();\n            const auto renderModePose = (\n                wrapperStructPose.renderMode != RenderMode::Auto\n                    ? wrapperStructPose.renderMode\n                    : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu));\n            const auto renderModeFace = (\n                wrapperStructFace.renderMode != RenderMode::Auto\n                    ? wrapperStructFace.renderMode\n                    : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu));\n            const auto renderModeHand = (\n                wrapperStructHand.renderMode != RenderMode::Auto\n                    ? wrapperStructHand.renderMode\n                    : (gpuMode == GpuMode::Cuda ? RenderMode::Gpu : RenderMode::Cpu));\n            const auto renderOutput = renderModePose != RenderMode::None\n                                        || renderModeFace != RenderMode::None\n                                        || renderModeHand != RenderMode::None;\n            const bool renderOutputGpu = renderModePose == RenderMode::Gpu\n                || (wrapperStructFace.enable && renderModeFace == RenderMode::Gpu)\n                || (wrapperStructHand.enable && renderModeHand == RenderMode::Gpu);\n            const bool renderFace = wrapperStructFace.enable && renderModeFace != RenderMode::None;\n            const bool renderHand = wrapperStructHand.enable && renderModeHand != RenderMode::None;\n            const bool renderHandGpu = wrapperStructHand.enable && renderModeHand == RenderMode::Gpu;\n            opLog(\"renderModePose = \" + std::to_string(int(renderModePose)), Priority::Normal);\n            opLog(\"renderModeFace = \" + std::to_string(int(renderModeFace)), Priority::Normal);\n            opLog(\"renderModeHand = \" + std::to_string(int(renderModeHand)), Priority::Normal);\n            opLog(\"renderOutput = \" + std::to_string(int(renderOutput)), Priority::Normal);\n            opLog(\"renderOutputGpu = \" + std::to_string(int(renderOutput)), Priority::Normal);\n            opLog(\"renderFace = \" + std::to_string(int(renderFace)), Priority::Normal);\n            opLog(\"renderHand = \" + std::to_string(int(renderHand)), Priority::Normal);\n            opLog(\"renderHandGpu = \" + std::to_string(int(renderHandGpu)), Priority::Normal);\n\n            // Check no wrong/contradictory flags enabled\n            const bool userInputAndPreprocessingWsEmpty = userInputWs.empty() && userPreProcessingWs.empty();\n            const bool userOutputWsEmpty = userOutputWs.empty();\n            wrapperConfigureSanityChecks(\n                wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructExtra, wrapperStructInput,\n                wrapperStructOutput, wrapperStructGui, renderOutput, userInputAndPreprocessingWsEmpty,\n                userOutputWsEmpty, producerSharedPtr, threadManagerMode);\n            opLog(\"userInputAndPreprocessingWsEmpty = \" + std::to_string(int(userInputAndPreprocessingWsEmpty)),\n                Priority::Normal);\n            opLog(\"userOutputWsEmpty = \" + std::to_string(int(userOutputWsEmpty)), Priority::Normal);\n\n            // Get number threads\n            auto numberGpuThreads = wrapperStructPose.gpuNumber;\n            auto gpuNumberStart = wrapperStructPose.gpuNumberStart;\n            opLog(\"numberGpuThreads = \" + std::to_string(numberGpuThreads), Priority::Normal);\n            opLog(\"gpuNumberStart = \" + std::to_string(gpuNumberStart), Priority::Normal);\n            // CPU --> 1 thread or no pose extraction\n            if (gpuMode == GpuMode::NoGpu)\n            {\n                numberGpuThreads = (wrapperStructPose.gpuNumber == 0 ? 0 : 1);\n                gpuNumberStart = 0;\n                // Disabling multi-thread makes the code 400 ms faster (2.3 sec vs. 2.7 in i7-6850K)\n                // and fixes the bug that the screen was not properly displayed and only refreshed sometimes\n                // Note: The screen bug could be also fixed by using waitKey(30) rather than waitKey(1)\n                multiThreadEnabled = false;\n            }\n            // GPU --> user picks (<= #GPUs)\n            else\n            {\n                // Get total number GPUs\n                const auto totalGpuNumber = getGpuNumber();\n                // If number GPU < 0 --> set it to all the available GPUs\n                if (numberGpuThreads < 0)\n                {\n                    if (totalGpuNumber <= gpuNumberStart)\n                        error(\"Number of initial GPU (`--number_gpu_start`) must be lower than the total number of\"\n                              \" used GPUs (`--number_gpu`)\", __LINE__, __FUNCTION__, __FILE__);\n                    numberGpuThreads = totalGpuNumber - gpuNumberStart;\n                    // Reset initial GPU to 0 (we want them all)\n                    // Logging message\n                    opLog(\"Auto-detecting all available GPUs... Detected \" + std::to_string(totalGpuNumber)\n                        + \" GPU(s), using \" + std::to_string(numberGpuThreads) + \" of them starting at GPU \"\n                        + std::to_string(gpuNumberStart) + \".\", Priority::High);\n                }\n                // Sanity check\n                if (gpuNumberStart + numberGpuThreads > totalGpuNumber)\n                    error(\"Initial GPU selected (`--number_gpu_start`) + number GPUs to use (`--number_gpu`) must\"\n                          \" be lower or equal than the total number of GPUs in your machine (\"\n                          + std::to_string(gpuNumberStart) + \" + \"\n                          + std::to_string(numberGpuThreads) + \" vs. \"\n                          + std::to_string(totalGpuNumber) + \").\",\n                          __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Proper format\n            const auto writeImagesCleaned = formatAsDirectory(wrapperStructOutput.writeImages.getStdString());\n            const auto writeKeypointCleaned = formatAsDirectory(wrapperStructOutput.writeKeypoint.getStdString());\n            const auto writeJsonCleaned = formatAsDirectory(wrapperStructOutput.writeJson.getStdString());\n            const auto writeHeatMapsCleaned = formatAsDirectory(wrapperStructOutput.writeHeatMaps.getStdString());\n            const auto modelFolder = formatAsDirectory(wrapperStructPose.modelFolder.getStdString());\n            opLog(\"writeImagesCleaned = \" + writeImagesCleaned, Priority::Normal);\n            opLog(\"writeKeypointCleaned = \" + writeKeypointCleaned, Priority::Normal);\n            opLog(\"writeJsonCleaned = \" + writeJsonCleaned, Priority::Normal);\n            opLog(\"writeHeatMapsCleaned = \" + writeHeatMapsCleaned, Priority::Normal);\n            opLog(\"modelFolder = \" + modelFolder, Priority::Normal);\n\n            // Common parameters\n            auto finalOutputSize = wrapperStructPose.outputSize;\n            Point<int> producerSize{-1,-1};\n            const auto oPProducer = (producerSharedPtr != nullptr);\n            if (oPProducer)\n            {\n                // 1. Set producer properties\n                const auto displayProducerFpsMode = (wrapperStructInput.realTimeProcessing\n                                                      ? ProducerFpsMode::OriginalFps : ProducerFpsMode::RetrievalFps);\n                producerSharedPtr->setProducerFpsMode(displayProducerFpsMode);\n                producerSharedPtr->set(ProducerProperty::Flip, wrapperStructInput.frameFlip);\n                producerSharedPtr->set(ProducerProperty::Rotation, wrapperStructInput.frameRotate);\n                producerSharedPtr->set(ProducerProperty::AutoRepeat, wrapperStructInput.framesRepeat);\n                // 2. Set finalOutputSize\n                producerSize = Point<int>{(int)producerSharedPtr->get(getCvCapPropFrameWidth()),\n                                          (int)producerSharedPtr->get(getCvCapPropFrameHeight())};\n                // Set finalOutputSize to input size if desired\n                if (finalOutputSize.x == -1 || finalOutputSize.y == -1)\n                    finalOutputSize = producerSize;\n            }\n            opLog(\"finalOutputSize = [\" + std::to_string(finalOutputSize.x) + \",\" + std::to_string(finalOutputSize.y)\n                + \"]\", Priority::Normal);\n\n            // Producer\n            TWorker datumProducerW;\n            if (oPProducer)\n            {\n                const auto datumProducer = std::make_shared<DatumProducer<TDatum>>(\n                    producerSharedPtr, wrapperStructInput.frameFirst, wrapperStructInput.frameStep,\n                    wrapperStructInput.frameLast, spVideoSeek\n                );\n                datumProducerW = std::make_shared<WDatumProducer<TDatum>>(datumProducer);\n            }\n            else\n                datumProducerW = nullptr;\n\n            std::vector<std::shared_ptr<PoseExtractorNet>> poseExtractorNets;\n            std::vector<std::shared_ptr<FaceExtractorNet>> faceExtractorNets;\n            std::vector<std::shared_ptr<HandExtractorNet>> handExtractorNets;\n            std::vector<std::shared_ptr<PoseGpuRenderer>> poseGpuRenderers;\n            // CUDA vs. CPU resize\n            std::vector<std::shared_ptr<CvMatToOpOutput>> cvMatToOpOutputs;\n            std::vector<std::shared_ptr<OpOutputToCvMat>> opOutputToCvMats;\n            std::shared_ptr<PoseCpuRenderer> poseCpuRenderer;\n            // Workers\n            TWorker scaleAndSizeExtractorW;\n            TWorker cvMatToOpInputW;\n            TWorker cvMatToOpOutputW;\n            bool addCvMatToOpOutput = renderOutput;\n            bool addCvMatToOpOutputInCpu = addCvMatToOpOutput;\n            std::vector<std::vector<TWorker>> poseExtractorsWs;\n            std::vector<std::vector<TWorker>> poseTriangulationsWs;\n            std::vector<std::vector<TWorker>> jointAngleEstimationsWs;\n            std::vector<TWorker> postProcessingWs;\n            if (numberGpuThreads > 0)\n            {\n                // Get input scales and sizes\n                const auto scaleAndSizeExtractor = std::make_shared<ScaleAndSizeExtractor>(\n                    wrapperStructPose.netInputSize, (float)wrapperStructPose.netInputSizeDynamicBehavior, finalOutputSize,\n                    wrapperStructPose.scalesNumber, wrapperStructPose.scaleGap);\n                scaleAndSizeExtractorW = std::make_shared<WScaleAndSizeExtractor<TDatumsSP>>(scaleAndSizeExtractor);\n\n                // Input cvMat to OpenPose input & output format\n                // Note: resize on GPU reduces accuracy about 0.1%\n                bool resizeOnCpu = true;\n                // const auto resizeOnCpu = (wrapperStructPose.poseMode != PoseMode::Enabled);\n                if (resizeOnCpu)\n                {\n                    const auto gpuResize = false;\n                    const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>(\n                        wrapperStructPose.poseModel, gpuResize);\n                    cvMatToOpInputW = std::make_shared<WCvMatToOpInput<TDatumsSP>>(cvMatToOpInput);\n                }\n                // Note: We realized that somehow doing it on GPU for any number of GPUs does speedup the whole OP\n                resizeOnCpu = false;\n                addCvMatToOpOutputInCpu = addCvMatToOpOutput\n                    && (resizeOnCpu || !renderOutputGpu || wrapperStructPose.poseMode != PoseMode::Enabled\n                        // Resize in GPU causing bug\n                        || wrapperStructPose.outputSize.x != -1 || wrapperStructPose.outputSize.y != -1);\n                if (addCvMatToOpOutputInCpu)\n                {\n                    const auto gpuResize = false;\n                    const auto cvMatToOpOutput = std::make_shared<CvMatToOpOutput>(gpuResize);\n                    cvMatToOpOutputW = std::make_shared<WCvMatToOpOutput<TDatumsSP>>(cvMatToOpOutput);\n                }\n\n                // Pose estimators & renderers\n                std::vector<TWorker> cpuRenderers;\n                poseExtractorsWs.clear();\n                poseExtractorsWs.resize(numberGpuThreads);\n                if (wrapperStructPose.poseMode != PoseMode::Disabled)\n                {\n                    // Pose estimators\n                    for (auto gpuId = 0; gpuId < numberGpuThreads; gpuId++)\n                        poseExtractorNets.emplace_back(std::make_shared<PoseExtractorCaffe>(\n                            wrapperStructPose.poseModel, modelFolder, gpuId + gpuNumberStart,\n                            wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode,\n                            wrapperStructPose.addPartCandidates, wrapperStructPose.maximizePositives,\n                            wrapperStructPose.protoTxtPath.getStdString(),\n                            wrapperStructPose.caffeModelPath.getStdString(),\n                            wrapperStructPose.upsamplingRatio, wrapperStructPose.poseMode == PoseMode::Enabled,\n                            wrapperStructPose.enableGoogleLogging\n                        ));\n\n                    // Pose renderers\n                    if (renderOutputGpu || renderModePose == RenderMode::Cpu)\n                    {\n                        // If renderModePose != RenderMode::Gpu but renderOutput, then we create an\n                        // alpha = 0 pose renderer in order to keep the removing background option\n                        const auto alphaKeypoint = (renderModePose != RenderMode::None\n                                                    ? wrapperStructPose.alphaKeypoint : 0.f);\n                        const auto alphaHeatMap = (renderModePose != RenderMode::None\n                                                    ? wrapperStructPose.alphaHeatMap : 0.f);\n                        // GPU rendering\n                        if (renderOutputGpu)\n                        {\n                            for (const auto& poseExtractorNet : poseExtractorNets)\n                            {\n                                poseGpuRenderers.emplace_back(std::make_shared<PoseGpuRenderer>(\n                                    wrapperStructPose.poseModel, poseExtractorNet, wrapperStructPose.renderThreshold,\n                                    wrapperStructPose.blendOriginalFrame, alphaKeypoint,\n                                    alphaHeatMap, wrapperStructPose.defaultPartToRender\n                                ));\n                            }\n                        }\n                        // CPU rendering\n                        if (renderModePose == RenderMode::Cpu)\n                        {\n                            poseCpuRenderer = std::make_shared<PoseCpuRenderer>(\n                                wrapperStructPose.poseModel, wrapperStructPose.renderThreshold,\n                                wrapperStructPose.blendOriginalFrame, alphaKeypoint, alphaHeatMap,\n                                wrapperStructPose.defaultPartToRender);\n                            cpuRenderers.emplace_back(std::make_shared<WPoseRenderer<TDatumsSP>>(poseCpuRenderer));\n                        }\n                    }\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                    // Pose extractor(s)\n                    poseExtractorsWs.resize(poseExtractorNets.size());\n                    const auto personIdExtractor = (wrapperStructExtra.identification\n                        ? std::make_shared<PersonIdExtractor>() : nullptr);\n                    // Keep top N people\n                    // Added right after PoseExtractorNet to avoid:\n                    // 1) Rendering people that are later deleted (wrong visualization).\n                    // 2) Processing faces and hands on people that will be deleted (speed up).\n                    // 3) Running tracking before deleting the people.\n                    // Add KeepTopNPeople for each PoseExtractorNet\n                    const auto keepTopNPeople = (wrapperStructPose.numberPeopleMax > 0 ?\n                        std::make_shared<KeepTopNPeople>(wrapperStructPose.numberPeopleMax)\n                        : nullptr);\n                    // Person tracker\n                    auto personTrackers = std::make_shared<std::vector<std::shared_ptr<PersonTracker>>>();\n                    if (wrapperStructExtra.tracking > -1)\n                        personTrackers->emplace_back(\n                            std::make_shared<PersonTracker>(wrapperStructExtra.tracking == 0));\n                    for (auto i = 0u; i < poseExtractorsWs.size(); i++)\n                    {\n                        // OpenPose keypoint detector + keepTopNPeople\n                        //    + ID extractor (experimental) + tracking (experimental)\n                        const auto poseExtractor = std::make_shared<PoseExtractor>(\n                            poseExtractorNets.at(i), keepTopNPeople, personIdExtractor, personTrackers,\n                            wrapperStructPose.numberPeopleMax, wrapperStructExtra.tracking);\n                        // If we want the initial image resize on GPU\n                        if (cvMatToOpInputW == nullptr)\n                        {\n                            const auto gpuResize = true;\n                            const auto cvMatToOpInput = std::make_shared<CvMatToOpInput>(\n                                wrapperStructPose.poseModel, gpuResize);\n                            poseExtractorsWs.at(i).emplace_back(\n                                std::make_shared<WCvMatToOpInput<TDatumsSP>>(cvMatToOpInput));\n                        }\n                        // If we want the final image resize on GPU\n                        if (addCvMatToOpOutput && cvMatToOpOutputW == nullptr)\n                        {\n                            const auto gpuResize = true;\n                            cvMatToOpOutputs.emplace_back(std::make_shared<CvMatToOpOutput>(gpuResize));\n                            poseExtractorsWs.at(i).emplace_back(\n                                std::make_shared<WCvMatToOpOutput<TDatumsSP>>(cvMatToOpOutputs.back()));\n                        }\n                        poseExtractorsWs.at(i).emplace_back(\n                            std::make_shared<WPoseExtractor<TDatumsSP>>(poseExtractor));\n                        // poseExtractorsWs.at(i) = {std::make_shared<WPoseExtractor<TDatumsSP>>(poseExtractor)};\n                        // // Just OpenPose keypoint detector\n                        // poseExtractorsWs.at(i) = {std::make_shared<WPoseExtractorNet<TDatumsSP>>(\n                        //     poseExtractorNets.at(i))};\n                    }\n\n                    // // (Before tracking / id extractor)\n                    // // Added right after PoseExtractorNet to avoid:\n                    // // 1) Rendering people that are later deleted (wrong visualization).\n                    // // 2) Processing faces and hands on people that will be deleted (speed up).\n                    // if (wrapperStructPose.numberPeopleMax > 0)\n                    // {\n                    //     // Add KeepTopNPeople for each PoseExtractorNet\n                    //     const auto keepTopNPeople = std::make_shared<KeepTopNPeople>(\n                    //         wrapperStructPose.numberPeopleMax);\n                    //     for (auto& wPose : poseExtractorsWs)\n                    //         wPose.emplace_back(std::make_shared<WKeepTopNPeople<TDatumsSP>>(keepTopNPeople));\n                    // }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Pose renderer(s)\n                if (!poseGpuRenderers.empty())\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    for (auto i = 0u; i < poseExtractorsWs.size(); i++)\n                    {\n                        poseExtractorsWs.at(i).emplace_back(std::make_shared<WPoseRenderer<TDatumsSP>>(\n                            poseGpuRenderers.at(i)));\n                        // Get shared params\n                        if (!cvMatToOpOutputs.empty())\n                            poseGpuRenderers.at(i)->setSharedParameters(\n                                cvMatToOpOutputs.at(i)->getSharedParameters());\n                    }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Face extractor(s)\n                if (wrapperStructFace.enable)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // Face detector\n                    // OpenPose body-based face detector\n                    if (wrapperStructFace.detector == Detector::Body)\n                    {\n                        // Sanity check\n                        if (wrapperStructPose.poseMode == PoseMode::Disabled)\n                            error(\"Body keypoint detection is disabled but face Detector is set to Body. Either\"\n                                  \" re-enable OpenPose body or select a different face Detector (`--face_detector`).\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                        // Constructors\n                        const auto faceDetector = std::make_shared<FaceDetector>(wrapperStructPose.poseModel);\n                        for (auto& wPose : poseExtractorsWs)\n                            wPose.emplace_back(std::make_shared<WFaceDetector<TDatumsSP>>(faceDetector));\n                    }\n                    // OpenCV face detector\n                    else if (wrapperStructFace.detector == Detector::OpenCV)\n                    {\n                        opLog(\"Body keypoint detection is disabled. Hence, using OpenCV face detector (much less\"\n                            \" accurate but faster).\", Priority::High);\n                        for (auto& wPose : poseExtractorsWs)\n                        {\n                            // 1 FaceDetectorOpenCV per thread, OpenCV face detector is not thread-safe\n                            const auto faceDetectorOpenCV = std::make_shared<FaceDetectorOpenCV>(modelFolder);\n                            wPose.emplace_back(\n                                std::make_shared<WFaceDetectorOpenCV<TDatumsSP>>(faceDetectorOpenCV)\n                            );\n                        }\n                    }\n                    // If provided by user: We do not need to create a FaceDetector\n                    // Unknown face Detector\n                    else if (wrapperStructFace.detector != Detector::Provided)\n                        error(\"Unknown face Detector. Select a valid face Detector (`--face_detector`).\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    // Face keypoint extractor\n                    for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)\n                    {\n                        // Face keypoint extractor\n                        const auto netOutputSize = wrapperStructFace.netInputSize;\n                        const auto faceExtractorNet = std::make_shared<FaceExtractorCaffe>(\n                            wrapperStructFace.netInputSize, netOutputSize, modelFolder,\n                            gpu + gpuNumberStart, wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode,\n                            wrapperStructPose.enableGoogleLogging\n                        );\n                        faceExtractorNets.emplace_back(faceExtractorNet);\n                        poseExtractorsWs.at(gpu).emplace_back(\n                            std::make_shared<WFaceExtractorNet<TDatumsSP>>(faceExtractorNet));\n                    }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Hand extractor(s)\n                if (wrapperStructHand.enable)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    const auto handDetector = std::make_shared<HandDetector>(wrapperStructPose.poseModel);\n                    for (auto gpu = 0u; gpu < poseExtractorsWs.size(); gpu++)\n                    {\n                        // Sanity check\n                        if ((wrapperStructHand.detector == Detector::BodyWithTracking\n                             || wrapperStructHand.detector == Detector::Body)\n                            && wrapperStructPose.poseMode == PoseMode::Disabled)\n                            error(\"Body keypoint detection is disabled but hand Detector is set to Body. Either\"\n                                  \" re-enable OpenPose body or select a different hand Detector (`--hand_detector`).\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                        // Hand detector\n                        // OpenPose body-based hand detector with tracking\n                        if (wrapperStructHand.detector == Detector::BodyWithTracking)\n                        {\n                            poseExtractorsWs.at(gpu).emplace_back(\n                                std::make_shared<WHandDetectorTracking<TDatumsSP>>(handDetector));\n                        }\n                        // OpenPose body-based hand detector\n                        else if (wrapperStructHand.detector == Detector::Body)\n                        {\n                            poseExtractorsWs.at(gpu).emplace_back(\n                                std::make_shared<WHandDetector<TDatumsSP>>(handDetector));\n                        }\n                        // If provided by user: We do not need to create a FaceDetector\n                        // Unknown hand Detector\n                        else if (wrapperStructHand.detector != Detector::Provided)\n                            error(\"Unknown hand Detector. Select a valid hand Detector (`--hand_detector`).\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                        // Hand keypoint extractor\n                        const auto netOutputSize = wrapperStructHand.netInputSize;\n                        const auto handExtractorNet = std::make_shared<HandExtractorCaffe>(\n                            wrapperStructHand.netInputSize, netOutputSize, modelFolder,\n                            gpu + gpuNumberStart, wrapperStructHand.scalesNumber, wrapperStructHand.scaleRange,\n                            wrapperStructPose.heatMapTypes, wrapperStructPose.heatMapScaleMode,\n                            wrapperStructPose.enableGoogleLogging\n                        );\n                        handExtractorNets.emplace_back(handExtractorNet);\n                        poseExtractorsWs.at(gpu).emplace_back(\n                            std::make_shared<WHandExtractorNet<TDatumsSP>>(handExtractorNet)\n                            );\n                        // If OpenPose body-based hand detector with tracking\n                        if (wrapperStructHand.detector == Detector::BodyWithTracking)\n                            poseExtractorsWs.at(gpu).emplace_back(\n                                std::make_shared<WHandDetectorUpdate<TDatumsSP>>(handDetector));\n                    }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Face renderer(s)\n                if (renderFace)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // CPU rendering\n                    if (renderModeFace == RenderMode::Cpu)\n                    {\n                        // Construct face renderer\n                        const auto faceRenderer = std::make_shared<FaceCpuRenderer>(\n                            wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint,\n                            wrapperStructFace.alphaHeatMap);\n                        // Add worker\n                        cpuRenderers.emplace_back(std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));\n                    }\n                    // GPU rendering\n                    else if (renderModeFace == RenderMode::Gpu)\n                    {\n                        for (auto i = 0u; i < poseExtractorsWs.size(); i++)\n                        {\n                            // Construct face renderer\n                            const auto faceRenderer = std::make_shared<FaceGpuRenderer>(\n                                wrapperStructFace.renderThreshold, wrapperStructFace.alphaKeypoint,\n                                wrapperStructFace.alphaHeatMap\n                            );\n                            // Performance boost -> share spGpuMemory for all renderers\n                            if (!poseGpuRenderers.empty())\n                            {\n                                // const bool isLastRenderer = !renderHandGpu;\n                                const bool isLastRenderer = !renderHandGpu && !(addCvMatToOpOutput && !addCvMatToOpOutputInCpu);\n                                const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(\n                                    poseGpuRenderers.at(i));\n                                faceRenderer->setSharedParametersAndIfLast(\n                                    renderer->getSharedParameters(), isLastRenderer);\n                            }\n                            // Add worker\n                            poseExtractorsWs.at(i).emplace_back(\n                                std::make_shared<WFaceRenderer<TDatumsSP>>(faceRenderer));\n                        }\n                    }\n                    else\n                        error(\"Unknown RenderMode.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Hand renderer(s)\n                if (renderHand)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // CPU rendering\n                    if (renderModeHand == RenderMode::Cpu)\n                    {\n                        // Construct hand renderer\n                        const auto handRenderer = std::make_shared<HandCpuRenderer>(\n                            wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint,\n                            wrapperStructHand.alphaHeatMap);\n                        // Add worker\n                        cpuRenderers.emplace_back(std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));\n                    }\n                    // GPU rendering\n                    else if (renderModeHand == RenderMode::Gpu)\n                    {\n                        for (auto i = 0u; i < poseExtractorsWs.size(); i++)\n                        {\n                            // Construct hands renderer\n                            const auto handRenderer = std::make_shared<HandGpuRenderer>(\n                                wrapperStructHand.renderThreshold, wrapperStructHand.alphaKeypoint,\n                                wrapperStructHand.alphaHeatMap\n                            );\n                            // Performance boost -> share spGpuMemory for all renderers\n                            if (!poseGpuRenderers.empty())\n                            {\n                                // const bool isLastRenderer = true;\n                                const bool isLastRenderer = !(addCvMatToOpOutput && !addCvMatToOpOutputInCpu);\n                                const auto renderer = std::static_pointer_cast<PoseGpuRenderer>(\n                                    poseGpuRenderers.at(i));\n                                handRenderer->setSharedParametersAndIfLast(\n                                    renderer->getSharedParameters(), isLastRenderer);\n                            }\n                            // Add worker\n                            poseExtractorsWs.at(i).emplace_back(\n                                std::make_shared<WHandRenderer<TDatumsSP>>(handRenderer));\n                        }\n                    }\n                    else\n                        error(\"Unknown RenderMode.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // Frames processor (OpenPose format -> cv::Mat format)\n                if (addCvMatToOpOutput && !addCvMatToOpOutputInCpu)\n                {\n                    // for (auto& poseExtractorsW : poseExtractorsWs)\n                    for (auto i = 0u ; i < poseExtractorsWs.size() ; ++i)\n                    {\n                        const auto gpuResize = true;\n                        opOutputToCvMats.emplace_back(std::make_shared<OpOutputToCvMat>(gpuResize));\n                        poseExtractorsWs.at(i).emplace_back(\n                            std::make_shared<WOpOutputToCvMat<TDatumsSP>>(opOutputToCvMats.back()));\n                        // Assign shared parameters\n                        opOutputToCvMats.back()->setSharedParameters(\n                            cvMatToOpOutputs.at(i)->getSharedParameters());\n                    }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n                // 3-D reconstruction\n                poseTriangulationsWs.clear();\n                if (wrapperStructExtra.reconstruct3d)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // For all (body/face/hands): PoseTriangulations ~30 msec, 8 GPUS ~30 msec for keypoint estimation\n                    poseTriangulationsWs.resize(fastMax(1, int(poseExtractorsWs.size() / 4)));\n                    for (auto i = 0u ; i < poseTriangulationsWs.size() ; i++)\n                    {\n                        const auto poseTriangulation = std::make_shared<PoseTriangulation>(\n                            wrapperStructExtra.minViews3d);\n                        poseTriangulationsWs.at(i) = {std::make_shared<WPoseTriangulation<TDatumsSP>>(\n                            poseTriangulation)};\n                    }\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Itermediate workers (e.g., OpenPose format to cv::Mat, json & frames recorder, ...)\n                postProcessingWs.clear();\n                // // Person ID identification (when no multi-thread and no dependency on tracking)\n                // if (wrapperStructExtra.identification)\n                // {\n                //     const auto personIdExtractor = std::make_shared<PersonIdExtractor>();\n                //     postProcessingWs.emplace_back(\n                //         std::make_shared<WPersonIdExtractor<TDatumsSP>>(personIdExtractor)\n                //     );\n                // }\n                // Frames processor (OpenPose format -> cv::Mat format)\n                if (addCvMatToOpOutputInCpu)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    postProcessingWs = mergeVectors(postProcessingWs, cpuRenderers);\n                    const auto opOutputToCvMat = std::make_shared<OpOutputToCvMat>();\n                    postProcessingWs.emplace_back(std::make_shared<WOpOutputToCvMat<TDatumsSP>>(opOutputToCvMat));\n                }\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Re-scale pose if desired\n                // If desired scale is not the current input\n                if (wrapperStructPose.keypointScaleMode != ScaleMode::InputResolution\n                    // and desired scale is not output when size(input) = size(output)\n                    && !(wrapperStructPose.keypointScaleMode == ScaleMode::OutputResolution &&\n                         (finalOutputSize == producerSize || finalOutputSize.x <= 0 || finalOutputSize.y <= 0))\n                    // and desired scale is not net output when size(input) = size(net output)\n                    && !(wrapperStructPose.keypointScaleMode == ScaleMode::NetOutputResolution\n                         && producerSize == wrapperStructPose.netInputSize))\n                {\n                    // Then we must rescale the keypoints\n                    auto keypointScaler = std::make_shared<KeypointScaler>(wrapperStructPose.keypointScaleMode);\n                    postProcessingWs.emplace_back(std::make_shared<WKeypointScaler<TDatumsSP>>(keypointScaler));\n                }\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n            // IK/Adam\n            const auto displayAdam = wrapperStructGui.displayMode == DisplayMode::DisplayAdam\n                                     || (wrapperStructGui.displayMode == DisplayMode::DisplayAll\n                                         && wrapperStructExtra.ikThreads > 0);\n            jointAngleEstimationsWs.clear();\n#ifdef USE_3D_ADAM_MODEL\n            if (wrapperStructExtra.ikThreads > 0)\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                jointAngleEstimationsWs.resize(wrapperStructExtra.ikThreads);\n                // Pose extractor(s)\n                for (auto i = 0u; i < jointAngleEstimationsWs.size(); i++)\n                {\n                    const auto jointAngleEstimation = std::make_shared<JointAngleEstimation>(displayAdam);\n                    jointAngleEstimationsWs.at(i) = {std::make_shared<WJointAngleEstimation<TDatumsSP>>(\n                        jointAngleEstimation)};\n                }\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n#endif\n\n            // Output workers\n            std::vector<TWorker> outputWs;\n            // Print verbose\n            if (wrapperStructOutput.verbose > 0.)\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto verbosePrinter = std::make_shared<VerbosePrinter>(\n                    wrapperStructOutput.verbose, uLongLongRound(producerSharedPtr->get(getCvCapPropFrameCount())));\n                outputWs.emplace_back(std::make_shared<WVerbosePrinter<TDatumsSP>>(verbosePrinter));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Send information (e.g., to Unity) though UDP client-server communication\n\n#ifdef USE_3D_ADAM_MODEL\n            if (!wrapperStructOutput.udpHost.empty() && !wrapperStructOutput.udpPort.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto udpSender = std::make_shared<UdpSender>(wrapperStructOutput.udpHost,\n                                                                   wrapperStructOutput.udpPort);\n                outputWs.emplace_back(std::make_shared<WUdpSender<TDatumsSP>>(udpSender));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n#endif\n            // Write people pose data on disk (json for OpenCV >= 3, xml, yml...)\n            if (!writeKeypointCleaned.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto keypointSaver = std::make_shared<KeypointSaver>(writeKeypointCleaned,\n                                                                           wrapperStructOutput.writeKeypointFormat);\n                outputWs.emplace_back(std::make_shared<WPoseSaver<TDatumsSP>>(keypointSaver));\n                if (wrapperStructFace.enable)\n                    outputWs.emplace_back(std::make_shared<WFaceSaver<TDatumsSP>>(keypointSaver));\n                if (wrapperStructHand.enable)\n                    outputWs.emplace_back(std::make_shared<WHandSaver<TDatumsSP>>(keypointSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Write OpenPose output data on disk in JSON format (body/hand/face keypoints, body part locations if\n            // enabled, etc.)\n            if (!writeJsonCleaned.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto peopleJsonSaver = std::make_shared<PeopleJsonSaver>(writeJsonCleaned);\n                outputWs.emplace_back(std::make_shared<WPeopleJsonSaver<TDatumsSP>>(peopleJsonSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Write people pose/foot/face/hand/etc. data on disk (COCO validation JSON format)\n            if (!wrapperStructOutput.writeCocoJson.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // If humanFormat: bigger size (& maybe slower to process), but easier for user to read it\n                const auto humanFormat = true;\n                const auto cocoJsonSaver = std::make_shared<CocoJsonSaver>(\n                    wrapperStructOutput.writeCocoJson.getStdString(), wrapperStructPose.poseModel, humanFormat,\n                    wrapperStructOutput.writeCocoJsonVariants,\n                    (wrapperStructPose.poseModel != PoseModel::CAR_22\n                        && wrapperStructPose.poseModel != PoseModel::CAR_12\n                        ? CocoJsonFormat::Body : CocoJsonFormat::Car),\n                    wrapperStructOutput.writeCocoJsonVariant);\n                outputWs.emplace_back(std::make_shared<WCocoJsonSaver<TDatumsSP>>(cocoJsonSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Write frames as desired image format on hard disk\n            if (!writeImagesCleaned.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto imageSaver = std::make_shared<ImageSaver>(\n                    writeImagesCleaned, wrapperStructOutput.writeImagesFormat.getStdString());\n                outputWs.emplace_back(std::make_shared<WImageSaver<TDatumsSP>>(imageSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            auto originalVideoFps = 0.;\n            if (!wrapperStructOutput.writeVideo.empty() || !wrapperStructOutput.writeVideo3D.empty()\n                || !wrapperStructOutput.writeBvh.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                if (wrapperStructOutput.writeVideoFps <= 0\n                    && (!oPProducer || producerSharedPtr->get(getCvCapPropFrameFps()) <= 0))\n                    error(\"The frame rate of the frames producer is unknown. Set `--write_video_fps` to your desired\"\n                          \" FPS if you wanna record video (`--write_video`). E.g., if it is a folder of images, you\"\n                          \" will have to know or guess the frame rate; if it is a webcam, you should use the OpenPose\"\n                          \" displayed FPS as desired value. If you do not care, simply add `--write_video_fps 30`.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                originalVideoFps = (\n                    wrapperStructOutput.writeVideoFps > 0 ?\n                    wrapperStructOutput.writeVideoFps : producerSharedPtr->get(getCvCapPropFrameFps()));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Write frames as *.avi video on hard disk\n            if (!wrapperStructOutput.writeVideo.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Sanity checks\n                if (!oPProducer)\n                    error(\"Video file can only be recorded inside `wrapper/wrapper.hpp` if the producer\"\n                          \" is one of the default ones (e.g., video, webcam, ...).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                if (wrapperStructOutput.writeVideoWithAudio && producerSharedPtr->getType() != ProducerType::Video)\n                    error(\"Audio can only be added to the output saved video if the input is also a video (either\"\n                          \" disable `--write_video_with_audio` or use a video as input with `--video`).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // Create video saver worker\n                const auto videoSaver = std::make_shared<VideoSaver>(\n                    wrapperStructOutput.writeVideo.getStdString(), getCvFourcc('M','J','P','G'), originalVideoFps,\n                    (wrapperStructOutput.writeVideoWithAudio ? wrapperStructInput.producerString.getStdString() : \"\"));\n                outputWs.emplace_back(std::make_shared<WVideoSaver<TDatumsSP>>(videoSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Write joint angles as *.bvh file on hard disk\n#ifdef USE_3D_ADAM_MODEL\n            if (!wrapperStructOutput.writeBvh.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto bvhSaver = std::make_shared<BvhSaver>(\n                    wrapperStructOutput.writeBvh, JointAngleEstimation::getTotalModel(), originalVideoFps\n                );\n                outputWs.emplace_back(std::make_shared<WBvhSaver<TDatumsSP>>(bvhSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n#endif\n            // Write heat maps as desired image format on hard disk\n            if (!writeHeatMapsCleaned.empty())\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto heatMapSaver = std::make_shared<HeatMapSaver>(\n                    writeHeatMapsCleaned, wrapperStructOutput.writeHeatMapsFormat.getStdString());\n                outputWs.emplace_back(std::make_shared<WHeatMapSaver<TDatumsSP>>(heatMapSaver));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Add frame information for GUI\n            const bool guiEnabled = (wrapperStructGui.displayMode != DisplayMode::NoDisplay);\n            // If this WGuiInfoAdder instance is placed before the WImageSaver or WVideoSaver, then the resulting\n            // recorded frames will look exactly as the final displayed image by the GUI\n            if (wrapperStructGui.guiVerbose && (guiEnabled || !userOutputWs.empty()\n                                                || threadManagerMode == ThreadManagerMode::Asynchronous\n                                                || threadManagerMode == ThreadManagerMode::AsynchronousOut))\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto guiInfoAdder = std::make_shared<GuiInfoAdder>(numberGpuThreads, guiEnabled);\n                outputWs.emplace_back(std::make_shared<WGuiInfoAdder<TDatumsSP>>(guiInfoAdder));\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Minimal graphical user interface (GUI)\n            TWorker guiW;\n            TWorker videoSaver3DW;\n            if (guiEnabled)\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // PoseRenderers to Renderers\n                std::vector<std::shared_ptr<Renderer>> renderers;\n                if (renderModePose == RenderMode::Cpu)\n                    renderers.emplace_back(std::static_pointer_cast<Renderer>(poseCpuRenderer));\n                else\n                    for (const auto& poseGpuRenderer : poseGpuRenderers)\n                        renderers.emplace_back(std::static_pointer_cast<Renderer>(poseGpuRenderer));\n                // Display\n                const auto numberViews = (producerSharedPtr != nullptr\n                    ? positiveIntRound(producerSharedPtr->get(ProducerProperty::NumberViews)) : 1);\n                auto finalOutputSizeGui = finalOutputSize;\n                if (numberViews > 1 && finalOutputSizeGui.x > 0)\n                    finalOutputSizeGui.x *= numberViews;\n                // Adam (+3-D/2-D) display\n                if (displayAdam)\n                {\n#ifdef USE_3D_ADAM_MODEL\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // Gui\n                    const auto gui = std::make_shared<GuiAdam>(\n                        finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),\n                        spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,\n                        wrapperStructGui.displayMode, JointAngleEstimation::getTotalModel(),\n                        wrapperStructOutput.writeVideoAdam\n                    );\n                    // WGui\n                    guiW = {std::make_shared<WGuiAdam<TDatumsSP>>(gui)};\n                    // Write 3D frames as *.avi video on hard disk\n                    if (!wrapperStructOutput.writeVideo3D.empty())\n                        error(\"3D video can only be recorded if 3D render is enabled.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n#endif\n                }\n                // 3-D (+2-D) display\n                else if (wrapperStructGui.displayMode == DisplayMode::Display3D\n                    || wrapperStructGui.displayMode == DisplayMode::DisplayAll)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // Gui\n                    const auto gui = std::make_shared<Gui3D>(\n                        finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),\n                        spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers,\n                        wrapperStructPose.poseModel, wrapperStructGui.displayMode,\n                        !wrapperStructOutput.writeVideo3D.empty()\n                    );\n                    // WGui\n                    guiW = {std::make_shared<WGui3D<TDatumsSP>>(gui)};\n                    // Write 3D frames as *.avi video on hard disk\n                    if (!wrapperStructOutput.writeVideo3D.empty())\n                    {\n                        const auto videoSaver = std::make_shared<VideoSaver>(\n                            wrapperStructOutput.writeVideo3D.getStdString(), getCvFourcc('M','J','P','G'), originalVideoFps, \"\");\n                        videoSaver3DW = std::make_shared<WVideoSaver3D<TDatumsSP>>(videoSaver);\n                    }\n                }\n                // 2-D display\n                else if (wrapperStructGui.displayMode == DisplayMode::Display2D)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // Gui\n                    const auto gui = std::make_shared<Gui>(\n                        finalOutputSizeGui, wrapperStructGui.fullScreen, threadManager.getIsRunningSharedPtr(),\n                        spVideoSeek, poseExtractorNets, faceExtractorNets, handExtractorNets, renderers\n                    );\n                    // WGui\n                    guiW = {std::make_shared<WGui<TDatumsSP>>(gui)};\n                    // Write 3D frames as *.avi video on hard disk\n                    if (!wrapperStructOutput.writeVideo3D.empty())\n                        error(\"3D video can only be recorded if 3D render is enabled.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                }\n                else\n                    error(\"Unknown DisplayMode.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Set FpsMax\n            TWorker wFpsMax;\n            if (wrapperStructPose.fpsMax > 0.)\n                wFpsMax = std::make_shared<WFpsMax<TDatumsSP>>(wrapperStructPose.fpsMax);\n            // Set wrapper as configured\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n\n\n\n\n            // The less number of queues -> the less threads opened, and potentially the less lag\n\n            // Sanity checks\n            if ((datumProducerW == nullptr) == (userInputWs.empty())\n                && threadManagerMode != ThreadManagerMode::Asynchronous\n                && threadManagerMode != ThreadManagerMode::AsynchronousIn)\n            {\n                const auto message = \"You need to have 1 and only 1 producer selected. You can introduce your own\"\n                                     \" producer by using setWorker(WorkerType::Input, ...) or use the OpenPose\"\n                                     \" default producer by configuring it in the configure function) or use the\"\n                                     \" ThreadManagerMode::Asynchronous(In) mode.\";\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n            if (outputWs.empty() && userOutputWs.empty() && guiW == nullptr\n                && threadManagerMode != ThreadManagerMode::Asynchronous\n                && threadManagerMode != ThreadManagerMode::AsynchronousOut)\n            {\n                error(\"No output selected.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Thread Manager\n            // Clean previous thread manager (avoid configure to crash the program if used more than once)\n            threadManager.reset();\n            unsigned long long threadId = 0ull;\n            auto queueIn = 0ull;\n            auto queueOut = 1ull;\n            // After producer\n            // ID generator (before any multi-threading or any function that requires the ID)\n            const auto wIdGenerator = std::make_shared<WIdGenerator<TDatumsSP>>();\n            // If custom user Worker and uses its own thread\n            std::vector<TWorker> workersAux;\n            if (!userPreProcessingWs.empty())\n            {\n                // If custom user Worker in its own thread\n                if (userPreProcessingWsOnNewThread)\n                    opLog(\"You chose to add your pre-processing function in a new thread. However, OpenPose will\"\n                        \" add it in the same thread than the input frame producer.\",\n                        Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                workersAux = mergeVectors(workersAux, {userPreProcessingWs});\n            }\n            workersAux = mergeVectors(workersAux, {wIdGenerator});\n            // Scale & cv::Mat to OP format\n            if (scaleAndSizeExtractorW != nullptr)\n                workersAux = mergeVectors(workersAux, {scaleAndSizeExtractorW});\n            if (cvMatToOpInputW != nullptr)\n                workersAux = mergeVectors(workersAux, {cvMatToOpInputW});\n            // cv::Mat to output format\n            if (cvMatToOpOutputW != nullptr)\n                workersAux = mergeVectors(workersAux, {cvMatToOpOutputW});\n\n            // Producer\n            // If custom user Worker and uses its own thread\n            if (!userInputWs.empty() && userInputWsOnNewThread)\n            {\n                // Thread 0, queues 0 -> 1\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                threadManager.add(threadId, userInputWs, queueIn++, queueOut++);\n                threadIdPP(threadId, multiThreadEnabled);\n            }\n            // If custom user Worker in same thread\n            else if (!userInputWs.empty())\n                workersAux = mergeVectors(userInputWs, workersAux);\n            // If OpenPose producer (same thread)\n            else if (datumProducerW != nullptr)\n                workersAux = mergeVectors({datumProducerW}, workersAux);\n            // Otherwise\n            else if (threadManagerMode != ThreadManagerMode::Asynchronous\n                     && threadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"No input selected.\", __LINE__, __FUNCTION__, __FILE__);\n            // Thread 0 or 1, queues 0 -> 1\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            threadManager.add(threadId, workersAux, queueIn++, queueOut++);\n            // Increase thread\n            threadIdPP(threadId, multiThreadEnabled);\n\n            // Pose estimation & rendering\n            // Thread 1 or 2...X, queues 1 -> 2, X = 2 + #GPUs\n            if (!poseExtractorsWs.empty())\n            {\n                if (multiThreadEnabled)\n                {\n                    for (auto& wPose : poseExtractorsWs)\n                    {\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wPose, queueIn, queueOut);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                    queueIn++;\n                    queueOut++;\n                    // Sort frames - Required own thread\n                    if (poseExtractorsWs.size() > 1u)\n                    {\n                        const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                }\n                else\n                {\n                    if (poseExtractorsWs.size() > 1)\n                        opLog(\"Multi-threading disabled, only 1 thread running. All GPUs have been disabled but the\"\n                            \" first one, which is defined by gpuNumberStart (e.g., in the OpenPose demo, it is set\"\n                            \" with the `--num_gpu_start` flag).\", Priority::High);\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId, poseExtractorsWs.at(0), queueIn++, queueOut++);\n                }\n            }\n            // Assemble all frames from same time instant (3-D module)\n            const auto wQueueAssembler = std::make_shared<WQueueAssembler<TDatums>>();\n            // 3-D reconstruction\n            if (!poseTriangulationsWs.empty())\n            {\n                // Assemble frames\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                threadManager.add(threadId, wQueueAssembler, queueIn++, queueOut++);\n                threadIdPP(threadId, multiThreadEnabled);\n                // 3-D reconstruction\n                if (multiThreadEnabled)\n                {\n                    for (auto& wPoseTriangulations : poseTriangulationsWs)\n                    {\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wPoseTriangulations, queueIn, queueOut);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                    queueIn++;\n                    queueOut++;\n                    // Sort frames\n                    if (poseTriangulationsWs.size() > 1u)\n                    {\n                        const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                }\n                else\n                {\n                    if (poseTriangulationsWs.size() > 1)\n                        opLog(\"Multi-threading disabled, only 1 thread running for 3-D triangulation.\",\n                            Priority::High);\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId, poseTriangulationsWs.at(0), queueIn++, queueOut++);\n                }\n            }\n            else\n                postProcessingWs = mergeVectors({wQueueAssembler}, postProcessingWs);\n            // Adam/IK step\n            if (!jointAngleEstimationsWs.empty())\n            {\n                if (multiThreadEnabled)\n                {\n                    for (auto& wJointAngleEstimator : jointAngleEstimationsWs)\n                    {\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wJointAngleEstimator, queueIn, queueOut);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                    queueIn++;\n                    queueOut++;\n                    // Sort frames\n                    if (jointAngleEstimationsWs.size() > 1)\n                    {\n                        const auto wQueueOrderer = std::make_shared<WQueueOrderer<TDatumsSP>>();\n                        opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                        threadManager.add(threadId, wQueueOrderer, queueIn++, queueOut++);\n                        threadIdPP(threadId, multiThreadEnabled);\n                    }\n                }\n                else\n                {\n                    if (jointAngleEstimationsWs.size() > 1)\n                        opLog(\"Multi-threading disabled, only 1 thread running for joint angle estimation.\",\n                            Priority::High);\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId, jointAngleEstimationsWs.at(0), queueIn++, queueOut++);\n                }\n            }\n            // Post processing workers\n            if (!postProcessingWs.empty())\n            {\n                // Combining postProcessingWs and outputWs\n                outputWs = mergeVectors(postProcessingWs, outputWs);\n                // // If I wanna split them\n                // opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // threadManager.add(threadId, postProcessingWs, queueIn++, queueOut++);\n                // threadIdPP(threadId, multiThreadEnabled);\n            }\n            // If custom user Worker and uses its own thread\n            if (!userPostProcessingWs.empty())\n            {\n                // If custom user Worker in its own thread\n                if (userPostProcessingWsOnNewThread)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId, userPostProcessingWs, queueIn++, queueOut++);\n                    threadIdPP(threadId, multiThreadEnabled);\n                }\n                // If custom user Worker in same thread\n                // Merge with outputWs\n                else\n                    outputWs = mergeVectors(outputWs, userPostProcessingWs);\n            }\n            // Output workers\n            if (!outputWs.empty())\n            {\n                // Thread 4 or 5, queues 4 -> 5\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                threadManager.add(threadId, outputWs, queueIn++, queueOut++);\n                threadIdPP(threadId, multiThreadEnabled);\n            }\n            // User output worker\n            // Thread Y, queues Q -> Q+1\n            if (!userOutputWs.empty())\n            {\n                if (userOutputWsOnNewThread)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId, userOutputWs, queueIn++, queueOut++);\n                    threadIdPP(threadId, multiThreadEnabled);\n                }\n                else\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    threadManager.add(threadId-1, userOutputWs, queueIn++, queueOut++);\n                }\n            }\n            // OpenPose GUI\n            if (guiW != nullptr)\n            {\n                // Thread Y+1, queues Q+1 -> Q+2\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                threadManager.add(threadId, guiW, queueIn++, queueOut++);\n                // Saving 3D output\n                if (videoSaver3DW != nullptr)\n                    threadManager.add(threadId, videoSaver3DW, queueIn++, queueOut++);\n                threadIdPP(threadId, multiThreadEnabled);\n            }\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Setting maximum speed\n            if (wFpsMax != nullptr)\n            {\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                threadManager.add(threadId, wFpsMax, queueIn++, queueOut++);\n                threadIdPP(threadId, multiThreadEnabled);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename TDatum, typename TDatums, typename TDatumsSP>\n    void createMultiviewTDatum(\n        TDatumsSP& tDatumsSP, unsigned long long& frameCounter,\n        const CameraParameterReader& cameraParameterReader, const void* const cvMatPtr)\n    {\n        try\n        {\n            // Sanity check\n            if (tDatumsSP == nullptr)\n                op::error(\"tDatumsSP was nullptr, it must be initialized.\", __LINE__, __FUNCTION__, __FILE__);\n            // Camera parameters\n            const std::vector<op::Matrix>& cameraMatrices = cameraParameterReader.getCameraMatrices();\n            const std::vector<op::Matrix>& cameraIntrinsics = cameraParameterReader.getCameraIntrinsics();\n            const std::vector<op::Matrix>& cameraExtrinsics = cameraParameterReader.getCameraExtrinsics();\n            const auto matrixesSize = cameraMatrices.size();\n            // More sanity checks\n            if (cameraMatrices.size() < 2)\n                op::error(\"There is less than 2 camera parameter matrices.\",\n                    __LINE__, __FUNCTION__, __FILE__);\n            if (cameraMatrices.size() != cameraIntrinsics.size() || cameraMatrices.size() != cameraExtrinsics.size())\n                op::error(\"Camera parameters must have the same size.\", __LINE__, __FUNCTION__, __FILE__);\n            // Split image to process\n            std::vector<op::Matrix> imagesToProcess(matrixesSize);\n            op::Matrix::splitCvMatIntoVectorMatrix(imagesToProcess, cvMatPtr);\n            // Fill tDatumsSP\n            tDatumsSP->resize(cameraMatrices.size());\n            for (auto datumIndex = 0 ; datumIndex < matrixesSize ; ++datumIndex)\n            {\n                auto& datumPtr = tDatumsSP->at(datumIndex);\n                datumPtr = std::make_shared<op::Datum>();\n                datumPtr->frameNumber = frameCounter;\n                datumPtr->cvInputData = imagesToProcess[datumIndex];\n                if (matrixesSize > 1)\n                {\n                    datumPtr->subId = datumIndex;\n                    datumPtr->subIdMax = matrixesSize-1;\n                    datumPtr->cameraMatrix = cameraMatrices[datumIndex];\n                    datumPtr->cameraExtrinsics = cameraExtrinsics[datumIndex];\n                    datumPtr->cameraIntrinsics = cameraIntrinsics[datumIndex];\n                }\n            }\n            ++frameCounter;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_AUXILIARY_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructExtra.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP\n\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructExtra: Pose estimation and rendering configuration struct.\n     * WrapperStructExtra allows the user to set up the pose estimation and rendering parameters that will be used for\n     * the OpenPose WrapperT template and Wrapper class.\n     */\n    struct OP_API WrapperStructExtra\n    {\n        /**\n         * Whether to run the 3-D reconstruction demo, i.e.,\n         * 1) Reading from a stereo camera system.\n         * 2) Performing 3-D reconstruction from the multiple views.\n         * 3) Displaying 3-D reconstruction results.\n         */\n        bool reconstruct3d;\n\n        /**\n         * Minimum number of views required to reconstruct each keypoint.\n         * By default (-1), it will require max(2, min(4, #cameras-1)) cameras to see the keypoint in order to\n         * reconstruct it.\n         */\n        int minViews3d;\n\n        /**\n         * Whether to return a person ID for each body skeleton, providing temporal consistency.\n         */\n        bool identification;\n\n        /**\n         * Whether to enable people tracking across frames. The value indicates the number of frames where tracking\n         * is run between each OpenPose keypoint detection. Select -1 (default) to disable it or 0 to run\n         * simultaneously OpenPose keypoint detector and tracking for potentially higher accuracy than only OpenPose.\n         */\n        int tracking;\n\n        /**\n         * Whether to enable inverse kinematics (IK) from 3-D keypoints to obtain 3-D joint angles. By default\n         * (0 threads), it is disabled. Increasing the number of threads will increase the speed but also the\n         * global system latency.\n         */\n        int ikThreads;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructExtra(\n            const bool reconstruct3d = false, const int minViews3d = -1, const bool identification = false,\n            const int tracking = -1, const int ikThreads = 0);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_EXTRA_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructFace.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructFace: Face estimation and rendering configuration struct.\n     * WrapperStructFace allows the user to set up the face estimation and rendering parameters that will be used for\n     * the OpenPose WrapperT template and Wrapper class.\n     */\n    struct OP_API WrapperStructFace\n    {\n        /**\n         * Whether to extract face.\n         */\n        bool enable;\n\n        /**\n         * Kind of face rectangle detector. Recommended Detector::Body (fastest one if body is enabled and most\n         * accurate one), which is based on the OpenPose body keypoint detector.\n         */\n        Detector detector;\n\n        /**\n         * CCN (Conv Net) input size.\n         * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy.\n         * Both width and height must be divisible by 16.\n         */\n        Point<int> netInputSize;\n\n        /**\n         * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU.\n         * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively.\n         */\n        RenderMode renderMode;\n\n        /**\n         * Rendering blending alpha value of the pose point locations with respect to the background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose.\n         */\n        float alphaKeypoint;\n\n        /**\n         * Rendering blending alpha value of the heat maps (face part, background or PAF) with respect to the\n         * background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map.\n         */\n        float alphaHeatMap;\n\n        /**\n         * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be\n         * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results.\n         * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds\n         * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong\n         * detections).\n         */\n        float renderThreshold;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructFace(\n            const bool enable = false, const Detector detector = Detector::Body,\n            const Point<int>& netInputSize = Point<int>{368, 368}, const RenderMode renderMode = RenderMode::Auto,\n            const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT,\n            const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP, const float renderThreshold = 0.4f);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructGui.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/gui/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructGui: It controls a small GUI for quick visualization.\n     */\n    struct OP_API WrapperStructGui\n    {\n        /**\n         * Display mode\n         * a) -1 for automatic selection.\n         * b) 0 for no display. Useful if there is no X server and/or to slightly speed up the processing if visual\n         *    output is not required.\n         * c) 2 for 2-D display in the OpenPose small integrated GUI.\n         * d) 3 for 3-D display, if `--3d` was enabled.\n         * e) 1 for both 2-D and 3-D display.\n         */\n        DisplayMode displayMode;\n\n        /**\n         * Whether to add some information to the frame (number of frame, number people detected, etc.) after it is\n         * saved on disk and before it is displayed and/or returned to the user.\n         */\n        bool guiVerbose;\n\n        /**\n         * Whether to display the OpenPose small integrated GUI on fullscreen mode. It can be changed by interacting\n         * with the GUI itself.\n         */\n        bool fullScreen;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructGui(\n            const DisplayMode displayMode = DisplayMode::NoDisplay, const bool guiVerbose = false,\n            const bool fullScreen = false);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_GUI_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructHand.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructHand: Hand estimation and rendering configuration struct.\n     * WrapperStructHand allows the user to set up the hand estimation and rendering parameters that will be used for\n     * the OpenPose WrapperT template and Wrapper class.\n     */\n    struct OP_API WrapperStructHand\n    {\n        /**\n         * Whether to extract hand.\n         */\n        bool enable;\n\n        /**\n         * Kind of hand rectangle detector. Recommended Detector::Body (fastest one if body is enabled and most\n         * accurate one), which is based on the OpenPose body keypoint detector.\n         * For hand, there is the alternative of Detector::BodyWithTracking. If selected, it will add tracking\n         * between frames. Adding hand tracking might improve hand keypoints detection for webcam (if the frame\n         * rate is high enough, i.e., >7 FPS per GPU) and video. This is not person ID tracking, it simply looks\n         * for hands in positions at which hands were located in previous frames, but it does not guarantee the\n         * same person id among frames.\n         */\n        Detector detector;\n\n        /**\n         * CCN (Conv Net) input size.\n         * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy.\n         * Both width and height must be divisible by 16.\n         */\n        Point<int> netInputSize;\n\n        /**\n         * Number of scales to process.\n         * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy.\n         * This parameter is related with scaleRange, such as the final pose estimation will be an average of the\n         * predicted results for each scale.\n         */\n        int scalesNumber;\n\n        /**\n         * Total range between smallest and biggest scale. The scales will be centered in ratio 1. E.g., if\n         * scaleRange = 0.4 and scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2.\n         */\n        float scaleRange;\n\n        /**\n         * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU.\n         * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively.\n         */\n        RenderMode renderMode;\n\n        /**\n         * Rendering blending alpha value of the pose point locations with respect to the background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose.\n         */\n        float alphaKeypoint;\n\n        /**\n         * Rendering blending alpha value of the heat maps (hand part, background or PAF) with respect to the\n         * background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map.\n         */\n        float alphaHeatMap;\n\n        /**\n         * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be\n         * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results.\n         * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds\n         * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong\n         * detections).\n         */\n        float renderThreshold;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructHand(\n            const bool enable = false, const Detector detector = Detector::Body,\n            const Point<int>& netInputSize = Point<int>{368, 368}, const int scalesNumber = 1,\n            const float scaleRange = 0.4f, const RenderMode renderMode = RenderMode::Auto,\n            const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT,\n            const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP, const float renderThreshold = 0.2f);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_HAND_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructInput.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP\n\n#include <limits> // std::numeric_limits\n#include <openpose/core/common.hpp>\n#include <openpose/producer/producer.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructInput: Input (images, video, webcam, etc.) configuration struct.\n     * WrapperStructInput allows the user to set up the input frames generator.\n     */\n    struct OP_API WrapperStructInput\n    {\n        /**\n         * Desired type of producer (FlirCamera, ImageDirectory, IPCamera, Video, Webcam, None, etc.).\n         * Default: ProducerType::None.\n         */\n        ProducerType producerType;\n\n        /**\n         * Path of the producer (image directory path for ImageDirectory, video path for Video,\n         * camera index for Webcam and FlirCamera, URL for IPCamera, etc.).\n         * Default: \"\".\n         */\n        String producerString;\n\n        /**\n         * First image to process.\n         * Default: 0.\n         */\n        unsigned long long frameFirst;\n\n        /**\n         * Step or gap across processed frames.\n         * Default: 1 (i.e., process all frames).\n         * Example: A value of 5 would mean to process frames 0, 5, 10, etc.\n         */\n        unsigned long long frameStep;\n\n        /**\n         * Last image to process.\n         * Default: -1 (i.e., process all frames).\n         */\n        unsigned long long frameLast;\n\n        /**\n         * Whether to skip or sleep in order to keep the same FPS as the frames producer.\n         */\n        bool realTimeProcessing;\n\n        /**\n         * Whether to flip (mirror) the image.\n         */\n        bool frameFlip;\n\n        /**\n         * Image rotation.\n         * Only 4 possible values: 0 (default, no rotation), 90, 180 or 270 degrees\n         */\n        int frameRotate;\n\n        /**\n         * Whether to re-open the producer if it reaches the end (e.g., video or image directory after the last frame).\n         */\n        bool framesRepeat;\n\n        /**\n         * Camera resolution (only for Webcam and FlirCamera).\n         */\n        Point<int> cameraResolution;\n\n        /**\n         * Directory path for the camera parameters (intrinsic and extrinsic parameters) or optionally XML file\n         * full path (if only 1 view).\n         */\n        String cameraParameterPath;\n\n        /**\n         * Whether to undistort the image given the camera parameters.\n         */\n        bool undistortImage;\n\n        /**\n         * Number of camera views.\n         * Complementary option for `--image_dir` or `--video`\n         * It is -1 for Flir cameras (# cameras detected at runtime), as well as for any other frames source (-1 and 1\n         * are equivalent for those). It could be greater than 1 only for prerecorded produced sources, such as video\n         * and image directory.\n         */\n        int numberViews;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructInput(\n            const ProducerType producerType = ProducerType::None, const String& producerString = \"\",\n            const unsigned long long frameFirst = 0, const unsigned long long frameStep = 1,\n            const unsigned long long frameLast = std::numeric_limits<unsigned long long>::max(),\n            const bool realTimeProcessing = false, const bool frameFlip = false, const int frameRotate = 0,\n            const bool framesRepeat = false, const Point<int>& cameraResolution = Point<int>{-1,-1},\n            const String& cameraParameterPath = \"models/cameraParameters/\",\n            const bool undistortImage = false, const int numberViews = -1);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_INPUT_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructOutput.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/filestream/enumClasses.hpp>\n#include <openpose/gui/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructOutput: Output ( writing rendered results and/or pose data, etc.) configuration struct.\n     */\n    struct OP_API WrapperStructOutput\n    {\n        /**\n         * Output verbose in the command line.\n         * If -1, it will be disabled (default). If it is a positive integer number, it will print on\"\n         * the command line every `verbose` frames. If number in the range (0,1), it will print the\"\n         * progress every `verbose` times the total of frames.\n         */\n        double verbose;\n\n        /**\n         * Pose (x, y, score) locations saving folder location.\n         * If it is empty (default), it is disabled.\n         * Select format with writeKeypointFormat.\n         */\n        String writeKeypoint;\n\n        /**\n         * Data format to save Pose (x, y, score) locations.\n         * Options: DataFormat::Json (default), DataFormat::Xml and DataFormat::Yml (equivalent to DataFormat::Yaml)\n         * JSON option only available for OpenCV >= 3.0.\n         */\n        DataFormat writeKeypointFormat;\n\n        /**\n         * Directory to write OpenPose output in JSON format.\n         * If it is empty (default), it is disabled.\n         * It includes:\n         *     - `people` field with body, hand, and face pose keypoints in (x, y, score) format.\n         *     - `part_candidates` field with body part candidates in (x, y, score) format (if enabled with\n         *       `--part_candidates`).\n         */\n        String writeJson;\n\n        /**\n         * Pose (x, y, score) locations saving folder location in JSON COCO validation format.\n         * If it is empty (default), it is disabled.\n         */\n        String writeCocoJson;\n\n        /**\n         * It selects the COCO variants for cocoJsonSaver.\n         * Add 1 for body, add 2 for foot, 4 for face, and/or 8 for hands. Use 0 to use all the possible candidates.\n         * E.g., 7 would mean body+foot+face COCO JSON..\n         */\n        int writeCocoJsonVariants;\n\n        /**\n         * Experimental option (only makes effect on car JSON generation).\n         * It selects the COCO variant for cocoJsonSaver.\n         */\n        int writeCocoJsonVariant;\n\n        /**\n         * Rendered image saving folder.\n         * If it is empty (default), it is disabled.\n         */\n        String writeImages;\n\n        /**\n         * Rendered image saving folder format.\n         * Check your OpenCV version documentation for a list of compatible formats.\n         * E.g., png, jpg, etc.\n         * If writeImages is empty (default), it makes no effect.\n         */\n        String writeImagesFormat;\n\n        /**\n         * Rendered images saving video path.\n         * Please, use *.avi format.\n         * If it is empty (default), it is disabled.\n         */\n        String writeVideo;\n\n        /**\n         * Frame rate of the recorded video.\n         * By default (-1.), it will try to get the input frames producer frame rate (e.g., input video or webcam frame\n         * rate). If the input frames producer does not have a set FPS (e.g., image_dir or webcam if OpenCV not\n         * compiled with its support), set this value accordingly (e.g., to the frame rate displayed by the OpenPose\n         * GUI).\n         */\n        double writeVideoFps;\n\n        /**\n         * Whether to save the output video with audio. The input producer must be a video too.\n         */\n        bool writeVideoWithAudio;\n\n        /**\n         * Rendered heat maps saving folder.\n         * In order to save the heatmaps, WrapperStructPose.heatMapTypes must also be filled.\n         * If it is empty (default), it is disabled.\n         */\n        String writeHeatMaps;\n\n        /**\n         * Heat maps image saving format.\n         * Analogous to writeImagesFormat.\n         */\n        String writeHeatMapsFormat;\n\n        /**\n         * Rendered 3D images saving video path.\n         * Please, use *.avi format.\n         * If it is empty (default), it is disabled.\n         */\n        String writeVideo3D;\n\n        /**\n         * Rendered Adam images saving video path.\n         * Please, use *.avi format.\n         * If it is empty (default), it is disabled.\n         */\n        String writeVideoAdam;\n\n        /**\n         * Path to save a 3-D joint angle BVH file.\n         * Please, use *.bvh format.\n         * If it is empty (default), it is disabled.\n         */\n        String writeBvh;\n\n        /**\n         * Target server IP address for UDP client-server communication.\n         */\n        String udpHost;\n\n        /**\n         * Target server IP port for UDP client-server communication.\n         */\n        String udpPort;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructOutput(\n            const double verbose = -1, const String& writeKeypoint = \"\",\n            const DataFormat writeKeypointFormat = DataFormat::Xml, const String& writeJson = \"\",\n            const String& writeCocoJson = \"\", const int writeCocoJsonVariants = 1,\n            const int writeCocoJsonVariant = 1, const String& writeImages = \"\",\n            const String& writeImagesFormat = \"png\", const String& writeVideo = \"\",\n            const double writeVideoFps = -1., const bool writeVideoWithAudio = false,\n            const String& writeHeatMaps = \"\", const String& writeHeatMapsFormat = \"png\",\n            const String& writeVideo3D = \"\", const String& writeVideoAdam = \"\",\n            const String& writeBvh = \"\", const String& udpHost = \"\",\n            const String& udpPort = \"8051\");\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_OUTPUT_HPP\n"
  },
  {
    "path": "include/openpose/wrapper/wrapperStructPose.hpp",
    "content": "#ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP\n#define OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP\n\n#include <openpose/core/common.hpp>\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/pose/enumClasses.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/wrapper/enumClasses.hpp>\n\nnamespace op\n{\n    /**\n     * WrapperStructPose: Pose estimation and rendering configuration struct.\n     * WrapperStructPose allows the user to set up the pose estimation and rendering parameters that will be used for\n     * the OpenPose WrapperT template and Wrapper class.\n     */\n    struct OP_API WrapperStructPose\n    {\n        /**\n         * Whether to extract body.\n         * It might be optionally disabled for very few cases (e.g., if only face keypoint detection is desired for\n         * speedup while reducing its accuracy). Otherwise, it must be always enabled.\n         */\n        PoseMode poseMode;\n\n        /**\n         * CCN (Conv Net) input size.\n         * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy.\n         * Both width and height must be divisible by 16.\n         */\n        Point<int> netInputSize;\n\n        /**\n         * Zero or negative means that using `-1` in netInputSize will behave as explained in its flag description.\n         * Otherwise, and to avoid out of memory errors, the `-1` in netInputSize will clip to this value times the\n         * default 16/9 aspect ratio value (i.e., 656 width for a 368 height). E.g., netInputSizeDynamicBehavior = 10\n         * and netInputSize = {-1x368} will clip to 6560x368 (10 x 656). Recommended 1 for small GPUs (to avoid out of\n         * memory errors but maximize speed) and 0 for big GPUs (for maximum accuracy and speed).\n         */\n        double netInputSizeDynamicBehavior;\n\n        /**\n         * Output size of the final rendered image.\n         * It barely affects performance compared to netInputSize.\n         * The final Datum.poseKeypoints can be scaled with respect to outputSize if `keypointScaleMode` is set to\n         * ScaleMode::OutputResolution, even if the rendering is disabled.\n         */\n        Point<int> outputSize;\n\n        /**\n         * Final scale of the Array<float> Datum.poseKeypoints and the written pose data.\n         * The final Datum.poseKeypoints can be scaled with respect to input size (ScaleMode::InputResolution), net\n         * output size (ScaleMode::NetOutputResolution), output rendering size (ScaleMode::OutputResolution), from 0 to\n         * 1 (ScaleMode::ZeroToOne(FixedAspect)), and -1 to 1 (ScaleMode::PlusMinusOne(FixedAspect)).\n         */\n        ScaleMode keypointScaleMode;\n\n        /**\n         * Number of GPUs processing in parallel.\n         * The greater, the faster the algorithm will run, but potentially higher lag will appear (which only affects\n         * in real-time webcam scenarios).\n         */\n        int gpuNumber;\n\n        /**\n         * First GPU device.\n         * Such as the GPUs used will be the ones in the range: [gpuNumberStart, gpuNumberStart + gpuNumber].\n         */\n        int gpuNumberStart;\n\n        /**\n         * Number of scales to process.\n         * The greater, the slower and more memory it will be needed, but it will potentially increase accuracy.\n         * This parameter is related with scaleGap, such as the final pose estimation will be an average of the\n         * predicted results for each scale.\n         */\n        int scalesNumber;\n\n        /**\n         * Gap between successive scales.\n         * The pose estimation will be estimation for the scales in the range [1, 1-scaleGap*scalesNumber], with a gap\n         * of scaleGap.\n         */\n        float scaleGap;\n\n        /**\n         * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU.\n         * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively.\n         */\n        RenderMode renderMode;\n\n        /**\n         * Pose model, it affects the number of body parts to render\n         * Select PoseModel::BODY_25 for 25 body-part COCO + foot model; PoseModel::COCO_18 for 18 body-part COCO;\n         * PoseModel::MPI_15 for 15 body-part MPI; PoseModel::MPI_15_4 for faster version of MPI; etc..\n         */\n        PoseModel poseModel;\n\n        /**\n         * Whether to blend the final results on top of the original image, or just render them on a flat background.\n         */\n        bool blendOriginalFrame;\n\n        /**\n         * Rendering blending alpha value of the pose point locations with respect to the background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will fully render the pose.\n         */\n        float alphaKeypoint;\n\n        /**\n         * Rendering blending alpha value of the heat maps (body part, background or PAF) with respect to the\n         * background image.\n         * Value in the range [0, 1]. 0 will only render the background, 1 will only render the heat map.\n         */\n        float alphaHeatMap;\n\n        /**\n         * Element to initially render.\n         * Set 0 for pose, [1, #body parts] for each body part following the order on POSE_BODY_PART_MAPPING on\n         * `include/pose/poseParameters.hpp`, #body parts+1 for background, #body parts+2 for all body parts\n         * overlapped, #body parts+3 for all PAFs, and [#body parts+4, #body parts+4+#pair pairs] for each PAF\n         * following the order on POSE_BODY_PART_PAIRS.\n         */\n        int defaultPartToRender;\n\n        /**\n         * Folder where the pose Caffe models are located.\n         */\n        String modelFolder;\n\n        /**\n         * Whether and which heat maps to save on the Array<float> Datum.heatmaps.\n         * Use HeatMapType::Parts for body parts, HeatMapType::Background for the background, and HeatMapType::PAFs for\n         * the Part Affinity Fields.\n         */\n        std::vector<HeatMapType> heatMapTypes;\n\n        /**\n         * Scale of the Datum.heatmaps.\n         * Select ScaleMode::ZeroToOne(FixedAspect) for range [0,1], ScaleMode::PlusMinusOne(FixedAspect) for [-1,1]\n         * and ScaleMode::UnsignedChar for [0, 255].\n         * If heatMapTypes.empty(), then this parameters makes no effect.\n         */\n        ScaleMode heatMapScaleMode;\n\n        /**\n         * Whether to add the body part candidates.\n         * Candidates refer to all the detected body parts, before being assembled into people.\n         */\n        bool addPartCandidates;\n\n        /**\n         * Rendering threshold. Only estimated keypoints whose score confidences are higher than this value will be\n         * rendered. Note: Rendered refers only to visual display in the OpenPose basic GUI, not in the saved results.\n         * Generally, a high threshold (> 0.5) will only render very clear body parts; while small thresholds\n         * (~0.1) will also output guessed and occluded keypoints, but also more false positives (i.e., wrong\n         * detections).\n         */\n        float renderThreshold;\n\n        /**\n         * Maximum number of people to be detected.\n         * This parameter will limit the maximum number of people detected, by keeping the people with the\n         * `numberPeopleMax` top scores.\n         * Useful if you know the exact number of people in the scene, so it can remove false positives (if all the\n         * people have been detected.\n         * However, it might also include false negatives by removing very small or highly occluded people.\n         */\n        int numberPeopleMax;\n\n        /**\n         * Whether to maximize the number of positives.\n         * It reduces the thresholds to accept a person candidate. It highly increases both false and true positives.\n         * I.e., it maximizes average recall but could harm average precision.\n         */\n        bool maximizePositives;\n\n        /**\n         * Maximum processing frame rate.\n         * By default (-1), OpenPose will process frames as fast as possible.\n         * Example usage: If OpenPose is displaying images too quickly, this can reduce the speed so the user can\n         * analyze better each frame from the GUI.\n         */\n        double fpsMax;\n\n        /**\n         * Final path where the pose Caffe ProtoTxt file is located.\n         * The combination modelFolder + protoTxtPath represents the whole path to the prototxt file.\n         * If empty, it will use the default OpenPose ProtoTxt file.\n         */\n        String protoTxtPath;\n\n        /**\n         * Final path where the pose Caffe CaffeModel is located.\n         * The combination modelFolder + caffeModelPath represents the whole path to the caffemodel file.\n         * If empty, it will use the default OpenPose CaffeModel file.\n         */\n        String caffeModelPath;\n\n        /**\n         * The image upsampling scale. 8 is the stride of the network, so the ideal value to maximize the\n         * speed/accuracy trade-off.\n         */\n        float upsamplingRatio;\n\n        /**\n         * Whether to internally enable Google Logging.\n         * This option is only applicable if Caffe is used.\n         * Only disable it if the user is already calling google::InitGoogleLogging() in his code.\n         * If the user disables Google Logging and he does not call it by himself, then Caffe will start to pop up\n         * all the verbose messages.\n         */\n        bool enableGoogleLogging;\n\n        /**\n         * Constructor of the struct.\n         * It has the recommended and default values we recommend for each element of the struct.\n         * Since all the elements of the struct are public, they can also be manually filled.\n         */\n        WrapperStructPose(\n            const PoseMode poseMode = PoseMode::Enabled, const Point<int>& netInputSize = Point<int>{-1, 368},\n            const double netInputSizeDynamicBehavior = 1.,\n            const Point<int>& outputSize = Point<int>{-1, -1},\n            const ScaleMode keypointScaleMode = ScaleMode::InputResolution, const int gpuNumber = -1,\n            const int gpuNumberStart = 0, const int scalesNumber = 1, const float scaleGap = 0.25f,\n            const RenderMode renderMode = RenderMode::Auto, const PoseModel poseModel = PoseModel::BODY_25,\n            const bool blendOriginalFrame = true, const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT,\n            const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const int defaultPartToRender = 0,\n            const String& modelFolder = \"models/\", const std::vector<HeatMapType>& heatMapTypes = {},\n            const ScaleMode heatMapScaleMode = ScaleMode::UnsignedChar, const bool addPartCandidates = false,\n            const float renderThreshold = 0.05f, const int numberPeopleMax = -1, const bool maximizePositives = false,\n            const double fpsMax = -1., const String& protoTxtPath = \"\", const String& caffeModelPath = \"\",\n            const float upsamplingRatio = 0.f, const bool enableGoogleLogging = true);\n    };\n}\n\n#endif // OPENPOSE_WRAPPER_WRAPPER_STRUCT_POSE_HPP\n"
  },
  {
    "path": "include/openpose_private/3d/poseTriangulationPrivate.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP\n#define OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP\n\n#include <opencv2/core/core.hpp>\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    /**\n     * 3D triangulation given known camera parameter matrices and based on linear DLT algorithm.\n     * The returned cv::Mat is a 4x1 matrix, where the last coordinate is 1.\n     */\n    double triangulate(\n        cv::Mat& reconstructedPoint, const std::vector<cv::Mat>& cameraMatrices,\n        const std::vector<cv::Point2d>& pointsOnEachCamera);\n\n    /**\n     * 3D triangulation given known camera parameter matrices and based on linear DLT algorithm with additional LMA\n     * non-linear refinement.\n     * The returned cv::Mat is a 4x1 matrix, where the last coordinate is 1.\n     * Note: If Ceres is not enabled, the LMA refinement is skipped and this function is equivalent to triangulate().\n     */\n    double triangulateWithOptimization(\n        cv::Mat& reconstructedPoint, const std::vector<cv::Mat>& cameraMatrices,\n        const std::vector<cv::Point2d>& pointsOnEachCamera, const double reprojectionMaxAcceptable);\n}\n\n#endif // OPENPOSE_PRIVATE_3D_POSE_TRIANGULATION_PRIVATE_HPP\n"
  },
  {
    "path": "include/openpose_private/calibration/gridPatternFunctions.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP\n#define OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP\n\n#include <opencv2/opencv.hpp>\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    enum class Points2DOrigin\n    {\n        TopLeft,\n        TopRight,\n        BottomLeft,\n        BottomRight\n    };\n\n    std::pair<bool, std::vector<cv::Point2f>> findAccurateGridCorners(\n        const cv::Mat& image, const cv::Size& gridInnerCorners);\n\n    std::vector<cv::Point3f> getObjects3DVector(\n        const cv::Size& gridInnerCorners, const float gridSquareSizeMm);\n\n    void drawGridCorners(\n        cv::Mat& image, const cv::Size& gridInnerCorners, const std::vector<cv::Point2f>& points2DVector);\n\n    std::array<unsigned int, 4> getOutterCornerIndices(\n        const std::vector<cv::Point2f>& points2DVector, const cv::Size& gridInnerCorners);\n\n    void reorderPoints(\n        std::vector<cv::Point2f>& points2DVector, const cv::Size& gridInnerCorners,\n        const cv::Mat& image, const bool showWarning = true);\n\n    void plotGridCorners(\n        const cv::Size& gridInnerCorners, const std::vector<cv::Point2f>& points2DVector,\n        const std::string& imagePath, const cv::Mat& image);\n}\n\n#endif // OPENPOSE_PRIVATE_CALIBRATION_GRID_PATTERN_FUNCTIONS_HPP\n"
  },
  {
    "path": "include/openpose_private/gpu/cl2.hpp",
    "content": "/*******************************************************************************\n * Copyright (c) 2008-2016 The Khronos Group Inc.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and/or associated documentation files (the\n * \"Materials\"), to deal in the Materials without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Materials, and to\n * permit persons to whom the Materials are furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Materials.\n *\n * MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS\n * KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS\n * SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT\n *    https://www.khronos.org/registry/\n *\n * THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n ******************************************************************************/\n\n/*! \\file\n *\n *   \\brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33),\n *       OpenCL 1.2 (rev 15) and OpenCL 2.0 (rev 29)\n *   \\author Lee Howes and Bruce Merry\n *\n *   Derived from the OpenCL 1.x C++ bindings written by\n *   Benedict R. Gaster, Laurent Morichetti and Lee Howes\n *   With additions and fixes from:\n *       Brian Cole, March 3rd 2010 and April 2012\n *       Matt Gruenke, April 2012.\n *       Bruce Merry, February 2013.\n *       Tom Deakin and Simon McIntosh-Smith, July 2013\n *       James Price, 2015-\n *\n *   \\version 2.0.10\n *   \\date 2016-07-20\n *\n *   Optional extension support\n *\n *         cl_ext_device_fission\n *         #define CL_HPP_USE_CL_DEVICE_FISSION\n *         cl_khr_d3d10_sharing\n *         #define CL_HPP_USE_DX_INTEROP\n *         cl_khr_sub_groups\n *         #define CL_HPP_USE_CL_SUB_GROUPS_KHR\n *\n *   Doxygen documentation for this header is available here:\n *\n *       http://khronosgroup.github.io/OpenCL-CLHPP/\n *\n *   The latest version of this header can be found on the GitHub releases page:\n *\n *       https://github.com/KhronosGroup/OpenCL-CLHPP/releases\n *\n *   Bugs and patches can be submitted to the GitHub repository:\n *\n *       https://github.com/KhronosGroup/OpenCL-CLHPP\n */\n\n/*! \\mainpage\n * \\section intro Introduction\n * For many large applications C++ is the language of choice and so it seems\n * reasonable to define C++ bindings for OpenCL.\n *\n * The interface is contained with a single C++ header file \\em cl2.hpp and all\n * definitions are contained within the namespace \\em cl. There is no additional\n * requirement to include \\em cl.h and to use either the C++ or original C\n * bindings; it is enough to simply include \\em cl2.hpp.\n *\n * The bindings themselves are lightweight and correspond closely to the\n * underlying C API. Using the C++ bindings introduces no additional execution\n * overhead.\n *\n * There are numerous compatibility, portability and memory management\n * fixes in the new header as well as additional OpenCL 2.0 features.\n * As a result the header is not directly backward compatible and for this\n * reason we release it as cl2.hpp rather than a new version of cl.hpp.\n *\n *\n * \\section compatibility Compatibility\n * Due to the evolution of the underlying OpenCL API the 2.0 C++ bindings\n * include an updated approach to defining supported feature versions\n * and the range of valid underlying OpenCL runtime versions supported.\n *\n * The combination of preprocessor macros CL_HPP_TARGET_OPENCL_VERSION and\n * CL_HPP_MINIMUM_OPENCL_VERSION control this range. These are three digit\n * decimal values representing OpenCL runime versions. The default for\n * the target is 200, representing OpenCL 2.0 and the minimum is also\n * defined as 200. These settings would use 2.0 API calls only.\n * If backward compatibility with a 1.2 runtime is required, the minimum\n * version may be set to 120.\n *\n * Note that this is a compile-time setting, and so affects linking against\n * a particular SDK version rather than the versioning of the loaded runtime.\n *\n * The earlier versions of the header included basic vector and string\n * classes based loosely on STL versions. These were difficult to\n * maintain and very rarely used. For the 2.0 header we now assume\n * the presence of the standard library unless requested otherwise.\n * We use std::array, std::vector, std::shared_ptr and std::string\n * throughout to safely manage memory and reduce the chance of a\n * recurrence of earlier memory management bugs.\n *\n * These classes are used through typedefs in the cl namespace:\n * cl::array, cl::vector, cl::pointer and cl::string.\n * In addition cl::allocate_pointer forwards to std::allocate_shared\n * by default.\n * In all cases these standard library classes can be replaced with\n * custom interface-compatible versions using the CL_HPP_NO_STD_ARRAY,\n * CL_HPP_NO_STD_VECTOR, CL_HPP_NO_STD_UNIQUE_PTR and\n * CL_HPP_NO_STD_STRING macros.\n *\n * The OpenCL 1.x versions of the C++ bindings included a size_t wrapper\n * class to interface with kernel enqueue. This caused unpleasant interactions\n * with the standard size_t declaration and led to namespacing bugs.\n * In the 2.0 version we have replaced this with a std::array-based interface.\n * However, the old behaviour can be regained for backward compatibility\n * using the CL_HPP_ENABLE_SIZE_T_COMPATIBILITY macro.\n *\n * Finally, the program construction interface used a clumsy vector-of-pairs\n * design in the earlier versions. We have replaced that with a cleaner\n * vector-of-vectors and vector-of-strings design. However, for backward\n * compatibility old behaviour can be regained with the\n * CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY macro.\n *\n * In OpenCL 2.0 OpenCL C is not entirely backward compatibility with\n * earlier versions. As a result a flag must be passed to the OpenCL C\n * compiled to request OpenCL 2.0 compilation of kernels with 1.2 as\n * the default in the absence of the flag.\n * In some cases the C++ bindings automatically compile code for ease.\n * For those cases the compilation defaults to OpenCL C 2.0.\n * If this is not wanted, the CL_HPP_CL_1_2_DEFAULT_BUILD macro may\n * be specified to assume 1.2 compilation.\n * If more fine-grained decisions on a per-kernel bases are required\n * then explicit build operations that take the flag should be used.\n *\n *\n * \\section parameterization Parameters\n * This header may be parameterized by a set of preprocessor macros.\n *\n * - CL_HPP_TARGET_OPENCL_VERSION\n *\n *   Defines the target OpenCL runtime version to build the header\n *   against. Defaults to 200, representing OpenCL 2.0.\n *\n * - CL_HPP_NO_STD_STRING\n *\n *   Do not use the standard library string class. cl::string is not\n *   defined and may be defined by the user before cl2.hpp is\n *   included.\n *\n * - CL_HPP_NO_STD_VECTOR\n *\n *   Do not use the standard library vector class. cl::vector is not\n *   defined and may be defined by the user before cl2.hpp is\n *   included.\n *\n * - CL_HPP_NO_STD_ARRAY\n *\n *   Do not use the standard library array class. cl::array is not\n *   defined and may be defined by the user before cl2.hpp is\n *   included.\n *\n * - CL_HPP_NO_STD_UNIQUE_PTR\n *\n *   Do not use the standard library unique_ptr class. cl::pointer and\n *   the cl::allocate_pointer functions are not defined and may be\n *   defined by the user before cl2.hpp is included.\n *\n * - CL_HPP_ENABLE_DEVICE_FISSION\n *\n *   Enables device fission for OpenCL 1.2 platforms.\n *\n * - CL_HPP_ENABLE_EXCEPTIONS\n *\n *   Enable exceptions for use in the C++ bindings header. This is the\n *   preferred error handling mechanism but is not required.\n *\n * - CL_HPP_ENABLE_SIZE_T_COMPATIBILITY\n *\n *   Backward compatibility option to support cl.hpp-style size_t\n *   class.  Replaces the updated std::array derived version and\n *   removal of size_t from the namespace. Note that in this case the\n *   new size_t class is placed in the cl::compatibility namespace and\n *   thus requires an additional using declaration for direct backward\n *   compatibility.\n *\n * - CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY\n *\n *   Enable older vector of pairs interface for construction of\n *   programs.\n *\n * - CL_HPP_CL_1_2_DEFAULT_BUILD\n *\n *   Default to OpenCL C 1.2 compilation rather than OpenCL C 2.0\n *   applies to use of cl::Program construction and other program\n *   build variants.\n *\n *\n * \\section example Example\n *\n * The following example shows a general use case for the C++\n * bindings, including support for the optional exception feature and\n * also the supplied vector and string classes, see following sections for\n * descriptions of these features.\n *\n * \\code\n    #define CL_HPP_ENABLE_EXCEPTIONS\n    #define CL_HPP_TARGET_OPENCL_VERSION 200\n\n    #include <CL/cl2.hpp>\n    #include <iostream>\n    #include <vector>\n    #include <memory>\n    #include <algorithm>\n\n    const int numElements = 32;\n\n    int main(void)\n    {\n        // Filter for a 2.0 platform and set it as the default\n        std::vector<cl::Platform> platforms;\n        cl::Platform::get(&platforms);\n        cl::Platform plat;\n        for (auto &p : platforms) {\n            std::string platver = p.getInfo<CL_PLATFORM_VERSION>();\n            if (platver.find(\"OpenCL 2.\") != std::string::npos) {\n                plat = p;\n            }\n        }\n        if (plat() == 0)  {\n            std::cout << \"No OpenCL 2.0 platform found.\";\n            return -1;\n        }\n\n        cl::Platform newP = cl::Platform::setDefault(plat);\n        if (newP != plat) {\n            std::cout << \"Error setting default platform.\";\n            return -1;\n        }\n\n        // Use C++11 raw string literals for kernel source code\n        std::string kernel1{R\"CLC(\n            global int globalA;\n            kernel void updateGlobal()\n            {\n              globalA = 75;\n            }\n        )CLC\"};\n        std::string kernel2{R\"CLC(\n            typedef struct { global int *bar; } Foo;\n            kernel void vectorAdd(global const Foo* aNum, global const int *inputA, global const int *inputB,\n                                  global int *output, int val, write_only pipe int outPipe, queue_t childQueue)\n            {\n              output[get_global_id(0)] = inputA[get_global_id(0)] + inputB[get_global_id(0)] + val + *(aNum->bar);\n              write_pipe(outPipe, &val);\n              queue_t default_queue = get_default_queue();\n              ndrange_t ndrange = ndrange_1D(get_global_size(0)/2, get_global_size(0)/2);\n\n              // Have a child kernel write into third quarter of output\n              enqueue_kernel(default_queue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange,\n                ^{\n                    output[get_global_size(0)*2 + get_global_id(0)] =\n                      inputA[get_global_size(0)*2 + get_global_id(0)] + inputB[get_global_size(0)*2 + get_global_id(0)] + globalA;\n                });\n\n              // Have a child kernel write into last quarter of output\n              enqueue_kernel(childQueue, CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange,\n                ^{\n                    output[get_global_size(0)*3 + get_global_id(0)] =\n                      inputA[get_global_size(0)*3 + get_global_id(0)] + inputB[get_global_size(0)*3 + get_global_id(0)] + globalA + 2;\n                });\n            }\n        )CLC\"};\n\n        // New simpler string interface style\n        std::vector<std::string> programStrings {kernel1, kernel2};\n\n        cl::Program vectorAddProgram(programStrings);\n        try {\n            vectorAddProgram.build(\"-cl-std=CL2.0\");\n        }\n        catch (...) {\n            // Print build info for all devices\n            cl_int buildErr = CL_SUCCESS;\n            auto buildInfo = vectorAddProgram.getBuildInfo<CL_PROGRAM_BUILD_LOG>(&buildErr);\n            for (auto &pair : buildInfo) {\n                std::cerr << pair.second << std::endl << std::endl;\n            }\n\n            return 1;\n        }\n\n        typedef struct { int *bar; } Foo;\n\n        // Get and run kernel that initializes the program-scope global\n        // A test for kernels that take no arguments\n        auto program2Kernel =\n            cl::KernelFunctor<>(vectorAddProgram, \"updateGlobal\");\n        program2Kernel(\n            cl::EnqueueArgs(\n            cl::NDRange(1)));\n\n        //////////////////\n        // SVM allocations\n\n        auto anSVMInt = cl::allocate_svm<int, cl::SVMTraitCoarse<>>();\n        *anSVMInt = 5;\n        cl::SVMAllocator<Foo, cl::SVMTraitCoarse<cl::SVMTraitReadOnly<>>> svmAllocReadOnly;\n        auto fooPointer = cl::allocate_pointer<Foo>(svmAllocReadOnly);\n        fooPointer->bar = anSVMInt.get();\n        cl::SVMAllocator<int, cl::SVMTraitCoarse<>> svmAlloc;\n        std::vector<int, cl::SVMAllocator<int, cl::SVMTraitCoarse<>>> inputA(numElements, 1, svmAlloc);\n        cl::coarse_svm_vector<int> inputB(numElements, 2, svmAlloc);\n\n        //\n        //////////////\n\n        // Traditional cl_mem allocations\n        std::vector<int> output(numElements, 0xdeadbeef);\n        cl::Buffer outputBuffer(begin(output), end(output), false);\n        cl::Pipe aPipe(sizeof(cl_int), numElements / 2);\n\n        // Default command queue, also passed in as a parameter\n        cl::DeviceCommandQueue defaultDeviceQueue = cl::DeviceCommandQueue::makeDefault(\n            cl::Context::getDefault(), cl::Device::getDefault());\n\n        auto vectorAddKernel =\n            cl::KernelFunctor<\n                decltype(fooPointer)&,\n                int*,\n                cl::coarse_svm_vector<int>&,\n                cl::Buffer,\n                int,\n                cl::Pipe&,\n                cl::DeviceCommandQueue\n                >(vectorAddProgram, \"vectorAdd\");\n\n        // Ensure that the additional SVM pointer is available to the kernel\n        // This one was not passed as a parameter\n        vectorAddKernel.setSVMPointers(anSVMInt);\n\n        // Hand control of coarse allocations to runtime\n        cl::enqueueUnmapSVM(anSVMInt);\n        cl::enqueueUnmapSVM(fooPointer);\n        cl::unmapSVM(inputB);\n        cl::unmapSVM(output2);\n\n        cl_int error;\n        vectorAddKernel(\n            cl::EnqueueArgs(\n                cl::NDRange(numElements/2),\n                cl::NDRange(numElements/2)),\n            fooPointer,\n            inputA.data(),\n            inputB,\n            outputBuffer,\n            3,\n            aPipe,\n            defaultDeviceQueue,\n            error\n            );\n\n        cl::copy(outputBuffer, begin(output), end(output));\n        // Grab the SVM output vector using a map\n        cl::mapSVM(output2);\n\n        cl::Device d = cl::Device::getDefault();\n\n        std::cout << \"Output:\\n\";\n        for (int i = 1; i < numElements; ++i) {\n            std::cout << \"\\t\" << output[i] << \"\\n\";\n        }\n        std::cout << \"\\n\\n\";\n\n        return 0;\n    }\n *\n * \\endcode\n *\n */\n#ifndef CL_HPP_\n#define CL_HPP_\n\n/* Handle deprecated preprocessor definitions. In each case, we only check for\n * the old name if the new name is not defined, so that user code can define\n * both and hence work with either version of the bindings.\n */\n#if !defined(CL_HPP_USE_DX_INTEROP) && defined(USE_DX_INTEROP)\n# pragma message(\"cl2.hpp: USE_DX_INTEROP is deprecated. Define CL_HPP_USE_DX_INTEROP instead\")\n# define CL_HPP_USE_DX_INTEROP\n#endif\n#if !defined(CL_HPP_USE_CL_DEVICE_FISSION) && defined(USE_CL_DEVICE_FISSION)\n# pragma message(\"cl2.hpp: USE_CL_DEVICE_FISSION is deprecated. Define CL_HPP_USE_CL_DEVICE_FISSION instead\")\n# define CL_HPP_USE_CL_DEVICE_FISSION\n#endif\n#if !defined(CL_HPP_ENABLE_EXCEPTIONS) && defined(__CL_ENABLE_EXCEPTIONS)\n# pragma message(\"cl2.hpp: __CL_ENABLE_EXCEPTIONS is deprecated. Define CL_HPP_ENABLE_EXCEPTIONS instead\")\n# define CL_HPP_ENABLE_EXCEPTIONS\n#endif\n#if !defined(CL_HPP_NO_STD_VECTOR) && defined(__NO_STD_VECTOR)\n# pragma message(\"cl2.hpp: __NO_STD_VECTOR is deprecated. Define CL_HPP_NO_STD_VECTOR instead\")\n# define CL_HPP_NO_STD_VECTOR\n#endif\n#if !defined(CL_HPP_NO_STD_STRING) && defined(__NO_STD_STRING)\n# pragma message(\"cl2.hpp: __NO_STD_STRING is deprecated. Define CL_HPP_NO_STD_STRING instead\")\n# define CL_HPP_NO_STD_STRING\n#endif\n#if defined(VECTOR_CLASS)\n# pragma message(\"cl2.hpp: VECTOR_CLASS is deprecated. Alias cl::vector instead\")\n#endif\n#if defined(STRING_CLASS)\n# pragma message(\"cl2.hpp: STRING_CLASS is deprecated. Alias cl::string instead.\")\n#endif\n#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS) && defined(__CL_USER_OVERRIDE_ERROR_STRINGS)\n# pragma message(\"cl2.hpp: __CL_USER_OVERRIDE_ERROR_STRINGS is deprecated. Define CL_HPP_USER_OVERRIDE_ERROR_STRINGS instead\")\n# define CL_HPP_USER_OVERRIDE_ERROR_STRINGS\n#endif\n\n/* Warn about features that are no longer supported\n */\n#if defined(__USE_DEV_VECTOR)\n# pragma message(\"cl2.hpp: __USE_DEV_VECTOR is no longer supported. Expect compilation errors\")\n#endif\n#if defined(__USE_DEV_STRING)\n# pragma message(\"cl2.hpp: __USE_DEV_STRING is no longer supported. Expect compilation errors\")\n#endif\n\n/* Detect which version to target */\n#if !defined(CL_HPP_TARGET_OPENCL_VERSION)\n# pragma message(\"cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 200 (OpenCL 2.0)\")\n# define CL_HPP_TARGET_OPENCL_VERSION 200\n#endif\n#if CL_HPP_TARGET_OPENCL_VERSION != 100 && CL_HPP_TARGET_OPENCL_VERSION != 110 && CL_HPP_TARGET_OPENCL_VERSION != 120 && CL_HPP_TARGET_OPENCL_VERSION != 200\n# pragma message(\"cl2.hpp: CL_HPP_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 200\")\n# undef CL_HPP_TARGET_OPENCL_VERSION\n# define CL_HPP_TARGET_OPENCL_VERSION 200\n#endif\n\n#if !defined(CL_HPP_MINIMUM_OPENCL_VERSION)\n# define CL_HPP_MINIMUM_OPENCL_VERSION 200\n#endif\n#if CL_HPP_MINIMUM_OPENCL_VERSION != 100 && CL_HPP_MINIMUM_OPENCL_VERSION != 110 && CL_HPP_MINIMUM_OPENCL_VERSION != 120 && CL_HPP_MINIMUM_OPENCL_VERSION != 200\n# pragma message(\"cl2.hpp: CL_HPP_MINIMUM_OPENCL_VERSION is not a valid value (100, 110, 120 or 200). It will be set to 100\")\n# undef CL_HPP_MINIMUM_OPENCL_VERSION\n# define CL_HPP_MINIMUM_OPENCL_VERSION 100\n#endif\n#if CL_HPP_MINIMUM_OPENCL_VERSION > CL_HPP_TARGET_OPENCL_VERSION\n# error \"CL_HPP_MINIMUM_OPENCL_VERSION must not be greater than CL_HPP_TARGET_OPENCL_VERSION\"\n#endif\n\n#if CL_HPP_MINIMUM_OPENCL_VERSION <= 100 && !defined(CL_USE_DEPRECATED_OPENCL_1_0_APIS)\n# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n#endif\n#if CL_HPP_MINIMUM_OPENCL_VERSION <= 110 && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n#endif\n#if CL_HPP_MINIMUM_OPENCL_VERSION <= 120 && !defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)\n# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n#endif\n#if CL_HPP_MINIMUM_OPENCL_VERSION <= 200 && !defined(CL_USE_DEPRECATED_OPENCL_2_0_APIS)\n# define CL_USE_DEPRECATED_OPENCL_2_0_APIS\n#endif\n\n#ifdef _WIN32\n\n#include <malloc.h>\n\n#if defined(CL_HPP_USE_DX_INTEROP)\n#include <CL/cl_d3d10.h>\n#include <CL/cl_dx9_media_sharing.h>\n#endif\n#endif // _WIN32\n\n#if defined(_MSC_VER)\n#include <intrin.h>\n#endif // _MSC_VER\n\n // Check for a valid C++ version\n\n// Need to do both tests here because for some reason __cplusplus is not\n// updated in visual studio\n#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1700)\n#error Visual studio 2013 or another C++11-supporting compiler required\n#endif\n\n//\n#if defined(CL_HPP_USE_CL_DEVICE_FISSION) || defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)\n#include <CL/cl_ext.h>\n#endif\n\n#if defined(__APPLE__) || defined(__MACOSX)\n#include <OpenCL/opencl.h>\n#else\n#include <CL/opencl.h>\n#endif // !__APPLE__\n\n#if (__cplusplus >= 201103L)\n#define CL_HPP_NOEXCEPT_ noexcept\n#else\n#define CL_HPP_NOEXCEPT_\n#endif\n\n#if defined(_MSC_VER)\n# define CL_HPP_DEFINE_STATIC_MEMBER_ __declspec(selectany)\n#else\n# define CL_HPP_DEFINE_STATIC_MEMBER_ __attribute__((weak))\n#endif // !_MSC_VER\n\n// Define deprecated prefixes and suffixes to ensure compilation\n// in case they are not pre-defined\n#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)\n#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED\n#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)\n#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED)\n#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED\n#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)\n\n#if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)\n#define CL_EXT_PREFIX__VERSION_1_2_DEPRECATED\n#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)\n#if !defined(CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED)\n#define CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED\n#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)\n\n#if !defined(CL_CALLBACK)\n#define CL_CALLBACK\n#endif //CL_CALLBACK\n\n#include <utility>\n#include <limits>\n#include <iterator>\n#include <mutex>\n#include <cstring>\n#include <functional>\n\n\n// Define a size_type to represent a correctly resolved size_t\n#if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)\nnamespace cl {\n    using size_type = ::size_t;\n} // namespace cl\n#else // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)\nnamespace cl {\n    using size_type = size_t;\n} // namespace cl\n#endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)\n\n\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n#include <exception>\n#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)\n\n#if !defined(CL_HPP_NO_STD_VECTOR)\n#include <vector>\nnamespace cl {\n    template < class T, class Alloc = std::allocator<T> >\n    using vector = std::vector<T, Alloc>;\n} // namespace cl\n#endif // #if !defined(CL_HPP_NO_STD_VECTOR)\n\n#if !defined(CL_HPP_NO_STD_STRING)\n#include <string>\nnamespace cl {\n    using string = std::string;\n} // namespace cl\n#endif // #if !defined(CL_HPP_NO_STD_STRING)\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n#if !defined(CL_HPP_NO_STD_UNIQUE_PTR)\n#include <memory>\nnamespace cl {\n    // Replace unique_ptr and allocate_pointer for internal use\n    // to allow user to replace them\n    template<class T, class D>\n    using pointer = std::unique_ptr<T, D>;\n} // namespace cl\n#endif\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n#if !defined(CL_HPP_NO_STD_ARRAY)\n#include <array>\nnamespace cl {\n    template < class T, size_type N >\n    using array = std::array<T, N>;\n} // namespace cl\n#endif // #if !defined(CL_HPP_NO_STD_ARRAY)\n\n// Define size_type appropriately to allow backward-compatibility\n// use of the old size_t interface class\n#if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)\nnamespace cl {\n    namespace compatibility {\n        /*! \\brief class used to interface between C++ and\n        *  OpenCL C calls that require arrays of size_t values, whose\n        *  size is known statically.\n        */\n        template <int N>\n        class size_t\n        {\n        private:\n            size_type data_[N];\n\n        public:\n            //! \\brief Initialize size_t to all 0s\n            size_t()\n            {\n                for (int i = 0; i < N; ++i) {\n                    data_[i] = 0;\n                }\n            }\n\n            size_t(const array<size_type, N> &rhs)\n            {\n                for (int i = 0; i < N; ++i) {\n                    data_[i] = rhs[i];\n                }\n            }\n\n            size_type& operator[](int index)\n            {\n                return data_[index];\n            }\n\n            const size_type& operator[](int index) const\n            {\n                return data_[index];\n            }\n\n            //! \\brief Conversion operator to T*.\n            operator size_type* ()             { return data_; }\n\n            //! \\brief Conversion operator to const T*.\n            operator const size_type* () const { return data_; }\n\n            operator array<size_type, N>() const\n            {\n                array<size_type, N> ret;\n\n                for (int i = 0; i < N; ++i) {\n                    ret[i] = data_[i];\n                }\n                return ret;\n            }\n        };\n    } // namespace compatibility\n\n    template<int N>\n    using size_t = compatibility::size_t<N>;\n} // namespace cl\n#endif // #if defined(CL_HPP_ENABLE_SIZE_T_COMPATIBILITY)\n\n// Helper alias to avoid confusing the macros\nnamespace cl {\n    namespace detail {\n        using size_t_array = array<size_type, 3>;\n    } // namespace detail\n} // namespace cl\n\n\n/*! \\namespace cl\n *\n * \\brief The OpenCL C++ bindings are defined within this namespace.\n *\n */\nnamespace cl {\n    class Memory;\n\n#define CL_HPP_INIT_CL_EXT_FCN_PTR_(name) \\\n    if (!pfn_##name) {    \\\n    pfn_##name = (PFN_##name) \\\n    clGetExtensionFunctionAddress(#name); \\\n    if (!pfn_##name) {    \\\n    } \\\n    }\n\n#define CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, name) \\\n    if (!pfn_##name) {    \\\n    pfn_##name = (PFN_##name) \\\n    clGetExtensionFunctionAddressForPlatform(platform, #name); \\\n    if (!pfn_##name) {    \\\n    } \\\n    }\n\n    class Program;\n    class Device;\n    class Context;\n    class CommandQueue;\n    class DeviceCommandQueue;\n    class Memory;\n    class Buffer;\n    class Pipe;\n\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n    /*! \\brief Exception class\n     *\n     *  This may be thrown by API functions when CL_HPP_ENABLE_EXCEPTIONS is defined.\n     */\n    class Error : public std::exception\n    {\n    private:\n        cl_int err_;\n        const char * errStr_;\n    public:\n        /*! \\brief Create a new CL error exception for a given error code\n         *  and corresponding message.\n         *\n         *  \\param err error code value.\n         *\n         *  \\param errStr a descriptive string that must remain in scope until\n         *                handling of the exception has concluded.  If set, it\n         *                will be returned by what().\n         */\n        Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr)\n        {}\n\n        ~Error() throw() {}\n\n        /*! \\brief Get error string associated with exception\n         *\n         * \\return A memory pointer to the error message string.\n         */\n        virtual const char * what() const throw ()\n        {\n            if (errStr_ == NULL) {\n                return \"empty\";\n            }\n            else {\n                return errStr_;\n            }\n        }\n\n        /*! \\brief Get error code associated with exception\n         *\n         *  \\return The error code.\n         */\n        cl_int err(void) const { return err_; }\n    };\n#define CL_HPP_ERR_STR_(x) #x\n#else\n#define CL_HPP_ERR_STR_(x) NULL\n#endif // CL_HPP_ENABLE_EXCEPTIONS\n\n\nnamespace detail\n{\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\nstatic inline cl_int errHandler (\n    cl_int err,\n    const char * errStr = NULL)\n{\n    if (err != CL_SUCCESS) {\n        throw Error(err, errStr);\n    }\n    return err;\n}\n#else\nstatic inline cl_int errHandler (cl_int err, const char * errStr = NULL)\n{\n    (void) errStr; // suppress unused variable warning\n    return err;\n}\n#endif // CL_HPP_ENABLE_EXCEPTIONS\n}\n\n\n\n//! \\cond DOXYGEN_DETAIL\n#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS)\n#define __GET_DEVICE_INFO_ERR               CL_HPP_ERR_STR_(clGetDeviceInfo)\n#define __GET_PLATFORM_INFO_ERR             CL_HPP_ERR_STR_(clGetPlatformInfo)\n#define __GET_DEVICE_IDS_ERR                CL_HPP_ERR_STR_(clGetDeviceIDs)\n#define __GET_PLATFORM_IDS_ERR              CL_HPP_ERR_STR_(clGetPlatformIDs)\n#define __GET_CONTEXT_INFO_ERR              CL_HPP_ERR_STR_(clGetContextInfo)\n#define __GET_EVENT_INFO_ERR                CL_HPP_ERR_STR_(clGetEventInfo)\n#define __GET_EVENT_PROFILE_INFO_ERR        CL_HPP_ERR_STR_(clGetEventProfileInfo)\n#define __GET_MEM_OBJECT_INFO_ERR           CL_HPP_ERR_STR_(clGetMemObjectInfo)\n#define __GET_IMAGE_INFO_ERR                CL_HPP_ERR_STR_(clGetImageInfo)\n#define __GET_SAMPLER_INFO_ERR              CL_HPP_ERR_STR_(clGetSamplerInfo)\n#define __GET_KERNEL_INFO_ERR               CL_HPP_ERR_STR_(clGetKernelInfo)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __GET_KERNEL_ARG_INFO_ERR           CL_HPP_ERR_STR_(clGetKernelArgInfo)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __GET_KERNEL_WORK_GROUP_INFO_ERR    CL_HPP_ERR_STR_(clGetKernelWorkGroupInfo)\n#define __GET_PROGRAM_INFO_ERR              CL_HPP_ERR_STR_(clGetProgramInfo)\n#define __GET_PROGRAM_BUILD_INFO_ERR        CL_HPP_ERR_STR_(clGetProgramBuildInfo)\n#define __GET_COMMAND_QUEUE_INFO_ERR        CL_HPP_ERR_STR_(clGetCommandQueueInfo)\n\n#define __CREATE_CONTEXT_ERR                CL_HPP_ERR_STR_(clCreateContext)\n#define __CREATE_CONTEXT_FROM_TYPE_ERR      CL_HPP_ERR_STR_(clCreateContextFromType)\n#define __GET_SUPPORTED_IMAGE_FORMATS_ERR   CL_HPP_ERR_STR_(clGetSupportedImageFormats)\n\n#define __CREATE_BUFFER_ERR                 CL_HPP_ERR_STR_(clCreateBuffer)\n#define __COPY_ERR                          CL_HPP_ERR_STR_(cl::copy)\n#define __CREATE_SUBBUFFER_ERR              CL_HPP_ERR_STR_(clCreateSubBuffer)\n#define __CREATE_GL_BUFFER_ERR              CL_HPP_ERR_STR_(clCreateFromGLBuffer)\n#define __CREATE_GL_RENDER_BUFFER_ERR       CL_HPP_ERR_STR_(clCreateFromGLBuffer)\n#define __GET_GL_OBJECT_INFO_ERR            CL_HPP_ERR_STR_(clGetGLObjectInfo)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __CREATE_IMAGE_ERR                  CL_HPP_ERR_STR_(clCreateImage)\n#define __CREATE_GL_TEXTURE_ERR             CL_HPP_ERR_STR_(clCreateFromGLTexture)\n#define __IMAGE_DIMENSION_ERR               CL_HPP_ERR_STR_(Incorrect image dimensions)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR CL_HPP_ERR_STR_(clSetMemObjectDestructorCallback)\n\n#define __CREATE_USER_EVENT_ERR             CL_HPP_ERR_STR_(clCreateUserEvent)\n#define __SET_USER_EVENT_STATUS_ERR         CL_HPP_ERR_STR_(clSetUserEventStatus)\n#define __SET_EVENT_CALLBACK_ERR            CL_HPP_ERR_STR_(clSetEventCallback)\n#define __WAIT_FOR_EVENTS_ERR               CL_HPP_ERR_STR_(clWaitForEvents)\n\n#define __CREATE_KERNEL_ERR                 CL_HPP_ERR_STR_(clCreateKernel)\n#define __SET_KERNEL_ARGS_ERR               CL_HPP_ERR_STR_(clSetKernelArg)\n#define __CREATE_PROGRAM_WITH_SOURCE_ERR    CL_HPP_ERR_STR_(clCreateProgramWithSource)\n#define __CREATE_PROGRAM_WITH_BINARY_ERR    CL_HPP_ERR_STR_(clCreateProgramWithBinary)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR    CL_HPP_ERR_STR_(clCreateProgramWithBuiltInKernels)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __BUILD_PROGRAM_ERR                 CL_HPP_ERR_STR_(clBuildProgram)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __COMPILE_PROGRAM_ERR               CL_HPP_ERR_STR_(clCompileProgram)\n#define __LINK_PROGRAM_ERR                  CL_HPP_ERR_STR_(clLinkProgram)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __CREATE_KERNELS_IN_PROGRAM_ERR     CL_HPP_ERR_STR_(clCreateKernelsInProgram)\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n#define __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR          CL_HPP_ERR_STR_(clCreateCommandQueueWithProperties)\n#define __CREATE_SAMPLER_WITH_PROPERTIES_ERR                CL_HPP_ERR_STR_(clCreateSamplerWithProperties)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200\n#define __SET_COMMAND_QUEUE_PROPERTY_ERR    CL_HPP_ERR_STR_(clSetCommandQueueProperty)\n#define __ENQUEUE_READ_BUFFER_ERR           CL_HPP_ERR_STR_(clEnqueueReadBuffer)\n#define __ENQUEUE_READ_BUFFER_RECT_ERR      CL_HPP_ERR_STR_(clEnqueueReadBufferRect)\n#define __ENQUEUE_WRITE_BUFFER_ERR          CL_HPP_ERR_STR_(clEnqueueWriteBuffer)\n#define __ENQUEUE_WRITE_BUFFER_RECT_ERR     CL_HPP_ERR_STR_(clEnqueueWriteBufferRect)\n#define __ENQEUE_COPY_BUFFER_ERR            CL_HPP_ERR_STR_(clEnqueueCopyBuffer)\n#define __ENQEUE_COPY_BUFFER_RECT_ERR       CL_HPP_ERR_STR_(clEnqueueCopyBufferRect)\n#define __ENQUEUE_FILL_BUFFER_ERR           CL_HPP_ERR_STR_(clEnqueueFillBuffer)\n#define __ENQUEUE_READ_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueReadImage)\n#define __ENQUEUE_WRITE_IMAGE_ERR           CL_HPP_ERR_STR_(clEnqueueWriteImage)\n#define __ENQUEUE_COPY_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueCopyImage)\n#define __ENQUEUE_FILL_IMAGE_ERR            CL_HPP_ERR_STR_(clEnqueueFillImage)\n#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR  CL_HPP_ERR_STR_(clEnqueueCopyImageToBuffer)\n#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR  CL_HPP_ERR_STR_(clEnqueueCopyBufferToImage)\n#define __ENQUEUE_MAP_BUFFER_ERR            CL_HPP_ERR_STR_(clEnqueueMapBuffer)\n#define __ENQUEUE_MAP_IMAGE_ERR             CL_HPP_ERR_STR_(clEnqueueMapImage)\n#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR      CL_HPP_ERR_STR_(clEnqueueUnMapMemObject)\n#define __ENQUEUE_NDRANGE_KERNEL_ERR        CL_HPP_ERR_STR_(clEnqueueNDRangeKernel)\n#define __ENQUEUE_NATIVE_KERNEL             CL_HPP_ERR_STR_(clEnqueueNativeKernel)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR   CL_HPP_ERR_STR_(clEnqueueMigrateMemObjects)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n#define __ENQUEUE_ACQUIRE_GL_ERR            CL_HPP_ERR_STR_(clEnqueueAcquireGLObjects)\n#define __ENQUEUE_RELEASE_GL_ERR            CL_HPP_ERR_STR_(clEnqueueReleaseGLObjects)\n\n#define __CREATE_PIPE_ERR             CL_HPP_ERR_STR_(clCreatePipe)\n#define __GET_PIPE_INFO_ERR           CL_HPP_ERR_STR_(clGetPipeInfo)\n\n\n#define __RETAIN_ERR                        CL_HPP_ERR_STR_(Retain Object)\n#define __RELEASE_ERR                       CL_HPP_ERR_STR_(Release Object)\n#define __FLUSH_ERR                         CL_HPP_ERR_STR_(clFlush)\n#define __FINISH_ERR                        CL_HPP_ERR_STR_(clFinish)\n#define __VECTOR_CAPACITY_ERR               CL_HPP_ERR_STR_(Vector capacity error)\n\n/**\n * CL 1.2 version that uses device fission.\n */\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __CREATE_SUB_DEVICES_ERR            CL_HPP_ERR_STR_(clCreateSubDevices)\n#else\n#define __CREATE_SUB_DEVICES_ERR            CL_HPP_ERR_STR_(clCreateSubDevicesEXT)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n/**\n * Deprecated APIs for 1.2\n */\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n#define __ENQUEUE_MARKER_ERR                CL_HPP_ERR_STR_(clEnqueueMarker)\n#define __ENQUEUE_WAIT_FOR_EVENTS_ERR       CL_HPP_ERR_STR_(clEnqueueWaitForEvents)\n#define __ENQUEUE_BARRIER_ERR               CL_HPP_ERR_STR_(clEnqueueBarrier)\n#define __UNLOAD_COMPILER_ERR               CL_HPP_ERR_STR_(clUnloadCompiler)\n#define __CREATE_GL_TEXTURE_2D_ERR          CL_HPP_ERR_STR_(clCreateFromGLTexture2D)\n#define __CREATE_GL_TEXTURE_3D_ERR          CL_HPP_ERR_STR_(clCreateFromGLTexture3D)\n#define __CREATE_IMAGE2D_ERR                CL_HPP_ERR_STR_(clCreateImage2D)\n#define __CREATE_IMAGE3D_ERR                CL_HPP_ERR_STR_(clCreateImage3D)\n#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n\n/**\n * Deprecated APIs for 2.0\n */\n#if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)\n#define __CREATE_COMMAND_QUEUE_ERR          CL_HPP_ERR_STR_(clCreateCommandQueue)\n#define __ENQUEUE_TASK_ERR                  CL_HPP_ERR_STR_(clEnqueueTask)\n#define __CREATE_SAMPLER_ERR                CL_HPP_ERR_STR_(clCreateSampler)\n#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n\n/**\n * CL 1.2 marker and barrier commands\n */\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#define __ENQUEUE_MARKER_WAIT_LIST_ERR                CL_HPP_ERR_STR_(clEnqueueMarkerWithWaitList)\n#define __ENQUEUE_BARRIER_WAIT_LIST_ERR               CL_HPP_ERR_STR_(clEnqueueBarrierWithWaitList)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n#endif // CL_HPP_USER_OVERRIDE_ERROR_STRINGS\n//! \\endcond\n\n\nnamespace detail {\n\n// Generic getInfoHelper. The final parameter is used to guide overload\n// resolution: the actual parameter passed is an int, which makes this\n// a worse conversion sequence than a specialization that declares the\n// parameter as an int.\ntemplate<typename Functor, typename T>\ninline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long)\n{\n    return f(name, sizeof(T), param, NULL);\n}\n\n// Specialized for getInfo<CL_PROGRAM_BINARIES>\n// Assumes that the output vector was correctly resized on the way in\ntemplate <typename Func>\ninline cl_int getInfoHelper(Func f, cl_uint name, vector<vector<unsigned char>>* param, int)\n{\n    if (name != CL_PROGRAM_BINARIES) {\n        return CL_INVALID_VALUE;\n    }\n    if (param) {\n        // Create array of pointers, calculate total size and pass pointer array in\n        size_type numBinaries = param->size();\n        vector<unsigned char*> binariesPointers(numBinaries);\n\n        for (size_type i = 0; i < numBinaries; ++i)\n        {\n            binariesPointers[i] = (*param)[i].data();\n        }\n\n        cl_int err = f(name, numBinaries * sizeof(unsigned char*), binariesPointers.data(), NULL);\n\n        if (err != CL_SUCCESS) {\n            return err;\n        }\n    }\n\n\n    return CL_SUCCESS;\n}\n\n// Specialized getInfoHelper for vector params\ntemplate <typename Func, typename T>\ninline cl_int getInfoHelper(Func f, cl_uint name, vector<T>* param, long)\n{\n    size_type required;\n    cl_int err = f(name, 0, NULL, &required);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n    const size_type elements = required / sizeof(T);\n\n    // Temporary to avoid changing param on an error\n    vector<T> localData(elements);\n    err = f(name, required, localData.data(), NULL);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n    if (param) {\n        *param = std::move(localData);\n    }\n\n    return CL_SUCCESS;\n}\n\n/* Specialization for reference-counted types. This depends on the\n * existence of Wrapper<T>::cl_type, and none of the other types having the\n * cl_type member. Note that simplify specifying the parameter as Wrapper<T>\n * does not work, because when using a derived type (e.g. Context) the generic\n * template will provide a better match.\n */\ntemplate <typename Func, typename T>\ninline cl_int getInfoHelper(\n    Func f, cl_uint name, vector<T>* param, int, typename T::cl_type = 0)\n{\n    size_type required;\n    cl_int err = f(name, 0, NULL, &required);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n\n    const size_type elements = required / sizeof(typename T::cl_type);\n\n    vector<typename T::cl_type> value(elements);\n    err = f(name, required, value.data(), NULL);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n\n    if (param) {\n        // Assign to convert CL type to T for each element\n        param->resize(elements);\n\n        // Assign to param, constructing with retain behaviour\n        // to correctly capture each underlying CL object\n        for (size_type i = 0; i < elements; i++) {\n            (*param)[i] = T(value[i], true);\n        }\n    }\n    return CL_SUCCESS;\n}\n\n// Specialized GetInfoHelper for string params\ntemplate <typename Func>\ninline cl_int getInfoHelper(Func f, cl_uint name, string* param, long)\n{\n    size_type required;\n    cl_int err = f(name, 0, NULL, &required);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n\n    // std::string has a constant data member\n    // a char vector does not\n    if (required > 0) {\n        vector<char> value(required);\n        err = f(name, required, value.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return err;\n        }\n        if (param) {\n            param->assign(begin(value), prev(end(value)));\n        }\n    }\n    else if (param) {\n        param->assign(\"\");\n    }\n    return CL_SUCCESS;\n}\n\n// Specialized GetInfoHelper for clsize_t params\ntemplate <typename Func, size_type N>\ninline cl_int getInfoHelper(Func f, cl_uint name, array<size_type, N>* param, long)\n{\n    size_type required;\n    cl_int err = f(name, 0, NULL, &required);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n\n    size_type elements = required / sizeof(size_type);\n    vector<size_type> value(elements, 0);\n\n    err = f(name, required, value.data(), NULL);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n\n    // Bound the copy with N to prevent overruns\n    // if passed N > than the amount copied\n    if (elements > N) {\n        elements = N;\n    }\n    for (size_type i = 0; i < elements; ++i) {\n        (*param)[i] = value[i];\n    }\n\n    return CL_SUCCESS;\n}\n\ntemplate<typename T> struct ReferenceHandler;\n\n/* Specialization for reference-counted types. This depends on the\n * existence of Wrapper<T>::cl_type, and none of the other types having the\n * cl_type member. Note that simplify specifying the parameter as Wrapper<T>\n * does not work, because when using a derived type (e.g. Context) the generic\n * template will provide a better match.\n */\ntemplate<typename Func, typename T>\ninline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0)\n{\n    typename T::cl_type value;\n    cl_int err = f(name, sizeof(value), &value, NULL);\n    if (err != CL_SUCCESS) {\n        return err;\n    }\n    *param = value;\n    if (value != NULL)\n    {\n        err = param->retain();\n        if (err != CL_SUCCESS) {\n            return err;\n        }\n    }\n    return CL_SUCCESS;\n}\n\n#define CL_HPP_PARAM_NAME_INFO_1_0_(F) \\\n    F(cl_platform_info, CL_PLATFORM_PROFILE, string) \\\n    F(cl_platform_info, CL_PLATFORM_VERSION, string) \\\n    F(cl_platform_info, CL_PLATFORM_NAME, string) \\\n    F(cl_platform_info, CL_PLATFORM_VENDOR, string) \\\n    F(cl_platform_info, CL_PLATFORM_EXTENSIONS, string) \\\n    \\\n    F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \\\n    F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, size_type) \\\n    F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, cl::vector<size_type>) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \\\n    F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, size_type) \\\n    F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, size_type) \\\n    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, size_type) \\\n    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, size_type) \\\n    F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, size_type) \\\n    F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \\\n    F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, size_type) \\\n    F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \\\n    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \\\n    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\\\n    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \\\n    F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \\\n    F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \\\n    F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \\\n    F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \\\n    F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \\\n    F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, size_type) \\\n    F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \\\n    F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \\\n    F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \\\n    F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \\\n    F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \\\n    F(cl_device_info, CL_DEVICE_NAME, string) \\\n    F(cl_device_info, CL_DEVICE_VENDOR, string) \\\n    F(cl_device_info, CL_DRIVER_VERSION, string) \\\n    F(cl_device_info, CL_DEVICE_PROFILE, string) \\\n    F(cl_device_info, CL_DEVICE_VERSION, string) \\\n    F(cl_device_info, CL_DEVICE_EXTENSIONS, string) \\\n    \\\n    F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \\\n    F(cl_context_info, CL_CONTEXT_DEVICES, cl::vector<Device>) \\\n    F(cl_context_info, CL_CONTEXT_PROPERTIES, cl::vector<cl_context_properties>) \\\n    \\\n    F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \\\n    F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \\\n    F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \\\n    F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \\\n    \\\n    F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \\\n    F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \\\n    F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \\\n    F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \\\n    \\\n    F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \\\n    F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \\\n    F(cl_mem_info, CL_MEM_SIZE, size_type) \\\n    F(cl_mem_info, CL_MEM_HOST_PTR, void*) \\\n    F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \\\n    F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \\\n    F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \\\n    \\\n    F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \\\n    F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, size_type) \\\n    F(cl_image_info, CL_IMAGE_ROW_PITCH, size_type) \\\n    F(cl_image_info, CL_IMAGE_SLICE_PITCH, size_type) \\\n    F(cl_image_info, CL_IMAGE_WIDTH, size_type) \\\n    F(cl_image_info, CL_IMAGE_HEIGHT, size_type) \\\n    F(cl_image_info, CL_IMAGE_DEPTH, size_type) \\\n    \\\n    F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \\\n    F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \\\n    F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \\\n    F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \\\n    F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \\\n    \\\n    F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \\\n    F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \\\n    F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \\\n    F(cl_program_info, CL_PROGRAM_DEVICES, cl::vector<Device>) \\\n    F(cl_program_info, CL_PROGRAM_SOURCE, string) \\\n    F(cl_program_info, CL_PROGRAM_BINARY_SIZES, cl::vector<size_type>) \\\n    F(cl_program_info, CL_PROGRAM_BINARIES, cl::vector<cl::vector<unsigned char>>) \\\n    \\\n    F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \\\n    F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, string) \\\n    F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, string) \\\n    \\\n    F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, string) \\\n    F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \\\n    F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \\\n    F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \\\n    F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \\\n    \\\n    F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, size_type) \\\n    F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::detail::size_t_array) \\\n    F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \\\n    \\\n    F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \\\n    F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \\\n    F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \\\n    F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties)\n\n\n#define CL_HPP_PARAM_NAME_INFO_1_1_(F) \\\n    F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\\\n    F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \\\n    F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \\\n    F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, string) \\\n    \\\n    F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \\\n    F(cl_mem_info, CL_MEM_OFFSET, size_type) \\\n    \\\n    F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, size_type) \\\n    F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \\\n    \\\n    F(cl_event_info, CL_EVENT_CONTEXT, cl::Context)\n\n#define CL_HPP_PARAM_NAME_INFO_1_2_(F) \\\n    F(cl_program_info, CL_PROGRAM_NUM_KERNELS, size_type) \\\n    F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, string) \\\n    \\\n    F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \\\n    \\\n    F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, string) \\\n    \\\n    F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \\\n    F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \\\n    F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, string) \\\n    F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, string) \\\n    F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \\\n    \\\n    F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl::Device) \\\n    F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, cl::vector<cl_device_partition_property>) \\\n    F(cl_device_info, CL_DEVICE_PARTITION_TYPE, cl::vector<cl_device_partition_property>)  \\\n    F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, size_type) \\\n    F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \\\n    F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, string) \\\n    \\\n    F(cl_image_info, CL_IMAGE_ARRAY_SIZE, size_type) \\\n    F(cl_image_info, CL_IMAGE_NUM_MIP_LEVELS, cl_uint) \\\n    F(cl_image_info, CL_IMAGE_NUM_SAMPLES, cl_uint)\n\n#define CL_HPP_PARAM_NAME_INFO_2_0_(F) \\\n    F(cl_device_info, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES, cl_command_queue_properties) \\\n    F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, cl_command_queue_properties) \\\n    F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_QUEUES, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_ON_DEVICE_EVENTS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_MAX_PIPE_ARGS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PIPE_MAX_PACKET_SIZE, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_SVM_CAPABILITIES, cl_device_svm_capabilities) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT, cl_uint) \\\n    F(cl_command_queue_info, CL_QUEUE_SIZE, cl_uint) \\\n    F(cl_mem_info, CL_MEM_USES_SVM_POINTER, cl_bool) \\\n    F(cl_program_build_info, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, size_type) \\\n    F(cl_pipe_info, CL_PIPE_PACKET_SIZE, cl_uint) \\\n    F(cl_pipe_info, CL_PIPE_MAX_PACKETS, cl_uint)\n\n#define CL_HPP_PARAM_NAME_DEVICE_FISSION_(F) \\\n    F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \\\n    F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, cl::vector<cl_device_partition_property_ext>) \\\n    F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, cl::vector<cl_device_partition_property_ext>) \\\n    F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \\\n    F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, cl::vector<cl_device_partition_property_ext>)\n\ntemplate <typename enum_type, cl_int Name>\nstruct param_traits {};\n\n#define CL_HPP_DECLARE_PARAM_TRAITS_(token, param_name, T) \\\nstruct token;                                        \\\ntemplate<>                                           \\\nstruct param_traits<detail:: token,param_name>       \\\n{                                                    \\\n    enum { value = param_name };                     \\\n    typedef T param_type;                            \\\n};\n\nCL_HPP_PARAM_NAME_INFO_1_0_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\nCL_HPP_PARAM_NAME_INFO_1_1_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\nCL_HPP_PARAM_NAME_INFO_1_2_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\nCL_HPP_PARAM_NAME_INFO_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\n\n// Flags deprecated in OpenCL 2.0\n#define CL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(F) \\\n    F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties)\n\n#define CL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(F) \\\n    F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool)\n\n#define CL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(F) \\\n    F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer)\n\n// Include deprecated query flags based on versions\n// Only include deprecated 1.0 flags if 2.0 not active as there is an enum clash\n#if CL_HPP_TARGET_OPENCL_VERSION > 100 && CL_HPP_MINIMUM_OPENCL_VERSION < 200 && CL_HPP_TARGET_OPENCL_VERSION < 200\nCL_HPP_PARAM_NAME_INFO_1_0_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 110\n#if CL_HPP_TARGET_OPENCL_VERSION > 110 && CL_HPP_MINIMUM_OPENCL_VERSION < 200\nCL_HPP_PARAM_NAME_INFO_1_1_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120\n#if CL_HPP_TARGET_OPENCL_VERSION > 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 200\nCL_HPP_PARAM_NAME_INFO_1_2_DEPRECATED_IN_2_0_(CL_HPP_DECLARE_PARAM_TRAITS_)\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 200\n\n#if defined(CL_HPP_USE_CL_DEVICE_FISSION)\nCL_HPP_PARAM_NAME_DEVICE_FISSION_(CL_HPP_DECLARE_PARAM_TRAITS_);\n#endif // CL_HPP_USE_CL_DEVICE_FISSION\n\n#ifdef CL_PLATFORM_ICD_SUFFIX_KHR\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, string)\n#endif\n\n#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong)\n#endif\n\n#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, vector<size_type>)\n#endif\n#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_SIMD_WIDTH_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint)\n#endif\n#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint)\n#endif\n\n#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint)\n#endif\n#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint)\n#endif\n#ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint)\n#endif\n#ifdef CL_DEVICE_WARP_SIZE_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint)\n#endif\n#ifdef CL_DEVICE_GPU_OVERLAP_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool)\n#endif\n#ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool)\n#endif\n#ifdef CL_DEVICE_INTEGRATED_MEMORY_NV\nCL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool)\n#endif\n\n// Convenience functions\n\ntemplate <typename Func, typename T>\ninline cl_int\ngetInfo(Func f, cl_uint name, T* param)\n{\n    return getInfoHelper(f, name, param, 0);\n}\n\ntemplate <typename Func, typename Arg0>\nstruct GetInfoFunctor0\n{\n    Func f_; const Arg0& arg0_;\n    cl_int operator ()(\n        cl_uint param, size_type size, void* value, size_type* size_ret)\n    { return f_(arg0_, param, size, value, size_ret); }\n};\n\ntemplate <typename Func, typename Arg0, typename Arg1>\nstruct GetInfoFunctor1\n{\n    Func f_; const Arg0& arg0_; const Arg1& arg1_;\n    cl_int operator ()(\n        cl_uint param, size_type size, void* value, size_type* size_ret)\n    { return f_(arg0_, arg1_, param, size, value, size_ret); }\n};\n\ntemplate <typename Func, typename Arg0, typename T>\ninline cl_int\ngetInfo(Func f, const Arg0& arg0, cl_uint name, T* param)\n{\n    GetInfoFunctor0<Func, Arg0> f0 = { f, arg0 };\n    return getInfoHelper(f0, name, param, 0);\n}\n\ntemplate <typename Func, typename Arg0, typename Arg1, typename T>\ninline cl_int\ngetInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param)\n{\n    GetInfoFunctor1<Func, Arg0, Arg1> f0 = { f, arg0, arg1 };\n    return getInfoHelper(f0, name, param, 0);\n}\n\n\ntemplate<typename T>\nstruct ReferenceHandler\n{ };\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n/**\n * OpenCL 1.2 devices do have retain/release.\n */\ntemplate <>\nstruct ReferenceHandler<cl_device_id>\n{\n    /**\n     * Retain the device.\n     * \\param device A valid device created using createSubDevices\n     * \\return\n     *   CL_SUCCESS if the function executed successfully.\n     *   CL_INVALID_DEVICE if device was not a valid subdevice\n     *   CL_OUT_OF_RESOURCES\n     *   CL_OUT_OF_HOST_MEMORY\n     */\n    static cl_int retain(cl_device_id device)\n    { return ::clRetainDevice(device); }\n    /**\n     * Retain the device.\n     * \\param device A valid device created using createSubDevices\n     * \\return\n     *   CL_SUCCESS if the function executed successfully.\n     *   CL_INVALID_DEVICE if device was not a valid subdevice\n     *   CL_OUT_OF_RESOURCES\n     *   CL_OUT_OF_HOST_MEMORY\n     */\n    static cl_int release(cl_device_id device)\n    { return ::clReleaseDevice(device); }\n};\n#else // CL_HPP_TARGET_OPENCL_VERSION >= 120\n/**\n * OpenCL 1.1 devices do not have retain/release.\n */\ntemplate <>\nstruct ReferenceHandler<cl_device_id>\n{\n    // cl_device_id does not have retain().\n    static cl_int retain(cl_device_id)\n    { return CL_SUCCESS; }\n    // cl_device_id does not have release().\n    static cl_int release(cl_device_id)\n    { return CL_SUCCESS; }\n};\n#endif // ! (CL_HPP_TARGET_OPENCL_VERSION >= 120)\n\ntemplate <>\nstruct ReferenceHandler<cl_platform_id>\n{\n    // cl_platform_id does not have retain().\n    static cl_int retain(cl_platform_id)\n    { return CL_SUCCESS; }\n    // cl_platform_id does not have release().\n    static cl_int release(cl_platform_id)\n    { return CL_SUCCESS; }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_context>\n{\n    static cl_int retain(cl_context context)\n    { return ::clRetainContext(context); }\n    static cl_int release(cl_context context)\n    { return ::clReleaseContext(context); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_command_queue>\n{\n    static cl_int retain(cl_command_queue queue)\n    { return ::clRetainCommandQueue(queue); }\n    static cl_int release(cl_command_queue queue)\n    { return ::clReleaseCommandQueue(queue); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_mem>\n{\n    static cl_int retain(cl_mem memory)\n    { return ::clRetainMemObject(memory); }\n    static cl_int release(cl_mem memory)\n    { return ::clReleaseMemObject(memory); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_sampler>\n{\n    static cl_int retain(cl_sampler sampler)\n    { return ::clRetainSampler(sampler); }\n    static cl_int release(cl_sampler sampler)\n    { return ::clReleaseSampler(sampler); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_program>\n{\n    static cl_int retain(cl_program program)\n    { return ::clRetainProgram(program); }\n    static cl_int release(cl_program program)\n    { return ::clReleaseProgram(program); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_kernel>\n{\n    static cl_int retain(cl_kernel kernel)\n    { return ::clRetainKernel(kernel); }\n    static cl_int release(cl_kernel kernel)\n    { return ::clReleaseKernel(kernel); }\n};\n\ntemplate <>\nstruct ReferenceHandler<cl_event>\n{\n    static cl_int retain(cl_event event)\n    { return ::clRetainEvent(event); }\n    static cl_int release(cl_event event)\n    { return ::clReleaseEvent(event); }\n};\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120\n// Extracts version number with major in the upper 16 bits, minor in the lower 16\nstatic cl_uint getVersion(const vector<char> &versionInfo)\n{\n    int highVersion = 0;\n    int lowVersion = 0;\n    int index = 7;\n    while(versionInfo[index] != '.' ) {\n        highVersion *= 10;\n        highVersion += versionInfo[index]-'0';\n        ++index;\n    }\n    ++index;\n    while(versionInfo[index] != ' ' &&  versionInfo[index] != '\\0') {\n        lowVersion *= 10;\n        lowVersion += versionInfo[index]-'0';\n        ++index;\n    }\n    return (highVersion << 16) | lowVersion;\n}\n\nstatic cl_uint getPlatformVersion(cl_platform_id platform)\n{\n    size_type size = 0;\n    clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size);\n\n    vector<char> versionInfo(size);\n    clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, versionInfo.data(), &size);\n    return getVersion(versionInfo);\n}\n\nstatic cl_uint getDevicePlatformVersion(cl_device_id device)\n{\n    cl_platform_id platform;\n    clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL);\n    return getPlatformVersion(platform);\n}\n\nstatic cl_uint getContextPlatformVersion(cl_context context)\n{\n    // The platform cannot be queried directly, so we first have to grab a\n    // device and obtain its context\n    size_type size = 0;\n    clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size);\n    if (size == 0)\n        return 0;\n    vector<cl_device_id> devices(size/sizeof(cl_device_id));\n    clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices.data(), NULL);\n    return getDevicePlatformVersion(devices[0]);\n}\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120\n\ntemplate <typename T>\nclass Wrapper\n{\npublic:\n    typedef T cl_type;\n\nprotected:\n    cl_type object_;\n\npublic:\n    Wrapper() : object_(NULL) { }\n\n    Wrapper(const cl_type &obj, bool retainObject) : object_(obj)\n    {\n        if (retainObject) {\n            detail::errHandler(retain(), __RETAIN_ERR);\n        }\n    }\n\n    ~Wrapper()\n    {\n        if (object_ != NULL) { release(); }\n    }\n\n    Wrapper(const Wrapper<cl_type>& rhs)\n    {\n        object_ = rhs.object_;\n        detail::errHandler(retain(), __RETAIN_ERR);\n    }\n\n    Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT_\n    {\n        object_ = rhs.object_;\n        rhs.object_ = NULL;\n    }\n\n    Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)\n    {\n        if (this != &rhs) {\n            detail::errHandler(release(), __RELEASE_ERR);\n            object_ = rhs.object_;\n            detail::errHandler(retain(), __RETAIN_ERR);\n        }\n        return *this;\n    }\n\n    Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)\n    {\n        if (this != &rhs) {\n            detail::errHandler(release(), __RELEASE_ERR);\n            object_ = rhs.object_;\n            rhs.object_ = NULL;\n        }\n        return *this;\n    }\n\n    Wrapper<cl_type>& operator = (const cl_type &rhs)\n    {\n        detail::errHandler(release(), __RELEASE_ERR);\n        object_ = rhs;\n        return *this;\n    }\n\n    const cl_type& operator ()() const { return object_; }\n\n    cl_type& operator ()() { return object_; }\n\n    const cl_type get() const { return object_; }\n\n    cl_type get() { return object_; }\n\n\nprotected:\n    template<typename Func, typename U>\n    friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);\n\n    cl_int retain() const\n    {\n        if (object_ != nullptr) {\n            return ReferenceHandler<cl_type>::retain(object_);\n        }\n        else {\n            return CL_SUCCESS;\n        }\n    }\n\n    cl_int release() const\n    {\n        if (object_ != nullptr) {\n            return ReferenceHandler<cl_type>::release(object_);\n        }\n        else {\n            return CL_SUCCESS;\n        }\n    }\n};\n\ntemplate <>\nclass Wrapper<cl_device_id>\n{\npublic:\n    typedef cl_device_id cl_type;\n\nprotected:\n    cl_type object_;\n    bool referenceCountable_;\n\n    static bool isReferenceCountable(cl_device_id device)\n    {\n        bool retVal = false;\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n#if CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        if (device != NULL) {\n            int version = getDevicePlatformVersion(device);\n            if(version > ((1 << 16) + 1)) {\n                retVal = true;\n            }\n        }\n#else // CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        retVal = true;\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n        return retVal;\n    }\n\npublic:\n    Wrapper() : object_(NULL), referenceCountable_(false)\n    {\n    }\n\n    Wrapper(const cl_type &obj, bool retainObject) :\n        object_(obj),\n        referenceCountable_(false)\n    {\n        referenceCountable_ = isReferenceCountable(obj);\n\n        if (retainObject) {\n            detail::errHandler(retain(), __RETAIN_ERR);\n        }\n    }\n\n    ~Wrapper()\n    {\n        release();\n    }\n\n    Wrapper(const Wrapper<cl_type>& rhs)\n    {\n        object_ = rhs.object_;\n        referenceCountable_ = isReferenceCountable(object_);\n        detail::errHandler(retain(), __RETAIN_ERR);\n    }\n\n    Wrapper(Wrapper<cl_type>&& rhs) CL_HPP_NOEXCEPT_\n    {\n        object_ = rhs.object_;\n        referenceCountable_ = rhs.referenceCountable_;\n        rhs.object_ = NULL;\n        rhs.referenceCountable_ = false;\n    }\n\n    Wrapper<cl_type>& operator = (const Wrapper<cl_type>& rhs)\n    {\n        if (this != &rhs) {\n            detail::errHandler(release(), __RELEASE_ERR);\n            object_ = rhs.object_;\n            referenceCountable_ = rhs.referenceCountable_;\n            detail::errHandler(retain(), __RETAIN_ERR);\n        }\n        return *this;\n    }\n\n    Wrapper<cl_type>& operator = (Wrapper<cl_type>&& rhs)\n    {\n        if (this != &rhs) {\n            detail::errHandler(release(), __RELEASE_ERR);\n            object_ = rhs.object_;\n            referenceCountable_ = rhs.referenceCountable_;\n            rhs.object_ = NULL;\n            rhs.referenceCountable_ = false;\n        }\n        return *this;\n    }\n\n    Wrapper<cl_type>& operator = (const cl_type &rhs)\n    {\n        detail::errHandler(release(), __RELEASE_ERR);\n        object_ = rhs;\n        referenceCountable_ = isReferenceCountable(object_);\n        return *this;\n    }\n\n    const cl_type& operator ()() const { return object_; }\n\n    cl_type& operator ()() { return object_; }\n\n    const cl_type get() const { return object_; }\n\n    cl_type get() { return object_; }\n\nprotected:\n    template<typename Func, typename U>\n    friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type);\n\n    template<typename Func, typename U>\n    friend inline cl_int getInfoHelper(Func, cl_uint, vector<U>*, int, typename U::cl_type);\n\n    cl_int retain() const\n    {\n        if( object_ != nullptr && referenceCountable_ ) {\n            return ReferenceHandler<cl_type>::retain(object_);\n        }\n        else {\n            return CL_SUCCESS;\n        }\n    }\n\n    cl_int release() const\n    {\n        if (object_ != nullptr && referenceCountable_) {\n            return ReferenceHandler<cl_type>::release(object_);\n        }\n        else {\n            return CL_SUCCESS;\n        }\n    }\n};\n\ntemplate <typename T>\ninline bool operator==(const Wrapper<T> &lhs, const Wrapper<T> &rhs)\n{\n    return lhs() == rhs();\n}\n\ntemplate <typename T>\ninline bool operator!=(const Wrapper<T> &lhs, const Wrapper<T> &rhs)\n{\n    return !operator==(lhs, rhs);\n}\n\n} // namespace detail\n//! \\endcond\n\n\nusing BuildLogType = vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, CL_PROGRAM_BUILD_LOG>::param_type>>;\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n/**\n* Exception class for build errors to carry build info\n*/\nclass BuildError : public Error\n{\nprivate:\n    BuildLogType buildLogs;\npublic:\n    BuildError(cl_int err, const char * errStr, const BuildLogType &vec) : Error(err, errStr), buildLogs(vec)\n    {\n    }\n\n    BuildLogType getBuildLog() const\n    {\n        return buildLogs;\n    }\n};\nnamespace detail {\n    static inline cl_int buildErrHandler(\n        cl_int err,\n        const char * errStr,\n        const BuildLogType &buildLogs)\n    {\n        if (err != CL_SUCCESS) {\n            throw BuildError(err, errStr, buildLogs);\n        }\n        return err;\n    }\n} // namespace detail\n\n#else\nnamespace detail {\n    static inline cl_int buildErrHandler(\n        cl_int err,\n        const char * errStr,\n        const BuildLogType &buildLogs)\n    {\n        (void)buildLogs; // suppress unused variable warning\n        (void)errStr;\n        return err;\n    }\n} // namespace detail\n#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)\n\n\n/*! \\struct ImageFormat\n *  \\brief Adds constructors and member functions for cl_image_format.\n *\n *  \\see cl_image_format\n */\nstruct ImageFormat : public cl_image_format\n{\n    //! \\brief Default constructor - performs no initialization.\n    ImageFormat(){}\n\n    //! \\brief Initializing constructor.\n    ImageFormat(cl_channel_order order, cl_channel_type type)\n    {\n        image_channel_order = order;\n        image_channel_data_type = type;\n    }\n\n    //! \\brief Assignment operator.\n    ImageFormat& operator = (const ImageFormat& rhs)\n    {\n        if (this != &rhs) {\n            this->image_channel_data_type = rhs.image_channel_data_type;\n            this->image_channel_order     = rhs.image_channel_order;\n        }\n        return *this;\n    }\n};\n\n/*! \\brief Class interface for cl_device_id.\n *\n *  \\note Copies of these objects are inexpensive, since they don't 'own'\n *        any underlying resources or data structures.\n *\n *  \\see cl_device_id\n */\nclass Device : public detail::Wrapper<cl_device_id>\n{\nprivate:\n    static std::once_flag default_initialized_;\n    static Device default_;\n    static cl_int default_error_;\n\n    /*! \\brief Create the default context.\n    *\n    * This sets @c default_ and @c default_error_. It does not throw\n    * @c cl::Error.\n    */\n    static void makeDefault();\n\n    /*! \\brief Create the default platform from a provided platform.\n    *\n    * This sets @c default_. It does not throw\n    * @c cl::Error.\n    */\n    static void makeDefaultProvided(const Device &p) {\n        default_ = p;\n    }\n\npublic:\n#ifdef CL_HPP_UNIT_TEST_ENABLE\n    /*! \\brief Reset the default.\n    *\n    * This sets @c default_ to an empty value to support cleanup in\n    * the unit test framework.\n    * This function is not thread safe.\n    */\n    static void unitTestClearDefault() {\n        default_ = Device();\n    }\n#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE\n\n    //! \\brief Default constructor - initializes to NULL.\n    Device() : detail::Wrapper<cl_type>() { }\n\n    /*! \\brief Constructor from cl_device_id.\n     *\n     *  This simply copies the device ID value, which is an inexpensive operation.\n     */\n    explicit Device(const cl_device_id &device, bool retainObject = false) :\n        detail::Wrapper<cl_type>(device, retainObject) { }\n\n    /*! \\brief Returns the first device on the default context.\n     *\n     *  \\see Context::getDefault()\n     */\n    static Device getDefault(\n        cl_int *errResult = NULL)\n    {\n        std::call_once(default_initialized_, makeDefault);\n        detail::errHandler(default_error_);\n        if (errResult != NULL) {\n            *errResult = default_error_;\n        }\n        return default_;\n    }\n\n    /**\n    * Modify the default device to be used by\n    * subsequent operations.\n    * Will only set the default if no default was previously created.\n    * @return updated default device.\n    *         Should be compared to the passed value to ensure that it was updated.\n    */\n    static Device setDefault(const Device &default_device)\n    {\n        std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_device));\n        detail::errHandler(default_error_);\n        return default_;\n    }\n\n    /*! \\brief Assignment operator from cl_device_id.\n     *\n     *  This simply copies the device ID value, which is an inexpensive operation.\n     */\n    Device& operator = (const cl_device_id& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n    * Required for MSVC.\n    */\n    Device(const Device& dev) : detail::Wrapper<cl_type>(dev) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n    * Required for MSVC.\n    */\n    Device& operator = (const Device &dev)\n    {\n        detail::Wrapper<cl_type>::operator=(dev);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n    * Required for MSVC.\n    */\n    Device(Device&& dev) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(dev)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n    * Required for MSVC.\n    */\n    Device& operator = (Device &&dev)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(dev));\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetDeviceInfo().\n    template <typename T>\n    cl_int getInfo(cl_device_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetDeviceInfo, object_, name, param),\n            __GET_DEVICE_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetDeviceInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_device_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_device_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /**\n     * CL 1.2 version\n     */\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    //! \\brief Wrapper for clCreateSubDevices().\n    cl_int createSubDevices(\n        const cl_device_partition_property * properties,\n        vector<Device>* devices)\n    {\n        cl_uint n = 0;\n        cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);\n        }\n\n        vector<cl_device_id> ids(n);\n        err = clCreateSubDevices(object_, properties, n, ids.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);\n        }\n\n        // Cannot trivially assign because we need to capture intermediates\n        // with safe construction\n        if (devices) {\n            devices->resize(ids.size());\n\n            // Assign to param, constructing with retain behaviour\n            // to correctly capture each underlying CL object\n            for (size_type i = 0; i < ids.size(); i++) {\n                // We do not need to retain because this device is being created\n                // by the runtime\n                (*devices)[i] = Device(ids[i], false);\n            }\n        }\n\n        return CL_SUCCESS;\n    }\n#elif defined(CL_HPP_USE_CL_DEVICE_FISSION)\n\n/**\n * CL 1.1 version that uses device fission extension.\n */\n    cl_int createSubDevices(\n        const cl_device_partition_property_ext * properties,\n        vector<Device>* devices)\n    {\n        typedef CL_API_ENTRY cl_int\n            ( CL_API_CALL * PFN_clCreateSubDevicesEXT)(\n                cl_device_id /*in_device*/,\n                const cl_device_partition_property_ext * /* properties */,\n                cl_uint /*num_entries*/,\n                cl_device_id * /*out_devices*/,\n                cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;\n\n        static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL;\n        CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateSubDevicesEXT);\n\n        cl_uint n = 0;\n        cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);\n        }\n\n        vector<cl_device_id> ids(n);\n        err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_SUB_DEVICES_ERR);\n        }\n        // Cannot trivially assign because we need to capture intermediates\n        // with safe construction\n        if (devices) {\n            devices->resize(ids.size());\n\n            // Assign to param, constructing with retain behaviour\n            // to correctly capture each underlying CL object\n            for (size_type i = 0; i < ids.size(); i++) {\n                // We do not need to retain because this device is being created\n                // by the runtime\n                (*devices)[i] = Device(ids[i], false);\n            }\n        }\n        return CL_SUCCESS;\n    }\n#endif // defined(CL_HPP_USE_CL_DEVICE_FISSION)\n};\n\nCL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Device::default_initialized_;\nCL_HPP_DEFINE_STATIC_MEMBER_ Device Device::default_;\nCL_HPP_DEFINE_STATIC_MEMBER_ cl_int Device::default_error_ = CL_SUCCESS;\n\n/*! \\brief Class interface for cl_platform_id.\n *\n *  \\note Copies of these objects are inexpensive, since they don't 'own'\n *        any underlying resources or data structures.\n *\n *  \\see cl_platform_id\n */\nclass Platform : public detail::Wrapper<cl_platform_id>\n{\nprivate:\n    static std::once_flag default_initialized_;\n    static Platform default_;\n    static cl_int default_error_;\n\n    /*! \\brief Create the default context.\n    *\n    * This sets @c default_ and @c default_error_. It does not throw\n    * @c cl::Error.\n    */\n    static void makeDefault() {\n        /* Throwing an exception from a call_once invocation does not do\n        * what we wish, so we catch it and save the error.\n        */\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        try\n#endif\n        {\n            // If default wasn't passed ,generate one\n            // Otherwise set it\n            cl_uint n = 0;\n\n            cl_int err = ::clGetPlatformIDs(0, NULL, &n);\n            if (err != CL_SUCCESS) {\n                default_error_ = err;\n                return;\n            }\n            if (n == 0) {\n                default_error_ = CL_INVALID_PLATFORM;\n                return;\n            }\n\n            vector<cl_platform_id> ids(n);\n            err = ::clGetPlatformIDs(n, ids.data(), NULL);\n            if (err != CL_SUCCESS) {\n                default_error_ = err;\n                return;\n            }\n\n            default_ = Platform(ids[0]);\n        }\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        catch (cl::Error &e) {\n            default_error_ = e.err();\n        }\n#endif\n    }\n\n    /*! \\brief Create the default platform from a provided platform.\n     *\n     * This sets @c default_. It does not throw\n     * @c cl::Error.\n     */\n    static void makeDefaultProvided(const Platform &p) {\n       default_ = p;\n    }\n\npublic:\n#ifdef CL_HPP_UNIT_TEST_ENABLE\n    /*! \\brief Reset the default.\n    *\n    * This sets @c default_ to an empty value to support cleanup in\n    * the unit test framework.\n    * This function is not thread safe.\n    */\n    static void unitTestClearDefault() {\n        default_ = Platform();\n    }\n#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE\n\n    //! \\brief Default constructor - initializes to NULL.\n    Platform() : detail::Wrapper<cl_type>()  { }\n\n    /*! \\brief Constructor from cl_platform_id.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  This simply copies the platform ID value, which is an inexpensive operation.\n     */\n    explicit Platform(const cl_platform_id &platform, bool retainObject = false) :\n        detail::Wrapper<cl_type>(platform, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_platform_id.\n     *\n     *  This simply copies the platform ID value, which is an inexpensive operation.\n     */\n    Platform& operator = (const cl_platform_id& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    static Platform getDefault(\n        cl_int *errResult = NULL)\n    {\n        std::call_once(default_initialized_, makeDefault);\n        detail::errHandler(default_error_);\n        if (errResult != NULL) {\n            *errResult = default_error_;\n        }\n        return default_;\n    }\n\n    /**\n     * Modify the default platform to be used by\n     * subsequent operations.\n     * Will only set the default if no default was previously created.\n     * @return updated default platform.\n     *         Should be compared to the passed value to ensure that it was updated.\n     */\n    static Platform setDefault(const Platform &default_platform)\n    {\n        std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_platform));\n        detail::errHandler(default_error_);\n        return default_;\n    }\n\n    //! \\brief Wrapper for clGetPlatformInfo().\n    cl_int getInfo(cl_platform_info name, string* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetPlatformInfo, object_, name, param),\n            __GET_PLATFORM_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetPlatformInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_platform_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_platform_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /*! \\brief Gets a list of devices for this platform.\n     *\n     *  Wraps clGetDeviceIDs().\n     */\n    cl_int getDevices(\n        cl_device_type type,\n        vector<Device>* devices) const\n    {\n        cl_uint n = 0;\n        if( devices == NULL ) {\n            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);\n        }\n        cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);\n        }\n\n        vector<cl_device_id> ids(n);\n        err = ::clGetDeviceIDs(object_, type, n, ids.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);\n        }\n\n        // Cannot trivially assign because we need to capture intermediates\n        // with safe construction\n        // We must retain things we obtain from the API to avoid releasing\n        // API-owned objects.\n        if (devices) {\n            devices->resize(ids.size());\n\n            // Assign to param, constructing with retain behaviour\n            // to correctly capture each underlying CL object\n            for (size_type i = 0; i < ids.size(); i++) {\n                (*devices)[i] = Device(ids[i], true);\n            }\n        }\n        return CL_SUCCESS;\n    }\n\n#if defined(CL_HPP_USE_DX_INTEROP)\n   /*! \\brief Get the list of available D3D10 devices.\n     *\n     *  \\param d3d_device_source.\n     *\n     *  \\param d3d_object.\n     *\n     *  \\param d3d_device_set.\n     *\n     *  \\param devices returns a vector of OpenCL D3D10 devices found. The cl::Device\n     *  values returned in devices can be used to identify a specific OpenCL\n     *  device. If \\a devices argument is NULL, this argument is ignored.\n     *\n     *  \\return One of the following values:\n     *    - CL_SUCCESS if the function is executed successfully.\n     *\n     *  The application can query specific capabilities of the OpenCL device(s)\n     *  returned by cl::getDevices. This can be used by the application to\n     *  determine which device(s) to use.\n     *\n     * \\note In the case that exceptions are enabled and a return value\n     * other than CL_SUCCESS is generated, then cl::Error exception is\n     * generated.\n     */\n    cl_int getDevices(\n        cl_d3d10_device_source_khr d3d_device_source,\n        void *                     d3d_object,\n        cl_d3d10_device_set_khr    d3d_device_set,\n        vector<Device>* devices) const\n    {\n        typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)(\n            cl_platform_id platform,\n            cl_d3d10_device_source_khr d3d_device_source,\n            void * d3d_object,\n            cl_d3d10_device_set_khr d3d_device_set,\n            cl_uint num_entries,\n            cl_device_id * devices,\n            cl_uint* num_devices);\n\n        if( devices == NULL ) {\n            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR);\n        }\n\n        static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL;\n        CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(object_, clGetDeviceIDsFromD3D10KHR);\n\n        cl_uint n = 0;\n        cl_int err = pfn_clGetDeviceIDsFromD3D10KHR(\n            object_,\n            d3d_device_source,\n            d3d_object,\n            d3d_device_set,\n            0,\n            NULL,\n            &n);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);\n        }\n\n        vector<cl_device_id> ids(n);\n        err = pfn_clGetDeviceIDsFromD3D10KHR(\n            object_,\n            d3d_device_source,\n            d3d_object,\n            d3d_device_set,\n            n,\n            ids.data(),\n            NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_DEVICE_IDS_ERR);\n        }\n\n        // Cannot trivially assign because we need to capture intermediates\n        // with safe construction\n        // We must retain things we obtain from the API to avoid releasing\n        // API-owned objects.\n        if (devices) {\n            devices->resize(ids.size());\n\n            // Assign to param, constructing with retain behaviour\n            // to correctly capture each underlying CL object\n            for (size_type i = 0; i < ids.size(); i++) {\n                (*devices)[i] = Device(ids[i], true);\n            }\n        }\n        return CL_SUCCESS;\n    }\n#endif\n\n    /*! \\brief Gets a list of available platforms.\n     *\n     *  Wraps clGetPlatformIDs().\n     */\n    static cl_int get(\n        vector<Platform>* platforms)\n    {\n        cl_uint n = 0;\n\n        if( platforms == NULL ) {\n            return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR);\n        }\n\n        cl_int err = ::clGetPlatformIDs(0, NULL, &n);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);\n        }\n\n        vector<cl_platform_id> ids(n);\n        err = ::clGetPlatformIDs(n, ids.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_PLATFORM_IDS_ERR);\n        }\n\n        if (platforms) {\n            platforms->resize(ids.size());\n\n            // Platforms don't reference count\n            for (size_type i = 0; i < ids.size(); i++) {\n                (*platforms)[i] = Platform(ids[i]);\n            }\n        }\n        return CL_SUCCESS;\n    }\n\n    /*! \\brief Gets the first available platform.\n     *\n     *  Wraps clGetPlatformIDs(), returning the first result.\n     */\n    static cl_int get(\n        Platform * platform)\n    {\n        cl_int err;\n        Platform default_platform = Platform::getDefault(&err);\n        if (platform) {\n            *platform = default_platform;\n        }\n        return err;\n    }\n\n    /*! \\brief Gets the first available platform, returning it by value.\n     *\n     * \\return Returns a valid platform if one is available.\n     *         If no platform is available will return a null platform.\n     * Throws an exception if no platforms are available\n     * or an error condition occurs.\n     * Wraps clGetPlatformIDs(), returning the first result.\n     */\n    static Platform get(\n        cl_int * errResult = NULL)\n    {\n        cl_int err;\n        Platform default_platform = Platform::getDefault(&err);\n        if (errResult) {\n            *errResult = err;\n        }\n        return default_platform;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    //! \\brief Wrapper for clUnloadCompiler().\n    cl_int\n    unloadCompiler()\n    {\n        return ::clUnloadPlatformCompiler(object_);\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n}; // class Platform\n\nCL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Platform::default_initialized_;\nCL_HPP_DEFINE_STATIC_MEMBER_ Platform Platform::default_;\nCL_HPP_DEFINE_STATIC_MEMBER_ cl_int Platform::default_error_ = CL_SUCCESS;\n\n\n/**\n * Deprecated APIs for 1.2\n */\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n/**\n * Unload the OpenCL compiler.\n * \\note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead.\n */\ninline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int\nUnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;\ninline cl_int\nUnloadCompiler()\n{\n    return ::clUnloadCompiler();\n}\n#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n\n/*! \\brief Class interface for cl_context.\n *\n *  \\note Copies of these objects are shallow, meaning that the copy will refer\n *        to the same underlying cl_context as the original.  For details, see\n *        clRetainContext() and clReleaseContext().\n *\n *  \\see cl_context\n */\nclass Context\n    : public detail::Wrapper<cl_context>\n{\nprivate:\n    static std::once_flag default_initialized_;\n    static Context default_;\n    static cl_int default_error_;\n\n    /*! \\brief Create the default context from the default device type in the default platform.\n     *\n     * This sets @c default_ and @c default_error_. It does not throw\n     * @c cl::Error.\n     */\n    static void makeDefault() {\n        /* Throwing an exception from a call_once invocation does not do\n         * what we wish, so we catch it and save the error.\n         */\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        try\n#endif\n        {\n#if !defined(__APPLE__) && !defined(__MACOS)\n            const Platform &p = Platform::getDefault();\n            cl_platform_id defaultPlatform = p();\n            cl_context_properties properties[3] = {\n                CL_CONTEXT_PLATFORM, (cl_context_properties)defaultPlatform, 0\n            };\n#else // #if !defined(__APPLE__) && !defined(__MACOS)\n            cl_context_properties *properties = nullptr;\n#endif // #if !defined(__APPLE__) && !defined(__MACOS)\n\n            default_ = Context(\n                CL_DEVICE_TYPE_DEFAULT,\n                properties,\n                NULL,\n                NULL,\n                &default_error_);\n        }\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        catch (cl::Error &e) {\n            default_error_ = e.err();\n        }\n#endif\n    }\n\n\n    /*! \\brief Create the default context from a provided Context.\n     *\n     * This sets @c default_. It does not throw\n     * @c cl::Error.\n     */\n    static void makeDefaultProvided(const Context &c) {\n        default_ = c;\n    }\n\npublic:\n#ifdef CL_HPP_UNIT_TEST_ENABLE\n    /*! \\brief Reset the default.\n    *\n    * This sets @c default_ to an empty value to support cleanup in\n    * the unit test framework.\n    * This function is not thread safe.\n    */\n    static void unitTestClearDefault() {\n        default_ = Context();\n    }\n#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE\n\n    /*! \\brief Constructs a context including a list of specified devices.\n     *\n     *  Wraps clCreateContext().\n     */\n    Context(\n        const vector<Device>& devices,\n        cl_context_properties* properties = NULL,\n        void (CL_CALLBACK * notifyFptr)(\n            const char *,\n            const void *,\n            size_type,\n            void *) = NULL,\n        void* data = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        size_type numDevices = devices.size();\n        vector<cl_device_id> deviceIDs(numDevices);\n\n        for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {\n            deviceIDs[deviceIndex] = (devices[deviceIndex])();\n        }\n\n        object_ = ::clCreateContext(\n            properties, (cl_uint) numDevices,\n            deviceIDs.data(),\n            notifyFptr, data, &error);\n\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    Context(\n        const Device& device,\n        cl_context_properties* properties = NULL,\n        void (CL_CALLBACK * notifyFptr)(\n            const char *,\n            const void *,\n            size_type,\n            void *) = NULL,\n        void* data = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        cl_device_id deviceID = device();\n\n        object_ = ::clCreateContext(\n            properties, 1,\n            &deviceID,\n            notifyFptr, data, &error);\n\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*! \\brief Constructs a context including all or a subset of devices of a specified type.\n     *\n     *  Wraps clCreateContextFromType().\n     */\n    Context(\n        cl_device_type type,\n        cl_context_properties* properties = NULL,\n        void (CL_CALLBACK * notifyFptr)(\n            const char *,\n            const void *,\n            size_type,\n            void *) = NULL,\n        void* data = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n#if !defined(__APPLE__) && !defined(__MACOS)\n        cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 };\n\n        if (properties == NULL) {\n            // Get a valid platform ID as we cannot send in a blank one\n            vector<Platform> platforms;\n            error = Platform::get(&platforms);\n            if (error != CL_SUCCESS) {\n                detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);\n                if (err != NULL) {\n                    *err = error;\n                }\n                return;\n            }\n\n            // Check the platforms we found for a device of our specified type\n            cl_context_properties platform_id = 0;\n            for (unsigned int i = 0; i < platforms.size(); i++) {\n\n                vector<Device> devices;\n\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n                try {\n#endif\n\n                    error = platforms[i].getDevices(type, &devices);\n\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n                } catch (Error) {}\n    // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type\n    // We do error checking next anyway, and can throw there if needed\n#endif\n\n                // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND\n                if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) {\n                    detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);\n                    if (err != NULL) {\n                        *err = error;\n                    }\n                }\n\n                if (devices.size() > 0) {\n                    platform_id = (cl_context_properties)platforms[i]();\n                    break;\n                }\n            }\n\n            if (platform_id == 0) {\n                detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR);\n                if (err != NULL) {\n                    *err = CL_DEVICE_NOT_FOUND;\n                }\n                return;\n            }\n\n            prop[1] = platform_id;\n            properties = &prop[0];\n        }\n#endif\n        object_ = ::clCreateContextFromType(\n            properties, type, notifyFptr, data, &error);\n\n        detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Context(const Context& ctx) : detail::Wrapper<cl_type>(ctx) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Context& operator = (const Context &ctx)\n    {\n        detail::Wrapper<cl_type>::operator=(ctx);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Context(Context&& ctx) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(ctx)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Context& operator = (Context &&ctx)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(ctx));\n        return *this;\n    }\n\n\n    /*! \\brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT.\n     *\n     *  \\note All calls to this function return the same cl_context as the first.\n     */\n    static Context getDefault(cl_int * err = NULL)\n    {\n        std::call_once(default_initialized_, makeDefault);\n        detail::errHandler(default_error_);\n        if (err != NULL) {\n            *err = default_error_;\n        }\n        return default_;\n    }\n\n    /**\n     * Modify the default context to be used by\n     * subsequent operations.\n     * Will only set the default if no default was previously created.\n     * @return updated default context.\n     *         Should be compared to the passed value to ensure that it was updated.\n     */\n    static Context setDefault(const Context &default_context)\n    {\n        std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_context));\n        detail::errHandler(default_error_);\n        return default_;\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Context() : detail::Wrapper<cl_type>() { }\n\n    /*! \\brief Constructor from cl_context - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the cl_context\n     *  into the new Context object.\n     */\n    explicit Context(const cl_context& context, bool retainObject = false) :\n        detail::Wrapper<cl_type>(context, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_context - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the rhs and calls\n     *  clReleaseContext() on the value previously held by this instance.\n     */\n    Context& operator = (const cl_context& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetContextInfo().\n    template <typename T>\n    cl_int getInfo(cl_context_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetContextInfo, object_, name, param),\n            __GET_CONTEXT_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetContextInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_context_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_context_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /*! \\brief Gets a list of supported image formats.\n     *\n     *  Wraps clGetSupportedImageFormats().\n     */\n    cl_int getSupportedImageFormats(\n        cl_mem_flags flags,\n        cl_mem_object_type type,\n        vector<ImageFormat>* formats) const\n    {\n        cl_uint numEntries;\n\n        if (!formats) {\n            return CL_SUCCESS;\n        }\n\n        cl_int err = ::clGetSupportedImageFormats(\n           object_,\n           flags,\n           type,\n           0,\n           NULL,\n           &numEntries);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);\n        }\n\n        if (numEntries > 0) {\n            vector<ImageFormat> value(numEntries);\n            err = ::clGetSupportedImageFormats(\n                object_,\n                flags,\n                type,\n                numEntries,\n                (cl_image_format*)value.data(),\n                NULL);\n            if (err != CL_SUCCESS) {\n                return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR);\n            }\n\n            formats->assign(begin(value), end(value));\n        }\n        else {\n            // If no values are being returned, ensure an empty vector comes back\n            formats->clear();\n        }\n\n        return CL_SUCCESS;\n    }\n};\n\ninline void Device::makeDefault()\n{\n    /* Throwing an exception from a call_once invocation does not do\n    * what we wish, so we catch it and save the error.\n    */\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n    try\n#endif\n    {\n        cl_int error = 0;\n\n        Context context = Context::getDefault(&error);\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n\n        if (error != CL_SUCCESS) {\n            default_error_ = error;\n        }\n        else {\n            default_ = context.getInfo<CL_CONTEXT_DEVICES>()[0];\n            default_error_ = CL_SUCCESS;\n        }\n    }\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n    catch (cl::Error &e) {\n        default_error_ = e.err();\n    }\n#endif\n}\n\nCL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag Context::default_initialized_;\nCL_HPP_DEFINE_STATIC_MEMBER_ Context Context::default_;\nCL_HPP_DEFINE_STATIC_MEMBER_ cl_int Context::default_error_ = CL_SUCCESS;\n\n/*! \\brief Class interface for cl_event.\n *\n *  \\note Copies of these objects are shallow, meaning that the copy will refer\n *        to the same underlying cl_event as the original.  For details, see\n *        clRetainEvent() and clReleaseEvent().\n *\n *  \\see cl_event\n */\nclass Event : public detail::Wrapper<cl_event>\n{\npublic:\n    //! \\brief Default constructor - initializes to NULL.\n    Event() : detail::Wrapper<cl_type>() { }\n\n    /*! \\brief Constructor from cl_event - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  This effectively transfers ownership of a refcount on the cl_event\n     *  into the new Event object.\n     */\n    explicit Event(const cl_event& event, bool retainObject = false) :\n        detail::Wrapper<cl_type>(event, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_event - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the rhs and calls\n     *  clReleaseEvent() on the value previously held by this instance.\n     */\n    Event& operator = (const cl_event& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetEventInfo().\n    template <typename T>\n    cl_int getInfo(cl_event_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetEventInfo, object_, name, param),\n            __GET_EVENT_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetEventInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_event_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_event_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    //! \\brief Wrapper for clGetEventProfilingInfo().\n    template <typename T>\n    cl_int getProfilingInfo(cl_profiling_info name, T* param) const\n    {\n        return detail::errHandler(detail::getInfo(\n            &::clGetEventProfilingInfo, object_, name, param),\n            __GET_EVENT_PROFILE_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetEventProfilingInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_profiling_info, name>::param_type\n    getProfilingInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_profiling_info, name>::param_type param;\n        cl_int result = getProfilingInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /*! \\brief Blocks the calling thread until this event completes.\n     *\n     *  Wraps clWaitForEvents().\n     */\n    cl_int wait() const\n    {\n        return detail::errHandler(\n            ::clWaitForEvents(1, &object_),\n            __WAIT_FOR_EVENTS_ERR);\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n    /*! \\brief Registers a user callback function for a specific command execution status.\n     *\n     *  Wraps clSetEventCallback().\n     */\n    cl_int setCallback(\n        cl_int type,\n        void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *),\n        void * user_data = NULL)\n    {\n        return detail::errHandler(\n            ::clSetEventCallback(\n                object_,\n                type,\n                pfn_notify,\n                user_data),\n            __SET_EVENT_CALLBACK_ERR);\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\n    /*! \\brief Blocks the calling thread until every event specified is complete.\n     *\n     *  Wraps clWaitForEvents().\n     */\n    static cl_int\n    waitForEvents(const vector<Event>& events)\n    {\n        return detail::errHandler(\n            ::clWaitForEvents(\n                (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),\n            __WAIT_FOR_EVENTS_ERR);\n    }\n};\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n/*! \\brief Class interface for user events (a subset of cl_event's).\n *\n *  See Event for details about copy semantics, etc.\n */\nclass UserEvent : public Event\n{\npublic:\n    /*! \\brief Constructs a user event on a given context.\n     *\n     *  Wraps clCreateUserEvent().\n     */\n    UserEvent(\n        const Context& context,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateUserEvent(\n            context(),\n            &error);\n\n        detail::errHandler(error, __CREATE_USER_EVENT_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    UserEvent() : Event() { }\n\n    /*! \\brief Sets the execution status of a user event object.\n     *\n     *  Wraps clSetUserEventStatus().\n     */\n    cl_int setStatus(cl_int status)\n    {\n        return detail::errHandler(\n            ::clSetUserEventStatus(object_,status),\n            __SET_USER_EVENT_STATUS_ERR);\n    }\n};\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\n/*! \\brief Blocks the calling thread until every event specified is complete.\n *\n *  Wraps clWaitForEvents().\n */\ninline static cl_int\nWaitForEvents(const vector<Event>& events)\n{\n    return detail::errHandler(\n        ::clWaitForEvents(\n            (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL),\n        __WAIT_FOR_EVENTS_ERR);\n}\n\n/*! \\brief Class interface for cl_mem.\n *\n *  \\note Copies of these objects are shallow, meaning that the copy will refer\n *        to the same underlying cl_mem as the original.  For details, see\n *        clRetainMemObject() and clReleaseMemObject().\n *\n *  \\see cl_mem\n */\nclass Memory : public detail::Wrapper<cl_mem>\n{\npublic:\n    //! \\brief Default constructor - initializes to NULL.\n    Memory() : detail::Wrapper<cl_type>() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     *  Optionally transfer ownership of a refcount on the cl_mem\n     *  into the new Memory object.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *\n     *  See Memory for further details.\n     */\n    explicit Memory(const cl_mem& memory, bool retainObject) :\n        detail::Wrapper<cl_type>(memory, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_mem - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the rhs and calls\n     *  clReleaseMemObject() on the value previously held by this instance.\n     */\n    Memory& operator = (const cl_mem& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Memory(const Memory& mem) : detail::Wrapper<cl_type>(mem) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Memory& operator = (const Memory &mem)\n    {\n        detail::Wrapper<cl_type>::operator=(mem);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Memory(Memory&& mem) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(mem)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Memory& operator = (Memory &&mem)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(mem));\n        return *this;\n    }\n\n\n    //! \\brief Wrapper for clGetMemObjectInfo().\n    template <typename T>\n    cl_int getInfo(cl_mem_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetMemObjectInfo, object_, name, param),\n            __GET_MEM_OBJECT_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetMemObjectInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_mem_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_mem_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n    /*! \\brief Registers a callback function to be called when the memory object\n     *         is no longer needed.\n     *\n     *  Wraps clSetMemObjectDestructorCallback().\n     *\n     *  Repeated calls to this function, for a given cl_mem value, will append\n     *  to the list of functions called (in reverse order) when memory object's\n     *  resources are freed and the memory object is deleted.\n     *\n     *  \\note\n     *  The registered callbacks are associated with the underlying cl_mem\n     *  value - not the Memory class instance.\n     */\n    cl_int setDestructorCallback(\n        void (CL_CALLBACK * pfn_notify)(cl_mem, void *),\n        void * user_data = NULL)\n    {\n        return detail::errHandler(\n            ::clSetMemObjectDestructorCallback(\n                object_,\n                pfn_notify,\n                user_data),\n            __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR);\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\n};\n\n// Pre-declare copy functions\nclass Buffer;\ntemplate< typename IteratorType >\ncl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );\ntemplate< typename IteratorType >\ncl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );\ntemplate< typename IteratorType >\ncl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer );\ntemplate< typename IteratorType >\ncl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator );\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\nnamespace detail\n{\n    class SVMTraitNull\n    {\n    public:\n        static cl_svm_mem_flags getSVMMemFlags()\n        {\n            return 0;\n        }\n    };\n} // namespace detail\n\ntemplate<class Trait = detail::SVMTraitNull>\nclass SVMTraitReadWrite\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return CL_MEM_READ_WRITE |\n            Trait::getSVMMemFlags();\n    }\n};\n\ntemplate<class Trait = detail::SVMTraitNull>\nclass SVMTraitReadOnly\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return CL_MEM_READ_ONLY |\n            Trait::getSVMMemFlags();\n    }\n};\n\ntemplate<class Trait = detail::SVMTraitNull>\nclass SVMTraitWriteOnly\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return CL_MEM_WRITE_ONLY |\n            Trait::getSVMMemFlags();\n    }\n};\n\ntemplate<class Trait = SVMTraitReadWrite<>>\nclass SVMTraitCoarse\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return Trait::getSVMMemFlags();\n    }\n};\n\ntemplate<class Trait = SVMTraitReadWrite<>>\nclass SVMTraitFine\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return CL_MEM_SVM_FINE_GRAIN_BUFFER |\n            Trait::getSVMMemFlags();\n    }\n};\n\ntemplate<class Trait = SVMTraitReadWrite<>>\nclass SVMTraitAtomic\n{\npublic:\n    static cl_svm_mem_flags getSVMMemFlags()\n    {\n        return\n            CL_MEM_SVM_FINE_GRAIN_BUFFER |\n            CL_MEM_SVM_ATOMICS |\n            Trait::getSVMMemFlags();\n    }\n};\n\n// Pre-declare SVM map function\ntemplate<typename T>\ninline cl_int enqueueMapSVM(\n    T* ptr,\n    cl_bool blocking,\n    cl_map_flags flags,\n    size_type size,\n    const vector<Event>* events = NULL,\n    Event* event = NULL);\n\n/**\n * STL-like allocator class for managing SVM objects provided for convenience.\n *\n * Note that while this behaves like an allocator for the purposes of constructing vectors and similar objects,\n * care must be taken when using with smart pointers.\n * The allocator should not be used to construct a unique_ptr if we are using coarse-grained SVM mode because\n * the coarse-grained management behaviour would behave incorrectly with respect to reference counting.\n *\n * Instead the allocator embeds a Deleter which may be used with unique_ptr and is used\n * with the allocate_shared and allocate_ptr supplied operations.\n */\ntemplate<typename T, class SVMTrait>\nclass SVMAllocator {\nprivate:\n    Context context_;\n\npublic:\n    typedef T value_type;\n    typedef value_type* pointer;\n    typedef const value_type* const_pointer;\n    typedef value_type& reference;\n    typedef const value_type& const_reference;\n    typedef std::size_t size_type;\n    typedef std::ptrdiff_t difference_type;\n\n    template<typename U>\n    struct rebind\n    {\n        typedef SVMAllocator<U, SVMTrait> other;\n    };\n\n    template<typename U, typename V>\n    friend class SVMAllocator;\n\n    SVMAllocator() :\n        context_(Context::getDefault())\n    {\n    }\n\n    explicit SVMAllocator(cl::Context context) :\n        context_(context)\n    {\n    }\n\n\n    SVMAllocator(const SVMAllocator &other) :\n        context_(other.context_)\n    {\n    }\n\n    template<typename U>\n    SVMAllocator(const SVMAllocator<U, SVMTrait> &other) :\n        context_(other.context_)\n    {\n    }\n\n    ~SVMAllocator()\n    {\n    }\n\n    pointer address(reference r) CL_HPP_NOEXCEPT_\n    {\n        return std::addressof(r);\n    }\n\n    const_pointer address(const_reference r) CL_HPP_NOEXCEPT_\n    {\n        return std::addressof(r);\n    }\n\n    /**\n     * Allocate an SVM pointer.\n     *\n     * If the allocator is coarse-grained, this will take ownership to allow\n     * containers to correctly construct data in place.\n     */\n    pointer allocate(\n        size_type size,\n        typename cl::SVMAllocator<void, SVMTrait>::const_pointer = 0)\n    {\n        // Allocate memory with default alignment matching the size of the type\n        void* voidPointer =\n            clSVMAlloc(\n            context_(),\n            SVMTrait::getSVMMemFlags(),\n            size*sizeof(T),\n            0);\n        pointer retValue = reinterpret_cast<pointer>(\n            voidPointer);\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        if (!retValue) {\n            std::bad_alloc excep;\n            throw excep;\n        }\n#endif // #if defined(CL_HPP_ENABLE_EXCEPTIONS)\n\n        // If allocation was coarse-grained then map it\n        if (!(SVMTrait::getSVMMemFlags() & CL_MEM_SVM_FINE_GRAIN_BUFFER)) {\n            cl_int err = enqueueMapSVM(retValue, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, size*sizeof(T));\n            if (err != CL_SUCCESS) {\n                std::bad_alloc excep;\n                throw excep;\n            }\n        }\n\n        // If exceptions disabled, return null pointer from allocator\n        return retValue;\n    }\n\n    void deallocate(pointer p, size_type)\n    {\n        clSVMFree(context_(), p);\n    }\n\n    /**\n     * Return the maximum possible allocation size.\n     * This is the minimum of the maximum sizes of all devices in the context.\n     */\n    size_type max_size() const CL_HPP_NOEXCEPT_\n    {\n        size_type maxSize = std::numeric_limits<size_type>::max() / sizeof(T);\n\n        for (Device &d : context_.getInfo<CL_CONTEXT_DEVICES>()) {\n            maxSize = std::min(\n                maxSize,\n                static_cast<size_type>(d.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>()));\n        }\n\n        return maxSize;\n    }\n\n    template< class U, class... Args >\n    void construct(U* p, Args&&... args)\n    {\n        new(p)T(args...);\n    }\n\n    template< class U >\n    void destroy(U* p)\n    {\n        p->~U();\n    }\n\n    /**\n     * Returns true if the contexts match.\n     */\n    inline bool operator==(SVMAllocator const& rhs)\n    {\n        return (context_==rhs.context_);\n    }\n\n    inline bool operator!=(SVMAllocator const& a)\n    {\n        return !operator==(a);\n    }\n}; // class SVMAllocator        return cl::pointer<T>(tmp, detail::Deleter<T, Alloc>{alloc, copies});\n\n\ntemplate<class SVMTrait>\nclass SVMAllocator<void, SVMTrait> {\npublic:\n    typedef void value_type;\n    typedef value_type* pointer;\n    typedef const value_type* const_pointer;\n\n    template<typename U>\n    struct rebind\n    {\n        typedef SVMAllocator<U, SVMTrait> other;\n    };\n\n    template<typename U, typename V>\n    friend class SVMAllocator;\n};\n\n#if !defined(CL_HPP_NO_STD_UNIQUE_PTR)\nnamespace detail\n{\n    template<class Alloc>\n    class Deleter {\n    private:\n        Alloc alloc_;\n        size_type copies_;\n\n    public:\n        typedef typename std::allocator_traits<Alloc>::pointer pointer;\n\n        Deleter(const Alloc &alloc, size_type copies) : alloc_{ alloc }, copies_{ copies }\n        {\n        }\n\n        void operator()(pointer ptr) const {\n            Alloc tmpAlloc{ alloc_ };\n            std::allocator_traits<Alloc>::destroy(tmpAlloc, std::addressof(*ptr));\n            std::allocator_traits<Alloc>::deallocate(tmpAlloc, ptr, copies_);\n        }\n    };\n} // namespace detail\n\n/**\n * Allocation operation compatible with std::allocate_ptr.\n * Creates a unique_ptr<T> by default.\n * This requirement is to ensure that the control block is not\n * allocated in memory inaccessible to the host.\n */\ntemplate <class T, class Alloc, class... Args>\ncl::pointer<T, detail::Deleter<Alloc>> allocate_pointer(const Alloc &alloc_, Args&&... args)\n{\n    Alloc alloc(alloc_);\n    static const size_type copies = 1;\n\n    // Ensure that creation of the management block and the\n    // object are dealt with separately such that we only provide a deleter\n\n    T* tmp = std::allocator_traits<Alloc>::allocate(alloc, copies);\n    if (!tmp) {\n        std::bad_alloc excep;\n        throw excep;\n    }\n    try {\n        std::allocator_traits<Alloc>::construct(\n            alloc,\n            std::addressof(*tmp),\n            std::forward<Args>(args)...);\n\n        return cl::pointer<T, detail::Deleter<Alloc>>(tmp, detail::Deleter<Alloc>{alloc, copies});\n    }\n    catch (std::bad_alloc b)\n    {\n        std::allocator_traits<Alloc>::deallocate(alloc, tmp, copies);\n        throw;\n    }\n}\n\ntemplate< class T, class SVMTrait, class... Args >\ncl::pointer<T, detail::Deleter<SVMAllocator<T, SVMTrait>>> allocate_svm(Args... args)\n{\n    SVMAllocator<T, SVMTrait> alloc;\n    return cl::allocate_pointer<T>(alloc, args...);\n}\n\ntemplate< class T, class SVMTrait, class... Args >\ncl::pointer<T, detail::Deleter<SVMAllocator<T, SVMTrait>>> allocate_svm(const cl::Context &c, Args... args)\n{\n    SVMAllocator<T, SVMTrait> alloc(c);\n    return cl::allocate_pointer<T>(alloc, args...);\n}\n#endif // #if !defined(CL_HPP_NO_STD_UNIQUE_PTR)\n\n/*! \\brief Vector alias to simplify construction of coarse-grained SVM containers.\n *\n */\ntemplate < class T >\nusing coarse_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitCoarse<>>>;\n\n/*! \\brief Vector alias to simplify construction of fine-grained SVM containers.\n*\n*/\ntemplate < class T >\nusing fine_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitFine<>>>;\n\n/*! \\brief Vector alias to simplify construction of fine-grained SVM containers that support platform atomics.\n*\n*/\ntemplate < class T >\nusing atomic_svm_vector = vector<T, cl::SVMAllocator<int, cl::SVMTraitAtomic<>>>;\n\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n\n/*! \\brief Class interface for Buffer Memory Objects.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Buffer : public Memory\n{\npublic:\n\n    /*! \\brief Constructs a Buffer in a specified context.\n     *\n     *  Wraps clCreateBuffer().\n     *\n     *  \\param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was\n     *                  specified.  Note alignment & exclusivity requirements.\n     */\n    Buffer(\n        const Context& context,\n        cl_mem_flags flags,\n        size_type size,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);\n\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*! \\brief Constructs a Buffer in the default context.\n     *\n     *  Wraps clCreateBuffer().\n     *\n     *  \\param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was\n     *                  specified.  Note alignment & exclusivity requirements.\n     *\n     *  \\see Context::getDefault()\n     */\n    Buffer(\n         cl_mem_flags flags,\n        size_type size,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        Context context = Context::getDefault(err);\n\n        object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error);\n\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*!\n     * \\brief Construct a Buffer from a host container via iterators.\n     * IteratorType must be random access.\n     * If useHostPtr is specified iterators must represent contiguous data.\n     */\n    template< typename IteratorType >\n    Buffer(\n        IteratorType startIterator,\n        IteratorType endIterator,\n        bool readOnly,\n        bool useHostPtr = false,\n        cl_int* err = NULL)\n    {\n        typedef typename std::iterator_traits<IteratorType>::value_type DataType;\n        cl_int error;\n\n        cl_mem_flags flags = 0;\n        if( readOnly ) {\n            flags |= CL_MEM_READ_ONLY;\n        }\n        else {\n            flags |= CL_MEM_READ_WRITE;\n        }\n        if( useHostPtr ) {\n            flags |= CL_MEM_USE_HOST_PTR;\n        }\n\n        size_type size = sizeof(DataType)*(endIterator - startIterator);\n\n        Context context = Context::getDefault(err);\n\n        if( useHostPtr ) {\n            object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);\n        } else {\n            object_ = ::clCreateBuffer(context(), flags, size, 0, &error);\n        }\n\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        if( !useHostPtr ) {\n            error = cl::copy(startIterator, endIterator, *this);\n            detail::errHandler(error, __CREATE_BUFFER_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n    }\n\n    /*!\n     * \\brief Construct a Buffer from a host container via iterators using a specified context.\n     * IteratorType must be random access.\n     * If useHostPtr is specified iterators must represent contiguous data.\n     */\n    template< typename IteratorType >\n    Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator,\n        bool readOnly, bool useHostPtr = false, cl_int* err = NULL);\n\n    /*!\n    * \\brief Construct a Buffer from a host container via iterators using a specified queue.\n    * If useHostPtr is specified iterators must be random access.\n    */\n    template< typename IteratorType >\n    Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator,\n        bool readOnly, bool useHostPtr = false, cl_int* err = NULL);\n\n    //! \\brief Default constructor - initializes to NULL.\n    Buffer() : Memory() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with earlier versions.\n     *\n     *  See Memory for further details.\n     */\n    explicit Buffer(const cl_mem& buffer, bool retainObject = false) :\n        Memory(buffer, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n    *\n    *  See Memory for further details.\n    */\n    Buffer& operator = (const cl_mem& rhs)\n    {\n        Memory::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Buffer(const Buffer& buf) : Memory(buf) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Buffer& operator = (const Buffer &buf)\n    {\n        Memory::operator=(buf);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Buffer(Buffer&& buf) CL_HPP_NOEXCEPT_ : Memory(std::move(buf)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Buffer& operator = (Buffer &&buf)\n    {\n        Memory::operator=(std::move(buf));\n        return *this;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n    /*! \\brief Creates a new buffer object from this.\n     *\n     *  Wraps clCreateSubBuffer().\n     */\n    Buffer createSubBuffer(\n        cl_mem_flags flags,\n        cl_buffer_create_type buffer_create_type,\n        const void * buffer_create_info,\n        cl_int * err = NULL)\n    {\n        Buffer result;\n        cl_int error;\n        result.object_ = ::clCreateSubBuffer(\n            object_,\n            flags,\n            buffer_create_type,\n            buffer_create_info,\n            &error);\n\n        detail::errHandler(error, __CREATE_SUBBUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        return result;\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n};\n\n#if defined (CL_HPP_USE_DX_INTEROP)\n/*! \\brief Class interface for creating OpenCL buffers from ID3D10Buffer's.\n *\n *  This is provided to facilitate interoperability with Direct3D.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass BufferD3D10 : public Buffer\n{\npublic:\n\n\n    /*! \\brief Constructs a BufferD3D10, in a specified context, from a\n     *         given ID3D10Buffer.\n     *\n     *  Wraps clCreateFromD3D10BufferKHR().\n     */\n    BufferD3D10(\n        const Context& context,\n        cl_mem_flags flags,\n        ID3D10Buffer* bufobj,\n        cl_int * err = NULL) : pfn_clCreateFromD3D10BufferKHR(nullptr)\n    {\n        typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)(\n            cl_context context, cl_mem_flags flags, ID3D10Buffer*  buffer,\n            cl_int* errcode_ret);\n        PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR;\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n        vector<cl_context_properties> props = context.getInfo<CL_CONTEXT_PROPERTIES>();\n        cl_platform platform = -1;\n        for( int i = 0; i < props.size(); ++i ) {\n            if( props[i] == CL_CONTEXT_PLATFORM ) {\n                platform = props[i+1];\n            }\n        }\n        CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clCreateFromD3D10BufferKHR);\n#elif CL_HPP_TARGET_OPENCL_VERSION >= 110\n        CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateFromD3D10BufferKHR);\n#endif\n\n        cl_int error;\n        object_ = pfn_clCreateFromD3D10BufferKHR(\n            context(),\n            flags,\n            bufobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    BufferD3D10() : Buffer() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit BufferD3D10(const cl_mem& buffer, bool retainObject = false) :\n        Buffer(buffer, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    BufferD3D10& operator = (const cl_mem& rhs)\n    {\n        Buffer::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferD3D10(const BufferD3D10& buf) :\n        Buffer(buf) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferD3D10& operator = (const BufferD3D10 &buf)\n    {\n        Buffer::operator=(buf);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferD3D10& operator = (BufferD3D10 &&buf)\n    {\n        Buffer::operator=(std::move(buf));\n        return *this;\n    }\n};\n#endif\n\n/*! \\brief Class interface for GL Buffer Memory Objects.\n *\n *  This is provided to facilitate interoperability with OpenGL.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass BufferGL : public Buffer\n{\npublic:\n    /*! \\brief Constructs a BufferGL in a specified context, from a given\n     *         GL buffer.\n     *\n     *  Wraps clCreateFromGLBuffer().\n     */\n    BufferGL(\n        const Context& context,\n        cl_mem_flags flags,\n        cl_GLuint bufobj,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateFromGLBuffer(\n            context(),\n            flags,\n            bufobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    BufferGL() : Buffer() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit BufferGL(const cl_mem& buffer, bool retainObject = false) :\n        Buffer(buffer, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    BufferGL& operator = (const cl_mem& rhs)\n    {\n        Buffer::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferGL(const BufferGL& buf) : Buffer(buf) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferGL& operator = (const BufferGL &buf)\n    {\n        Buffer::operator=(buf);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferGL& operator = (BufferGL &&buf)\n    {\n        Buffer::operator=(std::move(buf));\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetGLObjectInfo().\n    cl_int getObjectInfo(\n        cl_gl_object_type *type,\n        cl_GLuint * gl_object_name)\n    {\n        return detail::errHandler(\n            ::clGetGLObjectInfo(object_,type,gl_object_name),\n            __GET_GL_OBJECT_INFO_ERR);\n    }\n};\n\n/*! \\brief Class interface for GL Render Buffer Memory Objects.\n *\n *  This is provided to facilitate interoperability with OpenGL.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass BufferRenderGL : public Buffer\n{\npublic:\n    /*! \\brief Constructs a BufferRenderGL in a specified context, from a given\n     *         GL Renderbuffer.\n     *\n     *  Wraps clCreateFromGLRenderbuffer().\n     */\n    BufferRenderGL(\n        const Context& context,\n        cl_mem_flags flags,\n        cl_GLuint bufobj,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateFromGLRenderbuffer(\n            context(),\n            flags,\n            bufobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_RENDER_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    BufferRenderGL() : Buffer() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit BufferRenderGL(const cl_mem& buffer, bool retainObject = false) :\n        Buffer(buffer, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    BufferRenderGL& operator = (const cl_mem& rhs)\n    {\n        Buffer::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferRenderGL(const BufferRenderGL& buf) : Buffer(buf) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferRenderGL& operator = (const BufferRenderGL &buf)\n    {\n        Buffer::operator=(buf);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT_ : Buffer(std::move(buf)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    BufferRenderGL& operator = (BufferRenderGL &&buf)\n    {\n        Buffer::operator=(std::move(buf));\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetGLObjectInfo().\n    cl_int getObjectInfo(\n        cl_gl_object_type *type,\n        cl_GLuint * gl_object_name)\n    {\n        return detail::errHandler(\n            ::clGetGLObjectInfo(object_,type,gl_object_name),\n            __GET_GL_OBJECT_INFO_ERR);\n    }\n};\n\n/*! \\brief C++ base class for Image Memory objects.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Image : public Memory\n{\nprotected:\n    //! \\brief Default constructor - initializes to NULL.\n    Image() : Memory() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image(const cl_mem& image, bool retainObject = false) :\n        Memory(image, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Image& operator = (const cl_mem& rhs)\n    {\n        Memory::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image(const Image& img) : Memory(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image& operator = (const Image &img)\n    {\n        Memory::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image(Image&& img) CL_HPP_NOEXCEPT_ : Memory(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image& operator = (Image &&img)\n    {\n        Memory::operator=(std::move(img));\n        return *this;\n    }\n\n\npublic:\n    //! \\brief Wrapper for clGetImageInfo().\n    template <typename T>\n    cl_int getImageInfo(cl_image_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetImageInfo, object_, name, param),\n            __GET_IMAGE_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetImageInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_image_info, name>::param_type\n    getImageInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_image_info, name>::param_type param;\n        cl_int result = getImageInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n};\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n/*! \\brief Class interface for 1D Image Memory objects.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Image1D : public Image\n{\npublic:\n    /*! \\brief Constructs a 1D Image in a specified context.\n     *\n     *  Wraps clCreateImage().\n     */\n    Image1D(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type width,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE1D,\n            width,\n            0, 0, 0, 0, 0, 0, 0, 0\n        };\n        object_ = ::clCreateImage(\n            context(),\n            flags,\n            &format,\n            &desc,\n            host_ptr,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Image1D() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image1D(const cl_mem& image1D, bool retainObject = false) :\n        Image(image1D, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Image1D& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1D(const Image1D& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1D& operator = (const Image1D &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1D(Image1D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1D& operator = (Image1D &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n\n};\n\n/*! \\class Image1DBuffer\n * \\brief Image interface for 1D buffer images.\n */\nclass Image1DBuffer : public Image\n{\npublic:\n    Image1DBuffer(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type width,\n        const Buffer &buffer,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE1D_BUFFER,\n            width,\n            0, 0, 0, 0, 0, 0, 0,\n            buffer()\n        };\n        object_ = ::clCreateImage(\n            context(),\n            flags,\n            &format,\n            &desc,\n            NULL,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    Image1DBuffer() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image1DBuffer(const cl_mem& image1D, bool retainObject = false) :\n        Image(image1D, retainObject) { }\n\n    Image1DBuffer& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DBuffer(const Image1DBuffer& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DBuffer& operator = (const Image1DBuffer &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DBuffer(Image1DBuffer&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DBuffer& operator = (Image1DBuffer &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n\n};\n\n/*! \\class Image1DArray\n * \\brief Image interface for arrays of 1D images.\n */\nclass Image1DArray : public Image\n{\npublic:\n    Image1DArray(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type arraySize,\n        size_type width,\n        size_type rowPitch,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE1D_ARRAY,\n            width,\n            0, 0,  // height, depth (unused)\n            arraySize,\n            rowPitch,\n            0, 0, 0, 0\n        };\n        object_ = ::clCreateImage(\n            context(),\n            flags,\n            &format,\n            &desc,\n            host_ptr,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    Image1DArray() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image1DArray(const cl_mem& imageArray, bool retainObject = false) :\n        Image(imageArray, retainObject) { }\n\n\n    Image1DArray& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DArray(const Image1DArray& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DArray& operator = (const Image1DArray &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DArray(Image1DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image1DArray& operator = (Image1DArray &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n\n};\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n\n/*! \\brief Class interface for 2D Image Memory objects.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Image2D : public Image\n{\npublic:\n    /*! \\brief Constructs a 2D Image in a specified context.\n     *\n     *  Wraps clCreateImage().\n     */\n    Image2D(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type width,\n        size_type height,\n        size_type row_pitch = 0,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        bool useCreateImage;\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        // Run-time decision based on the actual platform\n        {\n            cl_uint version = detail::getContextPlatformVersion(context());\n            useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above\n        }\n#elif CL_HPP_TARGET_OPENCL_VERSION >= 120\n        useCreateImage = true;\n#else\n        useCreateImage = false;\n#endif\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n        if (useCreateImage)\n        {\n            cl_image_desc desc =\n            {\n                CL_MEM_OBJECT_IMAGE2D,\n                width,\n                height,\n                0, 0, // depth, array size (unused)\n                row_pitch,\n                0, 0, 0, 0\n            };\n            object_ = ::clCreateImage(\n                context(),\n                flags,\n                &format,\n                &desc,\n                host_ptr,\n                &error);\n\n            detail::errHandler(error, __CREATE_IMAGE_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#if CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        if (!useCreateImage)\n        {\n            object_ = ::clCreateImage2D(\n                context(), flags,&format, width, height, row_pitch, host_ptr, &error);\n\n            detail::errHandler(error, __CREATE_IMAGE2D_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /*! \\brief Constructs a 2D Image from a buffer.\n    * \\note This will share storage with the underlying buffer.\n    *\n    *  Wraps clCreateImage().\n    */\n    Image2D(\n        const Context& context,\n        ImageFormat format,\n        const Buffer &sourceBuffer,\n        size_type width,\n        size_type height,\n        size_type row_pitch = 0,\n        cl_int* err = nullptr)\n    {\n        cl_int error;\n\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE2D,\n            width,\n            height,\n            0, 0, // depth, array size (unused)\n            row_pitch,\n            0, 0, 0,\n            // Use buffer as input to image\n            sourceBuffer()\n        };\n        object_ = ::clCreateImage(\n            context(),\n            0, // flags inherited from buffer\n            &format,\n            &desc,\n            nullptr,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != nullptr) {\n            *err = error;\n        }\n    }\n#endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /*! \\brief Constructs a 2D Image from an image.\n    * \\note This will share storage with the underlying image but may\n    *       reinterpret the channel order and type.\n    *\n    * The image will be created matching with a descriptor matching the source.\n    *\n    * \\param order is the channel order to reinterpret the image data as.\n    *              The channel order may differ as described in the OpenCL\n    *              2.0 API specification.\n    *\n    * Wraps clCreateImage().\n    */\n    Image2D(\n        const Context& context,\n        cl_channel_order order,\n        const Image &sourceImage,\n        cl_int* err = nullptr)\n    {\n        cl_int error;\n\n        // Descriptor fields have to match source image\n        size_type sourceWidth =\n            sourceImage.getImageInfo<CL_IMAGE_WIDTH>();\n        size_type sourceHeight =\n            sourceImage.getImageInfo<CL_IMAGE_HEIGHT>();\n        size_type sourceRowPitch =\n            sourceImage.getImageInfo<CL_IMAGE_ROW_PITCH>();\n        cl_uint sourceNumMIPLevels =\n            sourceImage.getImageInfo<CL_IMAGE_NUM_MIP_LEVELS>();\n        cl_uint sourceNumSamples =\n            sourceImage.getImageInfo<CL_IMAGE_NUM_SAMPLES>();\n        cl_image_format sourceFormat =\n            sourceImage.getImageInfo<CL_IMAGE_FORMAT>();\n\n        // Update only the channel order.\n        // Channel format inherited from source.\n        sourceFormat.image_channel_order = order;\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE2D,\n            sourceWidth,\n            sourceHeight,\n            0, 0, // depth (unused), array size (unused)\n            sourceRowPitch,\n            0, // slice pitch (unused)\n            sourceNumMIPLevels,\n            sourceNumSamples,\n            // Use buffer as input to image\n            sourceImage()\n        };\n        object_ = ::clCreateImage(\n            context(),\n            0, // flags should be inherited from mem_object\n            &sourceFormat,\n            &desc,\n            nullptr,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != nullptr) {\n            *err = error;\n        }\n    }\n#endif //#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n    //! \\brief Default constructor - initializes to NULL.\n    Image2D() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image2D(const cl_mem& image2D, bool retainObject = false) :\n        Image(image2D, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Image2D& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2D(const Image2D& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2D& operator = (const Image2D &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2D(Image2D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2D& operator = (Image2D &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n\n};\n\n\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n/*! \\brief Class interface for GL 2D Image Memory objects.\n *\n *  This is provided to facilitate interoperability with OpenGL.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n *  \\note Deprecated for OpenCL 1.2. Please use ImageGL instead.\n */\nclass CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D\n{\npublic:\n    /*! \\brief Constructs an Image2DGL in a specified context, from a given\n     *         GL Texture.\n     *\n     *  Wraps clCreateFromGLTexture2D().\n     */\n    Image2DGL(\n        const Context& context,\n        cl_mem_flags flags,\n        cl_GLenum target,\n        cl_GLint  miplevel,\n        cl_GLuint texobj,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateFromGLTexture2D(\n            context(),\n            flags,\n            target,\n            miplevel,\n            texobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_TEXTURE_2D_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Image2DGL() : Image2D() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image2DGL(const cl_mem& image, bool retainObject = false) :\n        Image2D(image, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *c\n     *  See Memory for further details.\n     */\n    Image2DGL& operator = (const cl_mem& rhs)\n    {\n        Image2D::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DGL(const Image2DGL& img) : Image2D(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DGL& operator = (const Image2DGL &img)\n    {\n        Image2D::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DGL(Image2DGL&& img) CL_HPP_NOEXCEPT_ : Image2D(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DGL& operator = (Image2DGL &&img)\n    {\n        Image2D::operator=(std::move(img));\n        return *this;\n    }\n\n} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;\n#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n/*! \\class Image2DArray\n * \\brief Image interface for arrays of 2D images.\n */\nclass Image2DArray : public Image\n{\npublic:\n    Image2DArray(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type arraySize,\n        size_type width,\n        size_type height,\n        size_type rowPitch,\n        size_type slicePitch,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        cl_image_desc desc =\n        {\n            CL_MEM_OBJECT_IMAGE2D_ARRAY,\n            width,\n            height,\n            0,       // depth (unused)\n            arraySize,\n            rowPitch,\n            slicePitch,\n            0, 0, 0\n        };\n        object_ = ::clCreateImage(\n            context(),\n            flags,\n            &format,\n            &desc,\n            host_ptr,\n            &error);\n\n        detail::errHandler(error, __CREATE_IMAGE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    Image2DArray() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image2DArray(const cl_mem& imageArray, bool retainObject = false) : Image(imageArray, retainObject) { }\n\n    Image2DArray& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DArray(const Image2DArray& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DArray& operator = (const Image2DArray &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DArray(Image2DArray&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image2DArray& operator = (Image2DArray &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n};\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n/*! \\brief Class interface for 3D Image Memory objects.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Image3D : public Image\n{\npublic:\n    /*! \\brief Constructs a 3D Image in a specified context.\n     *\n     *  Wraps clCreateImage().\n     */\n    Image3D(\n        const Context& context,\n        cl_mem_flags flags,\n        ImageFormat format,\n        size_type width,\n        size_type height,\n        size_type depth,\n        size_type row_pitch = 0,\n        size_type slice_pitch = 0,\n        void* host_ptr = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        bool useCreateImage;\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        // Run-time decision based on the actual platform\n        {\n            cl_uint version = detail::getContextPlatformVersion(context());\n            useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above\n        }\n#elif CL_HPP_TARGET_OPENCL_VERSION >= 120\n        useCreateImage = true;\n#else\n        useCreateImage = false;\n#endif\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n        if (useCreateImage)\n        {\n            cl_image_desc desc =\n            {\n                CL_MEM_OBJECT_IMAGE3D,\n                width,\n                height,\n                depth,\n                0,      // array size (unused)\n                row_pitch,\n                slice_pitch,\n                0, 0, 0\n            };\n            object_ = ::clCreateImage(\n                context(),\n                flags,\n                &format,\n                &desc,\n                host_ptr,\n                &error);\n\n            detail::errHandler(error, __CREATE_IMAGE_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n#endif  // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#if CL_HPP_MINIMUM_OPENCL_VERSION < 120\n        if (!useCreateImage)\n        {\n            object_ = ::clCreateImage3D(\n                context(), flags, &format, width, height, depth, row_pitch,\n                slice_pitch, host_ptr, &error);\n\n            detail::errHandler(error, __CREATE_IMAGE3D_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n#endif // CL_HPP_MINIMUM_OPENCL_VERSION < 120\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Image3D() : Image() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image3D(const cl_mem& image3D, bool retainObject = false) :\n        Image(image3D, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Image3D& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3D(const Image3D& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3D& operator = (const Image3D &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3D(Image3D&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3D& operator = (Image3D &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n};\n\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n/*! \\brief Class interface for GL 3D Image Memory objects.\n *\n *  This is provided to facilitate interoperability with OpenGL.\n *\n *  See Memory for details about copy semantics, etc.\n *\n *  \\see Memory\n */\nclass Image3DGL : public Image3D\n{\npublic:\n    /*! \\brief Constructs an Image3DGL in a specified context, from a given\n     *         GL Texture.\n     *\n     *  Wraps clCreateFromGLTexture3D().\n     */\n    Image3DGL(\n        const Context& context,\n        cl_mem_flags flags,\n        cl_GLenum target,\n        cl_GLint  miplevel,\n        cl_GLuint texobj,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateFromGLTexture3D(\n            context(),\n            flags,\n            target,\n            miplevel,\n            texobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_TEXTURE_3D_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Image3DGL() : Image3D() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit Image3DGL(const cl_mem& image, bool retainObject = false) :\n        Image3D(image, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Image3DGL& operator = (const cl_mem& rhs)\n    {\n        Image3D::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3DGL(const Image3DGL& img) : Image3D(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3DGL& operator = (const Image3DGL &img)\n    {\n        Image3D::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3DGL(Image3DGL&& img) CL_HPP_NOEXCEPT_ : Image3D(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Image3DGL& operator = (Image3DGL &&img)\n    {\n        Image3D::operator=(std::move(img));\n        return *this;\n    }\n};\n#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n/*! \\class ImageGL\n * \\brief general image interface for GL interop.\n * We abstract the 2D and 3D GL images into a single instance here\n * that wraps all GL sourced images on the grounds that setup information\n * was performed by OpenCL anyway.\n */\nclass ImageGL : public Image\n{\npublic:\n    ImageGL(\n        const Context& context,\n        cl_mem_flags flags,\n        cl_GLenum target,\n        cl_GLint  miplevel,\n        cl_GLuint texobj,\n        cl_int * err = NULL)\n    {\n        cl_int error;\n        object_ = ::clCreateFromGLTexture(\n            context(),\n            flags,\n            target,\n            miplevel,\n            texobj,\n            &error);\n\n        detail::errHandler(error, __CREATE_GL_TEXTURE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    ImageGL() : Image() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  See Memory for further details.\n     */\n    explicit ImageGL(const cl_mem& image, bool retainObject = false) :\n        Image(image, retainObject) { }\n\n    ImageGL& operator = (const cl_mem& rhs)\n    {\n        Image::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    ImageGL(const ImageGL& img) : Image(img) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    ImageGL& operator = (const ImageGL &img)\n    {\n        Image::operator=(img);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    ImageGL(ImageGL&& img) CL_HPP_NOEXCEPT_ : Image(std::move(img)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    ImageGL& operator = (ImageGL &&img)\n    {\n        Image::operator=(std::move(img));\n        return *this;\n    }\n};\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n/*! \\brief Class interface for Pipe Memory Objects.\n*\n*  See Memory for details about copy semantics, etc.\n*\n*  \\see Memory\n*/\nclass Pipe : public Memory\n{\npublic:\n\n    /*! \\brief Constructs a Pipe in a specified context.\n     *\n     * Wraps clCreatePipe().\n     * @param context Context in which to create the pipe.\n     * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid.\n     * @param packet_size Size in bytes of a single packet of the pipe.\n     * @param max_packets Number of packets that may be stored in the pipe.\n     *\n     */\n    Pipe(\n        const Context& context,\n        cl_uint packet_size,\n        cl_uint max_packets,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS;\n        object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error);\n\n        detail::errHandler(error, __CREATE_PIPE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*! \\brief Constructs a Pipe in a the default context.\n     *\n     * Wraps clCreatePipe().\n     * @param flags Bitfield. Only CL_MEM_READ_WRITE and CL_MEM_HOST_NO_ACCESS are valid.\n     * @param packet_size Size in bytes of a single packet of the pipe.\n     * @param max_packets Number of packets that may be stored in the pipe.\n     *\n     */\n    Pipe(\n        cl_uint packet_size,\n        cl_uint max_packets,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        Context context = Context::getDefault(err);\n\n        cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS;\n        object_ = ::clCreatePipe(context(), flags, packet_size, max_packets, nullptr, &error);\n\n        detail::errHandler(error, __CREATE_PIPE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    //! \\brief Default constructor - initializes to NULL.\n    Pipe() : Memory() { }\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with earlier versions.\n     *\n     *  See Memory for further details.\n     */\n    explicit Pipe(const cl_mem& pipe, bool retainObject = false) :\n        Memory(pipe, retainObject) { }\n\n    /*! \\brief Assignment from cl_mem - performs shallow copy.\n     *\n     *  See Memory for further details.\n     */\n    Pipe& operator = (const cl_mem& rhs)\n    {\n        Memory::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Pipe(const Pipe& pipe) : Memory(pipe) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Pipe& operator = (const Pipe &pipe)\n    {\n        Memory::operator=(pipe);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Pipe(Pipe&& pipe) CL_HPP_NOEXCEPT_ : Memory(std::move(pipe)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Pipe& operator = (Pipe &&pipe)\n    {\n        Memory::operator=(std::move(pipe));\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetMemObjectInfo().\n    template <typename T>\n    cl_int getInfo(cl_pipe_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetPipeInfo, object_, name, param),\n            __GET_PIPE_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetMemObjectInfo() that returns by value.\n    template <cl_int name> typename\n        detail::param_traits<detail::cl_pipe_info, name>::param_type\n        getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_pipe_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n}; // class Pipe\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n\n/*! \\brief Class interface for cl_sampler.\n *\n *  \\note Copies of these objects are shallow, meaning that the copy will refer\n *        to the same underlying cl_sampler as the original.  For details, see\n *        clRetainSampler() and clReleaseSampler().\n *\n *  \\see cl_sampler\n */\nclass Sampler : public detail::Wrapper<cl_sampler>\n{\npublic:\n    //! \\brief Default constructor - initializes to NULL.\n    Sampler() { }\n\n    /*! \\brief Constructs a Sampler in a specified context.\n     *\n     *  Wraps clCreateSampler().\n     */\n    Sampler(\n        const Context& context,\n        cl_bool normalized_coords,\n        cl_addressing_mode addressing_mode,\n        cl_filter_mode filter_mode,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n        cl_sampler_properties sampler_properties[] = {\n            CL_SAMPLER_NORMALIZED_COORDS, normalized_coords,\n            CL_SAMPLER_ADDRESSING_MODE, addressing_mode,\n            CL_SAMPLER_FILTER_MODE, filter_mode,\n            0 };\n        object_ = ::clCreateSamplerWithProperties(\n            context(),\n            sampler_properties,\n            &error);\n\n        detail::errHandler(error, __CREATE_SAMPLER_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#else\n        object_ = ::clCreateSampler(\n            context(),\n            normalized_coords,\n            addressing_mode,\n            filter_mode,\n            &error);\n\n        detail::errHandler(error, __CREATE_SAMPLER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#endif\n    }\n\n    /*! \\brief Constructor from cl_sampler - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  This effectively transfers ownership of a refcount on the cl_sampler\n     *  into the new Sampler object.\n     */\n    explicit Sampler(const cl_sampler& sampler, bool retainObject = false) :\n        detail::Wrapper<cl_type>(sampler, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_sampler - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the rhs and calls\n     *  clReleaseSampler() on the value previously held by this instance.\n     */\n    Sampler& operator = (const cl_sampler& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Sampler(const Sampler& sam) : detail::Wrapper<cl_type>(sam) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Sampler& operator = (const Sampler &sam)\n    {\n        detail::Wrapper<cl_type>::operator=(sam);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Sampler(Sampler&& sam) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(sam)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Sampler& operator = (Sampler &&sam)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(sam));\n        return *this;\n    }\n\n    //! \\brief Wrapper for clGetSamplerInfo().\n    template <typename T>\n    cl_int getInfo(cl_sampler_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetSamplerInfo, object_, name, param),\n            __GET_SAMPLER_INFO_ERR);\n    }\n\n    //! \\brief Wrapper for clGetSamplerInfo() that returns by value.\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_sampler_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_sampler_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n};\n\nclass Program;\nclass CommandQueue;\nclass DeviceCommandQueue;\nclass Kernel;\n\n//! \\brief Class interface for specifying NDRange values.\nclass NDRange\n{\nprivate:\n    size_type sizes_[3];\n    cl_uint dimensions_;\n\npublic:\n    //! \\brief Default constructor - resulting range has zero dimensions.\n    NDRange()\n        : dimensions_(0)\n    {\n        sizes_[0] = 0;\n        sizes_[1] = 0;\n        sizes_[2] = 0;\n    }\n\n    //! \\brief Constructs one-dimensional range.\n    NDRange(size_type size0)\n        : dimensions_(1)\n    {\n        sizes_[0] = size0;\n        sizes_[1] = 1;\n        sizes_[2] = 1;\n    }\n\n    //! \\brief Constructs two-dimensional range.\n    NDRange(size_type size0, size_type size1)\n        : dimensions_(2)\n    {\n        sizes_[0] = size0;\n        sizes_[1] = size1;\n        sizes_[2] = 1;\n    }\n\n    //! \\brief Constructs three-dimensional range.\n    NDRange(size_type size0, size_type size1, size_type size2)\n        : dimensions_(3)\n    {\n        sizes_[0] = size0;\n        sizes_[1] = size1;\n        sizes_[2] = size2;\n    }\n\n    /*! \\brief Conversion operator to const size_type *.\n     *\n     *  \\returns a pointer to the size of the first dimension.\n     */\n    operator const size_type*() const {\n        return sizes_;\n    }\n\n    //! \\brief Queries the number of dimensions in the range.\n    size_type dimensions() const\n    {\n        return dimensions_;\n    }\n\n    //! \\brief Returns the size of the object in bytes based on the\n    // runtime number of dimensions\n    size_type size() const\n    {\n        return dimensions_*sizeof(size_type);\n    }\n\n    size_type* get()\n    {\n        return sizes_;\n    }\n\n    const size_type* get() const\n    {\n        return sizes_;\n    }\n};\n\n//! \\brief A zero-dimensional range.\nstatic const NDRange NullRange;\n\n//! \\brief Local address wrapper for use with Kernel::setArg\nstruct LocalSpaceArg\n{\n    size_type size_;\n};\n\nnamespace detail {\n\ntemplate <typename T, class Enable = void>\nstruct KernelArgumentHandler;\n\n// Enable for objects that are not subclasses of memory\n// Pointers, constants etc\ntemplate <typename T>\nstruct KernelArgumentHandler<T, typename std::enable_if<!std::is_base_of<cl::Memory, T>::value>::type>\n{\n    static size_type size(const T&) { return sizeof(T); }\n    static const T* ptr(const T& value) { return &value; }\n};\n\n// Enable for subclasses of memory where we want to get a reference to the cl_mem out\n// and pass that in for safety\ntemplate <typename T>\nstruct KernelArgumentHandler<T, typename std::enable_if<std::is_base_of<cl::Memory, T>::value>::type>\n{\n    static size_type size(const T&) { return sizeof(cl_mem); }\n    static const cl_mem* ptr(const T& value) { return &(value()); }\n};\n\n// Specialization for DeviceCommandQueue defined later\n\ntemplate <>\nstruct KernelArgumentHandler<LocalSpaceArg, void>\n{\n    static size_type size(const LocalSpaceArg& value) { return value.size_; }\n    static const void* ptr(const LocalSpaceArg&) { return NULL; }\n};\n\n}\n//! \\endcond\n\n/*! Local\n * \\brief Helper function for generating LocalSpaceArg objects.\n */\ninline LocalSpaceArg\nLocal(size_type size)\n{\n    LocalSpaceArg ret = { size };\n    return ret;\n}\n\n/*! \\brief Class interface for cl_kernel.\n *\n *  \\note Copies of these objects are shallow, meaning that the copy will refer\n *        to the same underlying cl_kernel as the original.  For details, see\n *        clRetainKernel() and clReleaseKernel().\n *\n *  \\see cl_kernel\n */\nclass Kernel : public detail::Wrapper<cl_kernel>\n{\npublic:\n    inline Kernel(const Program& program, const char* name, cl_int* err = NULL);\n\n    //! \\brief Default constructor - initializes to NULL.\n    Kernel() { }\n\n    /*! \\brief Constructor from cl_kernel - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     *  This effectively transfers ownership of a refcount on the cl_kernel\n     *  into the new Kernel object.\n     */\n    explicit Kernel(const cl_kernel& kernel, bool retainObject = false) :\n        detail::Wrapper<cl_type>(kernel, retainObject) { }\n\n    /*! \\brief Assignment operator from cl_kernel - takes ownership.\n     *\n     *  This effectively transfers ownership of a refcount on the rhs and calls\n     *  clReleaseKernel() on the value previously held by this instance.\n     */\n    Kernel& operator = (const cl_kernel& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Kernel(const Kernel& kernel) : detail::Wrapper<cl_type>(kernel) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Kernel& operator = (const Kernel &kernel)\n    {\n        detail::Wrapper<cl_type>::operator=(kernel);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Kernel(Kernel&& kernel) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(kernel)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Kernel& operator = (Kernel &&kernel)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(kernel));\n        return *this;\n    }\n\n    template <typename T>\n    cl_int getInfo(cl_kernel_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetKernelInfo, object_, name, param),\n            __GET_KERNEL_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_kernel_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_kernel_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    template <typename T>\n    cl_int getArgInfo(cl_uint argIndex, cl_kernel_arg_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetKernelArgInfo, object_, argIndex, name, param),\n            __GET_KERNEL_ARG_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_kernel_arg_info, name>::param_type\n    getArgInfo(cl_uint argIndex, cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_kernel_arg_info, name>::param_type param;\n        cl_int result = getArgInfo(argIndex, name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    template <typename T>\n    cl_int getWorkGroupInfo(\n        const Device& device, cl_kernel_work_group_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(\n                &::clGetKernelWorkGroupInfo, object_, device(), name, param),\n                __GET_KERNEL_WORK_GROUP_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_kernel_work_group_info, name>::param_type\n        getWorkGroupInfo(const Device& device, cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n        detail::cl_kernel_work_group_info, name>::param_type param;\n        cl_int result = getWorkGroupInfo(device, name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n#if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)\n    cl_int getSubGroupInfo(const cl::Device &dev, cl_kernel_sub_group_info name, const cl::NDRange &range, size_type* param) const\n    {\n        typedef clGetKernelSubGroupInfoKHR_fn PFN_clGetKernelSubGroupInfoKHR;\n        static PFN_clGetKernelSubGroupInfoKHR pfn_clGetKernelSubGroupInfoKHR = NULL;\n        CL_HPP_INIT_CL_EXT_FCN_PTR_(clGetKernelSubGroupInfoKHR);\n\n        return detail::errHandler(\n            pfn_clGetKernelSubGroupInfoKHR(object_, dev(), name, range.size(), range.get(), sizeof(size_type), param, nullptr),\n            __GET_KERNEL_ARG_INFO_ERR);\n    }\n\n    template <cl_int name>\n        size_type getSubGroupInfo(const cl::Device &dev, const cl::NDRange &range, cl_int* err = NULL) const\n    {\n        size_type param;\n        cl_int result = getSubGroupInfo(dev, name, range, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n#endif // #if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR)\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /*! \\brief setArg overload taking a shared_ptr type\n     */\n    template<typename T, class D>\n    cl_int setArg(cl_uint index, const cl::pointer<T, D> &argPtr)\n    {\n        return detail::errHandler(\n            ::clSetKernelArgSVMPointer(object_, index, argPtr.get()),\n            __SET_KERNEL_ARGS_ERR);\n    }\n\n    /*! \\brief setArg overload taking a vector type.\n     */\n    template<typename T, class Alloc>\n    cl_int setArg(cl_uint index, const cl::vector<T, Alloc> &argPtr)\n    {\n        return detail::errHandler(\n            ::clSetKernelArgSVMPointer(object_, index, argPtr.data()),\n            __SET_KERNEL_ARGS_ERR);\n    }\n\n    /*! \\brief setArg overload taking a pointer type\n     */\n    template<typename T>\n    typename std::enable_if<std::is_pointer<T>::value, cl_int>::type\n        setArg(cl_uint index, const T argPtr)\n    {\n        return detail::errHandler(\n            ::clSetKernelArgSVMPointer(object_, index, argPtr),\n            __SET_KERNEL_ARGS_ERR);\n    }\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n    /*! \\brief setArg overload taking a POD type\n     */\n    template <typename T>\n    typename std::enable_if<!std::is_pointer<T>::value, cl_int>::type\n        setArg(cl_uint index, const T &value)\n    {\n        return detail::errHandler(\n            ::clSetKernelArg(\n                object_,\n                index,\n                detail::KernelArgumentHandler<T>::size(value),\n                detail::KernelArgumentHandler<T>::ptr(value)),\n            __SET_KERNEL_ARGS_ERR);\n    }\n\n    cl_int setArg(cl_uint index, size_type size, const void* argPtr)\n    {\n        return detail::errHandler(\n            ::clSetKernelArg(object_, index, size, argPtr),\n            __SET_KERNEL_ARGS_ERR);\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /*!\n     * Specify a vector of SVM pointers that the kernel may access in\n     * addition to its arguments.\n     */\n    cl_int setSVMPointers(const vector<void*> &pointerList)\n    {\n        return detail::errHandler(\n            ::clSetKernelExecInfo(\n                object_,\n                CL_KERNEL_EXEC_INFO_SVM_PTRS,\n                sizeof(void*)*pointerList.size(),\n                pointerList.data()));\n    }\n\n    /*!\n     * Specify a std::array of SVM pointers that the kernel may access in\n     * addition to its arguments.\n     */\n    template<int ArrayLength>\n    cl_int setSVMPointers(const std::array<void*, ArrayLength> &pointerList)\n    {\n        return detail::errHandler(\n            ::clSetKernelExecInfo(\n                object_,\n                CL_KERNEL_EXEC_INFO_SVM_PTRS,\n                sizeof(void*)*pointerList.size(),\n                pointerList.data()));\n    }\n\n    /*! \\brief Enable fine-grained system SVM.\n     *\n     * \\note It is only possible to enable fine-grained system SVM if all devices\n     *       in the context associated with kernel support it.\n     *\n     * \\param svmEnabled True if fine-grained system SVM is requested. False otherwise.\n     * \\return CL_SUCCESS if the function was executed successfully. CL_INVALID_OPERATION\n     *         if no devices in the context support fine-grained system SVM.\n     *\n     * \\see clSetKernelExecInfo\n     */\n    cl_int enableFineGrainedSystemSVM(bool svmEnabled)\n    {\n        cl_bool svmEnabled_ = svmEnabled ? CL_TRUE : CL_FALSE;\n        return detail::errHandler(\n            ::clSetKernelExecInfo(\n                object_,\n                CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM,\n                sizeof(cl_bool),\n                &svmEnabled_\n                )\n            );\n    }\n\n    template<int index, int ArrayLength, class D, typename T0, typename... Ts>\n    void setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, const pointer<T0, D> &t0, Ts... ts)\n    {\n        pointerList[index] = static_cast<void*>(t0.get());\n        setSVMPointersHelper<index + 1, Ts...>(ts...);\n    }\n\n    template<int index, int ArrayLength, typename T0, typename... Ts>\n    typename std::enable_if<std::is_pointer<T0>::value, void>::type\n    setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, T0 t0, Ts... ts)\n    {\n        pointerList[index] = static_cast<void*>(t0);\n        setSVMPointersHelper<index + 1, Ts...>(ts...);\n    }\n\n    template<int index, int ArrayLength, typename T0, class D>\n    void setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, const pointer<T0, D> &t0)\n    {\n        pointerList[index] = static_cast<void*>(t0.get());\n    }\n\n    template<int index, int ArrayLength, typename T0>\n    typename std::enable_if<std::is_pointer<T0>::value, void>::type\n    setSVMPointersHelper(std::array<void*, ArrayLength> &pointerList, T0 t0)\n    {\n        pointerList[index] = static_cast<void*>(t0);\n    }\n\n    template<typename T0, typename... Ts>\n    cl_int setSVMPointers(const T0 &t0, Ts... ts)\n    {\n        std::array<void*, 1 + sizeof...(Ts)> pointerList;\n\n        setSVMPointersHelper<0, 1 + sizeof...(Ts)>(pointerList, t0, ts...);\n        return detail::errHandler(\n            ::clSetKernelExecInfo(\n            object_,\n            CL_KERNEL_EXEC_INFO_SVM_PTRS,\n            sizeof(void*)*(1 + sizeof...(Ts)),\n            pointerList.data()));\n    }\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n};\n\n/*! \\class Program\n * \\brief Program interface that implements cl_program.\n */\nclass Program : public detail::Wrapper<cl_program>\n{\npublic:\n#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n    typedef vector<vector<unsigned char>> Binaries;\n    typedef vector<string> Sources;\n#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n    typedef vector<std::pair<const void*, size_type> > Binaries;\n    typedef vector<std::pair<const char*, size_type> > Sources;\n#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n\n    Program(\n        const string& source,\n        bool build = false,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        const char * strings = source.c_str();\n        const size_type length  = source.size();\n\n        Context context = Context::getDefault(err);\n\n        object_ = ::clCreateProgramWithSource(\n            context(), (cl_uint)1, &strings, &length, &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);\n\n        if (error == CL_SUCCESS && build) {\n\n            error = ::clBuildProgram(\n                object_,\n                0,\n                NULL,\n#if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)\n                \"-cl-std=CL2.0\",\n#else\n                \"\",\n#endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)\n                NULL,\n                NULL);\n\n            detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());\n        }\n\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    Program(\n        const Context& context,\n        const string& source,\n        bool build = false,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        const char * strings = source.c_str();\n        const size_type length  = source.size();\n\n        object_ = ::clCreateProgramWithSource(\n            context(), (cl_uint)1, &strings, &length, &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);\n\n        if (error == CL_SUCCESS && build) {\n            error = ::clBuildProgram(\n                object_,\n                0,\n                NULL,\n#if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)\n                \"-cl-std=CL2.0\",\n#else\n                \"\",\n#endif // #if !defined(CL_HPP_CL_1_2_DEFAULT_BUILD)\n                NULL,\n                NULL);\n\n            detail::buildErrHandler(error, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());\n        }\n\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /**\n     * Create a program from a vector of source strings and the default context.\n     * Does not compile or link the program.\n     */\n    Program(\n        const Sources& sources,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        Context context = Context::getDefault(err);\n\n        const size_type n = (size_type)sources.size();\n\n        vector<size_type> lengths(n);\n        vector<const char*> strings(n);\n\n        for (size_type i = 0; i < n; ++i) {\n#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n            strings[i] = sources[(int)i].data();\n            lengths[i] = sources[(int)i].length();\n#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n            strings[i] = sources[(int)i].first;\n            lengths[i] = sources[(int)i].second;\n#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n        }\n\n        object_ = ::clCreateProgramWithSource(\n            context(), (cl_uint)n, strings.data(), lengths.data(), &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /**\n     * Create a program from a vector of source strings and a provided context.\n     * Does not compile or link the program.\n     */\n    Program(\n        const Context& context,\n        const Sources& sources,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        const size_type n = (size_type)sources.size();\n\n        vector<size_type> lengths(n);\n        vector<const char*> strings(n);\n\n        for (size_type i = 0; i < n; ++i) {\n#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n            strings[i] = sources[(int)i].data();\n            lengths[i] = sources[(int)i].length();\n#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n            strings[i] = sources[(int)i].first;\n            lengths[i] = sources[(int)i].second;\n#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n        }\n\n        object_ = ::clCreateProgramWithSource(\n            context(), (cl_uint)n, strings.data(), lengths.data(), &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /**\n     * Construct a program object from a list of devices and a per-device list of binaries.\n     * \\param context A valid OpenCL context in which to construct the program.\n     * \\param devices A vector of OpenCL device objects for which the program will be created.\n     * \\param binaries A vector of pairs of a pointer to a binary object and its length.\n     * \\param binaryStatus An optional vector that on completion will be resized to\n     *   match the size of binaries and filled with values to specify if each binary\n     *   was successfully loaded.\n     *   Set to CL_SUCCESS if the binary was successfully loaded.\n     *   Set to CL_INVALID_VALUE if the length is 0 or the binary pointer is NULL.\n     *   Set to CL_INVALID_BINARY if the binary provided is not valid for the matching device.\n     * \\param err if non-NULL will be set to CL_SUCCESS on successful operation or one of the following errors:\n     *   CL_INVALID_CONTEXT if context is not a valid context.\n     *   CL_INVALID_VALUE if the length of devices is zero; or if the length of binaries does not match the length of devices;\n     *     or if any entry in binaries is NULL or has length 0.\n     *   CL_INVALID_DEVICE if OpenCL devices listed in devices are not in the list of devices associated with context.\n     *   CL_INVALID_BINARY if an invalid program binary was encountered for any device. binaryStatus will return specific status for each device.\n     *   CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by the OpenCL implementation on the host.\n     */\n    Program(\n        const Context& context,\n        const vector<Device>& devices,\n        const Binaries& binaries,\n        vector<cl_int>* binaryStatus = NULL,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        const size_type numDevices = devices.size();\n\n        // Catch size mismatch early and return\n        if(binaries.size() != numDevices) {\n            error = CL_INVALID_VALUE;\n            detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n            return;\n        }\n\n\n        vector<size_type> lengths(numDevices);\n        vector<const unsigned char*> images(numDevices);\n#if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n        for (size_type i = 0; i < numDevices; ++i) {\n            images[i] = binaries[i].data();\n            lengths[i] = binaries[(int)i].size();\n        }\n#else // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n        for (size_type i = 0; i < numDevices; ++i) {\n            images[i] = (const unsigned char*)binaries[i].first;\n            lengths[i] = binaries[(int)i].second;\n        }\n#endif // #if !defined(CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY)\n\n        vector<cl_device_id> deviceIDs(numDevices);\n        for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {\n            deviceIDs[deviceIndex] = (devices[deviceIndex])();\n        }\n\n        if(binaryStatus) {\n            binaryStatus->resize(numDevices);\n        }\n\n        object_ = ::clCreateProgramWithBinary(\n            context(), (cl_uint) devices.size(),\n            deviceIDs.data(),\n            lengths.data(), images.data(), (binaryStatus != NULL && numDevices > 0)\n               ? &binaryStatus->front()\n               : NULL, &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    /**\n     * Create program using builtin kernels.\n     * \\param kernelNames Semi-colon separated list of builtin kernel names\n     */\n    Program(\n        const Context& context,\n        const vector<Device>& devices,\n        const string& kernelNames,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n\n        size_type numDevices = devices.size();\n        vector<cl_device_id> deviceIDs(numDevices);\n        for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {\n            deviceIDs[deviceIndex] = (devices[deviceIndex])();\n        }\n\n        object_ = ::clCreateProgramWithBuiltInKernels(\n            context(),\n            (cl_uint) devices.size(),\n            deviceIDs.data(),\n            kernelNames.c_str(),\n            &error);\n\n        detail::errHandler(error, __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    Program() { }\n\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     */\n    explicit Program(const cl_program& program, bool retainObject = false) :\n        detail::Wrapper<cl_type>(program, retainObject) { }\n\n    Program& operator = (const cl_program& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Program(const Program& program) : detail::Wrapper<cl_type>(program) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    Program& operator = (const Program &program)\n    {\n        detail::Wrapper<cl_type>::operator=(program);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Program(Program&& program) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(program)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    Program& operator = (Program &&program)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(program));\n        return *this;\n    }\n\n    cl_int build(\n        const vector<Device>& devices,\n        const char* options = NULL,\n        void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,\n        void* data = NULL) const\n    {\n        size_type numDevices = devices.size();\n        vector<cl_device_id> deviceIDs(numDevices);\n\n        for( size_type deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) {\n            deviceIDs[deviceIndex] = (devices[deviceIndex])();\n        }\n\n        cl_int buildError = ::clBuildProgram(\n            object_,\n            (cl_uint)\n            devices.size(),\n            deviceIDs.data(),\n            options,\n            notifyFptr,\n            data);\n\n        return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());\n    }\n\n    cl_int build(\n        const char* options = NULL,\n        void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,\n        void* data = NULL) const\n    {\n        cl_int buildError = ::clBuildProgram(\n            object_,\n            0,\n            NULL,\n            options,\n            notifyFptr,\n            data);\n\n\n        return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    cl_int compile(\n        const char* options = NULL,\n        void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,\n        void* data = NULL) const\n    {\n        cl_int error = ::clCompileProgram(\n            object_,\n            0,\n            NULL,\n            options,\n            0,\n            NULL,\n            NULL,\n            notifyFptr,\n            data);\n        return detail::buildErrHandler(error, __COMPILE_PROGRAM_ERR, getBuildInfo<CL_PROGRAM_BUILD_LOG>());\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    template <typename T>\n    cl_int getInfo(cl_program_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(&::clGetProgramInfo, object_, name, param),\n            __GET_PROGRAM_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_program_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_program_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    template <typename T>\n    cl_int getBuildInfo(\n        const Device& device, cl_program_build_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(\n                &::clGetProgramBuildInfo, object_, device(), name, param),\n                __GET_PROGRAM_BUILD_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_program_build_info, name>::param_type\n    getBuildInfo(const Device& device, cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_program_build_info, name>::param_type param;\n        cl_int result = getBuildInfo(device, name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /**\n     * Build info function that returns a vector of device/info pairs for the specified\n     * info type and for all devices in the program.\n     * On an error reading the info for any device, an empty vector of info will be returned.\n     */\n    template <cl_int name>\n    vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>>\n        getBuildInfo(cl_int *err = NULL) const\n    {\n        cl_int result = CL_SUCCESS;\n\n        auto devs = getInfo<CL_PROGRAM_DEVICES>(&result);\n        vector<std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>>\n            devInfo;\n\n        // If there was an initial error from getInfo return the error\n        if (result != CL_SUCCESS) {\n            if (err != NULL) {\n                *err = result;\n            }\n            return devInfo;\n        }\n\n        for (cl::Device d : devs) {\n            typename detail::param_traits<\n                detail::cl_program_build_info, name>::param_type param;\n            result = getBuildInfo(d, name, &param);\n            devInfo.push_back(\n                std::pair<cl::Device, typename detail::param_traits<detail::cl_program_build_info, name>::param_type>\n                (d, param));\n            if (result != CL_SUCCESS) {\n                // On error, leave the loop and return the error code\n                break;\n            }\n        }\n        if (err != NULL) {\n            *err = result;\n        }\n        if (result != CL_SUCCESS) {\n            devInfo.clear();\n        }\n        return devInfo;\n    }\n\n    cl_int createKernels(vector<Kernel>* kernels)\n    {\n        cl_uint numKernels;\n        cl_int err = ::clCreateKernelsInProgram(object_, 0, NULL, &numKernels);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR);\n        }\n\n        vector<cl_kernel> value(numKernels);\n\n        err = ::clCreateKernelsInProgram(\n            object_, numKernels, value.data(), NULL);\n        if (err != CL_SUCCESS) {\n            return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR);\n        }\n\n        if (kernels) {\n            kernels->resize(value.size());\n\n            // Assign to param, constructing with retain behaviour\n            // to correctly capture each underlying CL object\n            for (size_type i = 0; i < value.size(); i++) {\n                // We do not need to retain because this kernel is being created\n                // by the runtime\n                (*kernels)[i] = Kernel(value[i], false);\n            }\n        }\n        return CL_SUCCESS;\n    }\n};\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\ninline Program linkProgram(\n    Program input1,\n    Program input2,\n    const char* options = NULL,\n    void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,\n    void* data = NULL,\n    cl_int* err = NULL)\n{\n    cl_int error_local = CL_SUCCESS;\n\n    cl_program programs[2] = { input1(), input2() };\n\n    Context ctx = input1.getInfo<CL_PROGRAM_CONTEXT>(&error_local);\n    if(error_local!=CL_SUCCESS) {\n        detail::errHandler(error_local, __LINK_PROGRAM_ERR);\n    }\n\n    cl_program prog = ::clLinkProgram(\n        ctx(),\n        0,\n        NULL,\n        options,\n        2,\n        programs,\n        notifyFptr,\n        data,\n        &error_local);\n\n    detail::errHandler(error_local,__COMPILE_PROGRAM_ERR);\n    if (err != NULL) {\n        *err = error_local;\n    }\n\n    return Program(prog);\n}\n\ninline Program linkProgram(\n    vector<Program> inputPrograms,\n    const char* options = NULL,\n    void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL,\n    void* data = NULL,\n    cl_int* err = NULL)\n{\n    cl_int error_local = CL_SUCCESS;\n\n    vector<cl_program> programs(inputPrograms.size());\n\n    for (unsigned int i = 0; i < inputPrograms.size(); i++) {\n        programs[i] = inputPrograms[i]();\n    }\n\n    Context ctx;\n    if(inputPrograms.size() > 0) {\n        ctx = inputPrograms[0].getInfo<CL_PROGRAM_CONTEXT>(&error_local);\n        if(error_local!=CL_SUCCESS) {\n            detail::errHandler(error_local, __LINK_PROGRAM_ERR);\n        }\n    }\n    cl_program prog = ::clLinkProgram(\n        ctx(),\n        0,\n        NULL,\n        options,\n        (cl_uint)inputPrograms.size(),\n        programs.data(),\n        notifyFptr,\n        data,\n        &error_local);\n\n    detail::errHandler(error_local,__COMPILE_PROGRAM_ERR);\n    if (err != NULL) {\n        *err = error_local;\n    }\n\n    return Program(prog, false);\n}\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n// Template specialization for CL_PROGRAM_BINARIES\ntemplate <>\ninline cl_int cl::Program::getInfo(cl_program_info name, vector<vector<unsigned char>>* param) const\n{\n    if (name != CL_PROGRAM_BINARIES) {\n        return CL_INVALID_VALUE;\n    }\n    if (param) {\n        // Resize the parameter array appropriately for each allocation\n        // and pass down to the helper\n\n        vector<size_type> sizes = getInfo<CL_PROGRAM_BINARY_SIZES>();\n        size_type numBinaries = sizes.size();\n\n        // Resize the parameter array and constituent arrays\n        param->resize(numBinaries);\n        for (size_type i = 0; i < numBinaries; ++i) {\n            (*param)[i].resize(sizes[i]);\n        }\n\n        return detail::errHandler(\n            detail::getInfo(&::clGetProgramInfo, object_, name, param),\n            __GET_PROGRAM_INFO_ERR);\n    }\n\n    return CL_SUCCESS;\n}\n\ntemplate<>\ninline vector<vector<unsigned char>> cl::Program::getInfo<CL_PROGRAM_BINARIES>(cl_int* err) const\n{\n    vector<vector<unsigned char>> binariesVectors;\n\n    cl_int result = getInfo(CL_PROGRAM_BINARIES, &binariesVectors);\n    if (err != NULL) {\n        *err = result;\n    }\n    return binariesVectors;\n}\n\ninline Kernel::Kernel(const Program& program, const char* name, cl_int* err)\n{\n    cl_int error;\n\n    object_ = ::clCreateKernel(program(), name, &error);\n    detail::errHandler(error, __CREATE_KERNEL_ERR);\n\n    if (err != NULL) {\n        *err = error;\n    }\n\n}\n\nenum class QueueProperties : cl_command_queue_properties\n{\n    None = 0,\n    Profiling = CL_QUEUE_PROFILING_ENABLE,\n    OutOfOrder = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,\n};\n\ninline QueueProperties operator|(QueueProperties lhs, QueueProperties rhs)\n{\n    return static_cast<QueueProperties>(static_cast<cl_command_queue_properties>(lhs) | static_cast<cl_command_queue_properties>(rhs));\n}\n\n/*! \\class CommandQueue\n * \\brief CommandQueue interface for cl_command_queue.\n */\nclass CommandQueue : public detail::Wrapper<cl_command_queue>\n{\nprivate:\n    static std::once_flag default_initialized_;\n    static CommandQueue default_;\n    static cl_int default_error_;\n\n    /*! \\brief Create the default command queue returned by @ref getDefault.\n     *\n     * It sets default_error_ to indicate success or failure. It does not throw\n     * @c cl::Error.\n     */\n    static void makeDefault()\n    {\n        /* We don't want to throw an error from this function, so we have to\n         * catch and set the error flag.\n         */\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        try\n#endif\n        {\n            int error;\n            Context context = Context::getDefault(&error);\n\n            if (error != CL_SUCCESS) {\n                default_error_ = error;\n            }\n            else {\n                Device device = Device::getDefault();\n                default_ = CommandQueue(context, device, 0, &default_error_);\n            }\n        }\n#if defined(CL_HPP_ENABLE_EXCEPTIONS)\n        catch (cl::Error &e) {\n            default_error_ = e.err();\n        }\n#endif\n    }\n\n    /*! \\brief Create the default command queue.\n     *\n     * This sets @c default_. It does not throw\n     * @c cl::Error.\n     */\n    static void makeDefaultProvided(const CommandQueue &c) {\n        default_ = c;\n    }\n\npublic:\n#ifdef CL_HPP_UNIT_TEST_ENABLE\n    /*! \\brief Reset the default.\n    *\n    * This sets @c default_ to an empty value to support cleanup in\n    * the unit test framework.\n    * This function is not thread safe.\n    */\n    static void unitTestClearDefault() {\n        default_ = CommandQueue();\n    }\n#endif // #ifdef CL_HPP_UNIT_TEST_ENABLE\n\n\n    /*!\n     * \\brief Constructs a CommandQueue based on passed properties.\n     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n     */\n   CommandQueue(\n        cl_command_queue_properties properties,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        Context context = Context::getDefault(&error);\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n\n        if (error != CL_SUCCESS) {\n            if (err != NULL) {\n                *err = error;\n            }\n        }\n        else {\n            Device device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n            cl_queue_properties queue_properties[] = {\n                CL_QUEUE_PROPERTIES, properties, 0 };\n            if ((properties & CL_QUEUE_ON_DEVICE) == 0) {\n                object_ = ::clCreateCommandQueueWithProperties(\n                    context(), device(), queue_properties, &error);\n            }\n            else {\n                error = CL_INVALID_QUEUE_PROPERTIES;\n            }\n\n            detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n#else\n            object_ = ::clCreateCommandQueue(\n                context(), device(), properties, &error);\n\n            detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n#endif\n        }\n    }\n\n   /*!\n    * \\brief Constructs a CommandQueue based on passed properties.\n    * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n    */\n   CommandQueue(\n       QueueProperties properties,\n       cl_int* err = NULL)\n   {\n       cl_int error;\n\n       Context context = Context::getDefault(&error);\n       detail::errHandler(error, __CREATE_CONTEXT_ERR);\n\n       if (error != CL_SUCCESS) {\n           if (err != NULL) {\n               *err = error;\n           }\n       }\n       else {\n           Device device = context.getInfo<CL_CONTEXT_DEVICES>()[0];\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n           cl_queue_properties queue_properties[] = {\n               CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };\n\n           object_ = ::clCreateCommandQueueWithProperties(\n               context(), device(), queue_properties, &error);\n\n\n           detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n           if (err != NULL) {\n               *err = error;\n           }\n#else\n           object_ = ::clCreateCommandQueue(\n               context(), device(), static_cast<cl_command_queue_properties>(properties), &error);\n\n           detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n           if (err != NULL) {\n               *err = error;\n           }\n#endif\n       }\n   }\n\n    /*!\n     * \\brief Constructs a CommandQueue for an implementation defined device in the given context\n     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n     */\n    explicit CommandQueue(\n        const Context& context,\n        cl_command_queue_properties properties = 0,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        vector<cl::Device> devices;\n        error = context.getInfo(CL_CONTEXT_DEVICES, &devices);\n\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n\n        if (error != CL_SUCCESS)\n        {\n            if (err != NULL) {\n                *err = error;\n            }\n            return;\n        }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, properties, 0 };\n        if ((properties & CL_QUEUE_ON_DEVICE) == 0) {\n            object_ = ::clCreateCommandQueueWithProperties(\n                context(), devices[0](), queue_properties, &error);\n        }\n        else {\n            error = CL_INVALID_QUEUE_PROPERTIES;\n        }\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#else\n        object_ = ::clCreateCommandQueue(\n            context(), devices[0](), properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#endif\n\n    }\n\n    /*!\n    * \\brief Constructs a CommandQueue for an implementation defined device in the given context\n    * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n    */\n    explicit CommandQueue(\n        const Context& context,\n        QueueProperties properties,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n        vector<cl::Device> devices;\n        error = context.getInfo(CL_CONTEXT_DEVICES, &devices);\n\n        detail::errHandler(error, __CREATE_CONTEXT_ERR);\n\n        if (error != CL_SUCCESS)\n        {\n            if (err != NULL) {\n                *err = error;\n            }\n            return;\n        }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };\n        object_ = ::clCreateCommandQueueWithProperties(\n            context(), devices[0](), queue_properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#else\n        object_ = ::clCreateCommandQueue(\n            context(), devices[0](), static_cast<cl_command_queue_properties>(properties), &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#endif\n\n    }\n\n    /*!\n     * \\brief Constructs a CommandQueue for a passed device and context\n     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n     */\n    CommandQueue(\n        const Context& context,\n        const Device& device,\n        cl_command_queue_properties properties = 0,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, properties, 0 };\n        object_ = ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#else\n        object_ = ::clCreateCommandQueue(\n            context(), device(), properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n#endif\n    }\n\n    /*!\n     * \\brief Constructs a CommandQueue for a passed device and context\n     * Will return an CL_INVALID_QUEUE_PROPERTIES error if CL_QUEUE_ON_DEVICE is specified.\n     */\n    CommandQueue(\n        const Context& context,\n        const Device& device,\n        QueueProperties properties,\n        cl_int* err = NULL)\n    {\n            cl_int error;\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n            cl_queue_properties queue_properties[] = {\n                CL_QUEUE_PROPERTIES, static_cast<cl_queue_properties>(properties), 0 };\n            object_ = ::clCreateCommandQueueWithProperties(\n                context(), device(), queue_properties, &error);\n\n            detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n#else\n            object_ = ::clCreateCommandQueue(\n                context(), device(), static_cast<cl_command_queue_properties>(properties), &error);\n\n            detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR);\n            if (err != NULL) {\n                *err = error;\n            }\n#endif\n        }\n\n    static CommandQueue getDefault(cl_int * err = NULL)\n    {\n        std::call_once(default_initialized_, makeDefault);\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n        detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n#else // CL_HPP_TARGET_OPENCL_VERSION >= 200\n        detail::errHandler(default_error_, __CREATE_COMMAND_QUEUE_ERR);\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 200\n        if (err != NULL) {\n            *err = default_error_;\n        }\n        return default_;\n    }\n\n    /**\n     * Modify the default command queue to be used by\n     * subsequent operations.\n     * Will only set the default if no default was previously created.\n     * @return updated default command queue.\n     *         Should be compared to the passed value to ensure that it was updated.\n     */\n    static CommandQueue setDefault(const CommandQueue &default_queue)\n    {\n        std::call_once(default_initialized_, makeDefaultProvided, std::cref(default_queue));\n        detail::errHandler(default_error_);\n        return default_;\n    }\n\n    CommandQueue() { }\n\n\n    /*! \\brief Constructor from cl_mem - takes ownership.\n     *\n     * \\param retainObject will cause the constructor to retain its cl object.\n     *                     Defaults to false to maintain compatibility with\n     *                     earlier versions.\n     */\n    explicit CommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) :\n        detail::Wrapper<cl_type>(commandQueue, retainObject) { }\n\n    CommandQueue& operator = (const cl_command_queue& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    CommandQueue(const CommandQueue& queue) : detail::Wrapper<cl_type>(queue) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    CommandQueue& operator = (const CommandQueue &queue)\n    {\n        detail::Wrapper<cl_type>::operator=(queue);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    CommandQueue(CommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(queue)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    CommandQueue& operator = (CommandQueue &&queue)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(queue));\n        return *this;\n    }\n\n    template <typename T>\n    cl_int getInfo(cl_command_queue_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(\n                &::clGetCommandQueueInfo, object_, name, param),\n                __GET_COMMAND_QUEUE_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n    detail::param_traits<detail::cl_command_queue_info, name>::param_type\n    getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_command_queue_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    cl_int enqueueReadBuffer(\n        const Buffer& buffer,\n        cl_bool blocking,\n        size_type offset,\n        size_type size,\n        void* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueReadBuffer(\n                object_, buffer(), blocking, offset, size,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_READ_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueWriteBuffer(\n        const Buffer& buffer,\n        cl_bool blocking,\n        size_type offset,\n        size_type size,\n        const void* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueWriteBuffer(\n                object_, buffer(), blocking, offset, size,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_WRITE_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueCopyBuffer(\n        const Buffer& src,\n        const Buffer& dst,\n        size_type src_offset,\n        size_type dst_offset,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueCopyBuffer(\n                object_, src(), dst(), src_offset, dst_offset, size,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQEUE_COPY_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueReadBufferRect(\n        const Buffer& buffer,\n        cl_bool blocking,\n        const array<size_type, 3>& buffer_offset,\n        const array<size_type, 3>& host_offset,\n        const array<size_type, 3>& region,\n        size_type buffer_row_pitch,\n        size_type buffer_slice_pitch,\n        size_type host_row_pitch,\n        size_type host_slice_pitch,\n        void *ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueReadBufferRect(\n                object_,\n                buffer(),\n                blocking,\n                buffer_offset.data(),\n                host_offset.data(),\n                region.data(),\n                buffer_row_pitch,\n                buffer_slice_pitch,\n                host_row_pitch,\n                host_slice_pitch,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_READ_BUFFER_RECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueWriteBufferRect(\n        const Buffer& buffer,\n        cl_bool blocking,\n        const array<size_type, 3>& buffer_offset,\n        const array<size_type, 3>& host_offset,\n        const array<size_type, 3>& region,\n        size_type buffer_row_pitch,\n        size_type buffer_slice_pitch,\n        size_type host_row_pitch,\n        size_type host_slice_pitch,\n        const void *ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueWriteBufferRect(\n                object_,\n                buffer(),\n                blocking,\n                buffer_offset.data(),\n                host_offset.data(),\n                region.data(),\n                buffer_row_pitch,\n                buffer_slice_pitch,\n                host_row_pitch,\n                host_slice_pitch,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_WRITE_BUFFER_RECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueCopyBufferRect(\n        const Buffer& src,\n        const Buffer& dst,\n        const array<size_type, 3>& src_origin,\n        const array<size_type, 3>& dst_origin,\n        const array<size_type, 3>& region,\n        size_type src_row_pitch,\n        size_type src_slice_pitch,\n        size_type dst_row_pitch,\n        size_type dst_slice_pitch,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueCopyBufferRect(\n                object_,\n                src(),\n                dst(),\n                src_origin.data(),\n                dst_origin.data(),\n                region.data(),\n                src_row_pitch,\n                src_slice_pitch,\n                dst_row_pitch,\n                dst_slice_pitch,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQEUE_COPY_BUFFER_RECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    /**\n     * Enqueue a command to fill a buffer object with a pattern\n     * of a given size. The pattern is specified as a vector type.\n     * \\tparam PatternType The datatype of the pattern field.\n     *     The pattern type must be an accepted OpenCL data type.\n     * \\tparam offset Is the offset in bytes into the buffer at\n     *     which to start filling. This must be a multiple of\n     *     the pattern size.\n     * \\tparam size Is the size in bytes of the region to fill.\n     *     This must be a multiple of the pattern size.\n     */\n    template<typename PatternType>\n    cl_int enqueueFillBuffer(\n        const Buffer& buffer,\n        PatternType pattern,\n        size_type offset,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueFillBuffer(\n                object_,\n                buffer(),\n                static_cast<void*>(&pattern),\n                sizeof(PatternType),\n                offset,\n                size,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_FILL_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    cl_int enqueueReadImage(\n        const Image& image,\n        cl_bool blocking,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        size_type row_pitch,\n        size_type slice_pitch,\n        void* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueReadImage(\n                object_,\n                image(),\n                blocking,\n                origin.data(),\n                region.data(),\n                row_pitch,\n                slice_pitch,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_READ_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueWriteImage(\n        const Image& image,\n        cl_bool blocking,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        size_type row_pitch,\n        size_type slice_pitch,\n        const void* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueWriteImage(\n                object_,\n                image(),\n                blocking,\n                origin.data(),\n                region.data(),\n                row_pitch,\n                slice_pitch,\n                ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_WRITE_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueCopyImage(\n        const Image& src,\n        const Image& dst,\n        const array<size_type, 3>& src_origin,\n        const array<size_type, 3>& dst_origin,\n        const array<size_type, 3>& region,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueCopyImage(\n                object_,\n                src(),\n                dst(),\n                src_origin.data(),\n                dst_origin.data(),\n                region.data(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_COPY_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    /**\n     * Enqueue a command to fill an image object with a specified color.\n     * \\param fillColor is the color to use to fill the image.\n     *     This is a four component RGBA floating-point color value if\n     *     the image channel data type is not an unnormalized signed or\n     *     unsigned data type.\n     */\n    cl_int enqueueFillImage(\n        const Image& image,\n        cl_float4 fillColor,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueFillImage(\n                object_,\n                image(),\n                static_cast<void*>(&fillColor),\n                origin.data(),\n                region.data(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_FILL_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueue a command to fill an image object with a specified color.\n     * \\param fillColor is the color to use to fill the image.\n     *     This is a four component RGBA signed integer color value if\n     *     the image channel data type is an unnormalized signed integer\n     *     type.\n     */\n    cl_int enqueueFillImage(\n        const Image& image,\n        cl_int4 fillColor,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueFillImage(\n                object_,\n                image(),\n                static_cast<void*>(&fillColor),\n                origin.data(),\n                region.data(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_FILL_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueue a command to fill an image object with a specified color.\n     * \\param fillColor is the color to use to fill the image.\n     *     This is a four component RGBA unsigned integer color value if\n     *     the image channel data type is an unnormalized unsigned integer\n     *     type.\n     */\n    cl_int enqueueFillImage(\n        const Image& image,\n        cl_uint4 fillColor,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueFillImage(\n                object_,\n                image(),\n                static_cast<void*>(&fillColor),\n                origin.data(),\n                region.data(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n                __ENQUEUE_FILL_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    cl_int enqueueCopyImageToBuffer(\n        const Image& src,\n        const Buffer& dst,\n        const array<size_type, 3>& src_origin,\n        const array<size_type, 3>& region,\n        size_type dst_offset,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueCopyImageToBuffer(\n                object_,\n                src(),\n                dst(),\n                src_origin.data(),\n                region.data(),\n                dst_offset,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    cl_int enqueueCopyBufferToImage(\n        const Buffer& src,\n        const Image& dst,\n        size_type src_offset,\n        const array<size_type, 3>& dst_origin,\n        const array<size_type, 3>& region,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueCopyBufferToImage(\n                object_,\n                src(),\n                dst(),\n                src_offset,\n                dst_origin.data(),\n                region.data(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    void* enqueueMapBuffer(\n        const Buffer& buffer,\n        cl_bool blocking,\n        cl_map_flags flags,\n        size_type offset,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL,\n        cl_int* err = NULL) const\n    {\n        cl_event tmp;\n        cl_int error;\n        void * result = ::clEnqueueMapBuffer(\n            object_, buffer(), blocking, flags, offset, size,\n            (events != NULL) ? (cl_uint) events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n            (event != NULL) ? &tmp : NULL,\n            &error);\n\n        detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n        if (event != NULL && error == CL_SUCCESS)\n            *event = tmp;\n\n        return result;\n    }\n\n    void* enqueueMapImage(\n        const Image& buffer,\n        cl_bool blocking,\n        cl_map_flags flags,\n        const array<size_type, 3>& origin,\n        const array<size_type, 3>& region,\n        size_type * row_pitch,\n        size_type * slice_pitch,\n        const vector<Event>* events = NULL,\n        Event* event = NULL,\n        cl_int* err = NULL) const\n    {\n        cl_event tmp;\n        cl_int error;\n        void * result = ::clEnqueueMapImage(\n            object_, buffer(), blocking, flags,\n            origin.data(),\n            region.data(),\n            row_pitch, slice_pitch,\n            (events != NULL) ? (cl_uint) events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n            (event != NULL) ? &tmp : NULL,\n            &error);\n\n        detail::errHandler(error, __ENQUEUE_MAP_IMAGE_ERR);\n        if (err != NULL) {\n              *err = error;\n        }\n        if (event != NULL && error == CL_SUCCESS)\n            *event = tmp;\n        return result;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /**\n     * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.\n     * This variant takes a raw SVM pointer.\n     */\n    template<typename T>\n    cl_int enqueueMapSVM(\n        T* ptr,\n        cl_bool blocking,\n        cl_map_flags flags,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(::clEnqueueSVMMap(\n            object_, blocking, flags, static_cast<void*>(ptr), size,\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_MAP_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n\n    /**\n     * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.\n     * This variant takes a cl::pointer instance.\n     */\n    template<typename T, class D>\n    cl_int enqueueMapSVM(\n        cl::pointer<T, D> &ptr,\n        cl_bool blocking,\n        cl_map_flags flags,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(::clEnqueueSVMMap(\n            object_, blocking, flags, static_cast<void*>(ptr.get()), size,\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_MAP_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueues a command that will allow the host to update a region of a coarse-grained SVM buffer.\n     * This variant takes a cl::vector instance.\n     */\n    template<typename T, class Alloc>\n    cl_int enqueueMapSVM(\n        cl::vector<T, Alloc> &container,\n        cl_bool blocking,\n        cl_map_flags flags,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(::clEnqueueSVMMap(\n            object_, blocking, flags, static_cast<void*>(container.data()), container.size(),\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_MAP_BUFFER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n    cl_int enqueueUnmapMemObject(\n        const Memory& memory,\n        void* mapped_ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueUnmapMemObject(\n                object_, memory(), mapped_ptr,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    /**\n     * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.\n     * This variant takes a raw SVM pointer.\n     */\n    template<typename T>\n    cl_int enqueueUnmapSVM(\n        T* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueSVMUnmap(\n            object_, static_cast<void*>(ptr),\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.\n     * This variant takes a cl::pointer instance.\n     */\n    template<typename T, class D>\n    cl_int enqueueUnmapSVM(\n        cl::pointer<T, D> &ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueSVMUnmap(\n            object_, static_cast<void*>(ptr.get()),\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueues a command that will release a coarse-grained SVM buffer back to the OpenCL runtime.\n     * This variant takes a cl::vector instance.\n     */\n    template<typename T, class Alloc>\n    cl_int enqueueUnmapSVM(\n        cl::vector<T, Alloc> &container,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueSVMUnmap(\n            object_, static_cast<void*>(container.data()),\n            (events != NULL) ? (cl_uint)events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n            (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n    /**\n     * Enqueues a marker command which waits for either a list of events to complete,\n     * or all previously enqueued commands to complete.\n     *\n     * Enqueues a marker command which waits for either a list of events to complete,\n     * or if the list is empty it waits for all commands previously enqueued in command_queue\n     * to complete before it completes. This command returns an event which can be waited on,\n     * i.e. this event can be waited on to insure that all events either in the event_wait_list\n     * or all previously enqueued commands, queued before this command to command_queue,\n     * have completed.\n     */\n    cl_int enqueueMarkerWithWaitList(\n        const vector<Event> *events = 0,\n        Event *event = 0)\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueMarkerWithWaitList(\n                object_,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_MARKER_WAIT_LIST_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * A synchronization point that enqueues a barrier operation.\n     *\n     * Enqueues a barrier command which waits for either a list of events to complete,\n     * or if the list is empty it waits for all commands previously enqueued in command_queue\n     * to complete before it completes. This command blocks command execution, that is, any\n     * following commands enqueued after it do not execute until it completes. This command\n     * returns an event which can be waited on, i.e. this event can be waited on to insure that\n     * all events either in the event_wait_list or all previously enqueued commands, queued\n     * before this command to command_queue, have completed.\n     */\n    cl_int enqueueBarrierWithWaitList(\n        const vector<Event> *events = 0,\n        Event *event = 0)\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueBarrierWithWaitList(\n                object_,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_BARRIER_WAIT_LIST_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    /**\n     * Enqueues a command to indicate with which device a set of memory objects\n     * should be associated.\n     */\n    cl_int enqueueMigrateMemObjects(\n        const vector<Memory> &memObjects,\n        cl_mem_migration_flags flags,\n        const vector<Event>* events = NULL,\n        Event* event = NULL\n        )\n    {\n        cl_event tmp;\n\n        vector<cl_mem> localMemObjects(memObjects.size());\n\n        for( int i = 0; i < (int)memObjects.size(); ++i ) {\n            localMemObjects[i] = memObjects[i]();\n        }\n\n\n        cl_int err = detail::errHandler(\n            ::clEnqueueMigrateMemObjects(\n                object_,\n                (cl_uint)memObjects.size(),\n                localMemObjects.data(),\n                flags,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n\n    cl_int enqueueNDRangeKernel(\n        const Kernel& kernel,\n        const NDRange& offset,\n        const NDRange& global,\n        const NDRange& local = NullRange,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueNDRangeKernel(\n                object_, kernel(), (cl_uint) global.dimensions(),\n                offset.dimensions() != 0 ? (const size_type*) offset : NULL,\n                (const size_type*) global,\n                local.dimensions() != 0 ? (const size_type*) local : NULL,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_NDRANGE_KERNEL_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n#if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)\n    CL_EXT_PREFIX__VERSION_1_2_DEPRECATED cl_int enqueueTask(\n        const Kernel& kernel,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueTask(\n                object_, kernel(),\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_TASK_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)\n\n    cl_int enqueueNativeKernel(\n        void (CL_CALLBACK *userFptr)(void *),\n        std::pair<void*, size_type> args,\n        const vector<Memory>* mem_objects = NULL,\n        const vector<const void*>* mem_locs = NULL,\n        const vector<Event>* events = NULL,\n        Event* event = NULL) const\n    {\n        size_type elements = 0;\n        if (mem_objects != NULL) {\n            elements = mem_objects->size();\n        }\n        vector<cl_mem> mems(elements);\n        for (unsigned int i = 0; i < elements; i++) {\n            mems[i] = ((*mem_objects)[i])();\n        }\n\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueNativeKernel(\n                object_, userFptr, args.first, args.second,\n                (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,\n                mems.data(),\n                (mem_locs != NULL && mem_locs->size() > 0) ? (const void **) &mem_locs->front() : NULL,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_NATIVE_KERNEL);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n/**\n * Deprecated APIs for 1.2\n */\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n    CL_EXT_PREFIX__VERSION_1_1_DEPRECATED\n    cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED\n    {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            ::clEnqueueMarker(\n                object_,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_MARKER_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n\n    CL_EXT_PREFIX__VERSION_1_1_DEPRECATED\n    cl_int enqueueWaitForEvents(const vector<Event>& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED\n    {\n        return detail::errHandler(\n            ::clEnqueueWaitForEvents(\n                object_,\n                (cl_uint) events.size(),\n                events.size() > 0 ? (const cl_event*) &events.front() : NULL),\n            __ENQUEUE_WAIT_FOR_EVENTS_ERR);\n    }\n#endif // defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n\n    cl_int enqueueAcquireGLObjects(\n         const vector<Memory>* mem_objects = NULL,\n         const vector<Event>* events = NULL,\n         Event* event = NULL) const\n     {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n             ::clEnqueueAcquireGLObjects(\n                 object_,\n                 (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,\n                 (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,\n                 (events != NULL) ? (cl_uint) events->size() : 0,\n                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                 (event != NULL) ? &tmp : NULL),\n             __ENQUEUE_ACQUIRE_GL_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n     }\n\n    cl_int enqueueReleaseGLObjects(\n         const vector<Memory>* mem_objects = NULL,\n         const vector<Event>* events = NULL,\n         Event* event = NULL) const\n     {\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n             ::clEnqueueReleaseGLObjects(\n                 object_,\n                 (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,\n                 (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,\n                 (events != NULL) ? (cl_uint) events->size() : 0,\n                 (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                 (event != NULL) ? &tmp : NULL),\n             __ENQUEUE_RELEASE_GL_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n     }\n\n#if defined (CL_HPP_USE_DX_INTEROP)\ntypedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueAcquireD3D10ObjectsKHR)(\n    cl_command_queue command_queue, cl_uint num_objects,\n    const cl_mem* mem_objects, cl_uint num_events_in_wait_list,\n    const cl_event* event_wait_list, cl_event* event);\ntypedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)(\n    cl_command_queue command_queue, cl_uint num_objects,\n    const cl_mem* mem_objects,  cl_uint num_events_in_wait_list,\n    const cl_event* event_wait_list, cl_event* event);\n\n    cl_int enqueueAcquireD3D10Objects(\n         const vector<Memory>* mem_objects = NULL,\n         const vector<Event>* events = NULL,\n         Event* event = NULL) const\n    {\n        static PFN_clEnqueueAcquireD3D10ObjectsKHR pfn_clEnqueueAcquireD3D10ObjectsKHR = NULL;\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n        cl_context context = getInfo<CL_QUEUE_CONTEXT>();\n        cl::Device device(getInfo<CL_QUEUE_DEVICE>());\n        cl_platform_id platform = device.getInfo<CL_DEVICE_PLATFORM>();\n        CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueAcquireD3D10ObjectsKHR);\n#endif\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n        CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueAcquireD3D10ObjectsKHR);\n#endif\n\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n             pfn_clEnqueueAcquireD3D10ObjectsKHR(\n                 object_,\n                 (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,\n                 (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,\n                 (events != NULL) ? (cl_uint) events->size() : 0,\n                 (events != NULL) ? (cl_event*) &events->front() : NULL,\n                 (event != NULL) ? &tmp : NULL),\n             __ENQUEUE_ACQUIRE_GL_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n     }\n\n    cl_int enqueueReleaseD3D10Objects(\n         const vector<Memory>* mem_objects = NULL,\n         const vector<Event>* events = NULL,\n         Event* event = NULL) const\n    {\n        static PFN_clEnqueueReleaseD3D10ObjectsKHR pfn_clEnqueueReleaseD3D10ObjectsKHR = NULL;\n#if CL_HPP_TARGET_OPENCL_VERSION >= 120\n        cl_context context = getInfo<CL_QUEUE_CONTEXT>();\n        cl::Device device(getInfo<CL_QUEUE_DEVICE>());\n        cl_platform_id platform = device.getInfo<CL_DEVICE_PLATFORM>();\n        CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_(platform, clEnqueueReleaseD3D10ObjectsKHR);\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 120\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\n        CL_HPP_INIT_CL_EXT_FCN_PTR_(clEnqueueReleaseD3D10ObjectsKHR);\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\n        cl_event tmp;\n        cl_int err = detail::errHandler(\n            pfn_clEnqueueReleaseD3D10ObjectsKHR(\n                object_,\n                (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0,\n                (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL,\n                (events != NULL) ? (cl_uint) events->size() : 0,\n                (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n                (event != NULL) ? &tmp : NULL),\n            __ENQUEUE_RELEASE_GL_ERR);\n\n        if (event != NULL && err == CL_SUCCESS)\n            *event = tmp;\n\n        return err;\n    }\n#endif\n\n/**\n * Deprecated APIs for 1.2\n */\n#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)\n    CL_EXT_PREFIX__VERSION_1_1_DEPRECATED\n    cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED\n    {\n        return detail::errHandler(\n            ::clEnqueueBarrier(object_),\n            __ENQUEUE_BARRIER_ERR);\n    }\n#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS\n\n    cl_int flush() const\n    {\n        return detail::errHandler(::clFlush(object_), __FLUSH_ERR);\n    }\n\n    cl_int finish() const\n    {\n        return detail::errHandler(::clFinish(object_), __FINISH_ERR);\n    }\n}; // CommandQueue\n\nCL_HPP_DEFINE_STATIC_MEMBER_ std::once_flag CommandQueue::default_initialized_;\nCL_HPP_DEFINE_STATIC_MEMBER_ CommandQueue CommandQueue::default_;\nCL_HPP_DEFINE_STATIC_MEMBER_ cl_int CommandQueue::default_error_ = CL_SUCCESS;\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\nenum class DeviceQueueProperties : cl_command_queue_properties\n{\n    None = 0,\n    Profiling = CL_QUEUE_PROFILING_ENABLE,\n};\n\ninline DeviceQueueProperties operator|(DeviceQueueProperties lhs, DeviceQueueProperties rhs)\n{\n    return static_cast<DeviceQueueProperties>(static_cast<cl_command_queue_properties>(lhs) | static_cast<cl_command_queue_properties>(rhs));\n}\n\n/*! \\class DeviceCommandQueue\n * \\brief DeviceCommandQueue interface for device cl_command_queues.\n */\nclass DeviceCommandQueue : public detail::Wrapper<cl_command_queue>\n{\npublic:\n\n    /*!\n     * Trivial empty constructor to create a null queue.\n     */\n    DeviceCommandQueue() { }\n\n    /*!\n     * Default construct device command queue on default context and device\n     */\n    DeviceCommandQueue(DeviceQueueProperties properties, cl_int* err = NULL)\n    {\n        cl_int error;\n        cl::Context context = cl::Context::getDefault();\n        cl::Device device = cl::Device::getDefault();\n\n        cl_command_queue_properties mergedProperties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);\n\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, mergedProperties, 0 };\n        object_ = ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*!\n     * Create a device command queue for a specified device in the passed context.\n     */\n    DeviceCommandQueue(\n        const Context& context,\n        const Device& device,\n        DeviceQueueProperties properties = DeviceQueueProperties::None,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        cl_command_queue_properties mergedProperties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, mergedProperties, 0 };\n        object_ = ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*!\n     * Create a device command queue for a specified device in the passed context.\n     */\n    DeviceCommandQueue(\n        const Context& context,\n        const Device& device,\n        cl_uint queueSize,\n        DeviceQueueProperties properties = DeviceQueueProperties::None,\n        cl_int* err = NULL)\n    {\n        cl_int error;\n\n        cl_command_queue_properties mergedProperties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | static_cast<cl_command_queue_properties>(properties);\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, mergedProperties,\n            CL_QUEUE_SIZE, queueSize,\n            0 };\n        object_ = ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error);\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n\n    /*! \\brief Constructor from cl_command_queue - takes ownership.\n    *\n    * \\param retainObject will cause the constructor to retain its cl object.\n    *                     Defaults to false to maintain compatibility with\n    *                     earlier versions.\n    */\n    explicit DeviceCommandQueue(const cl_command_queue& commandQueue, bool retainObject = false) :\n        detail::Wrapper<cl_type>(commandQueue, retainObject) { }\n\n    DeviceCommandQueue& operator = (const cl_command_queue& rhs)\n    {\n        detail::Wrapper<cl_type>::operator=(rhs);\n        return *this;\n    }\n\n    /*! \\brief Copy constructor to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    DeviceCommandQueue(const DeviceCommandQueue& queue) : detail::Wrapper<cl_type>(queue) {}\n\n    /*! \\brief Copy assignment to forward copy to the superclass correctly.\n     * Required for MSVC.\n     */\n    DeviceCommandQueue& operator = (const DeviceCommandQueue &queue)\n    {\n        detail::Wrapper<cl_type>::operator=(queue);\n        return *this;\n    }\n\n    /*! \\brief Move constructor to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    DeviceCommandQueue(DeviceCommandQueue&& queue) CL_HPP_NOEXCEPT_ : detail::Wrapper<cl_type>(std::move(queue)) {}\n\n    /*! \\brief Move assignment to forward move to the superclass correctly.\n     * Required for MSVC.\n     */\n    DeviceCommandQueue& operator = (DeviceCommandQueue &&queue)\n    {\n        detail::Wrapper<cl_type>::operator=(std::move(queue));\n        return *this;\n    }\n\n    template <typename T>\n    cl_int getInfo(cl_command_queue_info name, T* param) const\n    {\n        return detail::errHandler(\n            detail::getInfo(\n            &::clGetCommandQueueInfo, object_, name, param),\n            __GET_COMMAND_QUEUE_INFO_ERR);\n    }\n\n    template <cl_int name> typename\n        detail::param_traits<detail::cl_command_queue_info, name>::param_type\n        getInfo(cl_int* err = NULL) const\n    {\n        typename detail::param_traits<\n            detail::cl_command_queue_info, name>::param_type param;\n        cl_int result = getInfo(name, &param);\n        if (err != NULL) {\n            *err = result;\n        }\n        return param;\n    }\n\n    /*!\n    * Create a new default device command queue for the default device,\n    * in the default context and of the default size.\n    * If there is already a default queue for the specified device this\n    * function will return the pre-existing queue.\n    */\n    static DeviceCommandQueue makeDefault(\n        cl_int *err = nullptr)\n    {\n        cl_int error;\n        cl::Context context = cl::Context::getDefault();\n        cl::Device device = cl::Device::getDefault();\n\n        cl_command_queue_properties properties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, properties,\n            0 };\n        DeviceCommandQueue deviceQueue(\n            ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error));\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        return deviceQueue;\n    }\n\n    /*!\n    * Create a new default device command queue for the specified device\n    * and of the default size.\n    * If there is already a default queue for the specified device this\n    * function will return the pre-existing queue.\n    */\n    static DeviceCommandQueue makeDefault(\n        const Context &context, const Device &device, cl_int *err = nullptr)\n    {\n        cl_int error;\n\n        cl_command_queue_properties properties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, properties,\n            0 };\n        DeviceCommandQueue deviceQueue(\n            ::clCreateCommandQueueWithProperties(\n            context(), device(), queue_properties, &error));\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        return deviceQueue;\n    }\n\n    /*!\n     * Create a new default device command queue for the specified device\n     * and of the requested size in bytes.\n     * If there is already a default queue for the specified device this\n     * function will return the pre-existing queue.\n     */\n    static DeviceCommandQueue makeDefault(\n        const Context &context, const Device &device, cl_uint queueSize, cl_int *err = nullptr)\n    {\n        cl_int error;\n\n        cl_command_queue_properties properties =\n            CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT;\n        cl_queue_properties queue_properties[] = {\n            CL_QUEUE_PROPERTIES, properties,\n            CL_QUEUE_SIZE, queueSize,\n            0 };\n        DeviceCommandQueue deviceQueue(\n            ::clCreateCommandQueueWithProperties(\n                context(), device(), queue_properties, &error));\n\n        detail::errHandler(error, __CREATE_COMMAND_QUEUE_WITH_PROPERTIES_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        return deviceQueue;\n    }\n}; // DeviceCommandQueue\n\nnamespace detail\n{\n    // Specialization for device command queue\n    template <>\n    struct KernelArgumentHandler<cl::DeviceCommandQueue, void>\n    {\n        static size_type size(const cl::DeviceCommandQueue&) { return sizeof(cl_command_queue); }\n        static const cl_command_queue* ptr(const cl::DeviceCommandQueue& value) { return &(value()); }\n    };\n} // namespace detail\n\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n\ntemplate< typename IteratorType >\nBuffer::Buffer(\n    const Context &context,\n    IteratorType startIterator,\n    IteratorType endIterator,\n    bool readOnly,\n    bool useHostPtr,\n    cl_int* err)\n{\n    typedef typename std::iterator_traits<IteratorType>::value_type DataType;\n    cl_int error;\n\n    cl_mem_flags flags = 0;\n    if( readOnly ) {\n        flags |= CL_MEM_READ_ONLY;\n    }\n    else {\n        flags |= CL_MEM_READ_WRITE;\n    }\n    if( useHostPtr ) {\n        flags |= CL_MEM_USE_HOST_PTR;\n    }\n\n    size_type size = sizeof(DataType)*(endIterator - startIterator);\n\n    if( useHostPtr ) {\n        object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);\n    } else {\n        object_ = ::clCreateBuffer(context(), flags, size, 0, &error);\n    }\n\n    detail::errHandler(error, __CREATE_BUFFER_ERR);\n    if (err != NULL) {\n        *err = error;\n    }\n\n    if( !useHostPtr ) {\n        CommandQueue queue(context, 0, &error);\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n\n        error = cl::copy(queue, startIterator, endIterator, *this);\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n}\n\ntemplate< typename IteratorType >\nBuffer::Buffer(\n    const CommandQueue &queue,\n    IteratorType startIterator,\n    IteratorType endIterator,\n    bool readOnly,\n    bool useHostPtr,\n    cl_int* err)\n{\n    typedef typename std::iterator_traits<IteratorType>::value_type DataType;\n    cl_int error;\n\n    cl_mem_flags flags = 0;\n    if (readOnly) {\n        flags |= CL_MEM_READ_ONLY;\n    }\n    else {\n        flags |= CL_MEM_READ_WRITE;\n    }\n    if (useHostPtr) {\n        flags |= CL_MEM_USE_HOST_PTR;\n    }\n\n    size_type size = sizeof(DataType)*(endIterator - startIterator);\n\n    Context context = queue.getInfo<CL_QUEUE_CONTEXT>();\n\n    if (useHostPtr) {\n        object_ = ::clCreateBuffer(context(), flags, size, static_cast<DataType*>(&*startIterator), &error);\n    }\n    else {\n        object_ = ::clCreateBuffer(context(), flags, size, 0, &error);\n    }\n\n    detail::errHandler(error, __CREATE_BUFFER_ERR);\n    if (err != NULL) {\n        *err = error;\n    }\n\n    if (!useHostPtr) {\n        error = cl::copy(queue, startIterator, endIterator, *this);\n        detail::errHandler(error, __CREATE_BUFFER_ERR);\n        if (err != NULL) {\n            *err = error;\n        }\n    }\n}\n\ninline cl_int enqueueReadBuffer(\n    const Buffer& buffer,\n    cl_bool blocking,\n    size_type offset,\n    size_type size,\n    void* ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueReadBuffer(buffer, blocking, offset, size, ptr, events, event);\n}\n\ninline cl_int enqueueWriteBuffer(\n        const Buffer& buffer,\n        cl_bool blocking,\n        size_type offset,\n        size_type size,\n        const void* ptr,\n        const vector<Event>* events = NULL,\n        Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueWriteBuffer(buffer, blocking, offset, size, ptr, events, event);\n}\n\ninline void* enqueueMapBuffer(\n        const Buffer& buffer,\n        cl_bool blocking,\n        cl_map_flags flags,\n        size_type offset,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL,\n        cl_int* err = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    if (err != NULL) {\n        *err = error;\n    }\n\n    void * result = ::clEnqueueMapBuffer(\n            queue(), buffer(), blocking, flags, offset, size,\n            (events != NULL) ? (cl_uint) events->size() : 0,\n            (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,\n            (cl_event*) event,\n            &error);\n\n    detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    if (err != NULL) {\n        *err = error;\n    }\n    return result;\n}\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n/**\n * Enqueues to the default queue a command that will allow the host to\n * update a region of a coarse-grained SVM buffer.\n * This variant takes a raw SVM pointer.\n */\ntemplate<typename T>\ninline cl_int enqueueMapSVM(\n    T* ptr,\n    cl_bool blocking,\n    cl_map_flags flags,\n    size_type size,\n    const vector<Event>* events,\n    Event* event)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    }\n\n    return queue.enqueueMapSVM(\n        ptr, blocking, flags, size, events, event);\n}\n\n/**\n * Enqueues to the default queue a command that will allow the host to\n * update a region of a coarse-grained SVM buffer.\n * This variant takes a cl::pointer instance.\n */\ntemplate<typename T, class D>\ninline cl_int enqueueMapSVM(\n    cl::pointer<T, D> ptr,\n    cl_bool blocking,\n    cl_map_flags flags,\n    size_type size,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    }\n\n    return queue.enqueueMapSVM(\n        ptr, blocking, flags, size, events, event);\n}\n\n/**\n * Enqueues to the default queue a command that will allow the host to\n * update a region of a coarse-grained SVM buffer.\n * This variant takes a cl::vector instance.\n */\ntemplate<typename T, class Alloc>\ninline cl_int enqueueMapSVM(\n    cl::vector<T, Alloc> container,\n    cl_bool blocking,\n    cl_map_flags flags,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    }\n\n    return queue.enqueueMapSVM(\n        container, blocking, flags, events, event);\n}\n\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\ninline cl_int enqueueUnmapMemObject(\n    const Memory& memory,\n    void* mapped_ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR);\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    cl_event tmp;\n    cl_int err = detail::errHandler(\n        ::clEnqueueUnmapMemObject(\n        queue(), memory(), mapped_ptr,\n        (events != NULL) ? (cl_uint)events->size() : 0,\n        (events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,\n        (event != NULL) ? &tmp : NULL),\n        __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n    if (event != NULL && err == CL_SUCCESS)\n        *event = tmp;\n\n    return err;\n}\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n/**\n * Enqueues to the default queue a command that will release a coarse-grained\n * SVM buffer back to the OpenCL runtime.\n * This variant takes a raw SVM pointer.\n */\ntemplate<typename T>\ninline cl_int enqueueUnmapSVM(\n    T* ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n    }\n\n    return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event),\n        __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n\n}\n\n/**\n * Enqueues to the default queue a command that will release a coarse-grained\n * SVM buffer back to the OpenCL runtime.\n * This variant takes a cl::pointer instance.\n */\ntemplate<typename T, class D>\ninline cl_int enqueueUnmapSVM(\n    cl::pointer<T, D> &ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n    }\n\n    return detail::errHandler(queue.enqueueUnmapSVM(ptr, events, event),\n        __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n}\n\n/**\n * Enqueues to the default queue a command that will release a coarse-grained\n * SVM buffer back to the OpenCL runtime.\n * This variant takes a cl::vector instance.\n */\ntemplate<typename T, class Alloc>\ninline cl_int enqueueUnmapSVM(\n    cl::vector<T, Alloc> &container,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS) {\n        return detail::errHandler(error, __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n    }\n\n    return detail::errHandler(queue.enqueueUnmapSVM(container, events, event),\n        __ENQUEUE_UNMAP_MEM_OBJECT_ERR);\n}\n\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\ninline cl_int enqueueCopyBuffer(\n        const Buffer& src,\n        const Buffer& dst,\n        size_type src_offset,\n        size_type dst_offset,\n        size_type size,\n        const vector<Event>* events = NULL,\n        Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueCopyBuffer(src, dst, src_offset, dst_offset, size, events, event);\n}\n\n/**\n * Blocking copy operation between iterators and a buffer.\n * Host to Device.\n * Uses default command queue.\n */\ntemplate< typename IteratorType >\ninline cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer )\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS)\n        return error;\n\n    return cl::copy(queue, startIterator, endIterator, buffer);\n}\n\n/**\n * Blocking copy operation between iterators and a buffer.\n * Device to Host.\n * Uses default command queue.\n */\ntemplate< typename IteratorType >\ninline cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator )\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n    if (error != CL_SUCCESS)\n        return error;\n\n    return cl::copy(queue, buffer, startIterator, endIterator);\n}\n\n/**\n * Blocking copy operation between iterators and a buffer.\n * Host to Device.\n * Uses specified queue.\n */\ntemplate< typename IteratorType >\ninline cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer )\n{\n    typedef typename std::iterator_traits<IteratorType>::value_type DataType;\n    cl_int error;\n\n    size_type length = endIterator-startIterator;\n    size_type byteLength = length*sizeof(DataType);\n\n    DataType *pointer =\n        static_cast<DataType*>(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_WRITE, 0, byteLength, 0, 0, &error));\n    // if exceptions enabled, enqueueMapBuffer will throw\n    if( error != CL_SUCCESS ) {\n        return error;\n    }\n#if defined(_MSC_VER)\n    std::copy(\n        startIterator,\n        endIterator,\n        stdext::checked_array_iterator<DataType*>(\n            pointer, length));\n#else\n    std::copy(startIterator, endIterator, pointer);\n#endif\n    Event endEvent;\n    error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent);\n    // if exceptions enabled, enqueueUnmapMemObject will throw\n    if( error != CL_SUCCESS ) {\n        return error;\n    }\n    endEvent.wait();\n    return CL_SUCCESS;\n}\n\n/**\n * Blocking copy operation between iterators and a buffer.\n * Device to Host.\n * Uses specified queue.\n */\ntemplate< typename IteratorType >\ninline cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator )\n{\n    typedef typename std::iterator_traits<IteratorType>::value_type DataType;\n    cl_int error;\n\n    size_type length = endIterator-startIterator;\n    size_type byteLength = length*sizeof(DataType);\n\n    DataType *pointer =\n        static_cast<DataType*>(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, byteLength, 0, 0, &error));\n    // if exceptions enabled, enqueueMapBuffer will throw\n    if( error != CL_SUCCESS ) {\n        return error;\n    }\n    std::copy(pointer, pointer + length, startIterator);\n    Event endEvent;\n    error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent);\n    // if exceptions enabled, enqueueUnmapMemObject will throw\n    if( error != CL_SUCCESS ) {\n        return error;\n    }\n    endEvent.wait();\n    return CL_SUCCESS;\n}\n\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n/**\n * Blocking SVM map operation - performs a blocking map underneath.\n */\ntemplate<typename T, class Alloc>\ninline cl_int mapSVM(cl::vector<T, Alloc> &container)\n{\n    return enqueueMapSVM(container, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE);\n}\n\n/**\n* Blocking SVM map operation - performs a blocking map underneath.\n*/\ntemplate<typename T, class Alloc>\ninline cl_int unmapSVM(cl::vector<T, Alloc> &container)\n{\n    return enqueueUnmapSVM(container);\n}\n\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 110\ninline cl_int enqueueReadBufferRect(\n    const Buffer& buffer,\n    cl_bool blocking,\n    const array<size_type, 3>& buffer_offset,\n    const array<size_type, 3>& host_offset,\n    const array<size_type, 3>& region,\n    size_type buffer_row_pitch,\n    size_type buffer_slice_pitch,\n    size_type host_row_pitch,\n    size_type host_slice_pitch,\n    void *ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueReadBufferRect(\n        buffer,\n        blocking,\n        buffer_offset,\n        host_offset,\n        region,\n        buffer_row_pitch,\n        buffer_slice_pitch,\n        host_row_pitch,\n        host_slice_pitch,\n        ptr,\n        events,\n        event);\n}\n\ninline cl_int enqueueWriteBufferRect(\n    const Buffer& buffer,\n    cl_bool blocking,\n    const array<size_type, 3>& buffer_offset,\n    const array<size_type, 3>& host_offset,\n    const array<size_type, 3>& region,\n    size_type buffer_row_pitch,\n    size_type buffer_slice_pitch,\n    size_type host_row_pitch,\n    size_type host_slice_pitch,\n    const void *ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueWriteBufferRect(\n        buffer,\n        blocking,\n        buffer_offset,\n        host_offset,\n        region,\n        buffer_row_pitch,\n        buffer_slice_pitch,\n        host_row_pitch,\n        host_slice_pitch,\n        ptr,\n        events,\n        event);\n}\n\ninline cl_int enqueueCopyBufferRect(\n    const Buffer& src,\n    const Buffer& dst,\n    const array<size_type, 3>& src_origin,\n    const array<size_type, 3>& dst_origin,\n    const array<size_type, 3>& region,\n    size_type src_row_pitch,\n    size_type src_slice_pitch,\n    size_type dst_row_pitch,\n    size_type dst_slice_pitch,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueCopyBufferRect(\n        src,\n        dst,\n        src_origin,\n        dst_origin,\n        region,\n        src_row_pitch,\n        src_slice_pitch,\n        dst_row_pitch,\n        dst_slice_pitch,\n        events,\n        event);\n}\n#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110\n\ninline cl_int enqueueReadImage(\n    const Image& image,\n    cl_bool blocking,\n    const array<size_type, 3>& origin,\n    const array<size_type, 3>& region,\n    size_type row_pitch,\n    size_type slice_pitch,\n    void* ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueReadImage(\n        image,\n        blocking,\n        origin,\n        region,\n        row_pitch,\n        slice_pitch,\n        ptr,\n        events,\n        event);\n}\n\ninline cl_int enqueueWriteImage(\n    const Image& image,\n    cl_bool blocking,\n    const array<size_type, 3>& origin,\n    const array<size_type, 3>& region,\n    size_type row_pitch,\n    size_type slice_pitch,\n    const void* ptr,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueWriteImage(\n        image,\n        blocking,\n        origin,\n        region,\n        row_pitch,\n        slice_pitch,\n        ptr,\n        events,\n        event);\n}\n\ninline cl_int enqueueCopyImage(\n    const Image& src,\n    const Image& dst,\n    const array<size_type, 3>& src_origin,\n    const array<size_type, 3>& dst_origin,\n    const array<size_type, 3>& region,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueCopyImage(\n        src,\n        dst,\n        src_origin,\n        dst_origin,\n        region,\n        events,\n        event);\n}\n\ninline cl_int enqueueCopyImageToBuffer(\n    const Image& src,\n    const Buffer& dst,\n    const array<size_type, 3>& src_origin,\n    const array<size_type, 3>& region,\n    size_type dst_offset,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueCopyImageToBuffer(\n        src,\n        dst,\n        src_origin,\n        region,\n        dst_offset,\n        events,\n        event);\n}\n\ninline cl_int enqueueCopyBufferToImage(\n    const Buffer& src,\n    const Image& dst,\n    size_type src_offset,\n    const array<size_type, 3>& dst_origin,\n    const array<size_type, 3>& region,\n    const vector<Event>* events = NULL,\n    Event* event = NULL)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.enqueueCopyBufferToImage(\n        src,\n        dst,\n        src_offset,\n        dst_origin,\n        region,\n        events,\n        event);\n}\n\n\ninline cl_int flush(void)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n    return queue.flush();\n}\n\ninline cl_int finish(void)\n{\n    cl_int error;\n    CommandQueue queue = CommandQueue::getDefault(&error);\n\n    if (error != CL_SUCCESS) {\n        return error;\n    }\n\n\n    return queue.finish();\n}\n\nclass EnqueueArgs\n{\nprivate:\n    CommandQueue queue_;\n    const NDRange offset_;\n    const NDRange global_;\n    const NDRange local_;\n    vector<Event> events_;\n\n    template<typename... Ts>\n    friend class KernelFunctor;\n\npublic:\n    EnqueueArgs(NDRange global) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange)\n    {\n\n    }\n\n    EnqueueArgs(NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(local)\n    {\n\n    }\n\n    EnqueueArgs(NDRange offset, NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(offset),\n      global_(global),\n      local_(local)\n    {\n\n    }\n\n    EnqueueArgs(Event e, NDRange global) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(Event e, NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(local)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(Event e, NDRange offset, NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(offset),\n      global_(global),\n      local_(local)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(const vector<Event> &events, NDRange global) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange),\n      events_(events)\n    {\n\n    }\n\n    EnqueueArgs(const vector<Event> &events, NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(NullRange),\n      global_(global),\n      local_(local),\n      events_(events)\n    {\n\n    }\n\n    EnqueueArgs(const vector<Event> &events, NDRange offset, NDRange global, NDRange local) :\n      queue_(CommandQueue::getDefault()),\n      offset_(offset),\n      global_(global),\n      local_(local),\n      events_(events)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, NDRange global) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(local)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, NDRange offset, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(offset),\n      global_(global),\n      local_(local)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, Event e, NDRange global) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(CommandQueue &queue, Event e, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(local)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(CommandQueue &queue, Event e, NDRange offset, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(offset),\n      global_(global),\n      local_(local)\n    {\n        events_.push_back(e);\n    }\n\n    EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange global) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(NullRange),\n      events_(events)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(NullRange),\n      global_(global),\n      local_(local),\n      events_(events)\n    {\n\n    }\n\n    EnqueueArgs(CommandQueue &queue, const vector<Event> &events, NDRange offset, NDRange global, NDRange local) :\n      queue_(queue),\n      offset_(offset),\n      global_(global),\n      local_(local),\n      events_(events)\n    {\n\n    }\n};\n\n\n//----------------------------------------------------------------------------------------------\n\n\n/**\n * Type safe kernel functor.\n *\n */\ntemplate<typename... Ts>\nclass KernelFunctor\n{\nprivate:\n    Kernel kernel_;\n\n    template<int index, typename T0, typename... T1s>\n    void setArgs(T0&& t0, T1s&&... t1s)\n    {\n        kernel_.setArg(index, t0);\n        setArgs<index + 1, T1s...>(std::forward<T1s>(t1s)...);\n    }\n\n    template<int index, typename T0>\n    void setArgs(T0&& t0)\n    {\n        kernel_.setArg(index, t0);\n    }\n\n    template<int index>\n    void setArgs()\n    {\n    }\n\n\npublic:\n    KernelFunctor(Kernel kernel) : kernel_(kernel)\n    {}\n\n    KernelFunctor(\n        const Program& program,\n        const string name,\n        cl_int * err = NULL) :\n        kernel_(program, name.c_str(), err)\n    {}\n\n    //! \\brief Return type of the functor\n    typedef Event result_type;\n\n    /**\n     * Enqueue kernel.\n     * @param args Launch parameters of the kernel.\n     * @param t0... List of kernel arguments based on the template type of the functor.\n     */\n    Event operator() (\n        const EnqueueArgs& args,\n        Ts... ts)\n    {\n        Event event;\n        setArgs<0>(std::forward<Ts>(ts)...);\n\n        args.queue_.enqueueNDRangeKernel(\n            kernel_,\n            args.offset_,\n            args.global_,\n            args.local_,\n            &args.events_,\n            &event);\n\n        return event;\n    }\n\n    /**\n    * Enqueue kernel with support for error code.\n    * @param args Launch parameters of the kernel.\n    * @param t0... List of kernel arguments based on the template type of the functor.\n    * @param error Out parameter returning the error code from the execution.\n    */\n    Event operator() (\n        const EnqueueArgs& args,\n        Ts... ts,\n        cl_int &error)\n    {\n        Event event;\n        setArgs<0>(std::forward<Ts>(ts)...);\n\n        error = args.queue_.enqueueNDRangeKernel(\n            kernel_,\n            args.offset_,\n            args.global_,\n            args.local_,\n            &args.events_,\n            &event);\n\n        return event;\n    }\n\n#if CL_HPP_TARGET_OPENCL_VERSION >= 200\n    cl_int setSVMPointers(const vector<void*> &pointerList)\n    {\n        return kernel_.setSVMPointers(pointerList);\n    }\n\n    template<typename T0, typename... T1s>\n    cl_int setSVMPointers(const T0 &t0, T1s... ts)\n    {\n        return kernel_.setSVMPointers(t0, ts...);\n    }\n#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200\n\n    Kernel getKernel()\n    {\n        return kernel_;\n    }\n};\n\nnamespace compatibility {\n    /**\n     * Backward compatibility class to ensure that cl.hpp code works with cl2.hpp.\n     * Please use KernelFunctor directly.\n     */\n    template<typename... Ts>\n    struct make_kernel\n    {\n        typedef KernelFunctor<Ts...> FunctorType;\n\n        FunctorType functor_;\n\n        make_kernel(\n            const Program& program,\n            const string name,\n            cl_int * err = NULL) :\n            functor_(FunctorType(program, name, err))\n        {}\n\n        make_kernel(\n            const Kernel kernel) :\n            functor_(FunctorType(kernel))\n        {}\n\n        //! \\brief Return type of the functor\n        typedef Event result_type;\n\n        //! \\brief Function signature of kernel functor with no event dependency.\n        typedef Event type_(\n            const EnqueueArgs&,\n            Ts...);\n\n        Event operator()(\n            const EnqueueArgs& enqueueArgs,\n            Ts... args)\n        {\n            return functor_(\n                enqueueArgs, args...);\n        }\n    };\n} // namespace compatibility\n\n\n//----------------------------------------------------------------------------------------------------------------------\n\n#undef CL_HPP_ERR_STR_\n#if !defined(CL_HPP_USER_OVERRIDE_ERROR_STRINGS)\n#undef __GET_DEVICE_INFO_ERR\n#undef __GET_PLATFORM_INFO_ERR\n#undef __GET_DEVICE_IDS_ERR\n#undef __GET_CONTEXT_INFO_ERR\n#undef __GET_EVENT_INFO_ERR\n#undef __GET_EVENT_PROFILE_INFO_ERR\n#undef __GET_MEM_OBJECT_INFO_ERR\n#undef __GET_IMAGE_INFO_ERR\n#undef __GET_SAMPLER_INFO_ERR\n#undef __GET_KERNEL_INFO_ERR\n#undef __GET_KERNEL_ARG_INFO_ERR\n#undef __GET_KERNEL_WORK_GROUP_INFO_ERR\n#undef __GET_PROGRAM_INFO_ERR\n#undef __GET_PROGRAM_BUILD_INFO_ERR\n#undef __GET_COMMAND_QUEUE_INFO_ERR\n\n#undef __CREATE_CONTEXT_ERR\n#undef __CREATE_CONTEXT_FROM_TYPE_ERR\n#undef __GET_SUPPORTED_IMAGE_FORMATS_ERR\n\n#undef __CREATE_BUFFER_ERR\n#undef __CREATE_SUBBUFFER_ERR\n#undef __CREATE_IMAGE2D_ERR\n#undef __CREATE_IMAGE3D_ERR\n#undef __CREATE_SAMPLER_ERR\n#undef __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR\n\n#undef __CREATE_USER_EVENT_ERR\n#undef __SET_USER_EVENT_STATUS_ERR\n#undef __SET_EVENT_CALLBACK_ERR\n#undef __SET_PRINTF_CALLBACK_ERR\n\n#undef __WAIT_FOR_EVENTS_ERR\n\n#undef __CREATE_KERNEL_ERR\n#undef __SET_KERNEL_ARGS_ERR\n#undef __CREATE_PROGRAM_WITH_SOURCE_ERR\n#undef __CREATE_PROGRAM_WITH_BINARY_ERR\n#undef __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR\n#undef __BUILD_PROGRAM_ERR\n#undef __CREATE_KERNELS_IN_PROGRAM_ERR\n\n#undef __CREATE_COMMAND_QUEUE_ERR\n#undef __SET_COMMAND_QUEUE_PROPERTY_ERR\n#undef __ENQUEUE_READ_BUFFER_ERR\n#undef __ENQUEUE_WRITE_BUFFER_ERR\n#undef __ENQUEUE_READ_BUFFER_RECT_ERR\n#undef __ENQUEUE_WRITE_BUFFER_RECT_ERR\n#undef __ENQEUE_COPY_BUFFER_ERR\n#undef __ENQEUE_COPY_BUFFER_RECT_ERR\n#undef __ENQUEUE_READ_IMAGE_ERR\n#undef __ENQUEUE_WRITE_IMAGE_ERR\n#undef __ENQUEUE_COPY_IMAGE_ERR\n#undef __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR\n#undef __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR\n#undef __ENQUEUE_MAP_BUFFER_ERR\n#undef __ENQUEUE_MAP_IMAGE_ERR\n#undef __ENQUEUE_UNMAP_MEM_OBJECT_ERR\n#undef __ENQUEUE_NDRANGE_KERNEL_ERR\n#undef __ENQUEUE_TASK_ERR\n#undef __ENQUEUE_NATIVE_KERNEL\n\n#undef __UNLOAD_COMPILER_ERR\n#undef __CREATE_SUB_DEVICES_ERR\n\n#undef __CREATE_PIPE_ERR\n#undef __GET_PIPE_INFO_ERR\n\n#endif //CL_HPP_USER_OVERRIDE_ERROR_STRINGS\n\n// Extensions\n#undef CL_HPP_INIT_CL_EXT_FCN_PTR_\n#undef CL_HPP_INIT_CL_EXT_FCN_PTR_PLATFORM_\n\n#if defined(CL_HPP_USE_CL_DEVICE_FISSION)\n#undef CL_HPP_PARAM_NAME_DEVICE_FISSION_\n#endif // CL_HPP_USE_CL_DEVICE_FISSION\n\n#undef CL_HPP_NOEXCEPT_\n#undef CL_HPP_DEFINE_STATIC_MEMBER_\n\n} // namespace cl\n\n#endif // CL_HPP_\n"
  },
  {
    "path": "include/openpose_private/gpu/cuda.hu",
    "content": "#ifndef OPENPOSE_PRIVATE_GPU_CUDA_HU\n#define OPENPOSE_PRIVATE_GPU_CUDA_HU\n\n// Note: This class should only be included if CUDA is enabled\n\n#include <cuda.h>\n#include <cuda_runtime.h>\n\nnamespace op\n{\n    // VERY IMPORTANT: These fast functions does NOT work for negative integer numbers.\n    // E.g., positiveIntRound(-180.f) = -179.\n\n    // Round functions\n    // Signed\n    template<typename T>\n    inline __device__ char positiveCharRoundCuda(const T a)\n    {\n        return char(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ signed char positiveSCharRoundCuda(const T a)\n    {\n        return (signed char)(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ int positiveIntRoundCuda(const T a)\n    {\n        return int(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ long positiveLongRoundCuda(const T a)\n    {\n        return long(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ long long positiveLongLongRoundCuda(const T a)\n    {\n        return (long long)(a+0.5f);\n    }\n\n    // Unsigned\n    template<typename T>\n    inline __device__ unsigned char uCharRoundCuda(const T a)\n    {\n        return (unsigned char)(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ unsigned int uIntRoundCuda(const T a)\n    {\n        return (unsigned int)(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ unsigned long ulongRoundCuda(const T a)\n    {\n        return (unsigned long)(a+0.5f);\n    }\n\n    template<typename T>\n    inline __device__ unsigned long long uLongLongRoundCuda(const T a)\n    {\n        return (unsigned long long)(a+0.5f);\n    }\n\n    // Max/min functions\n    template<class T>\n    inline __device__ T fastMaxCuda(const T a, const T b)\n    {\n        return (a > b ? a : b);\n    }\n\n    template<class T>\n    inline __device__ T fastMinCuda(const T a, const T b)\n    {\n        return (a < b ? a : b);\n    }\n\n    template<class T>\n    inline __device__ T fastTruncateCuda(const T value, const T min = 0, const T max = 1)\n    {\n        return fastMinCuda(max, fastMaxCuda(min, value));\n    }\n\n    // Cubic interpolation\n    template <typename T>\n    inline __device__ void cubicSequentialData(\n        int* xIntArray, int* yIntArray, T& dx, T& dy, const T xSource, const T ySource, const int widthSource,\n        const int heightSource)\n    {\n        xIntArray[1] = fastTruncateCuda(int(floor(xSource)), 0, widthSource - 1);\n        xIntArray[0] = fastMaxCuda(0, xIntArray[1] - 1);\n        xIntArray[2] = fastMinCuda(widthSource - 1, xIntArray[1] + 1);\n        xIntArray[3] = fastMinCuda(widthSource - 1, xIntArray[2] + 1);\n        dx = xSource - xIntArray[1];\n\n        yIntArray[1] = fastTruncateCuda(int(floor(ySource)), 0, heightSource - 1);\n        yIntArray[0] = fastMaxCuda(0, yIntArray[1] - 1);\n        yIntArray[2] = fastMinCuda(heightSource - 1, yIntArray[1] + 1);\n        yIntArray[3] = fastMinCuda(heightSource - 1, yIntArray[2] + 1);\n        dy = ySource - yIntArray[1];\n    }\n\n    template <typename T>\n    inline __device__ T cubicInterpolate(const T v0, const T v1, const T v2, const T v3, const T dx)\n    {\n        // http://www.paulinternet.nl/?page=bicubic\n        // const auto a = (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3);\n        // const auto b = (v0 - 2.5f * v1 + 2.0 * v2 - 0.5 * v3);\n        // const auto c = (-0.5f * v0 + 0.5f * v2);\n        // out = ((a * dx + b) * dx + c) * dx + v1;\n        return (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3) * dx * dx * dx\n                + (v0 - 2.5f * v1 + 2.f * v2 - 0.5f * v3) * dx * dx\n                - 0.5f * (v0 - v2) * dx // + (-0.5f * v0 + 0.5f * v2) * dx\n                + v1;\n        // return v1 + 0.5f * dx * (v2 - v0 + dx * (2.f * v0 - 5.f * v1 + 4.f * v2 - v3 + dx * (3.f * (v1 - v2) + v3 - v0)));\n    }\n\n    template <typename T>\n    inline __device__ T bicubicInterpolate(\n        const T* const sourcePtr, const T xSource, const T ySource, const int widthSource, const int heightSource,\n        const int widthSourcePtr)\n    {\n        int xIntArray[4];\n        int yIntArray[4];\n        T dx;\n        T dy;\n        cubicSequentialData(xIntArray, yIntArray, dx, dy, xSource, ySource, widthSource, heightSource);\n\n        T temp[4];\n        for (unsigned char i = 0; i < 4; i++)\n        {\n            const auto offset = yIntArray[i]*widthSourcePtr;\n            temp[i] = cubicInterpolate(\n                sourcePtr[offset + xIntArray[0]], sourcePtr[offset + xIntArray[1]], sourcePtr[offset + xIntArray[2]],\n                sourcePtr[offset + xIntArray[3]], dx);\n        }\n        return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy);\n    }\n\n    template <typename T>\n    inline __device__ T bicubicInterpolate(\n        const unsigned char* const sourcePtr, const T xSource, const T ySource, const int widthSource,\n        const int heightSource, const int widthSourcePtr)\n    {\n        int xIntArray[4];\n        int yIntArray[4];\n        T dx;\n        T dy;\n        cubicSequentialData(xIntArray, yIntArray, dx, dy, xSource, ySource, widthSource, heightSource);\n\n        T temp[4];\n        for (unsigned char i = 0; i < 4; i++)\n        {\n            const auto offset = yIntArray[i]*widthSourcePtr;\n            temp[i] = cubicInterpolate(\n                T(sourcePtr[offset + xIntArray[0]]), T(sourcePtr[offset + xIntArray[1]]),\n                T(sourcePtr[offset + xIntArray[2]]), T(sourcePtr[offset + xIntArray[3]]), dx);\n        }\n        return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy);\n    }\n\n    template <typename T>\n    inline __device__ T bicubicInterpolate8Times(\n        const T* const sourcePtr, const T xSource, const T ySource, const int widthSource, const int heightSource,\n        const int threadIdxX, const int threadIdxY)\n    {\n        // Now we only need dx and dy\n        const T dx = xSource - fastTruncateCuda(int(floor(xSource)), 0, widthSource - 1);\n        const T dy = ySource - fastTruncateCuda(int(floor(ySource)), 0, heightSource - 1);\n\n        T temp[4];\n        for (unsigned char i = 0; i < 4; i++)\n        {\n            const auto offset = 5 * (i + (threadIdxY > 3 ? 1 : 0)) + (threadIdxX > 3 ? 1 : 0);\n            temp[i] = cubicInterpolate(\n                sourcePtr[offset], sourcePtr[offset+1], sourcePtr[offset+2],\n                sourcePtr[offset+3], dx);\n        }\n        return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy);\n    }\n\n    template <typename T>\n    inline __device__ T addWeighted(const T value1, const T value2, const T alphaValue2)\n    {\n        return (1.f - alphaValue2) * value1 + alphaValue2 * value2;\n    }\n\n    template <typename T>\n    inline __device__ void addColorWeighted(\n        T& colorR, T& colorG, T& colorB, const T* const colorToAdd, const T alphaColorToAdd)\n    {\n        colorR = addWeighted(colorR, colorToAdd[0], alphaColorToAdd);\n        colorG = addWeighted(colorG, colorToAdd[1], alphaColorToAdd);\n        colorB = addWeighted(colorB, colorToAdd[2], alphaColorToAdd);\n    }\n}\n\n#endif // OPENPOSE_PRIVATE_GPU_CUDA_HU\n"
  },
  {
    "path": "include/openpose_private/gpu/opencl.hcl",
    "content": "#ifndef OPENPOSE_PRIVATE_GPU_OPENCL_HPP\n#define OPENPOSE_PRIVATE_GPU_OPENCL_HPP\n\n#include <openpose/core/common.hpp>\n\n#define MULTI_LINE_STRING(ARG) #ARG\n\n#define CL_HPP_ENABLE_EXCEPTIONS\n\n#ifdef LOWER_CL_VERSION\n    #define CL_HPP_MINIMUM_OPENCL_VERSION 120\n    #define CL_HPP_TARGET_OPENCL_VERSION 120\n#else\n    #define CL_HPP_MINIMUM_OPENCL_VERSION 120\n    #define CL_HPP_TARGET_OPENCL_VERSION 120\n#endif\n\ntypedef struct _cl_buffer_region cl_buffer_region;\n#define CL_DEVICE_TYPE_GPU                          (1 << 2)\nnamespace cl\n{\n    class CommandQueue;\n    class Kernel;\n    class Device;\n    class Context;\n}\n\n// Singleton structure\n// https://stackoverflow.com/questions/1008019/c-singleton-design-pattern\n\nnamespace op\n{\n    class OpenCL\n    {\n    public:\n        static std::shared_ptr<OpenCL> getInstance(const int deviceId = 0, const int deviceType = CL_DEVICE_TYPE_GPU,\n                                                   bool getFromVienna = false);\n        ~OpenCL();\n\n        cl::CommandQueue& getQueue();\n\n        cl::Device& getDevice();\n\n        cl::Context& getContext();\n\n        template <typename T>\n        bool buildKernelIntoManager(const std::string& kernelName, const std::string& src = \"\", bool isFile = false);\n\n        template <typename T>\n        cl::Kernel& getKernelFromManager(const std::string& kernelName, const std::string& src = \"\", bool isFile = false);\n\n        template <typename K, typename T>\n        inline K getKernelFunctorFromManager(const std::string& kernelName, const std::string& src = \"\", bool isFile = false)\n        {\n            return K(getKernelFromManager<T>(kernelName, src, isFile));\n        }\n\n        template <typename T> static void getBufferRegion(cl_buffer_region& region, const int origin, const int size);\n\n        int getAlignment();\n\n        static std::string clErrorToString(int err);\n\n        static int getTotalGPU();\n\n    private:\n        struct ImplCLManager;\n        std::unique_ptr<ImplCLManager> upImpl;\n\n        OpenCL(const int deviceId, const int deviceType, bool getFromVienna);\n\n        DELETE_COPY(OpenCL);\n    };\n}\n\n#endif // OPENPOSE_PRIVATE_GPU_OPENCL_HPP\n"
  },
  {
    "path": "include/openpose_private/tracking/pyramidalLK.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP\n#define OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP\n\n#include <opencv2/core/core.hpp> // cv::Mat, cv::Point2f\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    void pyramidalLKCpu(\n        std::vector<cv::Point2f>& coordI, std::vector<cv::Point2f>& coordJ,\n        std::vector<cv::Mat>& pyramidImagesPrevious, std::vector<cv::Mat>& pyramidImagesCurrent,\n        std::vector<char>& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent,\n        const int levels = 3, const int patchSize = 21);\n\n    int pyramidalLKGpu(\n        std::vector<cv::Point2f>& ptsI, std::vector<cv::Point2f>& ptsJ,\n        std::vector<char>& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent,\n        const int levels = 3, const int patchSize = 21);\n\n    void pyramidalLKOcv(\n        std::vector<cv::Point2f>& coordI, std::vector<cv::Point2f>& coordJ,\n        std::vector<cv::Mat>& pyramidImagesPrevious, std::vector<cv::Mat>& pyramidImagesCurrent,\n        std::vector<char>& status, const cv::Mat& imagePrevious, const cv::Mat& imageCurrent,\n        const int levels = 3, const int patchSize = 21, const bool initFlow = false);\n}\n\n#endif // OPENPOSE_PRIVATE_TRACKING_LKPYRAMIDAL_HPP\n"
  },
  {
    "path": "include/openpose_private/utilities/avx.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_UTILITIES_AVX_HPP\n#define OPENPOSE_PRIVATE_UTILITIES_AVX_HPP\n\n// Warning:\n// This file contains auxiliary functions for AVX.\n// This file should only be included from cpp files.\n// Default #include <openpose/headers.hpp> does not include it.\n\n#ifdef WITH_AVX\n    #include <cstdint> // uintptr_t\n    #include <memory> // shared_ptr\n    #include <immintrin.h>\n    #include <openpose/utilities/errorAndLog.hpp>\n\n    namespace op\n    {\n        #ifdef __GNUC__\n            #define ALIGN32(x) x __attribute__((aligned(32)))\n        #elif defined(_MSC_VER) // defined(_WIN32)\n            #define ALIGN32(x) __declspec(align(32))\n        #else\n            #error Unknown environment!\n        #endif\n\n        // Functions\n        // Sources:\n        // - https://stackoverflow.com/questions/32612190/how-to-solve-the-32-byte-alignment-issue-for-avx-load-store-operations\n        // - https://embeddedartistry.com/blog/2017/2/20/implementing-aligned-malloc\n        // - https://embeddedartistry.com/blog/2017/2/23/c-smart-pointers-with-aligned-mallocfree\n        typedef unsigned long long offset_t;\n        #define PTR_OFFSET_SZ sizeof(offset_t)\n        #ifndef align_up\n        #define align_up(num, align) \\\n            (((num) + ((align) - 1)) & ~((align) - 1))\n        #endif\n        inline void * aligned_malloc(const size_t align, const size_t size)\n        {\n            void * ptr = nullptr;\n\n            // 2 conditions:\n            //  - We want both align and size to be greater than 0\n            //  - We want it to be a power of two since align_up operates on powers of two\n            if (align && size && (align & (align - 1)) == 0)\n            {\n                // We know we have to fit an offset value\n                // We also allocate extra bytes to ensure we can meet the alignment\n                const auto hdr_size = PTR_OFFSET_SZ + (align - 1);\n                void * p = malloc(size + hdr_size);\n\n                if (p)\n                {\n                    // Add the offset size to malloc's pointer (we will always store that)\n                    // Then align the resulting value to the arget alignment\n                    ptr = (void *) align_up(((uintptr_t)p + PTR_OFFSET_SZ), align);\n\n                    // Calculate the offset and store it behind our aligned pointer\n                    *((offset_t *)ptr - 1) = (offset_t)((uintptr_t)ptr - (uintptr_t)p);\n\n                } // else nullptr, could not malloc\n            } // else nullptr, invalid arguments\n\n            if (ptr == nullptr)\n            {\n                error(\"Shared pointer could not be allocated for Array data storage.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            return ptr;\n        }\n        inline void aligned_free(void * ptr)\n        {\n            if (ptr == nullptr)\n                error(\"Received nullptr.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Walk backwards from the passed-in pointer to get the pointer offset\n            // We convert to an offset_t pointer and rely on pointer math to get the data\n            offset_t offset = *((offset_t *)ptr - 1);\n\n            // Once we have the offset, we can get our original pointer and call free\n            void * p = (void *)((uint8_t *)ptr - offset);\n            free(p);\n        }\n        template<class T>\n        std::shared_ptr<T> aligned_shared_ptr(const size_t size)\n        {\n            try\n            {\n                return std::shared_ptr<T>(static_cast<T*>(\n                    aligned_malloc(8*sizeof(T), sizeof(T)*size)), &aligned_free);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::shared_ptr<T>{};\n            }\n        }\n    }\n#endif\n\n#endif // OPENPOSE_PRIVATE_UTILITIES_AVX_HPP\n"
  },
  {
    "path": "include/openpose_private/utilities/openCvMultiversionHeaders.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP\n#define OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP\n\n#include <opencv2/opencv.hpp>\n\n// Compatibility for OpenCV 4.0 while preserving 2.4.X and 3.X HEADERS\n// Note:\n// - CV_VERSION:         2.4.9.1 | 4.0.0-beta\n// - CV_MAJOR_VERSION:         2 | 4\n// - CV_MINOR_VERSION:         4 | 0\n// - CV_SUBMINOR_VERSION:      9 | 0\n// - CV_VERSION_EPOCH:         2 | Not defined\n#if (defined(CV_MAJOR_VERSION) && CV_MAJOR_VERSION > 3)\n    #define OPEN_CV_IS_4_OR_HIGHER\n#endif\n#ifdef OPEN_CV_IS_4_OR_HIGHER\n    #define CV_BGR2GRAY cv::COLOR_BGR2GRAY\n    #define CV_BGR2RGB cv::COLOR_BGR2RGB\n    #define CV_CALIB_CB_ADAPTIVE_THRESH cv::CALIB_CB_ADAPTIVE_THRESH\n    #define CV_CALIB_CB_NORMALIZE_IMAGE cv::CALIB_CB_NORMALIZE_IMAGE\n    #define CV_CALIB_CB_FILTER_QUADS cv::CALIB_CB_FILTER_QUADS\n    #define CV_CAP_PROP_FPS cv::CAP_PROP_FPS\n    #define CV_CAP_PROP_FRAME_COUNT cv::CAP_PROP_FRAME_COUNT\n    #define CV_CAP_PROP_FRAME_HEIGHT cv::CAP_PROP_FRAME_HEIGHT\n    #define CV_CAP_PROP_FRAME_WIDTH cv::CAP_PROP_FRAME_WIDTH\n    #define CV_CAP_PROP_POS_FRAMES cv::CAP_PROP_POS_FRAMES\n    #define CV_FOURCC cv::VideoWriter::fourcc\n    #define CV_GRAY2BGR cv::COLOR_GRAY2BGR\n    #define CV_HAAR_SCALE_IMAGE cv::CASCADE_SCALE_IMAGE\n    #define CV_INTER_CUBIC cv::INTER_CUBIC\n    #define CV_INTER_LINEAR cv::INTER_LINEAR\n    #define CV_L2 cv::NORM_L2\n    #define CV_RGB2BGR cv::COLOR_RGB2BGR\n    #define CV_TERMCRIT_EPS cv::TermCriteria::Type::EPS\n    #define CV_TERMCRIT_ITER cv::TermCriteria::Type::MAX_ITER\n    #define CV_WARP_INVERSE_MAP cv::WARP_INVERSE_MAP\n    #define CV_WINDOW_FULLSCREEN cv::WINDOW_FULLSCREEN\n    #define CV_WINDOW_KEEPRATIO cv::WINDOW_KEEPRATIO\n    #define CV_WINDOW_NORMAL cv::WINDOW_NORMAL\n    #define CV_WINDOW_OPENGL cv::WINDOW_OPENGL\n    #define CV_WND_PROP_FULLSCREEN cv::WND_PROP_FULLSCREEN\n    #include <opencv2/imgcodecs/imgcodecs.hpp>\n    #define CV_IMWRITE_JPEG_QUALITY cv::IMWRITE_JPEG_QUALITY\n    #define CV_IMWRITE_PNG_COMPRESSION cv::IMWRITE_PNG_COMPRESSION\n    #define CV_LOAD_IMAGE_ANYDEPTH cv::IMREAD_ANYDEPTH\n    #define CV_LOAD_IMAGE_COLOR cv::IMREAD_COLOR\n    #define CV_LOAD_IMAGE_GRAYSCALE cv::IMREAD_GRAYSCALE\n#endif\n\n#endif // OPENPOSE_PRIVATE_UTILITIES_OPENCV_MULTIVERSION_HEADERS_HPP\n"
  },
  {
    "path": "include/openpose_private/utilities/openCvPrivate.hpp",
    "content": "#ifndef OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP\n#define OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP\n\n#include <opencv2/core/core.hpp> // cv::Mat, cv::Rect, cv::Scalar\n#include <opencv2/imgproc/imgproc.hpp> // cv::BORDER_CONSTANT\n#include <openpose/core/common.hpp>\n\nnamespace op\n{\n    void putTextOnCvMat(\n        cv::Mat& cvMat, const std::string& textToDisplay, const Point<int>& position,\n        const cv::Scalar& color, const bool normalizeWidth, const int imageWidth);\n\n    void resizeFixedAspectRatio(\n        cv::Mat& resizedCvMat, const cv::Mat& cvMat, const double scaleFactor, const Point<int>& targetSize,\n        const int borderMode = cv::BORDER_CONSTANT, const cv::Scalar& borderValue = cv::Scalar{0,0,0});\n}\n\n#endif // OPENPOSE_PRIVATE_UTILITIES_OPEN_CV_PRIVATE_HPP\n"
  },
  {
    "path": "include/openpose_private/utilities/render.hu",
    "content": "#ifndef OPENPOSE_PRIVATE_UTILITIES_RENDER_HU\n#define OPENPOSE_PRIVATE_UTILITIES_RENDER_HU\n\nnamespace op\n{\n    __inline__ __device__ void getBoundingBoxPerPerson(\n        float* maxPtr, float* minPtr, float* scalePtr,const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const keypointsPtr, const int numberPeople, const int numberParts, const float threshold)\n    {\n        const unsigned long globalIdx = threadIdx.x;\n\n        // Fill shared parameters\n        if (globalIdx < numberPeople)\n        {\n            float minValueX = (float)targetWidth;\n            float minValueY = (float)targetHeight;\n            float maxValueX = 0.f;\n            float maxValueY = 0.f;\n            for (auto part = 0 ; part < numberParts ; part++)\n            {\n                const unsigned long index = 3u * (globalIdx*numberParts + part);\n                const float x = keypointsPtr[index];\n                const float y = keypointsPtr[index+1];\n                const float score = keypointsPtr[index+2];\n                if (score > threshold)\n                {\n                    if (x < minValueX)\n                        minValueX = x;\n                    if (x > maxValueX)\n                        maxValueX = x;\n                    if (y < minValueY)\n                        minValueY = y;\n                    if (y > maxValueY)\n                        maxValueY = y;\n                }\n            }\n            if (maxValueX != 0.f && maxValueY != 0.f)\n            {\n                const auto averageX = maxValueX - minValueX;\n                const auto averageY = maxValueY - minValueY;\n                // (averageX + averageY) / 2.f / 400.f\n                scalePtr[globalIdx] = fastTruncateCuda((averageX + averageY) / 400.f, 0.33f, 1.f);\n                const auto constantToAdd = 50.f;\n                maxValueX += constantToAdd;\n                maxValueY += constantToAdd;\n                minValueX -= constantToAdd;\n                minValueY -= constantToAdd;\n            }\n\n            // const auto xIndex = 2*globalIdx;\n            // const auto yIndex = xIndex+1;\n            const auto xIndex = globalIdx;\n            const auto yIndex = numberPeople+globalIdx;\n            minPtr[xIndex] = minValueX;\n            minPtr[yIndex] = minValueY;\n            maxPtr[xIndex] = maxValueX;\n            maxPtr[yIndex] = maxValueY;\n        }\n    }\n\n    // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n    __inline__ __device__ void renderKeypoints(\n        float* targetPtr, float* sharedMaxs, float* sharedMins, float* sharedScaleF, const float* const maxPtr,\n        const float* const minPtr, const float* const scalePtr, const int globalIdx, const int x, const int y,\n        const unsigned int targetWidth, const unsigned int targetHeight, const float* const keypointsPtr,\n        const unsigned int* const partPairsPtr, const int numberPeople, const int numberParts,\n        const int numberPartPairs, const float* const rgbColorsPtr, const int numberColors, const float radius,\n        const float lineWidth, const float* const keypointScalePtr, const int numberScales, const float threshold,\n        const float alphaColorToAdd, const bool blendOriginalFrame = true, const int googlyEye1 = -1,\n        const int googlyEye2 = -1)\n    {\n        // Load shared memory\n        if (globalIdx < 2*numberPeople)\n        {\n            sharedMins[globalIdx] = minPtr[globalIdx];\n            sharedMaxs[globalIdx] = maxPtr[globalIdx];\n            if (globalIdx < numberPeople)\n                sharedScaleF[globalIdx] = scalePtr[globalIdx];\n        }\n        __syncthreads();\n\n        // Fill each (x,y) target pixel\n        if (x < targetWidth && y < targetHeight)\n        {\n            const unsigned long baseIndex = 3u*(y * (unsigned long)targetWidth + x);\n            float b = targetPtr[baseIndex];\n            float g = targetPtr[baseIndex+1];\n            float r = targetPtr[baseIndex+2];\n            if (!blendOriginalFrame)\n            {\n                b = 0.f;\n                g = 0.f;\n                r = 0.f;\n            }\n\n            const auto lineWidthSquared = lineWidth * lineWidth;\n            const auto radiusSquared = radius * radius;\n            for (auto person = 0; person < numberPeople; person++)\n            {\n                // Make sure person x,y in the limits\n                // Make sure person is not empty. Assume all joints are below threshold. Then\n                // maxs = 0 and mins = width/height. So if statement would be false\n                // const auto xIndex = 2*person;\n                // const auto yIndex = xIndex+1;\n                const auto xIndex = person;\n                const auto yIndex = numberPeople+person;\n                if (x <= sharedMaxs[xIndex] && x >= sharedMins[xIndex]\n                    && y <= sharedMaxs[yIndex] && y >= sharedMins[yIndex])\n                {\n                    // Part pair connections\n                    for (auto partPair = 0; partPair < numberPartPairs; partPair++)\n                    {\n                        const auto partA = partPairsPtr[2*partPair];\n                        const auto partB = partPairsPtr[2*partPair+1];\n                        const auto indexA = person*numberParts*3 + partA*3;\n                        const auto xA = keypointsPtr[indexA];\n                        const auto yA = keypointsPtr[indexA + 1];\n                        const auto scoreA = keypointsPtr[indexA + 2];\n                        const auto indexB = person*numberParts*3 + partB*3;\n                        const auto xB = keypointsPtr[indexB];\n                        const auto yB = keypointsPtr[indexB + 1];\n                        const auto scoreB = keypointsPtr[indexB + 2];\n\n                        if (scoreA > threshold && scoreB > threshold)\n                        {\n                            const auto keypointScale = keypointScalePtr[partB%numberScales]\n                                                     * keypointScalePtr[partB%numberScales]\n                                                     * keypointScalePtr[partB%numberScales];\n                            const auto lineWidthScaled = lineWidthSquared * keypointScale;\n                            const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * lineWidthScaled;\n\n                            const auto xP = (xA + xB) / 2.f;\n                            const auto yP = (yA + yB) / 2.f;\n                            const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP);\n\n                            const auto angle = atan2f(yB - yA, xB - xA);\n                            const auto sine = sinf(angle);\n                            const auto cosine = cosf(angle);\n                            const auto A = cosine * (x - xP) + sine * (y - yP);\n                            const auto B = sine * (x - xP) - cosine * (y - yP);\n\n                            const auto judge = A * A / aSqrt + B * B / bSqrt;\n                            const auto minV = 0.f;\n                            const auto maxV = 1.f;\n                            if (minV <= judge && judge <= maxV)\n                                // Before used partPair vs partB\n                                addColorWeighted(r, g, b, &rgbColorsPtr[(partB%numberColors)*3], alphaColorToAdd);\n                        }\n                    }\n\n                    // Part circles\n                    for (auto part = 0u; part < numberParts; part++)\n                    {\n                        const auto index = 3 * (person*numberParts + part);\n                        const auto localX = keypointsPtr[index];\n                        const auto localY = keypointsPtr[index + 1];\n                        const auto score = keypointsPtr[index + 2];\n\n                        if (score > threshold)\n                        {\n                            const auto keypointScale = keypointScalePtr[part%numberScales]\n                                                     * keypointScalePtr[part%numberScales]\n                                                     * keypointScalePtr[part%numberScales];\n                            const auto radiusScaled = radiusSquared * keypointScale;\n                            const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY);\n                            // Googly eyes\n                            if (googlyEye1 == part || googlyEye2 == part)\n                            {\n                                const auto eyeRatio = 2.5f * sqrt(radiusScaled);\n                                const auto minr2 = sharedScaleF[person] * sharedScaleF[person]\n                                                 * (eyeRatio - 2) * (eyeRatio - 2);\n                                const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * eyeRatio * eyeRatio;\n                                if (dist2 <= maxr2)\n                                {\n                                    float colorToAdd [3] = {0., 0., 0.};\n                                    if (dist2 <= minr2)\n                                        for (auto& color : colorToAdd)\n                                            color = {255.f};\n                                    if (dist2 <= minr2*0.6f)\n                                    {\n                                        const auto dist3 = (x-4 - localX)\n                                                         * (x-4 - localX) + (y - localY+4) * (y - localY+4);\n                                        if (dist3 > 14.0625f) // 3.75f^2\n                                            for (auto& color : colorToAdd)\n                                                color = {0.f};\n                                    }\n                                    const auto alphaColorToAdd = 0.9f;\n                                    addColorWeighted(r, g, b, colorToAdd, alphaColorToAdd);\n                                }\n                            }\n                            // Other parts\n                            else\n                            {\n                                const auto minr2 = 0.f;\n                                const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * radiusScaled;\n                                if (minr2 <= dist2 && dist2 <= maxr2)\n                                    addColorWeighted(r, g, b, &rgbColorsPtr[(part%numberColors)*3], alphaColorToAdd);\n                            }\n                        }\n                    }\n                }\n            }\n            targetPtr[baseIndex] = b;\n            targetPtr[baseIndex+1] = g;\n            targetPtr[baseIndex+2] = r;\n        }\n    }\n\n    __inline__ __device__ void renderKeypointsOld(\n        float* targetPtr, float2* sharedMaxs, float2* sharedMins, float* sharedScaleF, const int globalIdx,\n        const int x, const int y, const unsigned int targetWidth, const unsigned int targetHeight, const float* const keypointsPtr,\n        const unsigned int* const partPairsPtr, const int numberPeople, const int numberParts,\n        const int numberPartPairs, const float* const rgbColorsPtr, const int numberColors, const float radius,\n        const float lineWidth, const float* const keypointScalePtr, const int numberScales, const float threshold,\n        const float alphaColorToAdd, const bool blendOriginalFrame = true, const int googlyEye1 = -1,\n        const int googlyEye2 = -1)\n    {\n        // Fill shared parameters\n        if (globalIdx < numberPeople)\n        {\n            float minValueX = (float)targetWidth;\n            float minValueY = (float)targetHeight;\n            float maxValueX = 0.f;\n            float maxValueY = 0.f;\n            for (auto part = 0 ; part < numberParts ; part++)\n            {\n                const unsigned long index = 3u * (((unsigned long)globalIdx)*numberParts + part);\n                const float x = keypointsPtr[index];\n                const float y = keypointsPtr[index+1];\n                const float score = keypointsPtr[index+2];\n                if (score > threshold)\n                {\n                    if (x < minValueX)\n                        minValueX = x;\n                    if (x > maxValueX)\n                        maxValueX = x;\n                    if (y < minValueY)\n                        minValueY = y;\n                    if (y > maxValueY)\n                        maxValueY = y;\n                }\n            }\n            if (maxValueX != 0.f && maxValueY != 0.f)\n            {\n                const auto averageX = maxValueX - minValueX;\n                const auto averageY = maxValueY - minValueY;\n                // (averageX + averageY) / 2.f / 400.f\n                sharedScaleF[globalIdx] = fastTruncateCuda((averageX + averageY) / 400.f, 0.33f, 1.f);\n                const auto constantToAdd = 50.f;\n                maxValueX += constantToAdd;\n                maxValueY += constantToAdd;\n                minValueX -= constantToAdd;\n                minValueY -= constantToAdd;\n            }\n\n            sharedMins[globalIdx].x = minValueX;\n            sharedMins[globalIdx].y = minValueY;\n            sharedMaxs[globalIdx].x = maxValueX;\n            sharedMaxs[globalIdx].y = maxValueY;\n        }\n        __syncthreads();\n\n        // Fill each (x,y) target pixel\n        if (x < targetWidth && y < targetHeight)\n        {\n            const unsigned long baseIndex = 3u*(y * (unsigned long)targetWidth + x);\n            float b = targetPtr[baseIndex];\n            float g = targetPtr[baseIndex+1];\n            float r = targetPtr[baseIndex+2];\n            if (!blendOriginalFrame)\n            {\n                b = 0.f;\n                g = 0.f;\n                r = 0.f;\n            }\n\n            const auto lineWidthSquared = lineWidth * lineWidth;\n            const auto radiusSquared = radius * radius;\n            for (auto person = 0; person < numberPeople; person++)\n            {\n                // Make sure person x,y in the limits\n                // Make sure person is not empty. Assume all joints are below threshold. Then\n                // maxs = 0 and mins = width/height. So if statement would be false\n                if (x <= sharedMaxs[person].x && x >= sharedMins[person].x\n                    && y <= sharedMaxs[person].y && y >= sharedMins[person].y)\n                {\n                    // Part pair connections\n                    for (auto partPair = 0; partPair < numberPartPairs; partPair++)\n                    {\n                        const auto partA = partPairsPtr[2*partPair];\n                        const auto partB = partPairsPtr[2*partPair+1];\n                        const auto indexA = person*numberParts*3 + partA*3;\n                        const auto xA = keypointsPtr[indexA];\n                        const auto yA = keypointsPtr[indexA + 1];\n                        const auto scoreA = keypointsPtr[indexA + 2];\n                        const auto indexB = person*numberParts*3 + partB*3;\n                        const auto xB = keypointsPtr[indexB];\n                        const auto yB = keypointsPtr[indexB + 1];\n                        const auto scoreB = keypointsPtr[indexB + 2];\n\n                        if (scoreA > threshold && scoreB > threshold)\n                        {\n                            const auto keypointScale = keypointScalePtr[partB%numberScales]\n                                                     * keypointScalePtr[partB%numberScales]\n                                                     * keypointScalePtr[partB%numberScales];\n                            const auto lineWidthScaled = lineWidthSquared * keypointScale;\n                            const auto bSqrt = sharedScaleF[person] * sharedScaleF[person] * lineWidthScaled;\n\n                            const auto xP = (xA + xB) / 2.f;\n                            const auto yP = (yA + yB) / 2.f;\n                            const auto aSqrt = (xA - xP) * (xA - xP) + (yA - yP) * (yA - yP);\n\n                            const auto angle = atan2f(yB - yA, xB - xA);\n                            const auto sine = sinf(angle);\n                            const auto cosine = cosf(angle);\n                            const auto A = cosine * (x - xP) + sine * (y - yP);\n                            const auto B = sine * (x - xP) - cosine * (y - yP);\n\n                            const auto judge = A * A / aSqrt + B * B / bSqrt;\n                            const auto minV = 0.f;\n                            const auto maxV = 1.f;\n                            if (minV <= judge && judge <= maxV)\n                                // Before used partPair vs partB\n                                addColorWeighted(r, g, b, &rgbColorsPtr[(partB%numberColors)*3], alphaColorToAdd);\n                        }\n                    }\n\n                    // Part circles\n                    for (auto part = 0u; part < numberParts; part++)\n                    {\n                        const auto index = 3 * (person*numberParts + part);\n                        const auto localX = keypointsPtr[index];\n                        const auto localY = keypointsPtr[index + 1];\n                        const auto score = keypointsPtr[index + 2];\n\n                        if (score > threshold)\n                        {\n                            const auto keypointScale = keypointScalePtr[part%numberScales]\n                                                     * keypointScalePtr[part%numberScales]\n                                                     * keypointScalePtr[part%numberScales];\n                            const auto radiusScaled = radiusSquared * keypointScale;\n                            const auto dist2 = (x - localX) * (x - localX) + (y - localY) * (y - localY);\n                            // Googly eyes\n                            if (googlyEye1 == part || googlyEye2 == part)\n                            {\n                                const auto eyeRatio = 2.5f * sqrt(radiusScaled);\n                                const auto minr2 = sharedScaleF[person] * sharedScaleF[person]\n                                                 * (eyeRatio - 2) * (eyeRatio - 2);\n                                const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * eyeRatio * eyeRatio;\n                                if (dist2 <= maxr2)\n                                {\n                                    float colorToAdd [3] = {0., 0., 0.};\n                                    if (dist2 <= minr2)\n                                        for (auto& color : colorToAdd)\n                                            color = {255.f};\n                                    if (dist2 <= minr2*0.6f)\n                                    {\n                                        const auto dist3 = (x-4 - localX)\n                                                         * (x-4 - localX) + (y - localY+4) * (y - localY+4);\n                                        if (dist3 > 14.0625f) // 3.75f^2\n                                            for (auto& color : colorToAdd)\n                                                color = {0.f};\n                                    }\n                                    const auto alphaColorToAdd = 0.9f;\n                                    addColorWeighted(r, g, b, colorToAdd, alphaColorToAdd);\n                                }\n                            }\n                            // Other parts\n                            else\n                            {\n                                const auto minr2 = 0.f;\n                                const auto maxr2 = sharedScaleF[person] * sharedScaleF[person] * radiusScaled;\n                                if (minr2 <= dist2 && dist2 <= maxr2)\n                                    addColorWeighted(r, g, b, &rgbColorsPtr[(part%numberColors)*3], alphaColorToAdd);\n                            }\n                        }\n                    }\n                }\n            }\n            targetPtr[baseIndex] = b;\n            targetPtr[baseIndex+1] = g;\n            targetPtr[baseIndex+2] = r;\n        }\n    }\n}\n\n\n#endif // OPENPOSE_PRIVATE_UTILITIES_RENDER_HU\n"
  },
  {
    "path": "models/cameraParameters/flir/17012332.xml.example",
    "content": "<?xml version=\"1.0\"?>\n<!-- Note: Camera matrix translation units are meters. -->\n<opencv_storage>\n<CameraMatrix type_id=\"opencv-matrix\">\n  <rows>3</rows>\n  <cols>4</cols>\n  <dt>d</dt>\n  <data>\n    1. 0. 0. 0.\n    0. 1. 0. 0.\n    0. 0. 1. 0.</data></CameraMatrix>\n<Intrinsics type_id=\"opencv-matrix\">\n  <rows>3</rows>\n  <cols>3</cols>\n  <dt>d</dt>\n  <data>\n    8.1793481631740565e+02 0. 6.0070689997785121e+02 0.\n    8.1651774059837908e+02 5.1784529566329593e+02 0. 0. 1.</data></Intrinsics>\n<Distortion type_id=\"opencv-matrix\">\n  <rows>8</rows>\n  <cols>1</cols>\n  <dt>d</dt>\n  <data>\n    -1.8102158829399091e+00 9.1966147162623262e+00\n    -4.4293900343777355e-04 1.3638377686816653e-03\n    1.3303863414979364e+00 -1.4189051636354870e+00\n    8.4725535468475819e+00 4.7911023525901033e+00</data></Distortion>\n</opencv_storage>\n"
  },
  {
    "path": "models/face/pose_deploy.prototxt",
    "content": "input: \"image\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 1 # Original: 368\ninput_dim: 1 # Original: 368\n# input: \"weights\"\n# input_dim: 1\n# input_dim: 71\n# input_dim: 184\n# input_dim: 184\n# input: \"labels\"\n# input_dim: 1\n# input_dim: 71\n# input_dim: 184\n# input_dim: 184\n\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv1_1_re\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv1_2_re\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1\"\n  top: \"conv2_1\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv2_1_re\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv2_2_re\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2\"\n  top: \"conv3_1\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv3_1_re\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv3_2_re\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv3_3_re\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv3_4_re\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3\"\n  top: \"conv4_1\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv4_1_re\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv4_2_re\"\n  type: \"ReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv4_3_re\"\n  type: \"ReLU\"\n  bottom: \"conv4_3\"\n  top: \"conv4_3\"\n}\nlayer {\n  name: \"conv4_4\"\n  type: \"Convolution\"\n  bottom: \"conv4_3\"\n  top: \"conv4_4\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv4_4_re\"\n  type: \"ReLU\"\n  bottom: \"conv4_4\"\n  top: \"conv4_4\"\n}\nlayer {\n  name: \"conv5_1\"\n  type: \"Convolution\"\n  bottom: \"conv4_4\"\n  top: \"conv5_1\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_1_re\"\n  type: \"ReLU\"\n  bottom: \"conv5_1\"\n  top: \"conv5_1\"\n}\nlayer {\n  name: \"conv5_2\"\n  type: \"Convolution\"\n  bottom: \"conv5_1\"\n  top: \"conv5_2\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_2_re\"\n  type: \"ReLU\"\n  bottom: \"conv5_2\"\n  top: \"conv5_2\"\n}\nlayer {\n  name: \"conv5_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv5_2\"\n  top: \"conv5_3_CPM\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_3_CPM_re\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM\"\n  top: \"conv5_3_CPM\"\n}\nlayer {\n  name: \"conv6_1_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM\"\n  top: \"conv6_1_CPM\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv6_1_CPM_re\"\n  type: \"ReLU\"\n  bottom: \"conv6_1_CPM\"\n  top: \"conv6_1_CPM\"\n}\nlayer {\n  name: \"conv6_2_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv6_1_CPM\"\n  top: \"conv6_2_CPM\"\n  param {\n    lr_mult: 1\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"features_in_stage_2\"\n  type: \"Concat\"\n  bottom: \"conv6_2_CPM\"\n  bottom: \"conv5_3_CPM\"\n  top: \"features_in_stage_2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2\"\n  type: \"Convolution\"\n  bottom: \"features_in_stage_2\"\n  top: \"Mconv1_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv1_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2\"\n  top: \"Mconv1_stage2\"\n}\nlayer {\n  name: \"Mconv2_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2\"\n  top: \"Mconv2_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv2_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2\"\n  top: \"Mconv2_stage2\"\n}\nlayer {\n  name: \"Mconv3_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2\"\n  top: \"Mconv3_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv3_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2\"\n  top: \"Mconv3_stage2\"\n}\nlayer {\n  name: \"Mconv4_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2\"\n  top: \"Mconv4_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv4_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2\"\n  top: \"Mconv4_stage2\"\n}\nlayer {\n  name: \"Mconv5_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2\"\n  top: \"Mconv5_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv5_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2\"\n  top: \"Mconv5_stage2\"\n}\nlayer {\n  name: \"Mconv6_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2\"\n  top: \"Mconv6_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv6_stage2_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2\"\n  top: \"Mconv6_stage2\"\n}\nlayer {\n  name: \"Mconv7_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2\"\n  top: \"Mconv7_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"features_in_stage_3\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage2\"\n  bottom: \"conv5_3_CPM\"\n  top: \"features_in_stage_3\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3\"\n  type: \"Convolution\"\n  bottom: \"features_in_stage_3\"\n  top: \"Mconv1_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv1_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3\"\n  top: \"Mconv1_stage3\"\n}\nlayer {\n  name: \"Mconv2_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3\"\n  top: \"Mconv2_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv2_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3\"\n  top: \"Mconv2_stage3\"\n}\nlayer {\n  name: \"Mconv3_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3\"\n  top: \"Mconv3_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv3_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3\"\n  top: \"Mconv3_stage3\"\n}\nlayer {\n  name: \"Mconv4_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3\"\n  top: \"Mconv4_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv4_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3\"\n  top: \"Mconv4_stage3\"\n}\nlayer {\n  name: \"Mconv5_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3\"\n  top: \"Mconv5_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv5_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3\"\n  top: \"Mconv5_stage3\"\n}\nlayer {\n  name: \"Mconv6_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3\"\n  top: \"Mconv6_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv6_stage3_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3\"\n  top: \"Mconv6_stage3\"\n}\nlayer {\n  name: \"Mconv7_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3\"\n  top: \"Mconv7_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"features_in_stage_4\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage3\"\n  bottom: \"conv5_3_CPM\"\n  top: \"features_in_stage_4\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage4\"\n  type: \"Convolution\"\n  bottom: \"features_in_stage_4\"\n  top: \"Mconv1_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv1_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4\"\n  top: \"Mconv1_stage4\"\n}\nlayer {\n  name: \"Mconv2_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4\"\n  top: \"Mconv2_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv2_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4\"\n  top: \"Mconv2_stage4\"\n}\nlayer {\n  name: \"Mconv3_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4\"\n  top: \"Mconv3_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv3_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4\"\n  top: \"Mconv3_stage4\"\n}\nlayer {\n  name: \"Mconv4_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4\"\n  top: \"Mconv4_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv4_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4\"\n  top: \"Mconv4_stage4\"\n}\nlayer {\n  name: \"Mconv5_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4\"\n  top: \"Mconv5_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv5_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4\"\n  top: \"Mconv5_stage4\"\n}\nlayer {\n  name: \"Mconv6_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4\"\n  top: \"Mconv6_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv6_stage4_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4\"\n  top: \"Mconv6_stage4\"\n}\nlayer {\n  name: \"Mconv7_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4\"\n  top: \"Mconv7_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"features_in_stage_5\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage4\"\n  bottom: \"conv5_3_CPM\"\n  top: \"features_in_stage_5\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage5\"\n  type: \"Convolution\"\n  bottom: \"features_in_stage_5\"\n  top: \"Mconv1_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv1_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5\"\n  top: \"Mconv1_stage5\"\n}\nlayer {\n  name: \"Mconv2_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5\"\n  top: \"Mconv2_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv2_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5\"\n  top: \"Mconv2_stage5\"\n}\nlayer {\n  name: \"Mconv3_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5\"\n  top: \"Mconv3_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv3_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5\"\n  top: \"Mconv3_stage5\"\n}\nlayer {\n  name: \"Mconv4_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5\"\n  top: \"Mconv4_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv4_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5\"\n  top: \"Mconv4_stage5\"\n}\nlayer {\n  name: \"Mconv5_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5\"\n  top: \"Mconv5_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv5_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5\"\n  top: \"Mconv5_stage5\"\n}\nlayer {\n  name: \"Mconv6_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5\"\n  top: \"Mconv6_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv6_stage5_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5\"\n  top: \"Mconv6_stage5\"\n}\nlayer {\n  name: \"Mconv7_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5\"\n  top: \"Mconv7_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"features_in_stage_6\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage5\"\n  bottom: \"conv5_3_CPM\"\n  top: \"features_in_stage_6\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage6\"\n  type: \"Convolution\"\n  bottom: \"features_in_stage_6\"\n  top: \"Mconv1_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv1_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6\"\n  top: \"Mconv1_stage6\"\n}\nlayer {\n  name: \"Mconv2_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6\"\n  top: \"Mconv2_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv2_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6\"\n  top: \"Mconv2_stage6\"\n}\nlayer {\n  name: \"Mconv3_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6\"\n  top: \"Mconv3_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv3_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6\"\n  top: \"Mconv3_stage6\"\n}\nlayer {\n  name: \"Mconv4_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6\"\n  top: \"Mconv4_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv4_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6\"\n  top: \"Mconv4_stage6\"\n}\nlayer {\n  name: \"Mconv5_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6\"\n  top: \"Mconv5_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv5_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6\"\n  top: \"Mconv5_stage6\"\n}\nlayer {\n  name: \"Mconv6_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6\"\n  top: \"Mconv6_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv6_stage6_re\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6\"\n  top: \"Mconv6_stage6\"\n}\nlayer {\n  name: \"Mconv7_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6\"\n#   top: \"Mconv7_stage6\"\n  top: \"net_output\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 71\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\n"
  },
  {
    "path": "models/getModels.bat",
    "content": ":: Avoid printing all the comments in the Windows cmd\n@echo off\n\necho ------------------------- BODY, FOOT, FACE, AND HAND MODELS -------------------------\necho ----- Downloading body pose (COCO and MPI), face and hand models -----\nSET WGET_EXE=..\\3rdparty\\windows\\wget\\wget.exe\nSET OPENPOSE_URL=http://vcl.snu.ac.kr/OpenPose/models/\nSET POSE_FOLDER=pose/\nSET FACE_FOLDER=face/\nSET HAND_FOLDER=hand/\n\necho:\necho ------------------------- POSE (BODY+FOOT) MODELS -------------------------\necho Body (BODY_25)\nset BODY_25_FOLDER=%POSE_FOLDER%body_25/\nset BODY_25_MODEL=%BODY_25_FOLDER%pose_iter_584000.caffemodel\n%WGET_EXE% -c %OPENPOSE_URL%%BODY_25_MODEL% -P %BODY_25_FOLDER%\n\necho Body (COCO)\nSET COCO_FOLDER=%POSE_FOLDER%coco/\nSET COCO_MODEL=%COCO_FOLDER%pose_iter_440000.caffemodel\n%WGET_EXE% -c %OPENPOSE_URL%%COCO_MODEL% -P %COCO_FOLDER%\n\necho:\necho Body (MPI)\nSET MPI_FOLDER=%POSE_FOLDER%mpi/\nSET MPI_MODEL=%MPI_FOLDER%pose_iter_160000.caffemodel\n%WGET_EXE% -c %OPENPOSE_URL%%MPI_MODEL% -P %MPI_FOLDER%\necho ----------------------- POSE DOWNLOADED -----------------------\n\necho:\necho ------------------------- FACE MODELS -------------------------\necho Face\nSET FACE_MODEL=%FACE_FOLDER%pose_iter_116000.caffemodel\n%WGET_EXE% -c %OPENPOSE_URL%%FACE_MODEL% -P %FACE_FOLDER%\necho ----------------------- FACE DOWNLOADED -----------------------\n\necho:\necho ------------------------- HAND MODELS -------------------------\necho Hand\nSET HAND_MODEL=%HAND_FOLDER%pose_iter_102000.caffemodel\n%WGET_EXE% -c %OPENPOSE_URL%%HAND_MODEL% -P %HAND_FOLDER%\necho ----------------------- HAND DOWNLOADED -----------------------\n"
  },
  {
    "path": "models/getModels.sh",
    "content": "# ------------------------- BODY, FOOT, FACE, AND HAND MODELS -------------------------\n# Downloading body pose (COCO and MPI), face and hand models\nOPENPOSE_URL=\"http://vcl.snu.ac.kr/OpenPose/models/\"\nPOSE_FOLDER=\"pose/\"\nFACE_FOLDER=\"face/\"\nHAND_FOLDER=\"hand/\"\n\n# ------------------------- POSE (BODY+FOOT) MODELS -------------------------\n# Body (BODY_25)\nBODY_25_FOLDER=${POSE_FOLDER}\"body_25/\"\nBODY_25_MODEL=${BODY_25_FOLDER}\"pose_iter_584000.caffemodel\"\nwget -c ${OPENPOSE_URL}${BODY_25_MODEL} -P ${BODY_25_FOLDER}\n\n# Body (COCO)\nCOCO_FOLDER=${POSE_FOLDER}\"coco/\"\nCOCO_MODEL=${COCO_FOLDER}\"pose_iter_440000.caffemodel\"\nwget -c ${OPENPOSE_URL}${COCO_MODEL} -P ${COCO_FOLDER}\n# Alternative: it will not check whether file was fully downloaded\n# if [ ! -f $COCO_MODEL ]; then\n#     wget ${OPENPOSE_URL}$COCO_MODEL -P $COCO_FOLDER\n# fi\n\n# Body (MPI)\nMPI_FOLDER=${POSE_FOLDER}\"mpi/\"\nMPI_MODEL=${MPI_FOLDER}\"pose_iter_160000.caffemodel\"\nwget -c ${OPENPOSE_URL}${MPI_MODEL} -P ${MPI_FOLDER}\n\n# \"------------------------- FACE MODELS -------------------------\"\n# Face\nFACE_MODEL=${FACE_FOLDER}\"pose_iter_116000.caffemodel\"\nwget -c ${OPENPOSE_URL}${FACE_MODEL} -P ${FACE_FOLDER}\n\n# \"------------------------- HAND MODELS -------------------------\"\n# Hand\nHAND_MODEL=$HAND_FOLDER\"pose_iter_102000.caffemodel\"\nwget -c ${OPENPOSE_URL}${HAND_MODEL} -P ${HAND_FOLDER}\n"
  },
  {
    "path": "models/hand/pose_deploy.prototxt",
    "content": "input: \"image\"\ninput_dim: 1 # Original: 2\ninput_dim: 3 # It crashes if not left to 3\ninput_dim: 1 # Original: 368\ninput_dim: 1 # Original: 368\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu1_1\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu1_2\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1_stage1\"\n  top: \"conv2_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu2_1\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu2_2\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2_stage1\"\n  top: \"conv3_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu3_1\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu3_2\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu3_3\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu3_4\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3_stage1\"\n  top: \"conv4_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu4_1\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu4_2\"\n  type: \"ReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu4_3\"\n  type: \"ReLU\"\n  bottom: \"conv4_3\"\n  top: \"conv4_3\"\n}\nlayer {\n  name: \"conv4_4\"\n  type: \"Convolution\"\n  bottom: \"conv4_3\"\n  top: \"conv4_4\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu4_4\"\n  type: \"ReLU\"\n  bottom: \"conv4_4\"\n  top: \"conv4_4\"\n}\nlayer {\n  name: \"conv5_1\"\n  type: \"Convolution\"\n  bottom: \"conv4_4\"\n  top: \"conv5_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu5_1\"\n  type: \"ReLU\"\n  bottom: \"conv5_1\"\n  top: \"conv5_1\"\n}\nlayer {\n  name: \"conv5_2\"\n  type: \"Convolution\"\n  bottom: \"conv5_1\"\n  top: \"conv5_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"xavier\"\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu5_2\"\n  type: \"ReLU\"\n  bottom: \"conv5_2\"\n  top: \"conv5_2\"\n}\nlayer {\n  name: \"conv5_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv5_2\"\n  top: \"conv5_3_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu5_4_stage1_3\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM\"\n  top: \"conv5_3_CPM\"\n}\nlayer {\n  name: \"conv6_1_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM\"\n  top: \"conv6_1_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"relu6_4_stage1_1\"\n  type: \"ReLU\"\n  bottom: \"conv6_1_CPM\"\n  top: \"conv6_1_CPM\"\n}\nlayer {\n  name: \"conv6_2_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv6_1_CPM\"\n  top: \"conv6_2_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"concat_stage2\"\n  type: \"Concat\"\n  bottom: \"conv6_2_CPM\"\n  bottom: \"conv5_3_CPM\"\n  top: \"concat_stage2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_2_stage2_1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2\"\n  top: \"Mconv1_stage2\"\n}\nlayer {\n  name: \"Mconv2_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2\"\n  top: \"Mconv2_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_3_stage2_2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2\"\n  top: \"Mconv2_stage2\"\n}\nlayer {\n  name: \"Mconv3_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2\"\n  top: \"Mconv3_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_4_stage2_3\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2\"\n  top: \"Mconv3_stage2\"\n}\nlayer {\n  name: \"Mconv4_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2\"\n  top: \"Mconv4_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_5_stage2_4\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2\"\n  top: \"Mconv4_stage2\"\n}\nlayer {\n  name: \"Mconv5_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2\"\n  top: \"Mconv5_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_6_stage2_5\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2\"\n  top: \"Mconv5_stage2\"\n}\nlayer {\n  name: \"Mconv6_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2\"\n  top: \"Mconv6_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_7_stage2_6\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2\"\n  top: \"Mconv6_stage2\"\n}\nlayer {\n  name: \"Mconv7_stage2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2\"\n  top: \"Mconv7_stage2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"concat_stage3\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage2\"\n  bottom: \"conv5_3_CPM\"\n  top: \"concat_stage3\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_2_stage3_1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3\"\n  top: \"Mconv1_stage3\"\n}\nlayer {\n  name: \"Mconv2_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3\"\n  top: \"Mconv2_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_3_stage3_2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3\"\n  top: \"Mconv2_stage3\"\n}\nlayer {\n  name: \"Mconv3_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3\"\n  top: \"Mconv3_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_4_stage3_3\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3\"\n  top: \"Mconv3_stage3\"\n}\nlayer {\n  name: \"Mconv4_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3\"\n  top: \"Mconv4_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_5_stage3_4\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3\"\n  top: \"Mconv4_stage3\"\n}\nlayer {\n  name: \"Mconv5_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3\"\n  top: \"Mconv5_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_6_stage3_5\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3\"\n  top: \"Mconv5_stage3\"\n}\nlayer {\n  name: \"Mconv6_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3\"\n  top: \"Mconv6_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_7_stage3_6\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3\"\n  top: \"Mconv6_stage3\"\n}\nlayer {\n  name: \"Mconv7_stage3\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3\"\n  top: \"Mconv7_stage3\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"concat_stage4\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage3\"\n  bottom: \"conv5_3_CPM\"\n  top: \"concat_stage4\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage4\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_2_stage4_1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4\"\n  top: \"Mconv1_stage4\"\n}\nlayer {\n  name: \"Mconv2_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4\"\n  top: \"Mconv2_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_3_stage4_2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4\"\n  top: \"Mconv2_stage4\"\n}\nlayer {\n  name: \"Mconv3_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4\"\n  top: \"Mconv3_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_4_stage4_3\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4\"\n  top: \"Mconv3_stage4\"\n}\nlayer {\n  name: \"Mconv4_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4\"\n  top: \"Mconv4_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_5_stage4_4\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4\"\n  top: \"Mconv4_stage4\"\n}\nlayer {\n  name: \"Mconv5_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4\"\n  top: \"Mconv5_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_6_stage4_5\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4\"\n  top: \"Mconv5_stage4\"\n}\nlayer {\n  name: \"Mconv6_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4\"\n  top: \"Mconv6_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_7_stage4_6\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4\"\n  top: \"Mconv6_stage4\"\n}\nlayer {\n  name: \"Mconv7_stage4\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4\"\n  top: \"Mconv7_stage4\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"concat_stage5\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage4\"\n  bottom: \"conv5_3_CPM\"\n  top: \"concat_stage5\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage5\"\n  type: \"Convolution\"\n  bottom: \"concat_stage5\"\n  top: \"Mconv1_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_2_stage5_1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5\"\n  top: \"Mconv1_stage5\"\n}\nlayer {\n  name: \"Mconv2_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5\"\n  top: \"Mconv2_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_3_stage5_2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5\"\n  top: \"Mconv2_stage5\"\n}\nlayer {\n  name: \"Mconv3_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5\"\n  top: \"Mconv3_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_4_stage5_3\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5\"\n  top: \"Mconv3_stage5\"\n}\nlayer {\n  name: \"Mconv4_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5\"\n  top: \"Mconv4_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_5_stage5_4\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5\"\n  top: \"Mconv4_stage5\"\n}\nlayer {\n  name: \"Mconv5_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5\"\n  top: \"Mconv5_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_6_stage5_5\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5\"\n  top: \"Mconv5_stage5\"\n}\nlayer {\n  name: \"Mconv6_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5\"\n  top: \"Mconv6_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_7_stage5_6\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5\"\n  top: \"Mconv6_stage5\"\n}\nlayer {\n  name: \"Mconv7_stage5\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5\"\n  top: \"Mconv7_stage5\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"concat_stage6\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage5\"\n  bottom: \"conv5_3_CPM\"\n  top: \"concat_stage6\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage6\"\n  type: \"Convolution\"\n  bottom: \"concat_stage6\"\n  top: \"Mconv1_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_2_stage6_1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6\"\n  top: \"Mconv1_stage6\"\n}\nlayer {\n  name: \"Mconv2_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6\"\n  top: \"Mconv2_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_3_stage6_2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6\"\n  top: \"Mconv2_stage6\"\n}\nlayer {\n  name: \"Mconv3_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6\"\n  top: \"Mconv3_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_4_stage6_3\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6\"\n  top: \"Mconv3_stage6\"\n}\nlayer {\n  name: \"Mconv4_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6\"\n  top: \"Mconv4_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_5_stage6_4\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6\"\n  top: \"Mconv4_stage6\"\n}\nlayer {\n  name: \"Mconv5_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6\"\n  top: \"Mconv5_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_6_stage6_5\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6\"\n  top: \"Mconv5_stage6\"\n}\nlayer {\n  name: \"Mconv6_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6\"\n  top: \"Mconv6_stage6\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\nlayer {\n  name: \"Mrelu1_7_stage6_6\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6\"\n  top: \"Mconv6_stage6\"\n}\nlayer {\n  name: \"Mconv7_stage6\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6\"\n#   top: \"Mconv7_stage6\"\n  top: \"net_output\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 22\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n    dilation: 1\n  }\n}\n\n"
  },
  {
    "path": "models/pose/body_25/pose_deploy.prototxt",
    "content": "name: \"OpenPose - BODY_25\"\ninput: \"image\"\ninput_dim: 1 # This value will be defined at runtime\ninput_dim: 3\ninput_dim: 16 # This value will be defined at runtime\ninput_dim: 16 # This value will be defined at runtime\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu1_1\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu1_2\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1_stage1\"\n  top: \"conv2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu2_1\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu2_2\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2_stage1\"\n  top: \"conv3_1\"\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu3_1\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu3_2\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu3_3\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu3_4\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3_stage1\"\n  top: \"conv4_1\"\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"relu4_1\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"prelu4_2\"\n  type: \"PReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3_CPM\"\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"prelu4_3_CPM\"\n  type: \"PReLU\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_3_CPM\"\n}\nlayer {\n  name: \"conv4_4_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_4_CPM\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"prelu4_4_CPM\"\n  type: \"PReLU\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv4_4_CPM\"\n}\nlayer {\n  name: \"Mconv1_stage0_L2_0\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"Mconv1_stage0_L2_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L2_0\"\n  top: \"Mconv1_stage0_L2_0\"\n}\nlayer {\n  name: \"Mconv1_stage0_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L2_0\"\n  top: \"Mconv1_stage0_L2_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L2_1\"\n  top: \"Mconv1_stage0_L2_1\"\n}\nlayer {\n  name: \"Mconv1_stage0_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L2_1\"\n  top: \"Mconv1_stage0_L2_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L2_2\"\n  top: \"Mconv1_stage0_L2_2\"\n}\nlayer {\n  name: \"Mconv1_stage0_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage0_L2_0\"\n  bottom: \"Mconv1_stage0_L2_1\"\n  bottom: \"Mconv1_stage0_L2_2\"\n  top: \"Mconv1_stage0_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage0_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L2_concat\"\n  top: \"Mconv2_stage0_L2_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L2_0\"\n  top: \"Mconv2_stage0_L2_0\"\n}\nlayer {\n  name: \"Mconv2_stage0_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L2_0\"\n  top: \"Mconv2_stage0_L2_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L2_1\"\n  top: \"Mconv2_stage0_L2_1\"\n}\nlayer {\n  name: \"Mconv2_stage0_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L2_1\"\n  top: \"Mconv2_stage0_L2_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L2_2\"\n  top: \"Mconv2_stage0_L2_2\"\n}\nlayer {\n  name: \"Mconv2_stage0_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage0_L2_0\"\n  bottom: \"Mconv2_stage0_L2_1\"\n  bottom: \"Mconv2_stage0_L2_2\"\n  top: \"Mconv2_stage0_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage0_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L2_concat\"\n  top: \"Mconv3_stage0_L2_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L2_0\"\n  top: \"Mconv3_stage0_L2_0\"\n}\nlayer {\n  name: \"Mconv3_stage0_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L2_0\"\n  top: \"Mconv3_stage0_L2_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L2_1\"\n  top: \"Mconv3_stage0_L2_1\"\n}\nlayer {\n  name: \"Mconv3_stage0_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L2_1\"\n  top: \"Mconv3_stage0_L2_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L2_2\"\n  top: \"Mconv3_stage0_L2_2\"\n}\nlayer {\n  name: \"Mconv3_stage0_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage0_L2_0\"\n  bottom: \"Mconv3_stage0_L2_1\"\n  bottom: \"Mconv3_stage0_L2_2\"\n  top: \"Mconv3_stage0_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage0_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L2_concat\"\n  top: \"Mconv4_stage0_L2_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L2_0\"\n  top: \"Mconv4_stage0_L2_0\"\n}\nlayer {\n  name: \"Mconv4_stage0_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L2_0\"\n  top: \"Mconv4_stage0_L2_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L2_1\"\n  top: \"Mconv4_stage0_L2_1\"\n}\nlayer {\n  name: \"Mconv4_stage0_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L2_1\"\n  top: \"Mconv4_stage0_L2_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L2_2\"\n  top: \"Mconv4_stage0_L2_2\"\n}\nlayer {\n  name: \"Mconv4_stage0_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage0_L2_0\"\n  bottom: \"Mconv4_stage0_L2_1\"\n  bottom: \"Mconv4_stage0_L2_2\"\n  top: \"Mconv4_stage0_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage0_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L2_concat\"\n  top: \"Mconv5_stage0_L2_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L2_0\"\n  top: \"Mconv5_stage0_L2_0\"\n}\nlayer {\n  name: \"Mconv5_stage0_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L2_0\"\n  top: \"Mconv5_stage0_L2_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L2_1\"\n  top: \"Mconv5_stage0_L2_1\"\n}\nlayer {\n  name: \"Mconv5_stage0_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L2_1\"\n  top: \"Mconv5_stage0_L2_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L2_2\"\n  top: \"Mconv5_stage0_L2_2\"\n}\nlayer {\n  name: \"Mconv5_stage0_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage0_L2_0\"\n  bottom: \"Mconv5_stage0_L2_1\"\n  bottom: \"Mconv5_stage0_L2_2\"\n  top: \"Mconv5_stage0_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage0_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L2_concat\"\n  top: \"Mconv6_stage0_L2\"\n  convolution_param {\n    num_output: 256\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage0_L2\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage0_L2\"\n  top: \"Mconv6_stage0_L2\"\n}\nlayer {\n  name: \"Mconv7_stage0_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage0_L2\"\n  top: \"Mconv7_stage0_L2\"\n  convolution_param {\n    num_output: 52\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"concat_stage1_L2\"\n  type: \"Concat\"\n  bottom: \"conv4_4_CPM\"\n  bottom: \"Mconv7_stage0_L2\"\n  top: \"concat_stage1_L2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage1_L2_0\"\n  type: \"Convolution\"\n  bottom: \"concat_stage1_L2\"\n  top: \"Mconv1_stage1_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L2_0\"\n  top: \"Mconv1_stage1_L2_0\"\n}\nlayer {\n  name: \"Mconv1_stage1_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L2_0\"\n  top: \"Mconv1_stage1_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L2_1\"\n  top: \"Mconv1_stage1_L2_1\"\n}\nlayer {\n  name: \"Mconv1_stage1_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L2_1\"\n  top: \"Mconv1_stage1_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L2_2\"\n  top: \"Mconv1_stage1_L2_2\"\n}\nlayer {\n  name: \"Mconv1_stage1_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage1_L2_0\"\n  bottom: \"Mconv1_stage1_L2_1\"\n  bottom: \"Mconv1_stage1_L2_2\"\n  top: \"Mconv1_stage1_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage1_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L2_concat\"\n  top: \"Mconv2_stage1_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L2_0\"\n  top: \"Mconv2_stage1_L2_0\"\n}\nlayer {\n  name: \"Mconv2_stage1_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L2_0\"\n  top: \"Mconv2_stage1_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L2_1\"\n  top: \"Mconv2_stage1_L2_1\"\n}\nlayer {\n  name: \"Mconv2_stage1_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L2_1\"\n  top: \"Mconv2_stage1_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L2_2\"\n  top: \"Mconv2_stage1_L2_2\"\n}\nlayer {\n  name: \"Mconv2_stage1_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage1_L2_0\"\n  bottom: \"Mconv2_stage1_L2_1\"\n  bottom: \"Mconv2_stage1_L2_2\"\n  top: \"Mconv2_stage1_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage1_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L2_concat\"\n  top: \"Mconv3_stage1_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L2_0\"\n  top: \"Mconv3_stage1_L2_0\"\n}\nlayer {\n  name: \"Mconv3_stage1_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L2_0\"\n  top: \"Mconv3_stage1_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L2_1\"\n  top: \"Mconv3_stage1_L2_1\"\n}\nlayer {\n  name: \"Mconv3_stage1_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L2_1\"\n  top: \"Mconv3_stage1_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L2_2\"\n  top: \"Mconv3_stage1_L2_2\"\n}\nlayer {\n  name: \"Mconv3_stage1_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage1_L2_0\"\n  bottom: \"Mconv3_stage1_L2_1\"\n  bottom: \"Mconv3_stage1_L2_2\"\n  top: \"Mconv3_stage1_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage1_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L2_concat\"\n  top: \"Mconv4_stage1_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L2_0\"\n  top: \"Mconv4_stage1_L2_0\"\n}\nlayer {\n  name: \"Mconv4_stage1_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L2_0\"\n  top: \"Mconv4_stage1_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L2_1\"\n  top: \"Mconv4_stage1_L2_1\"\n}\nlayer {\n  name: \"Mconv4_stage1_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L2_1\"\n  top: \"Mconv4_stage1_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L2_2\"\n  top: \"Mconv4_stage1_L2_2\"\n}\nlayer {\n  name: \"Mconv4_stage1_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage1_L2_0\"\n  bottom: \"Mconv4_stage1_L2_1\"\n  bottom: \"Mconv4_stage1_L2_2\"\n  top: \"Mconv4_stage1_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage1_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L2_concat\"\n  top: \"Mconv5_stage1_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L2_0\"\n  top: \"Mconv5_stage1_L2_0\"\n}\nlayer {\n  name: \"Mconv5_stage1_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L2_0\"\n  top: \"Mconv5_stage1_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L2_1\"\n  top: \"Mconv5_stage1_L2_1\"\n}\nlayer {\n  name: \"Mconv5_stage1_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L2_1\"\n  top: \"Mconv5_stage1_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L2_2\"\n  top: \"Mconv5_stage1_L2_2\"\n}\nlayer {\n  name: \"Mconv5_stage1_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage1_L2_0\"\n  bottom: \"Mconv5_stage1_L2_1\"\n  bottom: \"Mconv5_stage1_L2_2\"\n  top: \"Mconv5_stage1_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage1_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L2_concat\"\n  top: \"Mconv6_stage1_L2\"\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage1_L2\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage1_L2\"\n  top: \"Mconv6_stage1_L2\"\n}\nlayer {\n  name: \"Mconv7_stage1_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage1_L2\"\n  top: \"Mconv7_stage1_L2\"\n  convolution_param {\n    num_output: 52\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"concat_stage2_L2\"\n  type: \"Concat\"\n  bottom: \"conv4_4_CPM\"\n  bottom: \"Mconv7_stage1_L2\"\n  top: \"concat_stage2_L2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2_L2_0\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2_L2\"\n  top: \"Mconv1_stage2_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage2_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage2_L2_0\"\n  top: \"Mconv1_stage2_L2_0\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2_0\"\n  top: \"Mconv1_stage2_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage2_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage2_L2_1\"\n  top: \"Mconv1_stage2_L2_1\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2_1\"\n  top: \"Mconv1_stage2_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage2_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage2_L2_2\"\n  top: \"Mconv1_stage2_L2_2\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage2_L2_0\"\n  bottom: \"Mconv1_stage2_L2_1\"\n  bottom: \"Mconv1_stage2_L2_2\"\n  top: \"Mconv1_stage2_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage2_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2_concat\"\n  top: \"Mconv2_stage2_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage2_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage2_L2_0\"\n  top: \"Mconv2_stage2_L2_0\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2_0\"\n  top: \"Mconv2_stage2_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage2_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage2_L2_1\"\n  top: \"Mconv2_stage2_L2_1\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2_1\"\n  top: \"Mconv2_stage2_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage2_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage2_L2_2\"\n  top: \"Mconv2_stage2_L2_2\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage2_L2_0\"\n  bottom: \"Mconv2_stage2_L2_1\"\n  bottom: \"Mconv2_stage2_L2_2\"\n  top: \"Mconv2_stage2_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage2_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2_concat\"\n  top: \"Mconv3_stage2_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage2_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage2_L2_0\"\n  top: \"Mconv3_stage2_L2_0\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2_0\"\n  top: \"Mconv3_stage2_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage2_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage2_L2_1\"\n  top: \"Mconv3_stage2_L2_1\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2_1\"\n  top: \"Mconv3_stage2_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage2_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage2_L2_2\"\n  top: \"Mconv3_stage2_L2_2\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage2_L2_0\"\n  bottom: \"Mconv3_stage2_L2_1\"\n  bottom: \"Mconv3_stage2_L2_2\"\n  top: \"Mconv3_stage2_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage2_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2_concat\"\n  top: \"Mconv4_stage2_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage2_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage2_L2_0\"\n  top: \"Mconv4_stage2_L2_0\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2_0\"\n  top: \"Mconv4_stage2_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage2_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage2_L2_1\"\n  top: \"Mconv4_stage2_L2_1\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2_1\"\n  top: \"Mconv4_stage2_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage2_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage2_L2_2\"\n  top: \"Mconv4_stage2_L2_2\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage2_L2_0\"\n  bottom: \"Mconv4_stage2_L2_1\"\n  bottom: \"Mconv4_stage2_L2_2\"\n  top: \"Mconv4_stage2_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage2_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2_concat\"\n  top: \"Mconv5_stage2_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage2_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage2_L2_0\"\n  top: \"Mconv5_stage2_L2_0\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2_0\"\n  top: \"Mconv5_stage2_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage2_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage2_L2_1\"\n  top: \"Mconv5_stage2_L2_1\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2_1\"\n  top: \"Mconv5_stage2_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage2_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage2_L2_2\"\n  top: \"Mconv5_stage2_L2_2\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage2_L2_0\"\n  bottom: \"Mconv5_stage2_L2_1\"\n  bottom: \"Mconv5_stage2_L2_2\"\n  top: \"Mconv5_stage2_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2_concat\"\n  top: \"Mconv6_stage2_L2\"\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage2_L2\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n}\nlayer {\n  name: \"Mconv7_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv7_stage2_L2\"\n  convolution_param {\n    num_output: 52\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"concat_stage3_L2\"\n  type: \"Concat\"\n  bottom: \"conv4_4_CPM\"\n  bottom: \"Mconv7_stage2_L2\"\n  top: \"concat_stage3_L2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3_L2_0\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3_L2\"\n  top: \"Mconv1_stage3_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage3_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage3_L2_0\"\n  top: \"Mconv1_stage3_L2_0\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2_0\"\n  top: \"Mconv1_stage3_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage3_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage3_L2_1\"\n  top: \"Mconv1_stage3_L2_1\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2_1\"\n  top: \"Mconv1_stage3_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage3_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage3_L2_2\"\n  top: \"Mconv1_stage3_L2_2\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage3_L2_0\"\n  bottom: \"Mconv1_stage3_L2_1\"\n  bottom: \"Mconv1_stage3_L2_2\"\n  top: \"Mconv1_stage3_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage3_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2_concat\"\n  top: \"Mconv2_stage3_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage3_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage3_L2_0\"\n  top: \"Mconv2_stage3_L2_0\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2_0\"\n  top: \"Mconv2_stage3_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage3_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage3_L2_1\"\n  top: \"Mconv2_stage3_L2_1\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2_1\"\n  top: \"Mconv2_stage3_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage3_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage3_L2_2\"\n  top: \"Mconv2_stage3_L2_2\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage3_L2_0\"\n  bottom: \"Mconv2_stage3_L2_1\"\n  bottom: \"Mconv2_stage3_L2_2\"\n  top: \"Mconv2_stage3_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage3_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2_concat\"\n  top: \"Mconv3_stage3_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage3_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage3_L2_0\"\n  top: \"Mconv3_stage3_L2_0\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2_0\"\n  top: \"Mconv3_stage3_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage3_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage3_L2_1\"\n  top: \"Mconv3_stage3_L2_1\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2_1\"\n  top: \"Mconv3_stage3_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage3_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage3_L2_2\"\n  top: \"Mconv3_stage3_L2_2\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage3_L2_0\"\n  bottom: \"Mconv3_stage3_L2_1\"\n  bottom: \"Mconv3_stage3_L2_2\"\n  top: \"Mconv3_stage3_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage3_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2_concat\"\n  top: \"Mconv4_stage3_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage3_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage3_L2_0\"\n  top: \"Mconv4_stage3_L2_0\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2_0\"\n  top: \"Mconv4_stage3_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage3_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage3_L2_1\"\n  top: \"Mconv4_stage3_L2_1\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2_1\"\n  top: \"Mconv4_stage3_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage3_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage3_L2_2\"\n  top: \"Mconv4_stage3_L2_2\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage3_L2_0\"\n  bottom: \"Mconv4_stage3_L2_1\"\n  bottom: \"Mconv4_stage3_L2_2\"\n  top: \"Mconv4_stage3_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage3_L2_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2_concat\"\n  top: \"Mconv5_stage3_L2_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage3_L2_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage3_L2_0\"\n  top: \"Mconv5_stage3_L2_0\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2_0\"\n  top: \"Mconv5_stage3_L2_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage3_L2_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage3_L2_1\"\n  top: \"Mconv5_stage3_L2_1\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2_1\"\n  top: \"Mconv5_stage3_L2_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage3_L2_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage3_L2_2\"\n  top: \"Mconv5_stage3_L2_2\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage3_L2_0\"\n  bottom: \"Mconv5_stage3_L2_1\"\n  bottom: \"Mconv5_stage3_L2_2\"\n  top: \"Mconv5_stage3_L2_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2_concat\"\n  top: \"Mconv6_stage3_L2\"\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage3_L2\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n}\nlayer {\n  name: \"Mconv7_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv7_stage3_L2\"\n  convolution_param {\n    num_output: 52\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"concat_stage0_L1\"\n  type: \"Concat\"\n  bottom: \"conv4_4_CPM\"\n  bottom: \"Mconv7_stage3_L2\"\n  top: \"concat_stage0_L1\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage0_L1_0\"\n  type: \"Convolution\"\n  bottom: \"concat_stage0_L1\"\n  top: \"Mconv1_stage0_L1_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L1_0\"\n  top: \"Mconv1_stage0_L1_0\"\n}\nlayer {\n  name: \"Mconv1_stage0_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L1_0\"\n  top: \"Mconv1_stage0_L1_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L1_1\"\n  top: \"Mconv1_stage0_L1_1\"\n}\nlayer {\n  name: \"Mconv1_stage0_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L1_1\"\n  top: \"Mconv1_stage0_L1_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage0_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage0_L1_2\"\n  top: \"Mconv1_stage0_L1_2\"\n}\nlayer {\n  name: \"Mconv1_stage0_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage0_L1_0\"\n  bottom: \"Mconv1_stage0_L1_1\"\n  bottom: \"Mconv1_stage0_L1_2\"\n  top: \"Mconv1_stage0_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage0_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage0_L1_concat\"\n  top: \"Mconv2_stage0_L1_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L1_0\"\n  top: \"Mconv2_stage0_L1_0\"\n}\nlayer {\n  name: \"Mconv2_stage0_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L1_0\"\n  top: \"Mconv2_stage0_L1_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L1_1\"\n  top: \"Mconv2_stage0_L1_1\"\n}\nlayer {\n  name: \"Mconv2_stage0_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L1_1\"\n  top: \"Mconv2_stage0_L1_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage0_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage0_L1_2\"\n  top: \"Mconv2_stage0_L1_2\"\n}\nlayer {\n  name: \"Mconv2_stage0_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage0_L1_0\"\n  bottom: \"Mconv2_stage0_L1_1\"\n  bottom: \"Mconv2_stage0_L1_2\"\n  top: \"Mconv2_stage0_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage0_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage0_L1_concat\"\n  top: \"Mconv3_stage0_L1_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L1_0\"\n  top: \"Mconv3_stage0_L1_0\"\n}\nlayer {\n  name: \"Mconv3_stage0_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L1_0\"\n  top: \"Mconv3_stage0_L1_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L1_1\"\n  top: \"Mconv3_stage0_L1_1\"\n}\nlayer {\n  name: \"Mconv3_stage0_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L1_1\"\n  top: \"Mconv3_stage0_L1_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage0_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage0_L1_2\"\n  top: \"Mconv3_stage0_L1_2\"\n}\nlayer {\n  name: \"Mconv3_stage0_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage0_L1_0\"\n  bottom: \"Mconv3_stage0_L1_1\"\n  bottom: \"Mconv3_stage0_L1_2\"\n  top: \"Mconv3_stage0_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage0_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage0_L1_concat\"\n  top: \"Mconv4_stage0_L1_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L1_0\"\n  top: \"Mconv4_stage0_L1_0\"\n}\nlayer {\n  name: \"Mconv4_stage0_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L1_0\"\n  top: \"Mconv4_stage0_L1_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L1_1\"\n  top: \"Mconv4_stage0_L1_1\"\n}\nlayer {\n  name: \"Mconv4_stage0_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L1_1\"\n  top: \"Mconv4_stage0_L1_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage0_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage0_L1_2\"\n  top: \"Mconv4_stage0_L1_2\"\n}\nlayer {\n  name: \"Mconv4_stage0_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage0_L1_0\"\n  bottom: \"Mconv4_stage0_L1_1\"\n  bottom: \"Mconv4_stage0_L1_2\"\n  top: \"Mconv4_stage0_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage0_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage0_L1_concat\"\n  top: \"Mconv5_stage0_L1_0\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L1_0\"\n  top: \"Mconv5_stage0_L1_0\"\n}\nlayer {\n  name: \"Mconv5_stage0_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L1_0\"\n  top: \"Mconv5_stage0_L1_1\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L1_1\"\n  top: \"Mconv5_stage0_L1_1\"\n}\nlayer {\n  name: \"Mconv5_stage0_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L1_1\"\n  top: \"Mconv5_stage0_L1_2\"\n  convolution_param {\n    num_output: 96\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage0_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage0_L1_2\"\n  top: \"Mconv5_stage0_L1_2\"\n}\nlayer {\n  name: \"Mconv5_stage0_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage0_L1_0\"\n  bottom: \"Mconv5_stage0_L1_1\"\n  bottom: \"Mconv5_stage0_L1_2\"\n  top: \"Mconv5_stage0_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage0_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage0_L1_concat\"\n  top: \"Mconv6_stage0_L1\"\n  convolution_param {\n    num_output: 256\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage0_L1\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage0_L1\"\n  top: \"Mconv6_stage0_L1\"\n}\nlayer {\n  name: \"Mconv7_stage0_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage0_L1\"\n  top: \"Mconv7_stage0_L1\"\n  convolution_param {\n    num_output: 26\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"concat_stage1_L1\"\n  type: \"Concat\"\n  bottom: \"conv4_4_CPM\"\n  bottom: \"Mconv7_stage0_L1\"\n  bottom: \"Mconv7_stage3_L2\"\n  top: \"concat_stage1_L1\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage1_L1_0\"\n  type: \"Convolution\"\n  bottom: \"concat_stage1_L1\"\n  top: \"Mconv1_stage1_L1_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L1_0\"\n  top: \"Mconv1_stage1_L1_0\"\n}\nlayer {\n  name: \"Mconv1_stage1_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L1_0\"\n  top: \"Mconv1_stage1_L1_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L1_1\"\n  top: \"Mconv1_stage1_L1_1\"\n}\nlayer {\n  name: \"Mconv1_stage1_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L1_1\"\n  top: \"Mconv1_stage1_L1_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu1_stage1_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv1_stage1_L1_2\"\n  top: \"Mconv1_stage1_L1_2\"\n}\nlayer {\n  name: \"Mconv1_stage1_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv1_stage1_L1_0\"\n  bottom: \"Mconv1_stage1_L1_1\"\n  bottom: \"Mconv1_stage1_L1_2\"\n  top: \"Mconv1_stage1_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv2_stage1_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage1_L1_concat\"\n  top: \"Mconv2_stage1_L1_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L1_0\"\n  top: \"Mconv2_stage1_L1_0\"\n}\nlayer {\n  name: \"Mconv2_stage1_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L1_0\"\n  top: \"Mconv2_stage1_L1_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L1_1\"\n  top: \"Mconv2_stage1_L1_1\"\n}\nlayer {\n  name: \"Mconv2_stage1_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L1_1\"\n  top: \"Mconv2_stage1_L1_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu2_stage1_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv2_stage1_L1_2\"\n  top: \"Mconv2_stage1_L1_2\"\n}\nlayer {\n  name: \"Mconv2_stage1_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv2_stage1_L1_0\"\n  bottom: \"Mconv2_stage1_L1_1\"\n  bottom: \"Mconv2_stage1_L1_2\"\n  top: \"Mconv2_stage1_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv3_stage1_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage1_L1_concat\"\n  top: \"Mconv3_stage1_L1_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L1_0\"\n  top: \"Mconv3_stage1_L1_0\"\n}\nlayer {\n  name: \"Mconv3_stage1_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L1_0\"\n  top: \"Mconv3_stage1_L1_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L1_1\"\n  top: \"Mconv3_stage1_L1_1\"\n}\nlayer {\n  name: \"Mconv3_stage1_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L1_1\"\n  top: \"Mconv3_stage1_L1_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu3_stage1_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv3_stage1_L1_2\"\n  top: \"Mconv3_stage1_L1_2\"\n}\nlayer {\n  name: \"Mconv3_stage1_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv3_stage1_L1_0\"\n  bottom: \"Mconv3_stage1_L1_1\"\n  bottom: \"Mconv3_stage1_L1_2\"\n  top: \"Mconv3_stage1_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv4_stage1_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage1_L1_concat\"\n  top: \"Mconv4_stage1_L1_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L1_0\"\n  top: \"Mconv4_stage1_L1_0\"\n}\nlayer {\n  name: \"Mconv4_stage1_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L1_0\"\n  top: \"Mconv4_stage1_L1_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L1_1\"\n  top: \"Mconv4_stage1_L1_1\"\n}\nlayer {\n  name: \"Mconv4_stage1_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L1_1\"\n  top: \"Mconv4_stage1_L1_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu4_stage1_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv4_stage1_L1_2\"\n  top: \"Mconv4_stage1_L1_2\"\n}\nlayer {\n  name: \"Mconv4_stage1_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv4_stage1_L1_0\"\n  bottom: \"Mconv4_stage1_L1_1\"\n  bottom: \"Mconv4_stage1_L1_2\"\n  top: \"Mconv4_stage1_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv5_stage1_L1_0\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage1_L1_concat\"\n  top: \"Mconv5_stage1_L1_0\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L1_0\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L1_0\"\n  top: \"Mconv5_stage1_L1_0\"\n}\nlayer {\n  name: \"Mconv5_stage1_L1_1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L1_0\"\n  top: \"Mconv5_stage1_L1_1\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L1_1\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L1_1\"\n  top: \"Mconv5_stage1_L1_1\"\n}\nlayer {\n  name: \"Mconv5_stage1_L1_2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L1_1\"\n  top: \"Mconv5_stage1_L1_2\"\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n  }\n}\nlayer {\n  name: \"Mprelu5_stage1_L1_2\"\n  type: \"PReLU\"\n  bottom: \"Mconv5_stage1_L1_2\"\n  top: \"Mconv5_stage1_L1_2\"\n}\nlayer {\n  name: \"Mconv5_stage1_L1_concat\"\n  type: \"Concat\"\n  bottom: \"Mconv5_stage1_L1_0\"\n  bottom: \"Mconv5_stage1_L1_1\"\n  bottom: \"Mconv5_stage1_L1_2\"\n  top: \"Mconv5_stage1_L1_concat\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv6_stage1_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage1_L1_concat\"\n  top: \"Mconv6_stage1_L1\"\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"Mprelu6_stage1_L1\"\n  type: \"PReLU\"\n  bottom: \"Mconv6_stage1_L1\"\n  top: \"Mconv6_stage1_L1\"\n}\nlayer {\n  name: \"Mconv7_stage1_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage1_L1\"\n  top: \"Mconv7_stage1_L1\"\n  convolution_param {\n    num_output: 26\n    pad: 0\n    kernel_size: 1\n  }\n}\nlayer {\n  name: \"net_output\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage1_L1\"\n  bottom: \"Mconv7_stage3_L2\"\n  top: \"net_output\"\n  concat_param {\n    axis: 1\n  }\n}\n"
  },
  {
    "path": "models/pose/coco/pose_deploy_linevec.prototxt",
    "content": "input: \"image\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 1 # This value will be defined at runtime\ninput_dim: 1 # This value will be defined at runtime\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_1\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_2\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1_stage1\"\n  top: \"conv2_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_1\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_2\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2_stage1\"\n  top: \"conv3_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_1\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_2\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_3\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_4\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3_stage1\"\n  top: \"conv4_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_1\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_2\"\n  type: \"ReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_3_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_3_CPM\"\n}\nlayer {\n  name: \"conv4_4_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_4_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_4_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv4_4_CPM\"\n}\nlayer {\n  name: \"conv5_1_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_1_CPM_L1\"\n}\nlayer {\n  name: \"conv5_1_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_1_CPM_L2\"\n}\nlayer {\n  name: \"conv5_2_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n}\nlayer {\n  name: \"conv5_2_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n}\nlayer {\n  name: \"conv5_3_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n}\nlayer {\n  name: \"conv5_3_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n}\nlayer {\n  name: \"conv5_4_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n}\nlayer {\n  name: \"conv5_4_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n}\nlayer {\n  name: \"conv5_5_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_5_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_5_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_5_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage2\"\n  type: \"Concat\"\n  bottom: \"conv5_5_CPM_L1\"\n  bottom: \"conv5_5_CPM_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv1_stage2_L1\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv1_stage2_L2\"\n}\nlayer {\n  name: \"Mconv2_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n}\nlayer {\n  name: \"Mconv3_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n}\nlayer {\n  name: \"Mconv4_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n}\nlayer {\n  name: \"Mconv5_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n}\nlayer {\n  name: \"Mconv6_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n}\nlayer {\n  name: \"Mconv6_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n}\nlayer {\n  name: \"Mconv7_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv7_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv7_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage3\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage2_L1\"\n  bottom: \"Mconv7_stage2_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage3\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv1_stage3_L1\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv1_stage3_L2\"\n}\nlayer {\n  name: \"Mconv2_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n}\nlayer {\n  name: \"Mconv3_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n}\nlayer {\n  name: \"Mconv4_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n}\nlayer {\n  name: \"Mconv5_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n}\nlayer {\n  name: \"Mconv6_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n}\nlayer {\n  name: \"Mconv6_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n}\nlayer {\n  name: \"Mconv7_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv7_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv7_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage4\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage3_L1\"\n  bottom: \"Mconv7_stage3_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage4\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv1_stage4_L1\"\n}\nlayer {\n  name: \"Mconv1_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv1_stage4_L2\"\n}\nlayer {\n  name: \"Mconv2_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n}\nlayer {\n  name: \"Mconv2_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n}\nlayer {\n  name: \"Mconv3_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n}\nlayer {\n  name: \"Mconv3_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n}\nlayer {\n  name: \"Mconv4_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n}\nlayer {\n  name: \"Mconv4_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n}\nlayer {\n  name: \"Mconv5_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n}\nlayer {\n  name: \"Mconv5_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n}\nlayer {\n  name: \"Mconv6_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n}\nlayer {\n  name: \"Mconv6_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n}\nlayer {\n  name: \"Mconv7_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv7_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv7_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage5\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage4_L1\"\n  bottom: \"Mconv7_stage4_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage5\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage5\"\n  top: \"Mconv1_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5_L1\"\n  top: \"Mconv1_stage5_L1\"\n}\nlayer {\n  name: \"Mconv1_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage5\"\n  top: \"Mconv1_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5_L2\"\n  top: \"Mconv1_stage5_L2\"\n}\nlayer {\n  name: \"Mconv2_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5_L1\"\n  top: \"Mconv2_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5_L1\"\n  top: \"Mconv2_stage5_L1\"\n}\nlayer {\n  name: \"Mconv2_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5_L2\"\n  top: \"Mconv2_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5_L2\"\n  top: \"Mconv2_stage5_L2\"\n}\nlayer {\n  name: \"Mconv3_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5_L1\"\n  top: \"Mconv3_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5_L1\"\n  top: \"Mconv3_stage5_L1\"\n}\nlayer {\n  name: \"Mconv3_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5_L2\"\n  top: \"Mconv3_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5_L2\"\n  top: \"Mconv3_stage5_L2\"\n}\nlayer {\n  name: \"Mconv4_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5_L1\"\n  top: \"Mconv4_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5_L1\"\n  top: \"Mconv4_stage5_L1\"\n}\nlayer {\n  name: \"Mconv4_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5_L2\"\n  top: \"Mconv4_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5_L2\"\n  top: \"Mconv4_stage5_L2\"\n}\nlayer {\n  name: \"Mconv5_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5_L1\"\n  top: \"Mconv5_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5_L1\"\n  top: \"Mconv5_stage5_L1\"\n}\nlayer {\n  name: \"Mconv5_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5_L2\"\n  top: \"Mconv5_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5_L2\"\n  top: \"Mconv5_stage5_L2\"\n}\nlayer {\n  name: \"Mconv6_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5_L1\"\n  top: \"Mconv6_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5_L1\"\n  top: \"Mconv6_stage5_L1\"\n}\nlayer {\n  name: \"Mconv6_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5_L2\"\n  top: \"Mconv6_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5_L2\"\n  top: \"Mconv6_stage5_L2\"\n}\nlayer {\n  name: \"Mconv7_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5_L1\"\n  top: \"Mconv7_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5_L2\"\n  top: \"Mconv7_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage6\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage5_L1\"\n  bottom: \"Mconv7_stage5_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage6\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage6\"\n  top: \"Mconv1_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6_L1\"\n  top: \"Mconv1_stage6_L1\"\n}\nlayer {\n  name: \"Mconv1_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage6\"\n  top: \"Mconv1_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6_L2\"\n  top: \"Mconv1_stage6_L2\"\n}\nlayer {\n  name: \"Mconv2_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6_L1\"\n  top: \"Mconv2_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6_L1\"\n  top: \"Mconv2_stage6_L1\"\n}\nlayer {\n  name: \"Mconv2_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6_L2\"\n  top: \"Mconv2_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6_L2\"\n  top: \"Mconv2_stage6_L2\"\n}\nlayer {\n  name: \"Mconv3_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6_L1\"\n  top: \"Mconv3_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6_L1\"\n  top: \"Mconv3_stage6_L1\"\n}\nlayer {\n  name: \"Mconv3_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6_L2\"\n  top: \"Mconv3_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6_L2\"\n  top: \"Mconv3_stage6_L2\"\n}\nlayer {\n  name: \"Mconv4_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6_L1\"\n  top: \"Mconv4_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6_L1\"\n  top: \"Mconv4_stage6_L1\"\n}\nlayer {\n  name: \"Mconv4_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6_L2\"\n  top: \"Mconv4_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6_L2\"\n  top: \"Mconv4_stage6_L2\"\n}\nlayer {\n  name: \"Mconv5_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6_L1\"\n  top: \"Mconv5_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6_L1\"\n  top: \"Mconv5_stage6_L1\"\n}\nlayer {\n  name: \"Mconv5_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6_L2\"\n  top: \"Mconv5_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6_L2\"\n  top: \"Mconv5_stage6_L2\"\n}\nlayer {\n  name: \"Mconv6_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6_L1\"\n  top: \"Mconv6_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6_L1\"\n  top: \"Mconv6_stage6_L1\"\n}\nlayer {\n  name: \"Mconv6_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6_L2\"\n  top: \"Mconv6_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6_L2\"\n  top: \"Mconv6_stage6_L2\"\n}\nlayer {\n  name: \"Mconv7_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6_L1\"\n  top: \"Mconv7_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 38\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6_L2\"\n  top: \"Mconv7_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 19\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage7\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage6_L2\"\n  bottom: \"Mconv7_stage6_L1\"\n  # top: \"concat_stage7\"\n  top: \"net_output\"\n  concat_param {\n    axis: 1\n  }\n}\n"
  },
  {
    "path": "models/pose/mpi/pose_deploy_linevec.prototxt",
    "content": "input: \"image\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 1 # This value will be defined at runtime\ninput_dim: 1 # This value will be defined at runtime\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_1\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_2\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1_stage1\"\n  top: \"conv2_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_1\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_2\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2_stage1\"\n  top: \"conv3_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_1\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_2\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_3\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_4\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3_stage1\"\n  top: \"conv4_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_1\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_2\"\n  type: \"ReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_3_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_3_CPM\"\n}\nlayer {\n  name: \"conv4_4_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_4_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_4_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv4_4_CPM\"\n}\nlayer {\n  name: \"conv5_1_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_1_CPM_L1\"\n}\nlayer {\n  name: \"conv5_1_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_1_CPM_L2\"\n}\nlayer {\n  name: \"conv5_2_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n}\nlayer {\n  name: \"conv5_2_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n}\nlayer {\n  name: \"conv5_3_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n}\nlayer {\n  name: \"conv5_3_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n}\nlayer {\n  name: \"conv5_4_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n}\nlayer {\n  name: \"conv5_4_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n}\nlayer {\n  name: \"conv5_5_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_5_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_5_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_5_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage2\"\n  type: \"Concat\"\n  bottom: \"conv5_5_CPM_L1\"\n  bottom: \"conv5_5_CPM_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv1_stage2_L1\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv1_stage2_L2\"\n}\nlayer {\n  name: \"Mconv2_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n}\nlayer {\n  name: \"Mconv3_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n}\nlayer {\n  name: \"Mconv4_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n}\nlayer {\n  name: \"Mconv5_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n}\nlayer {\n  name: \"Mconv6_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n}\nlayer {\n  name: \"Mconv6_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n}\nlayer {\n  name: \"Mconv7_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv7_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv7_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage3\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage2_L1\"\n  bottom: \"Mconv7_stage2_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage3\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv1_stage3_L1\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv1_stage3_L2\"\n}\nlayer {\n  name: \"Mconv2_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n}\nlayer {\n  name: \"Mconv3_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n}\nlayer {\n  name: \"Mconv4_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n}\nlayer {\n  name: \"Mconv5_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n}\nlayer {\n  name: \"Mconv6_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n}\nlayer {\n  name: \"Mconv6_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n}\nlayer {\n  name: \"Mconv7_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv7_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv7_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage4\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage3_L1\"\n  bottom: \"Mconv7_stage3_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage4\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv1_stage4_L1\"\n}\nlayer {\n  name: \"Mconv1_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv1_stage4_L2\"\n}\nlayer {\n  name: \"Mconv2_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n}\nlayer {\n  name: \"Mconv2_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n}\nlayer {\n  name: \"Mconv3_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n}\nlayer {\n  name: \"Mconv3_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n}\nlayer {\n  name: \"Mconv4_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n}\nlayer {\n  name: \"Mconv4_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n}\nlayer {\n  name: \"Mconv5_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n}\nlayer {\n  name: \"Mconv5_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n}\nlayer {\n  name: \"Mconv6_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n}\nlayer {\n  name: \"Mconv6_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n}\nlayer {\n  name: \"Mconv7_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv7_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv7_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage5\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage4_L1\"\n  bottom: \"Mconv7_stage4_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage5\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage5\"\n  top: \"Mconv1_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5_L1\"\n  top: \"Mconv1_stage5_L1\"\n}\nlayer {\n  name: \"Mconv1_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage5\"\n  top: \"Mconv1_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage5_L2\"\n  top: \"Mconv1_stage5_L2\"\n}\nlayer {\n  name: \"Mconv2_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5_L1\"\n  top: \"Mconv2_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5_L1\"\n  top: \"Mconv2_stage5_L1\"\n}\nlayer {\n  name: \"Mconv2_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage5_L2\"\n  top: \"Mconv2_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage5_L2\"\n  top: \"Mconv2_stage5_L2\"\n}\nlayer {\n  name: \"Mconv3_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5_L1\"\n  top: \"Mconv3_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5_L1\"\n  top: \"Mconv3_stage5_L1\"\n}\nlayer {\n  name: \"Mconv3_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage5_L2\"\n  top: \"Mconv3_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage5_L2\"\n  top: \"Mconv3_stage5_L2\"\n}\nlayer {\n  name: \"Mconv4_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5_L1\"\n  top: \"Mconv4_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5_L1\"\n  top: \"Mconv4_stage5_L1\"\n}\nlayer {\n  name: \"Mconv4_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage5_L2\"\n  top: \"Mconv4_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage5_L2\"\n  top: \"Mconv4_stage5_L2\"\n}\nlayer {\n  name: \"Mconv5_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5_L1\"\n  top: \"Mconv5_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5_L1\"\n  top: \"Mconv5_stage5_L1\"\n}\nlayer {\n  name: \"Mconv5_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage5_L2\"\n  top: \"Mconv5_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage5_L2\"\n  top: \"Mconv5_stage5_L2\"\n}\nlayer {\n  name: \"Mconv6_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5_L1\"\n  top: \"Mconv6_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage5_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5_L1\"\n  top: \"Mconv6_stage5_L1\"\n}\nlayer {\n  name: \"Mconv6_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage5_L2\"\n  top: \"Mconv6_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage5_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage5_L2\"\n  top: \"Mconv6_stage5_L2\"\n}\nlayer {\n  name: \"Mconv7_stage5_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5_L1\"\n  top: \"Mconv7_stage5_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage5_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage5_L2\"\n  top: \"Mconv7_stage5_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage6\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage5_L1\"\n  bottom: \"Mconv7_stage5_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage6\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage6\"\n  top: \"Mconv1_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6_L1\"\n  top: \"Mconv1_stage6_L1\"\n}\nlayer {\n  name: \"Mconv1_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage6\"\n  top: \"Mconv1_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage6_L2\"\n  top: \"Mconv1_stage6_L2\"\n}\nlayer {\n  name: \"Mconv2_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6_L1\"\n  top: \"Mconv2_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6_L1\"\n  top: \"Mconv2_stage6_L1\"\n}\nlayer {\n  name: \"Mconv2_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage6_L2\"\n  top: \"Mconv2_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage6_L2\"\n  top: \"Mconv2_stage6_L2\"\n}\nlayer {\n  name: \"Mconv3_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6_L1\"\n  top: \"Mconv3_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6_L1\"\n  top: \"Mconv3_stage6_L1\"\n}\nlayer {\n  name: \"Mconv3_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage6_L2\"\n  top: \"Mconv3_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage6_L2\"\n  top: \"Mconv3_stage6_L2\"\n}\nlayer {\n  name: \"Mconv4_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6_L1\"\n  top: \"Mconv4_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6_L1\"\n  top: \"Mconv4_stage6_L1\"\n}\nlayer {\n  name: \"Mconv4_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage6_L2\"\n  top: \"Mconv4_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage6_L2\"\n  top: \"Mconv4_stage6_L2\"\n}\nlayer {\n  name: \"Mconv5_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6_L1\"\n  top: \"Mconv5_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6_L1\"\n  top: \"Mconv5_stage6_L1\"\n}\nlayer {\n  name: \"Mconv5_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage6_L2\"\n  top: \"Mconv5_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage6_L2\"\n  top: \"Mconv5_stage6_L2\"\n}\nlayer {\n  name: \"Mconv6_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6_L1\"\n  top: \"Mconv6_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage6_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6_L1\"\n  top: \"Mconv6_stage6_L1\"\n}\nlayer {\n  name: \"Mconv6_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage6_L2\"\n  top: \"Mconv6_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage6_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage6_L2\"\n  top: \"Mconv6_stage6_L2\"\n}\nlayer {\n  name: \"Mconv7_stage6_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6_L1\"\n  top: \"Mconv7_stage6_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage6_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage6_L2\"\n  top: \"Mconv7_stage6_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage7\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage6_L2\"\n  bottom: \"Mconv7_stage6_L1\"\n  top: \"net_output\"\n  concat_param {\n    axis: 1\n  }\n}\n"
  },
  {
    "path": "models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt",
    "content": "input: \"image\"\ninput_dim: 1\ninput_dim: 3\ninput_dim: 1 # This value will be defined at runtime\ninput_dim: 1 # This value will be defined at runtime\nlayer {\n  name: \"conv1_1\"\n  type: \"Convolution\"\n  bottom: \"image\"\n  top: \"conv1_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_1\"\n  type: \"ReLU\"\n  bottom: \"conv1_1\"\n  top: \"conv1_1\"\n}\nlayer {\n  name: \"conv1_2\"\n  type: \"Convolution\"\n  bottom: \"conv1_1\"\n  top: \"conv1_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 64\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu1_2\"\n  type: \"ReLU\"\n  bottom: \"conv1_2\"\n  top: \"conv1_2\"\n}\nlayer {\n  name: \"pool1_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv1_2\"\n  top: \"pool1_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv2_1\"\n  type: \"Convolution\"\n  bottom: \"pool1_stage1\"\n  top: \"conv2_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_1\"\n  type: \"ReLU\"\n  bottom: \"conv2_1\"\n  top: \"conv2_1\"\n}\nlayer {\n  name: \"conv2_2\"\n  type: \"Convolution\"\n  bottom: \"conv2_1\"\n  top: \"conv2_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu2_2\"\n  type: \"ReLU\"\n  bottom: \"conv2_2\"\n  top: \"conv2_2\"\n}\nlayer {\n  name: \"pool2_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv2_2\"\n  top: \"pool2_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv3_1\"\n  type: \"Convolution\"\n  bottom: \"pool2_stage1\"\n  top: \"conv3_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_1\"\n  type: \"ReLU\"\n  bottom: \"conv3_1\"\n  top: \"conv3_1\"\n}\nlayer {\n  name: \"conv3_2\"\n  type: \"Convolution\"\n  bottom: \"conv3_1\"\n  top: \"conv3_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_2\"\n  type: \"ReLU\"\n  bottom: \"conv3_2\"\n  top: \"conv3_2\"\n}\nlayer {\n  name: \"conv3_3\"\n  type: \"Convolution\"\n  bottom: \"conv3_2\"\n  top: \"conv3_3\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_3\"\n  type: \"ReLU\"\n  bottom: \"conv3_3\"\n  top: \"conv3_3\"\n}\nlayer {\n  name: \"conv3_4\"\n  type: \"Convolution\"\n  bottom: \"conv3_3\"\n  top: \"conv3_4\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu3_4\"\n  type: \"ReLU\"\n  bottom: \"conv3_4\"\n  top: \"conv3_4\"\n}\nlayer {\n  name: \"pool3_stage1\"\n  type: \"Pooling\"\n  bottom: \"conv3_4\"\n  top: \"pool3_stage1\"\n  pooling_param {\n    pool: MAX\n    kernel_size: 2\n    stride: 2\n  }\n}\nlayer {\n  name: \"conv4_1\"\n  type: \"Convolution\"\n  bottom: \"pool3_stage1\"\n  top: \"conv4_1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_1\"\n  type: \"ReLU\"\n  bottom: \"conv4_1\"\n  top: \"conv4_1\"\n}\nlayer {\n  name: \"conv4_2\"\n  type: \"Convolution\"\n  bottom: \"conv4_1\"\n  top: \"conv4_2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_2\"\n  type: \"ReLU\"\n  bottom: \"conv4_2\"\n  top: \"conv4_2\"\n}\nlayer {\n  name: \"conv4_3_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_2\"\n  top: \"conv4_3_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 256\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_3_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_3_CPM\"\n}\nlayer {\n  name: \"conv4_4_CPM\"\n  type: \"Convolution\"\n  bottom: \"conv4_3_CPM\"\n  top: \"conv4_4_CPM\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu4_4_CPM\"\n  type: \"ReLU\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv4_4_CPM\"\n}\nlayer {\n  name: \"conv5_1_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_1_CPM_L1\"\n}\nlayer {\n  name: \"conv5_1_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv4_4_CPM\"\n  top: \"conv5_1_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_1_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_1_CPM_L2\"\n}\nlayer {\n  name: \"conv5_2_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_2_CPM_L1\"\n}\nlayer {\n  name: \"conv5_2_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_1_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_2_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_2_CPM_L2\"\n}\nlayer {\n  name: \"conv5_3_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_3_CPM_L1\"\n}\nlayer {\n  name: \"conv5_3_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_2_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 1\n    kernel_size: 3\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_3_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_3_CPM_L2\"\n}\nlayer {\n  name: \"conv5_4_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L1\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_4_CPM_L1\"\n}\nlayer {\n  name: \"conv5_4_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_3_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 512\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"relu5_4_CPM_L2\"\n  type: \"ReLU\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_4_CPM_L2\"\n}\nlayer {\n  name: \"conv5_5_CPM_L1\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L1\"\n  top: \"conv5_5_CPM_L1\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"conv5_5_CPM_L2\"\n  type: \"Convolution\"\n  bottom: \"conv5_4_CPM_L2\"\n  top: \"conv5_5_CPM_L2\"\n  param {\n    lr_mult: 1.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 2.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage2\"\n  type: \"Concat\"\n  bottom: \"conv5_5_CPM_L1\"\n  bottom: \"conv5_5_CPM_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage2\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv1_stage2_L1\"\n}\nlayer {\n  name: \"Mconv1_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage2\"\n  top: \"Mconv1_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv1_stage2_L2\"\n}\nlayer {\n  name: \"Mconv2_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv2_stage2_L1\"\n}\nlayer {\n  name: \"Mconv2_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv2_stage2_L2\"\n}\nlayer {\n  name: \"Mconv3_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv3_stage2_L1\"\n}\nlayer {\n  name: \"Mconv3_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv3_stage2_L2\"\n}\nlayer {\n  name: \"Mconv4_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv4_stage2_L1\"\n}\nlayer {\n  name: \"Mconv4_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv4_stage2_L2\"\n}\nlayer {\n  name: \"Mconv5_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv5_stage2_L1\"\n}\nlayer {\n  name: \"Mconv5_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv5_stage2_L2\"\n}\nlayer {\n  name: \"Mconv6_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv6_stage2_L1\"\n}\nlayer {\n  name: \"Mconv6_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage2_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv6_stage2_L2\"\n}\nlayer {\n  name: \"Mconv7_stage2_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L1\"\n  top: \"Mconv7_stage2_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage2_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage2_L2\"\n  top: \"Mconv7_stage2_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage3\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage2_L1\"\n  bottom: \"Mconv7_stage2_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage3\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv1_stage3_L1\"\n}\nlayer {\n  name: \"Mconv1_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage3\"\n  top: \"Mconv1_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv1_stage3_L2\"\n}\nlayer {\n  name: \"Mconv2_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv2_stage3_L1\"\n}\nlayer {\n  name: \"Mconv2_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv2_stage3_L2\"\n}\nlayer {\n  name: \"Mconv3_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv3_stage3_L1\"\n}\nlayer {\n  name: \"Mconv3_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv3_stage3_L2\"\n}\nlayer {\n  name: \"Mconv4_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv4_stage3_L1\"\n}\nlayer {\n  name: \"Mconv4_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv4_stage3_L2\"\n}\nlayer {\n  name: \"Mconv5_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv5_stage3_L1\"\n}\nlayer {\n  name: \"Mconv5_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv5_stage3_L2\"\n}\nlayer {\n  name: \"Mconv6_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv6_stage3_L1\"\n}\nlayer {\n  name: \"Mconv6_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage3_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv6_stage3_L2\"\n}\nlayer {\n  name: \"Mconv7_stage3_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L1\"\n  top: \"Mconv7_stage3_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage3_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage3_L2\"\n  top: \"Mconv7_stage3_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage4\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage3_L1\"\n  bottom: \"Mconv7_stage3_L2\"\n  bottom: \"conv4_4_CPM\"\n  top: \"concat_stage4\"\n  concat_param {\n    axis: 1\n  }\n}\nlayer {\n  name: \"Mconv1_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv1_stage4_L1\"\n}\nlayer {\n  name: \"Mconv1_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"concat_stage4\"\n  top: \"Mconv1_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu1_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv1_stage4_L2\"\n}\nlayer {\n  name: \"Mconv2_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv2_stage4_L1\"\n}\nlayer {\n  name: \"Mconv2_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv1_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu2_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv2_stage4_L2\"\n}\nlayer {\n  name: \"Mconv3_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv3_stage4_L1\"\n}\nlayer {\n  name: \"Mconv3_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv2_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu3_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv3_stage4_L2\"\n}\nlayer {\n  name: \"Mconv4_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv4_stage4_L1\"\n}\nlayer {\n  name: \"Mconv4_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv3_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu4_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv4_stage4_L2\"\n}\nlayer {\n  name: \"Mconv5_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv5_stage4_L1\"\n}\nlayer {\n  name: \"Mconv5_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv4_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 3\n    kernel_size: 7\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu5_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv5_stage4_L2\"\n}\nlayer {\n  name: \"Mconv6_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L1\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv6_stage4_L1\"\n}\nlayer {\n  name: \"Mconv6_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv5_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 128\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mrelu6_stage4_L2\"\n  type: \"ReLU\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv6_stage4_L2\"\n}\nlayer {\n  name: \"Mconv7_stage4_L1\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L1\"\n  top: \"Mconv7_stage4_L1\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 28\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"Mconv7_stage4_L2\"\n  type: \"Convolution\"\n  bottom: \"Mconv6_stage4_L2\"\n  top: \"Mconv7_stage4_L2\"\n  param {\n    lr_mult: 4.0\n    decay_mult: 1\n  }\n  param {\n    lr_mult: 8.0\n    decay_mult: 0\n  }\n  convolution_param {\n    num_output: 16\n    pad: 0\n    kernel_size: 1\n    weight_filler {\n      type: \"gaussian\"\n      std: 0.01\n    }\n    bias_filler {\n      type: \"constant\"\n    }\n  }\n}\nlayer {\n  name: \"concat_stage7\"\n  type: \"Concat\"\n  bottom: \"Mconv7_stage4_L2\"\n  bottom: \"Mconv7_stage4_L1\"\n  top: \"net_output\"\n  concat_param {\n    axis: 1\n  }\n}\n"
  },
  {
    "path": "python/CMakeLists.txt",
    "content": "add_subdirectory(openpose)\r\n"
  },
  {
    "path": "python/openpose/CMakeLists.txt",
    "content": "set(PYTHON_FILES\r\n    openpose.py\r\n    __init__.py\r\n    openpose_python.cpp)\r\n\r\npybind11_add_module(pyopenpose openpose_python.cpp)\r\n\r\ntarget_link_libraries(pyopenpose PRIVATE pybind11::module openpose ${OpenPose_3rdparty_libraries})\r\nSET_TARGET_PROPERTIES(pyopenpose PROPERTIES PREFIX \"\")\r\nconfigure_file(__init__.py __init__.py)\r\n\r\ninstall(TARGETS pyopenpose DESTINATION python)\r\ninstall(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION python/openpose FILES_MATCHING PATTERN \"*.so\")\r\ninstall(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ DESTINATION python/openpose FILES_MATCHING PATTERN \"*.py\")\r\n"
  },
  {
    "path": "python/openpose/__init__.py",
    "content": "from . import pyopenpose as pyopenpose\r\n"
  },
  {
    "path": "python/openpose/openpose_python.cpp",
    "content": "#ifndef OPENPOSE_PYTHON_HPP\r\n#define OPENPOSE_PYTHON_HPP\r\n#define BOOST_DATE_TIME_NO_LIB\r\n\r\n#include <openpose/flags.hpp>\r\n#include <openpose/headers.hpp>\r\n\r\n#include <pybind11/pybind11.h>\r\n#include <pybind11/stl.h>\r\n#include <pybind11/stl_bind.h>\r\n#include <pybind11/numpy.h>\r\n#include <opencv2/core/core.hpp>\r\n#include <stdexcept>\r\n\r\nPYBIND11_MAKE_OPAQUE(std::vector<std::shared_ptr<op::Datum>>);\r\n\r\n#ifdef _WIN32\r\n    #define OP_EXPORT __declspec(dllexport)\r\n#else\r\n    #define OP_EXPORT\r\n#endif\r\n\r\nnamespace op\r\n{\r\n\r\n    namespace py = pybind11;\r\n\r\n    void parse_gflags(const std::vector<std::string>& argv)\r\n    {\r\n        try\r\n        {\r\n            std::vector<char*> argv_vec;\r\n            for (auto& arg : argv)\r\n                argv_vec.emplace_back((char*)arg.c_str());\r\n            char** cast = &argv_vec[0];\r\n            int size = (int)argv_vec.size();\r\n            gflags::ParseCommandLineFlags(&size, &cast, true);\r\n        }\r\n        catch (const std::exception& e)\r\n        {\r\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n        }\r\n    }\r\n\r\n    void init_int(py::dict d)\r\n    {\r\n        try\r\n        {\r\n            std::vector<std::string> argv;\r\n            argv.emplace_back(\"openpose.py\");\r\n            for (auto item : d){\r\n                // Sanity check\r\n                std::size_t found = std::string(py::str(item.first)).find(\"=\");\r\n                if (found != std::string::npos)\r\n                    error(\"PyOpenPose does not support equal sign flags (e.g., \"\r\n                        + std::string(py::str(item.first)) + \").\", __LINE__, __FUNCTION__, __FILE__);\r\n                // Add argument\r\n                argv.emplace_back(\"--\" + std::string(py::str(item.first)) + \"=\" + std::string(py::str(item.second)));\r\n            }\r\n            parse_gflags(argv);\r\n        }\r\n        catch (const std::exception& e)\r\n        {\r\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n        }\r\n    }\r\n\r\n    void init_argv(std::vector<std::string> argv)\r\n    {\r\n        try\r\n        {\r\n            argv.insert(argv.begin(), \"openpose.py\");\r\n            parse_gflags(argv);\r\n        }\r\n        catch (const std::exception& e)\r\n        {\r\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n        }\r\n    }\r\n\r\n    class WrapperPython{\r\n    public:\r\n        std::unique_ptr<Wrapper> opWrapper;\r\n        bool synchronousIn;\r\n\r\n        WrapperPython(ThreadManagerMode mode = ThreadManagerMode::Asynchronous)\r\n        {\r\n            opLog(\"Starting OpenPose Python Wrapper...\", Priority::High);\r\n\r\n            // Construct opWrapper\r\n            opWrapper = std::unique_ptr<Wrapper>(new Wrapper(mode));\r\n\r\n            // Synchronous in\r\n            synchronousIn = (\r\n                mode == ThreadManagerMode::AsynchronousOut ||\r\n                mode == ThreadManagerMode::Synchronous\r\n            );\r\n        }\r\n\r\n        void configure(py::dict params = py::dict())\r\n        {\r\n            try\r\n            {\r\n                if (params.size())\r\n                    init_int(params);\r\n\r\n                // logging_level\r\n                checkBool(\r\n                    0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, \"Wrong logging_level value.\",\r\n                    __LINE__, __FUNCTION__, __FILE__);\r\n                ConfigureLog::setPriorityThreshold((Priority)FLAGS_logging_level);\r\n                Profiler::setDefaultX(FLAGS_profile_speed);\r\n\r\n                // Applying user defined configuration - GFlags to program variables\r\n                // outputSize\r\n                const auto outputSize = flagsToPoint(op::String(FLAGS_output_resolution), \"-1x-1\");\r\n                // netInputSize\r\n                const auto netInputSize = flagsToPoint(op::String(FLAGS_net_resolution), \"-1x368\");\r\n                // faceNetInputSize\r\n                const auto faceNetInputSize = flagsToPoint(op::String(FLAGS_face_net_resolution), \"368x368 (multiples of 16)\");\r\n                // handNetInputSize\r\n                const auto handNetInputSize = flagsToPoint(op::String(FLAGS_hand_net_resolution), \"368x368 (multiples of 16)\");\r\n                // poseMode\r\n                const auto poseMode = flagsToPoseMode(FLAGS_body);\r\n                // poseModel\r\n                const auto poseModel = flagsToPoseModel(op::String(FLAGS_model_pose));\r\n                // JSON saving\r\n                if (!FLAGS_write_keypoint.empty())\r\n                    opLog(\"Flag `write_keypoint` is deprecated and will eventually be removed.\"\r\n                            \" Please, use `write_json` instead.\", Priority::Max);\r\n                // keypointScaleMode\r\n                const auto keypointScaleMode = flagsToScaleMode(FLAGS_keypoint_scale);\r\n                // heatmaps to add\r\n                const auto heatMapTypes = flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,\r\n                                                              FLAGS_heatmaps_add_PAFs);\r\n                const auto heatMapScaleMode = flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);\r\n                // >1 camera view?\r\n                const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);\r\n                // Face and hand detectors\r\n                const auto faceDetector = flagsToDetector(FLAGS_face_detector);\r\n                const auto handDetector = flagsToDetector(FLAGS_hand_detector);\r\n                // Enabling Google Logging\r\n                const bool enableGoogleLogging = true;\r\n\r\n                // Pose configuration (use WrapperStructPose{} for default and recommended configuration)\r\n                const op::WrapperStructPose wrapperStructPose{\r\n                    poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,\r\n                    FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,\r\n                    op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,\r\n                    (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),\r\n                    heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,\r\n                    FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),\r\n                    op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};\r\n                opWrapper->configure(wrapperStructPose);\r\n                // Face configuration (use WrapperStructFace{} to disable it)\r\n                const WrapperStructFace wrapperStructFace{\r\n                    FLAGS_face, faceDetector, faceNetInputSize,\r\n                    flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),\r\n                    (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};\r\n                opWrapper->configure(wrapperStructFace);\r\n                // Hand configuration (use WrapperStructHand{} to disable it)\r\n                const WrapperStructHand wrapperStructHand{\r\n                    FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,\r\n                    flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,\r\n                    (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};\r\n                opWrapper->configure(wrapperStructHand);\r\n                // Extra functionality configuration (use WrapperStructExtra{} to disable it)\r\n                const WrapperStructExtra wrapperStructExtra{\r\n                    FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};\r\n                opWrapper->configure(wrapperStructExtra);\r\n                // Output (comment or use default argument to disable any output)\r\n                const WrapperStructOutput wrapperStructOutput{\r\n                    FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),\r\n                    op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,\r\n                    FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),\r\n                    op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,\r\n                    op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),\r\n                    op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),\r\n                    op::String(FLAGS_udp_port)};\r\n                opWrapper->configure(wrapperStructOutput);\r\n                if (synchronousIn) {\r\n                    // SynchronousIn => We need a producer\r\n\r\n                    // Producer (use default to disable any input)\r\n                    const auto cameraSize = flagsToPoint(op::String(FLAGS_camera_resolution), \"-1x-1\");\r\n                    ProducerType producerType;\r\n                    op::String producerString;\r\n                    std::tie(producerType, producerString) = flagsToProducer(\r\n                        op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,\r\n                        FLAGS_flir_camera, FLAGS_flir_camera_index);\r\n                    const WrapperStructInput wrapperStructInput{\r\n                        producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,\r\n                        FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,\r\n                        cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};\r\n                    opWrapper->configure(wrapperStructInput);\r\n                }\r\n                // No GUI. Equivalent to: opWrapper.configure(WrapperStructGui{});\r\n                // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)\r\n                if (FLAGS_disable_multi_thread)\r\n                    opWrapper->disableMultiThreading();\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n            }\r\n        }\r\n\r\n        void start()\r\n        {\r\n            try\r\n            {\r\n                opWrapper->start();\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n            }\r\n        }\r\n\r\n        void stop()\r\n        {\r\n            try\r\n            {\r\n                opWrapper->stop();\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n            }\r\n        }\r\n\r\n        void exec()\r\n        {\r\n            try\r\n            {\r\n                // GUI (comment or use default argument to disable any visual output)\r\n                const WrapperStructGui wrapperStructGui{\r\n                    flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};\r\n                opWrapper->configure(wrapperStructGui);\r\n                opWrapper->exec();\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n            }\r\n        }\r\n\r\n        bool emplaceAndPop(std::vector<std::shared_ptr<Datum>>& l)\r\n        {\r\n            try\r\n            {\r\n                std::shared_ptr<std::vector<std::shared_ptr<Datum>>> datumsPtr(\r\n                    &l,\r\n                    [](std::vector<std::shared_ptr<Datum>>*){}\r\n                );\r\n                auto got = opWrapper->emplaceAndPop(datumsPtr);\r\n                if (got && datumsPtr.get() != &l) {\r\n                    l.swap(*datumsPtr);\r\n                }\r\n                return got;\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n                return false;\r\n            }\r\n        }\r\n\r\n        bool waitAndEmplace(std::vector<std::shared_ptr<Datum>>& l)\r\n        {\r\n            try\r\n            {\r\n                std::shared_ptr<std::vector<std::shared_ptr<Datum>>> datumsPtr(&l);\r\n                return opWrapper->waitAndEmplace(datumsPtr);\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n                return false;\r\n            }\r\n        }\r\n\r\n        bool waitAndPop(std::vector<std::shared_ptr<Datum>>& l)\r\n        {\r\n            try\r\n            {\r\n                std::shared_ptr<std::vector<std::shared_ptr<Datum>>> datumsPtr;\r\n                auto got = opWrapper->waitAndPop(datumsPtr);\r\n                if (got) {\r\n                    l.swap(*datumsPtr);\r\n                }\r\n                return got;\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n                return false;\r\n            }\r\n        }\r\n    };\r\n\r\n    std::vector<std::string> getImagesFromDirectory(const std::string& directoryPath)\r\n    {\r\n        try\r\n        {\r\n            return getFilesOnDirectory(directoryPath, Extensions::Images);\r\n        }\r\n        catch (const std::exception& e)\r\n        {\r\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n            return {};\r\n        }\r\n    }\r\n\r\n    PYBIND11_MODULE(pyopenpose, m) {\r\n\r\n        // Functions for Init Params\r\n        m.def(\"init_int\", &init_int, \"Init Function\");\r\n        m.def(\"init_argv\", &init_argv, \"Init Function\");\r\n        m.def(\"get_gpu_number\", &getGpuNumber, \"Get Total GPU\");\r\n        m.def(\"get_images_on_directory\", &getImagesFromDirectory, \"Get Images On Directory\");\r\n\r\n        // Pose Mapping\r\n        // Code example in doc/02_output.md, section Keypoint Ordering in C++/Python\r\n        m.def(\"getPoseBodyPartMapping\", &getPoseBodyPartMapping, \"getPoseBodyPartMapping\");\r\n        m.def(\"getPoseNumberBodyParts\", &getPoseNumberBodyParts, \"getPoseNumberBodyParts\");\r\n        m.def(\"getPosePartPairs\", &getPosePartPairs, \"getPosePartPairs\");\r\n        m.def(\"getPoseMapIndex\", &getPoseMapIndex, \"getPoseMapIndex\");\r\n        py::enum_<PoseModel>(m, \"PoseModel\", py::arithmetic())\r\n                .value(\"BODY_25\", PoseModel::BODY_25)\r\n                .value(\"COCO_18\", PoseModel::COCO_18)\r\n                .value(\"MPI_15\", PoseModel::MPI_15)\r\n                .value(\"MPI_15_4\", PoseModel::MPI_15_4)\r\n                .value(\"BODY_25B\", PoseModel::BODY_25B)\r\n                .value(\"BODY_135\", PoseModel::BODY_135)\r\n                .export_values();\r\n\r\n        // OpenposePython\r\n        py::class_<WrapperPython>(m, \"WrapperPython\")\r\n            .def(py::init<>())\r\n            .def(py::init<ThreadManagerMode>())\r\n            .def(\"configure\", &WrapperPython::configure)\r\n            .def(\"start\", &WrapperPython::start)\r\n            .def(\"stop\", &WrapperPython::stop)\r\n            .def(\"execute\", &WrapperPython::exec)\r\n            .def(\"emplaceAndPop\", &WrapperPython::emplaceAndPop)\r\n            .def(\"waitAndEmplace\", &WrapperPython::waitAndEmplace)\r\n            .def(\"waitAndPop\", &WrapperPython::waitAndPop)\r\n            ;\r\n\r\n        // ThreadManagerMode\r\n        py::enum_<ThreadManagerMode>(m, \"ThreadManagerMode\")\r\n            .value(\"Asynchronous\", ThreadManagerMode::Asynchronous)\r\n            .value(\"AsynchronousIn\", ThreadManagerMode::AsynchronousIn)\r\n            .value(\"AsynchronousOut\", ThreadManagerMode::AsynchronousOut)\r\n            .value(\"Synchronous\", ThreadManagerMode::Synchronous)\r\n            ;\r\n\r\n        // Datum Object\r\n        py::class_<Datum, std::shared_ptr<Datum>>(m, \"Datum\")\r\n            .def(py::init<>())\r\n            .def_readwrite(\"id\", &Datum::id)\r\n            .def_readwrite(\"subId\", &Datum::subId)\r\n            .def_readwrite(\"subIdMax\", &Datum::subIdMax)\r\n            .def_readwrite(\"name\", &Datum::name)\r\n            .def_readwrite(\"frameNumber\", &Datum::frameNumber)\r\n            .def_readwrite(\"cvInputData\", &Datum::cvInputData)\r\n            .def_readwrite(\"inputNetData\", &Datum::inputNetData)\r\n            .def_readwrite(\"outputData\", &Datum::outputData)\r\n            .def_readwrite(\"cvOutputData\", &Datum::cvOutputData)\r\n            .def_readwrite(\"cvOutputData3D\", &Datum::cvOutputData3D)\r\n            .def_readwrite(\"poseKeypoints\", &Datum::poseKeypoints)\r\n            .def_readwrite(\"poseIds\", &Datum::poseIds)\r\n            .def_readwrite(\"poseScores\", &Datum::poseScores)\r\n            .def_readwrite(\"poseHeatMaps\", &Datum::poseHeatMaps)\r\n            .def_readwrite(\"poseCandidates\", &Datum::poseCandidates)\r\n            .def_readwrite(\"faceRectangles\", &Datum::faceRectangles)\r\n            .def_readwrite(\"faceKeypoints\", &Datum::faceKeypoints)\r\n            .def_readwrite(\"faceHeatMaps\", &Datum::faceHeatMaps)\r\n            .def_readwrite(\"handRectangles\", &Datum::handRectangles)\r\n            .def_readwrite(\"handKeypoints\", &Datum::handKeypoints)\r\n            .def_readwrite(\"handHeatMaps\", &Datum::handHeatMaps)\r\n            .def_readwrite(\"poseKeypoints3D\", &Datum::poseKeypoints3D)\r\n            .def_readwrite(\"faceKeypoints3D\", &Datum::faceKeypoints3D)\r\n            .def_readwrite(\"handKeypoints3D\", &Datum::handKeypoints3D)\r\n            .def_readwrite(\"cameraMatrix\", &Datum::cameraMatrix)\r\n            .def_readwrite(\"cameraExtrinsics\", &Datum::cameraExtrinsics)\r\n            .def_readwrite(\"cameraIntrinsics\", &Datum::cameraIntrinsics)\r\n            .def_readwrite(\"poseNetOutput\", &Datum::poseNetOutput)\r\n            .def_readwrite(\"scaleInputToNetInputs\", &Datum::scaleInputToNetInputs)\r\n            .def_readwrite(\"netInputSizes\", &Datum::netInputSizes)\r\n            .def_readwrite(\"scaleInputToOutput\", &Datum::scaleInputToOutput)\r\n            .def_readwrite(\"netOutputSize\", &Datum::netOutputSize)\r\n            .def_readwrite(\"scaleNetToOutput\", &Datum::scaleNetToOutput)\r\n            .def_readwrite(\"elementRendered\", &Datum::elementRendered)\r\n            ;\r\n\r\n        py::bind_vector<std::vector<std::shared_ptr<Datum>>>(m, \"VectorDatum\");\r\n\r\n        // Rectangle\r\n        py::class_<Rectangle<float>>(m, \"Rectangle\")\r\n            .def(\"__repr__\", [](Rectangle<float> &a) { return a.toString(); })\r\n            .def(py::init<>())\r\n            .def(py::init<float, float, float, float>())\r\n            .def_readwrite(\"x\", &Rectangle<float>::x)\r\n            .def_readwrite(\"y\", &Rectangle<float>::y)\r\n            .def_readwrite(\"width\", &Rectangle<float>::width)\r\n            .def_readwrite(\"height\", &Rectangle<float>::height)\r\n            ;\r\n\r\n        // Point\r\n        py::class_<Point<int>>(m, \"Point\")\r\n            .def(\"__repr__\", [](Point<int> &a) { return a.toString(); })\r\n            .def(py::init<>())\r\n            .def(py::init<int, int>())\r\n            .def_readwrite(\"x\", &Point<int>::x)\r\n            .def_readwrite(\"y\", &Point<int>::y)\r\n            ;\r\n\r\n        #ifdef VERSION_INFO\r\n            m.attr(\"__version__\") = VERSION_INFO;\r\n        #else\r\n            m.attr(\"__version__\") = \"dev\";\r\n        #endif\r\n    }\r\n}\r\n\r\n// Numpy - op::Array<float> interop\r\nnamespace pybind11 { namespace detail {\r\n\r\ntemplate <> struct type_caster<op::Array<float>> {\r\n    public:\r\n\r\n        PYBIND11_TYPE_CASTER(op::Array<float>, _(\"numpy.ndarray\"));\r\n\r\n        // Cast numpy to op::Array<float>\r\n        bool load(handle src, bool imp)\r\n        {\r\n            try\r\n            {\r\n                UNUSED(imp);\r\n                // array b(src, true);\r\n                array b = reinterpret_borrow<array>(src);\r\n                buffer_info info = b.request();\r\n\r\n                if (info.format != format_descriptor<float>::format())\r\n                    op::error(\"op::Array only supports float32 now\", __LINE__, __FUNCTION__, __FILE__);\r\n\r\n                //std::vector<int> a(info.shape);\r\n                std::vector<int> shape(std::begin(info.shape), std::end(info.shape));\r\n\r\n                // No copy\r\n                value = op::Array<float>(shape, (float*)info.ptr);\r\n                // Copy\r\n                //value = op::Array<float>(shape);\r\n                //memcpy(value.getPtr(), info.ptr, value.getVolume()*sizeof(float));\r\n\r\n                return true;\r\n            }\r\n            catch (const std::exception& e)\r\n            {\r\n                op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);\r\n                return {};\r\n            }\r\n        }\r\n\r\n        // Cast op::Array<float> to numpy\r\n        static handle cast(const op::Array<float> &m, return_value_policy, handle defval)\r\n        {\r\n            UNUSED(defval);\r\n            if (m.getSize().size() == 0) {\r\n                return Py_BuildValue(\"\");\r\n            }\r\n            std::string format = format_descriptor<float>::format();\r\n            return array(buffer_info(\r\n                m.getPseudoConstPtr(),/* Pointer to buffer */\r\n                sizeof(float),        /* Size of one scalar */\r\n                format,               /* Python struct-style format descriptor */\r\n                m.getSize().size(),   /* Number of dimensions */\r\n                m.getSize(),          /* Buffer dimensions */\r\n                m.getStride()         /* Strides (in bytes) for each index */\r\n                )).release();\r\n        }\r\n\r\n    };\r\n}} // namespace pybind11::detail\r\n\r\n// Numpy - op::Array<long long> interop\r\nnamespace pybind11 { namespace detail {\r\n\r\ntemplate <> struct type_caster<op::Array<long long>> {\r\n    public:\r\n\r\n        PYBIND11_TYPE_CASTER(op::Array<long long>, _(\"numpy.ndarray\"));\r\n\r\n        // Cast numpy to op::Array<long long>\r\n        bool load(handle src, bool imp)\r\n        {\r\n            op::error(\"op::Array<long long> is read only now\", __LINE__, __FUNCTION__, __FILE__);\r\n            return false;\r\n        }\r\n\r\n        // Cast op::Array<long long> to numpy\r\n        static handle cast(const op::Array<long long> &m, return_value_policy, handle defval)\r\n        {\r\n            UNUSED(defval);\r\n            if (m.getSize().size() == 0) {\r\n                return Py_BuildValue(\"\");\r\n            }\r\n            std::string format = format_descriptor<long long>::format();\r\n            return array(buffer_info(\r\n                m.getPseudoConstPtr(),/* Pointer to buffer */\r\n                sizeof(long long),    /* Size of one scalar */\r\n                format,               /* Python struct-style format descriptor */\r\n                m.getSize().size(),   /* Number of dimensions */\r\n                m.getSize(),          /* Buffer dimensions */\r\n                m.getStride()         /* Strides (in bytes) for each index */\r\n                )).release();\r\n        }\r\n\r\n    };\r\n}} // namespace pybind11::detail\r\n\r\n// Numpy - op::Matrix interop\r\nnamespace pybind11 { namespace detail {\r\n\r\ntemplate <> struct type_caster<op::Matrix> {\r\n    public:\r\n\r\n        PYBIND11_TYPE_CASTER(op::Matrix, _(\"numpy.ndarray\"));\r\n\r\n        // Cast numpy to op::Matrix\r\n        bool load(handle src, bool)\r\n        {\r\n            /* Try a default converting into a Python */\r\n            //array b(src, true);\r\n            array b = reinterpret_borrow<array>(src);\r\n            buffer_info info = b.request();\r\n\r\n            const int ndims = (int)info.ndim;\r\n\r\n            decltype(CV_32F) dtype;\r\n            size_t elemsize;\r\n            if (info.format == format_descriptor<float>::format())\r\n            {\r\n                if (ndims == 3)\r\n                    dtype = CV_32FC3;\r\n                else\r\n                    dtype = CV_32FC1;\r\n                elemsize = sizeof(float);\r\n            }\r\n            else if (info.format == format_descriptor<double>::format())\r\n            {\r\n                if (ndims == 3)\r\n                    dtype = CV_64FC3;\r\n                else\r\n                    dtype = CV_64FC1;\r\n                elemsize = sizeof(double);\r\n            }\r\n            else if (info.format == format_descriptor<unsigned char>::format())\r\n            {\r\n                if (ndims == 3)\r\n                    dtype = CV_8UC3;\r\n                else\r\n                    dtype = CV_8UC1;\r\n                elemsize = sizeof(unsigned char);\r\n            }\r\n            else\r\n            {\r\n                throw std::logic_error(\"Unsupported type\");\r\n                return false;\r\n            }\r\n\r\n            std::vector<int> shape = {(int)info.shape[0], (int)info.shape[1]};\r\n\r\n            value = op::Matrix(shape[0], shape[1], dtype, info.ptr);\r\n            // value = cv::Mat(cv::Size(shape[1], shape[0]), dtype, info.ptr, cv::Mat::AUTO_STEP);\r\n            return true;\r\n        }\r\n\r\n        // Cast op::Matrix to numpy\r\n        static handle cast(const op::Matrix &matrix, return_value_policy, handle defval)\r\n        {\r\n            UNUSED(defval);\r\n            std::string format = format_descriptor<unsigned char>::format();\r\n            size_t elemsize = sizeof(unsigned char);\r\n            int dim;\r\n            switch(matrix.type()) {\r\n                case CV_8U:\r\n                    format = format_descriptor<unsigned char>::format();\r\n                    elemsize = sizeof(unsigned char);\r\n                    dim = 2;\r\n                    break;\r\n                case CV_8UC3:\r\n                    format = format_descriptor<unsigned char>::format();\r\n                    elemsize = sizeof(unsigned char);\r\n                    dim = 3;\r\n                    break;\r\n                case CV_32F:\r\n                    format = format_descriptor<float>::format();\r\n                    elemsize = sizeof(float);\r\n                    dim = 2;\r\n                    break;\r\n                case CV_64F:\r\n                    format = format_descriptor<double>::format();\r\n                    elemsize = sizeof(double);\r\n                    dim = 2;\r\n                    break;\r\n                default:\r\n                    throw std::logic_error(\"Unsupported type\");\r\n            }\r\n\r\n            std::vector<size_t> bufferdim;\r\n            std::vector<size_t> strides;\r\n            if (dim == 2) {\r\n                bufferdim = {(size_t) matrix.rows(), (size_t) matrix.cols()};\r\n                strides = {elemsize * (size_t) matrix.cols(), elemsize};\r\n            } else if (dim == 3) {\r\n                bufferdim = {(size_t) matrix.rows(), (size_t) matrix.cols(), (size_t) 3};\r\n                strides = {(size_t) elemsize * matrix.cols() * 3, (size_t) elemsize * 3, (size_t) elemsize};\r\n            }\r\n            return array(buffer_info(\r\n                matrix.dataPseudoConst(),   /* Pointer to buffer */\r\n                elemsize,                   /* Size of one scalar */\r\n                format,                     /* Python struct-style format descriptor */\r\n                dim,                        /* Number of dimensions */\r\n                bufferdim,                  /* Buffer dimensions */\r\n                strides                     /* Strides (in bytes) for each index */\r\n                )).release();\r\n        }\r\n\r\n    };\r\n}} // namespace pybind11::detail\r\n\r\n#endif\r\n"
  },
  {
    "path": "scripts/CI/configure.sh",
    "content": "#!/bin/bash\n\n# Configure the project\n\nBASEDIR=$(dirname $0)\nsource $BASEDIR/defaults.sh\n\necho \"WITH_CMAKE = ${WITH_CMAKE}.\"\nif [[ $WITH_CMAKE == true ]] ; then\n  echo \"Running CMake configuration...\"\n  source $BASEDIR/configure_cmake.sh\nelse\n  echo \"Running Makefile configuration...\"\n  source $BASEDIR/configure_make.sh\nfi\n"
  },
  {
    "path": "scripts/CI/configure_cmake.sh",
    "content": "#!/bin/bash\n\n# CMake configuration\n\nmkdir build\ncd build\n\necho \"RUN_EXAMPLES = ${RUN_EXAMPLES}.\"\nif [[ $RUN_EXAMPLES == false ]] ; then\n  ARGS=\"-DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF\"\n  # ARGS=\"-DBUILD_CAFFE=ON -DDOWNLOAD_BODY_25_MODEL=OFF -DDOWNLOAD_BODY_COCO_MODEL=OFF -DDOWNLOAD_FACE_MODEL=OFF -DDOWNLOAD_HAND_MODEL=OFF -DDOWNLOAD_BODY_MPI_MODEL=OFF\"\nfi\n\necho \"WITH_PYTHON = ${WITH_PYTHON}.\"\nif [[ $WITH_PYTHON == true ]] ; then\n  if [[ \"$CI_OS_NAME\" == \"linux\" ]] ; then\n    ARGS=\"$ARGS -DBUILD_PYTHON=On\"\n    if [[ $PYTHON3_VERSION ]] ; then\n      ARGS=\"$ARGS -DPYTHON_EXECUTABLE=/usr/bin/${PYTHON3_VERSION} -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/lib${PYTHON3_VERSION}m.so\"\n    else\n      echo \"No Python version defined (or unknown one used), using the default v2.7\"\n      ARGS=\"$ARGS -DPYTHON_EXECUTABLE=/usr/bin/python2.7 -DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython2.7m.so\"\n    fi\n  fi\n  if [[ \"$CI_OS_NAME\" == \"osx\" ]] ; then\n    ARGS=\"$ARGS -DBUILD_PYTHON=On -DPYTHON_EXECUTABLE=/usr/local/bin/python2.7 -DPYTHON_LIBRARY=/usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7m.dylib\"\n  fi\n  echo \"Python arguments = $ARGS\"\nfi\n\n# CUDA version\necho \"WITH_CUDA = ${WITH_CUDA}.\"\necho \"WITH_OPEN_CL = ${WITH_OPEN_CL}.\"\necho \"WITH_MKL = ${WITH_MKL}.\"\nif [[ $WITH_CUDA == true ]] ; then\n  # Only build SM50\n  ARGS=\"$ARGS -DGPU_MODE=CUDA -DCUDA_ARCH=Manual -DCUDA_ARCH_BIN=\\\"52\\\" -DCUDA_ARCH_PTX=\\\"\\\"\"\n# OpenCL version\nelif [[ $WITH_OPEN_CL == true ]] ; then\n  ARGS=\"$ARGS -DGPU_MODE=OPENCL\"\n# CPU version\nelse\n  ARGS=\"$ARGS -DGPU_MODE=CPU_ONLY\"\n  # MKL (Intel Caffe)\n  if [[ $WITH_MKL == true ]] ; then\n    ARGS=\"$ARGS -DUSE_MKL=On\"\n  else\n    ARGS=\"$ARGS -DUSE_MKL=Off\"\n  fi\nfi\n\necho \"WITH_CUDNN = ${WITH_CUDNN}.\"\nif [[ $WITH_CUDNN == true ]] ; then\n  ARGS=\"$ARGS -DUSE_CUDNN=On\"\nelse\n  ARGS=\"$ARGS -DUSE_CUDNN=Off\"\nfi\n\necho \"WITH_UNITY = ${WITH_UNITY}.\"\nif [[ $WITH_UNITY == true ]] ; then\n  ARGS=\"$ARGS -DBUILD_UNITY_SUPPORT=On\"\nfi\n\necho \"WITH_DEBUG = ${WITH_DEBUG}.\"\nif [[ $WITH_DEBUG == true ]] ; then\n  ARGS=\"$ARGS -DCMAKE_BUILD_TYPE=Debug\"\nfi\n\necho \"ARGS = ${ARGS}.\"\n\ncmake .. $ARGS\n\n# Patch for OpenCL and OSX\nif [[ $WITH_OPEN_CL == true && $CI_OS_NAME == \"osx\" ]] ; then\n  cd ../3rdparty/caffe; git apply ../../scripts/osx/mac_opencl_patch.txt;\n  cd ../../build;\nfi\n\n# Run Cmake twice for pybind to register\nif [[ $WITH_PYTHON == true ]] ; then\n  cmake .. $ARGS\nfi\n"
  },
  {
    "path": "scripts/CI/configure_make.sh",
    "content": "#!/bin/bash\n\n# Raw Makefile configuration\n# # All in one line\n# bash scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh\n\nif [[ $MAKE_CONFIG_COMPATIBLE == false ]] ; then\n  echo \"Configuration not compatible for Makefile.\"\n  exit 99\nfi\n\nLINE () {\n  echo \"$@\" >> Makefile.config\n  echo \"$@\" >> 3rdparty/caffe/Makefile.config\n}\n\n# Install Caffe\necho \"Installing Caffe...\"\ncd ./3rdparty/caffe\nbash install_caffe_if_cuda8.sh\ncd ../..\n\n# Generate Makefile files for OpenPose\necho \"Generating Makefile files for OpenPose...\"\nbash scripts/ubuntu_deprecated/copy_makefile_files.sh\n\necho \"WITH_CUDA = ${WITH_CUDA}.\"\nif [[ $WITH_CUDA == true ]] ; then\n  # Only build SM50\n  LINE \"CUDA_ARCH := -gencode arch=compute_50,code=sm_50\"\nelse\n  LINE \"CPU_ONLY := 1\"\nfi\n\necho \"WITH_CUDNN = ${WITH_CUDNN}.\"\nif [[ $WITH_CUDNN == true ]] ; then\n  LINE \"USE_CUDNN := 1\"\nfi\n"
  },
  {
    "path": "scripts/CI/defaults.sh",
    "content": "#!/bin/bash\n\n# Set default environment variables\nset -e\nCI_OS_NAME=${CI_OS_NAME}\nWITH_CMAKE=${WITH_CMAKE:-true}\nWITH_PYTHON=${WITH_PYTHON:-false}\nWITH_CUDA=${WITH_CUDA:-true}\nWITH_CUDNN=${WITH_CUDNN:-true}\nWITH_OPEN_CL=${WITH_OPEN_CL:-false}\nWITH_MKL=${WITH_MKL:-false}\nWITH_UNITY=${WITH_UNITY:-false}\nWITH_DEBUG=${WITH_DEBUG:-false}\n\nif [[ $WITH_CUDA == false ]] && [[ $WITH_CUDNN == true ]]\nthen\n  echo \"CUDNN only possible in combination with CUDA, setting WITH_CUDNN to false\"\n  WITH_CUDNN=false\nfi\n\n# Examples should be run (CI environment not compatible with GPU code)\n# if [[ $WITH_CMAKE == true ]] && [[ $WITH_PYTHON == true ]] && [[ $WITH_CUDA == false ]] && [[ $WITH_OPEN_CL == false ]] && [[ $WITH_MKL == false ]]; then\nif [[ $WITH_CUDA == false ]] && [[ $WITH_OPEN_CL == false ]] && [[ $WITH_UNITY == false ]]; then\n  RUN_EXAMPLES=true\nelse\n  RUN_EXAMPLES=false\nfi\necho \"RUN_EXAMPLES = ${RUN_EXAMPLES}.\"\n\n# Makefile configuration compatible\n# if [[ $WITH_PYTHON == false ]] ; then\nif [[ $WITH_PYTHON == false ]] && [[ $WITH_DEBUG == false ]] && [[ $WITH_UNITY == false ]]; then\n  MAKE_CONFIG_COMPATIBLE=true\nelse\n  MAKE_CONFIG_COMPATIBLE=false\nfi\necho \"MAKE_CONFIG_COMPATIBLE = ${MAKE_CONFIG_COMPATIBLE}.\"\n"
  },
  {
    "path": "scripts/CI/install_deps_osx.sh",
    "content": "#!/bin/bash\n\n# Install dependencies for Mac OS\necho \"Running on Mac OS.\"\n\nBASEDIR=$(dirname $0)\nsource $BASEDIR/defaults.sh\n\n# To fix linking issue in CI during install of python as dep of opencv\n[[ -f /usr/local/bin/2to3 ]] && rm -f /usr/local/bin/2to3\n\nsource ./scripts/osx/install_brew.sh\nsource ./scripts/osx/install_deps.sh\n"
  },
  {
    "path": "scripts/CI/install_deps_ubuntu.sh",
    "content": "#!/bin/bash\n\n# Install dependencies for Ubuntu\necho \"Running on ${CI_OS_NAME} OS.\"\n\nBASEDIR=$(dirname $0)\nsource $BASEDIR/defaults.sh\n\nif [[ $WITH_CUDA == true ]]; then\n  bash $BASEDIR/../ubuntu/install_cuda.sh\nfi\nif [[ $WITH_CUDNN == true ]]; then\n  bash $BASEDIR/../ubuntu/install_cudnn_up_to_Ubuntu16.sh\nfi\n\nbash $BASEDIR/../ubuntu/install_deps.sh\n\nsudo apt-get -y install libatlas-base-dev\nsudo apt-get -y install libopencv-dev\n"
  },
  {
    "path": "scripts/CI/run_make.sh",
    "content": "#!/bin/bash\n\n# Build the project\n\nBASEDIR=$(dirname $0)\nsource $BASEDIR/defaults.sh\n\nif [[ $WITH_CMAKE == true ]] ; then\n  cd build\n  if [[ \"$CI_OS_NAME\" == \"linux\" ]]; then make -j`nproc` ; fi\n  if [[ \"$CI_OS_NAME\" == \"osx\" ]]; then make -j`sysctl -n hw.logicalcpu` ; fi\nelse\n  if [[ \"$CI_OS_NAME\" == \"linux\" ]]; then make all -j`nproc` ; fi\n  if [[ \"$CI_OS_NAME\" == \"osx\" ]]; then make all -j`sysctl -n hw.logicalcpu` ; fi\nfi\n"
  },
  {
    "path": "scripts/CI/run_tests.sh",
    "content": "#!/bin/bash\n\n# Test the project\n\nBASEDIR=$(dirname $0)\nsource $BASEDIR/defaults.sh\n\n# Only for NAME=\"default-cmake-cpu\" WITH_CUDA=false\nif [[ $RUN_EXAMPLES == true ]] ; then\n  echo \"Running demos and tutorials...\"\n  echo \" \"\n\n  echo \"OpenPose demo...\"\n  ./build/examples/openpose/openpose.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  echo \"(Deprecated) Tutorial Add Module: Example 1...\"\n  ./build/examples/deprecated/tutorial_add_module_custom_post_processing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  # # Note: Examples 1-2 require the whole OpenPose resolution (too much RAM memory) and the GUI\n  # echo \"Tutorial API C++: Examples 1-2...\"\n  # ./build/examples/tutorial_api_cpp/01_body_from_image_default.bin\n  # ./build/examples/tutorial_api_cpp/02_whole_body_from_image_default.bin\n  # echo \" \"\n\n  echo \"Tutorial API C++: Example 3...\"\n  ./build/examples/tutorial_api_cpp/03_keypoints_from_image.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 4...\"\n  ./build/examples/tutorial_api_cpp/04_keypoints_from_images.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 5...\"\n  ./build/examples/tutorial_api_cpp/05_keypoints_from_images_multi_gpu.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display --latency_is_irrelevant_and_computer_with_lots_of_ram\n  # Default configuration of this demo requires getGpuNumber(), which is not implement for CPU-only mode\n  # ./build/examples/tutorial_api_cpp/05_keypoints_from_images_multi_gpu.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 6...\"\n  ./build/examples/tutorial_api_cpp/06_face_from_image.bin --face_net_resolution 32x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 7...\"\n  ./build/examples/tutorial_api_cpp/07_hand_from_image.bin --hand_net_resolution 32x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 8...\"\n  ./build/examples/tutorial_api_cpp/08_heatmaps_from_image.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 9...\"\n  ./build/examples/tutorial_api_cpp/09_keypoints_from_heatmaps.bin --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 10...\"\n  ./build/examples/tutorial_api_cpp/10_asynchronous_custom_input.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  # # Note: Example 11 would require 3D video and camera parameters\n  # echo \"Tutorial API C++: Example 11...\"\n  # ./build/examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.bin\n  # echo \" \"\n\n  echo \"Tutorial API C++: Example 12...\"\n  ./build/examples/tutorial_api_cpp/12_asynchronous_custom_output.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 13...\"\n  ./build/examples/tutorial_api_cpp/13_asynchronous_custom_input_output_and_datum.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 14...\"\n  ./build/examples/tutorial_api_cpp/14_synchronous_custom_input.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 15...\"\n  ./build/examples/tutorial_api_cpp/15_synchronous_custom_preprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 16...\"\n  ./build/examples/tutorial_api_cpp/16_synchronous_custom_postprocessing.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 17...\"\n  ./build/examples/tutorial_api_cpp/17_synchronous_custom_output.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  echo \"Tutorial API C++: Example 18...\"\n  ./build/examples/tutorial_api_cpp/18_synchronous_custom_all_and_datum.bin --image_dir examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --no_display\n  echo \" \"\n\n  # Python examples\n  if [[ $WITH_PYTHON == true ]] ; then\n    if [[ $PYTHON3_VERSION ]] ; then\n      PYTHON_COMMAND=python3\n    else\n      PYTHON_COMMAND=python\n    fi\n    echo \"Tutorial API Python: OpenPose demo...\"\n    cd build/examples/tutorial_api_python\n    ${PYTHON_COMMAND} openpose_python.py --image_dir ../../../examples/media/ --net_resolution -1x32 --write_json output/ --write_images output/ --display 0\n    echo \" \"\n    # Note: All Python examples require GUI\n  fi\n\n  echo \"Demos and tutorials successfully finished!\"\n\n# Disable examples for all other CI Build configurations\nelse\n  echo \"Skipping tests for non CPU-only versions.\"\n  exit 0\nfi\n"
  },
  {
    "path": "scripts/osx/install_brew.sh",
    "content": "# In case the command line have already been installed, \"true\" will make it return a non-zero error code to avoid stopping the scripts\nxcode-select --install || true\nbash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)\"\nbrew update\n"
  },
  {
    "path": "scripts/osx/install_deps.sh",
    "content": "#!/bin/bash\nbrew_packages=\"openblas snappy leveldb gflags glog szip lmdb hdf5 opencv protobuf boost cmake viennacl\"\nfor pkg in $brew_packages\ndo\n    echo \"brew install $pkg || brew upgrade $pkg\"\n    brew install \"$pkg\" || brew upgrade \"$pkg\"\ndone\n\n# with Python pycaffe needs dependencies built from source\n#brew install --build-from-source --with-python -vd protobuf\n#brew install --build-from-source -vd boost boost-python\n# without Python the usual installation suffices\n\npip_packages=\"numpy<1.17 opencv-python<4.3\"\nfor pkg in $pip_packages\ndo\n    echo \"sudo -H python2 -m pip install $pkg\"\n    sudo -H python2 -m pip install \"$pkg\"\ndone\n"
  },
  {
    "path": "scripts/osx/mac_opencl_patch.txt",
    "content": "diff --git a/cmake/Modules/FindvecLib.cmake b/cmake/Modules/FindvecLib.cmake\nindex 7459f623..9c5ee818 100644\n--- a/cmake/Modules/FindvecLib.cmake\n+++ b/cmake/Modules/FindvecLib.cmake\n@@ -12,13 +12,17 @@ endif()\n \n set(__veclib_include_suffix \"Frameworks/vecLib.framework/Versions/Current/Headers\")\n \n-find_path(vecLib_INCLUDE_DIR vecLibTypes.h\n+exec_program(xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR)\n+find_path(vecLib_INCLUDE_DIR vecLib.h\n           DOC \"vecLib include directory\"\n           PATHS /System/Library/Frameworks/Accelerate.framework/Versions/Current/${__veclib_include_suffix}\n                 /System/Library/${__veclib_include_suffix}\n-                /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/\n+                ${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Headers/\n           NO_DEFAULT_PATH)\n \n+\n+set(vecLib_INCLUDE_DIR \"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/\")\n+\n include(FindPackageHandleStandardArgs)\n find_package_handle_standard_args(vecLib DEFAULT_MSG vecLib_INCLUDE_DIR)\n \ndiff --git a/src/caffe/layers/malis_loss_layer.cpp b/src/caffe/layers/malis_loss_layer.cpp\nindex dae3c7d1..68e8323a 100644\n--- a/src/caffe/layers/malis_loss_layer.cpp\n+++ b/src/caffe/layers/malis_loss_layer.cpp\n@@ -1,6 +1,6 @@\n #include <boost/pending/disjoint_sets.hpp>\n-#include <opencv2/highgui/highgui.hpp>\n-#include <opencv2/imgproc/imgproc.hpp>\n+//#include <opencv2/highgui/highgui.hpp>\n+//#include <opencv2/imgproc/imgproc.hpp>\n \n #include <algorithm>\n #include <cfloat>\n"
  },
  {
    "path": "scripts/tests/drawProtoTxt.sh",
    "content": "#!/bin/bash\n\n\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\n# Required\n# sudo apt-get install graphviz\n\n# USAGE EXAMPLE\n# clear && clear && make all -j`nproc` && bash ./scripts/tests/speed_test.sh\n\n# # Go back to main folder\n# cd ../../\n\nPROTO_TXT_PATH=/mnt/DataUbuntu/openpose_train/training_results/pose/pose_training.prototxt\nOUTPUT_PNG_PATH=/mnt/DataUbuntu/openpose_train/training_results/pose/pose_training.png\n\n# Get model speed\npython ~/devel/openpose_caffe_train/python/draw_net.py $PROTO_TXT_PATH $OUTPUT_PNG_PATH\ndisplay $OUTPUT_PNG_PATH\nrm $OUTPUT_PNG_PATH\n"
  },
  {
    "path": "scripts/tests/hand_accuracy_test.sh",
    "content": "#!/bin/bash\n\n\n\n# Disclaimer:\n# Script for internal use. We might make continuous changess on it and we will not answer questions about it.\n\n# Full usage description:\n    # Step 1 - Getting JSON output\n        # Running it:\n        # Run it from OpenPose main folder with the following command:\n        # clear && clear && make all -j`nproc` && bash ./scripts/tests/hand_accuracy_test.sh\n\n        # Image paths:\n        # Read that script for details about all the paths and change them for your own paths.\n\n        # Careful:\n        # If you are using the NAS, please do not override my files, i.e., please change the output paths (corresponding to the ones indicated by `--write_json`, which is ).\n\n        # In order to generate the JSON output:\n        # Uncomment the commented lines starting by `--write_json` and `--display 0`\n\n    # Step 2 - Running JSON output to get accuracy\n        # Once you have the JSON files, run them with the script Tomas prepared for it, which in my case I use:\n        # From Matlab, `cd /media/posefs3b/Users/gines/openpose_train/dataset/hand_testing`\n        # Run `b_keypointJsonToMatAndImage` to generate your new file (you can run the current code to try it, I commented everything but test 1)\n        # Run `c_plot_save_results` to plot and save the results. Just modify `models` and `texts` with your new model path and desired name.\n\n# Clear terminal screen\nclear && clear\n\n\n\n# Fix paths\nHAND_TESTING_FOLDER=\"/media/posefs3b/Users/gines/openpose_train/dataset/hand_testing/\"\nIMAGES_FOLDER=${HAND_TESTING_FOLDER}\"0_images/\"\nIMAGES_BB_FOLDER=${HAND_TESTING_FOLDER}\"3_images_bounding_box\"\nHAND_GROUND_TRUTH_FOLDER=${HAND_TESTING_FOLDER}\"4_hand_detections\"\nPEOPLE_JSON_FOLDER=${HAND_TESTING_FOLDER}\"5_keypointJson/\"\n\n# Variable paths\nSCALES=6\nSUFFIX=\"_${SCALES}\"\nHAND_RESULTS_FOLDER_BASE=${PEOPLE_JSON_FOLDER}\"hand_keypoints_estimated\"\nHAND_RESULTS_FOLDER_NO_BB=${HAND_RESULTS_FOLDER_BASE}\"_old\"${SUFFIX}\nHAND_RESULTS_FOLDER_BB=${HAND_RESULTS_FOLDER_BASE}\"_BBox\"${SUFFIX}\nHAND_RESULTS_FOLDER_BODY_65=${HAND_RESULTS_FOLDER_BASE}\"_BODY_65\"\n\n\n\n# Given bounding box\necho \"Output on ${HAND_RESULTS_FOLDER_BB}\"\nrm -rf $HAND_RESULTS_FOLDER_BB\n# 1 scale\n./build/examples/tests/handFromJsonTest.bin \\\n    --hand_scale_number ${SCALES} --hand_scale_range 0.4 \\\n    --image_dir ${IMAGES_BB_FOLDER} \\\n    --hand_ground_truth ${HAND_GROUND_TRUTH_FOLDER} \\\n    --write_json $HAND_RESULTS_FOLDER_BB \\\n    --display 0\n\n\n\n# No bounding box\necho \"Output on ${HAND_RESULTS_FOLDER_NO_BB}\"\nrm -rf $HAND_RESULTS_FOLDER_NO_BB\n# 1 scale\n./build/examples/openpose/openpose.bin \\\n    --hand \\\n    --hand_scale_number ${SCALES} --hand_scale_range 0.4 \\\n    --image_dir ${IMAGES_FOLDER} \\\n    --write_json $HAND_RESULTS_FOLDER_NO_BB \\\n    --display 0\n"
  },
  {
    "path": "scripts/tests/pose_accuracy_all_val.sh",
    "content": "#!/bin/bash\n# Script to extract COCO JSON file for each trained model\nclear && clear && make all -j`nproc`\n\n# Body/Foot\nIMAGE_DIR=\"/home/gines/devel/images/val2017/\"\nIMAGE_DIR_FOOT=\"/home/gines/devel/images/val2017_foot/\"\n# Face\nIMAGE_DIR_FRGC=\"/home/gines/devel/images/frgc_val/\"\nIMAGE_DIR_MPIE=\"/home/gines/devel/images/multipie_val/\"\nIMAGE_DIR_FACE_MASK_OUT=\"/home/gines/devel/images/face_mask_out_val/\"\n# Hand\nIMAGE_DIR_HAND_DOME=\"/home/gines/devel/images/hand_dome_val/\"\nIMAGE_DIR_HAND_MPII=\"/home/gines/devel/images/hand_mpii_val/\"\n\n# cd OpenPose folder\ncd /home/gines/Dropbox/Perceptual_Computing_Lab/openpose/openpose/\n\ntemporaryJsonFile1=~/Desktop/OpenPose_1.json\ntemporaryJsonFile4=~/Desktop/OpenPose_4.json\nOP_COMAND=\"./build/examples/openpose/openpose.bin --face --hand --render_pose 0 --display 0 --cli_verbose 0.2\"\nOP_COMAND_1SCALE=\"${OP_COMAND} --write_coco_json ${temporaryJsonFile1} --num_gpu_start 1\"\nOP_COMAND_4SCALES=\"${OP_COMAND} --maximize_positives --net_resolution_dynamic -1 --scale_number 4 --scale_gap 0.25 --write_coco_json ${temporaryJsonFile4} --num_gpu_start 1\"\n\n# NOTE: Uncomment those tests you are interested into. By default, all disabled.\n\n# # Body/foot 1 scale\n# echo \"Processing bodies/feet...\"\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR} --write_coco_json_variants 3\n\n# # Faces\n# echo \"Processing faces...\"\n# temporaryJsonFile1Face=~/Desktop/OpenPose_1_face.json\n# # Face FRGC processing\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_FRGC} --write_coco_json_variants 4\n# # Face MPIE processing\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_MPIE} --write_coco_json_variants 4\n# # Face Mask Out processing\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_FACE_MASK_OUT} --write_coco_json_variants 4\n\n# # Hands\n# echo \"Processing hands...\"\n# # Hand Dome processing\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_HAND_DOME} --write_coco_json_variants 8\n# Hand MPII processing\n# $OP_COMAND_1SCALE --image_dir ${IMAGE_DIR_HAND_MPII} --write_coco_json_variants 16\n\n# # Body/foot 4 scales\n# $OP_COMAND_4SCALES --image_dir ${IMAGE_DIR} --write_coco_json_variants 3 --net_resolution \"1312x736\"\n\necho \" \"\necho \"Finished! Exiting script...\"\necho \" \"\n"
  },
  {
    "path": "scripts/tests/pose_accuracy_car_val.sh",
    "content": "#!/bin/bash\n\n\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\nclear && clear\n\n# USAGE EXAMPLE\n# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_test.sh\n\n# # Go back to main folder\n# cd ../../\n\n\n# Write COCO-format JSON\n# Last id:\n    # ID 20671  <-->    #frames = 1471      -->     ~ 1.5 min at 15fps\n    # ID 50006  <-->    #frames = 3559      -->     ~ 4 min at 15fps\n\n# Parameters\nIMAGE_FOLDER_CF=/home/gines/devel/images/car-fusion_val/\nIMAGE_FOLDER_P3=/home/gines/devel/images/pascal3d+_val/\nIMAGE_FOLDER_V7=/home/gines/devel/images/veri-776_val/\nJSON_FOLDER=../evaluation/coco_val_jsons/\nOP_BIN=./build/examples/openpose/openpose.bin\nGPUS=-1\n# GPUS=1\n\n    # 1 scale\n$OP_BIN --image_dir $IMAGE_FOLDER_CF --write_coco_json_variant 0 --write_coco_json ${JSON_FOLDER}processed_carfusion_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS}\n$OP_BIN --image_dir $IMAGE_FOLDER_P3 --write_coco_json_variant 1 --write_coco_json ${JSON_FOLDER}processed_pascal3dplus_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS}\n$OP_BIN --image_dir $IMAGE_FOLDER_V7 --write_coco_json_variant 2 --write_coco_json ${JSON_FOLDER}processed_veri776_val_1.json --model_pose CAR_22 --display 0 --render_pose 0 --num_gpu ${GPUS}\n\n#     # 4 scales\n# $OP_BIN --image_dir $IMAGE_FOLDER_CF --write_coco_json_variant 0 --write_coco_json ${JSON_FOLDER}processed_carfusion_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\" --num_gpu ${GPUS}\n# $OP_BIN --image_dir $IMAGE_FOLDER_P3 --write_coco_json_variant 1 --write_coco_json ${JSON_FOLDER}processed_pascal3dplus_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\" --num_gpu ${GPUS}\n# $OP_BIN --image_dir $IMAGE_FOLDER_V7 --write_coco_json_variant 2 --write_coco_json ${JSON_FOLDER}processed_veri776_val_4.json --model_pose CAR_22 --display 0 --render_pose 0 --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\" --num_gpu ${GPUS}\n"
  },
  {
    "path": "scripts/tests/pose_accuracy_coco_test_dev.sh",
    "content": "#!/bin/bash\n\n\n\n# USAGE EXAMPLE\n# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_test_dev.sh\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\nclear && clear\n\n# Parameters\nIMAGE_FOLDER=/media/posefs3b/Users/gines/openpose_train/dataset/COCO/cocoapi/images/test2017_dev/\nJSON_FOLDER=../evaluation/coco_val_jsons/\n# JSON_FOLDER=/media/posefs3b/Users/gines/openpose_train/training_results/2_23_51/best_702k/\nOP_BIN=./build/examples/openpose/openpose.bin\n\n#     # 1 scale\n# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_test_max.json \\\n#     --scale_number 1 --scale_gap 0.25 --maximize_positives --net_resolution_dynamic -1 --model_pose BODY_25B\n# zip ${JSON_FOLDER}1_test_max.zip ${JSON_FOLDER}1_test_max.json\n\n    # 4 scales\n# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4_test.json \\\n#     --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\"\n$OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4_test_max.json \\\n    --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\" --maximize_positives --net_resolution_dynamic -1\nzip ${JSON_FOLDER}1_4_test_max.zip ${JSON_FOLDER}1_4_test_max.json\n\n\n\n# Additional settings:\n# 1. For maximum accuracy:\n#     --write_coco_json ${JSON_FOLDER}1_4_max.json --maximize_positives --net_resolution_dynamic -1\n# 2. For custom models:\n#     --model_pose BODY_25B/BODY_23 --model_folder ${JSON_FOLDER}\n"
  },
  {
    "path": "scripts/tests/pose_accuracy_coco_val.sh",
    "content": "#!/bin/bash\n\n\n\n# USAGE EXAMPLE\n# clear && clear && make all -j`nproc` && bash ./scripts/tests/pose_accuracy_coco_val.sh\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\nclear && clear\n\n# Parameters\nIMAGE_FOLDER=~/devel/images/val2017/\nIMAGE_FOOT_FOLDER=~/devel/images/val2017_foot/\nJSON_FOLDER=../evaluation/coco_val_jsons/\n# JSON_FOLDER=/media/posefs3b/Users/gines/openpose_train/training_results/2_23_51/best_702k/\nOP_BIN=./build/examples/openpose/openpose.bin\n\n    # 1 scale (body)\n$OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1.json --write_coco_json_variants 1\n# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_max.json --write_coco_json_variants 3 \\\n#     --maximize_positives --net_resolution_dynamic -1\n\n    # 1 scale (foot)\n$OP_BIN --image_dir $IMAGE_FOOT_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1.json --write_coco_json_variants 2\n\n#     # 4 scales\n# $OP_BIN --image_dir $IMAGE_FOLDER --display 0 --render_pose 0 --cli_verbose 0.2 --write_coco_json ${JSON_FOLDER}1_4.json --write_coco_json_variants 1 \\\n#     --scale_number 4 --scale_gap 0.25 --net_resolution \"1312x736\"\n\n\n\n# Additional settings:\n# 1. For maximum accuracy:\n#     --write_coco_json ${JSON_FOLDER}1_4_max.json --maximize_positives --net_resolution_dynamic -1\n# 2. For custom models:\n#     --model_pose BODY_25B/BODY_23 --model_folder ${JSON_FOLDER}\n"
  },
  {
    "path": "scripts/tests/pose_time_Caffe_layers.sh",
    "content": "#!/bin/bash\n\n\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\n# # Go back to main folder\n# cd ../../\n\n# Performance results\nPROTOTXT_PATH=/home/gines/Dropbox/Perceptual_Computing_Lab/openpose/openpose/models/pose/coco/pose_deploy_linevec.prototxt\n\ngedit $0\n# First: Add 656 x 368 as input_dim in:\ngedit $PROTOTXT_PATH\n./3rdparty/caffe/build/tools/caffe time -model $PROTOTXT_PATH -gpu 0 -phase TEST\ngedit $PROTOTXT_PATH\n"
  },
  {
    "path": "scripts/tests/pose_time_visual_GUI.sh",
    "content": "#!/bin/bash\n\n\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\n# # Go back to main folder\n# cd ../../\n\n# Re-build\nclear && clear && make all -j`nproc`\n\n# Performance results (~1400)\n./build/examples/openpose/openpose.bin --video soccer.mp4 --frame_last 1500\n# Including 2nd graphics card (~3500)\n# ./build/examples/openpose/openpose.bin --video soccer.mp4 --frame_last 3750\n"
  },
  {
    "path": "scripts/tests/speed_test.sh",
    "content": "#!/bin/bash\n\n\n\n# Script for internal use. We might completely change it continuously and we will not answer questions about it.\n\n# USAGE EXAMPLE\n# clear && clear && make all -j`nproc` && bash ./scripts/tests/speed_test.sh\n\n# # Go back to main folder\n# cd ../../\n\n# Get model speed\n~/devel/openpose_caffe_train/build/tools/caffe time -gpu 0 -model /mnt/DataUbuntu/openpose_train/training_results_light/pose/pose_training.prototxt\n# ./3rdparty/caffe/build/tools/caffe time -gpu 0 -model /mnt/DataUbuntu/openpose_train/training_results_light/pose/pose_training.prototxt\n"
  },
  {
    "path": "scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_61,code=compute_61\n# Deprecated\n# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \\\n# \t\t-gencode arch=compute_20,code=sm_21 \\\n# \t\t-gencode arch=compute_30,code=sm_30 \\\n# \t\t-gencode arch=compute_35,code=sm_35 \\\n# \t\t-gencode arch=compute_50,code=sm_50 \\\n# \t\t-gencode arch=compute_52,code=sm_52 \\\n# \t\t-gencode arch=compute_60,code=sm_60 \\\n# \t\t-gencode arch=compute_61,code=sm_61 \\\n# \t\t-gencode arch=compute_61,code=compute_61\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\nOPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_61,code=compute_61\n# Deprecated\n# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \\\n# \t\t-gencode arch=compute_20,code=sm_21 \\\n# \t\t-gencode arch=compute_30,code=sm_30 \\\n# \t\t-gencode arch=compute_35,code=sm_35 \\\n# \t\t-gencode arch=compute_50,code=sm_50 \\\n# \t\t-gencode arch=compute_52,code=sm_52 \\\n# \t\t-gencode arch=compute_60,code=sm_60 \\\n# \t\t-gencode arch=compute_61,code=sm_61 \\\n# \t\t-gencode arch=compute_61,code=compute_61\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/aarch64-linux-gnu /usr/lib/aarch64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu/Makefile.example",
    "content": "PROJECT := openpose\n\nCONFIG_FILE := Makefile.config\n# Explicitly check for the config file, otherwise make -k will proceed anyway.\nifeq ($(wildcard $(CONFIG_FILE)),)\n$(error $(CONFIG_FILE) not found. See $(CONFIG_FILE).example.)\nendif\ninclude $(CONFIG_FILE)\n\nBUILD_DIR_LINK := $(BUILD_DIR)\nifeq ($(RELEASE_BUILD_DIR),)\n\tRELEASE_BUILD_DIR := .$(BUILD_DIR)_release\nendif\nifeq ($(DEBUG_BUILD_DIR),)\n\tDEBUG_BUILD_DIR := .$(BUILD_DIR)_debug\nendif\n\nDEBUG ?= 0\nifeq ($(DEBUG), 1)\n\tBUILD_DIR := $(DEBUG_BUILD_DIR)\n\tOTHER_BUILD_DIR := $(RELEASE_BUILD_DIR)\nelse\n\tBUILD_DIR := $(RELEASE_BUILD_DIR)\n\tOTHER_BUILD_DIR := $(DEBUG_BUILD_DIR)\nendif\n\n# All of the directories containing code.\nSRC_DIRS := $(shell find * -type d -exec bash -c \"find {} -maxdepth 1 \\\n\t-name '*.cpp' | grep -q .\" \\; -print)\n\n# The target shared library name\nLIBRARY_NAME := $(PROJECT)\nLIB_BUILD_DIR := $(BUILD_DIR)/lib\nSTATIC_NAME := $(LIB_BUILD_DIR)/lib$(LIBRARY_NAME).a\nDYNAMIC_VERSION_MAJOR \t\t:= 1\nDYNAMIC_VERSION_MINOR \t\t:= 7\nDYNAMIC_VERSION_REVISION \t:= 0\nDYNAMIC_NAME_SHORT := lib$(LIBRARY_NAME).so\n#DYNAMIC_SONAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR)\nDYNAMIC_VERSIONED_NAME_SHORT := $(DYNAMIC_NAME_SHORT).$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION)\nDYNAMIC_NAME := $(LIB_BUILD_DIR)/$(DYNAMIC_VERSIONED_NAME_SHORT)\nCOMMON_FLAGS += -DOPEN_POSE_VERSION=$(DYNAMIC_VERSION_MAJOR).$(DYNAMIC_VERSION_MINOR).$(DYNAMIC_VERSION_REVISION)\n\n\n##############################\n# Enable profiler\n##############################\nPROFILER_ENABLED ?= 0\nifneq ($(PROFILER_ENABLED), 0)\n\tCOMMON_FLAGS += -DPROFILER_ENABLED=$(PROFILER_ENABLED)\nendif\n\n\n##############################\n# Deep net selection\n##############################\nDEEP_NET ?= caffe\n# TensorFlow\nifeq ($(DEEP_NET), tensorflow)\n\t# COMMON_FLAGS += -DUSE_TENSOR_FLOW\n# Torch\nelse ifeq ($(DEEP_NET), torch)\n\t# COMMON_FLAGS += -DUSE_TORCH\n# Caffe\nelse\n\tCOMMON_FLAGS += -DUSE_CAFFE\n\tLIBRARIES += caffe\n\tLDFLAGS += -Wl,-rpath=$(CAFFE_DIR)/lib\n\tINCLUDE_DIRS += $(CAFFE_DIR)/include\n\tLIBRARY_DIRS += $(CAFFE_DIR)/lib\nendif\n\n\n# Faster GUI display\nWITH_OPENCV_WITH_OPENGL ?= 0\nifneq ($(WITH_OPENCV_WITH_OPENGL), 0)\n\tCOMMON_FLAGS += -DUSE_OPENCV_WITH_OPENGL\n\t# FreeGLUT\n\tLIBRARIES += glut\n\t# LIBRARIES += GLU GL glut\nendif\n\n# 3-D\n# 3-D renderer\nWITH_3D_RENDERER ?= 0\nifneq ($(WITH_3D_RENDERER), 0)\n\tCOMMON_FLAGS += -DUSE_3D_RENDERER\n\t# FreeGLUT\n\tLIBRARIES += glut\n\t# LIBRARIES += GLU GL glut\nendif\n# Ceres support\nWITH_CERES ?= 0\nifneq ($(WITH_CERES), 0)\n\tCOMMON_FLAGS += -DUSE_CERES\n\t# Ceres\n\tLIBRARIES += ceres\n\tINCLUDE_DIRS += $(EIGEN_DIR)\n\t# If Ceres was built with Suitesparse:\n\tLIBRARIES += lapack camd amd ccolamd colamd cholmod\n\t# If Ceres was built with CXSparse:\n\tLIBRARIES += cxsparse\n\t# If Ceres was built with OpenMP:\n\tLIBRARIES += pthread gomp m\n\tCXXFLAGS += -fopenmp\n\tLINKFLAGS += -fopenmp\nendif\n# Eigen support\nWITH_EIGEN ?= 0\nifneq ($(WITH_EIGEN), 0)\n\tCOMMON_FLAGS += -DUSE_EIGEN\n\tINCLUDE_DIRS += $(EIGEN_DIR)\nendif\n# Spinnaker SDK\nWITH_FLIR_CAMERA ?= 0\nifneq ($(WITH_FLIR_CAMERA), 0)\n\tCOMMON_FLAGS += -DUSE_FLIR_CAMERA\n\t# Spinnaker SDK\n\tLIBRARIES += Spinnaker\n\t# INCLUDE_DIRS += $(SPINNAKER_DIR)\n\tCOMMON_FLAGS += -isystem $(SPINNAKER_DIR) # Remove warnings from this library\nendif\n\n##############################\n# Get all source files\n##############################\n# CXX_SRCS are the source files excluding the test ones.\n# CXX_SRCS := $(shell find src/$(PROJECT) ! -name \"test_*.cpp\" -name \"*.cpp\")\nCXX_SRCS := $(shell find src ! -name \"test_*.cpp\" -name \"*.cpp\")\n# CU_SRCS are the cuda source files\n# CU_SRCS := $(shell find src/$(PROJECT) ! -name \"test_*.cu\" -name \"*.cu\")\nCU_SRCS := $(shell find src ! -name \"test_*.cu\" -name \"*.cu\")\n# EXAMPLE_SRCS are the source files for the example binaries\nEXAMPLE_SRCS := $(shell find examples -name \"*.cpp\")\n# BUILD_INCLUDE_DIR contains any generated header files we want to include.\nBUILD_INCLUDE_DIR := $(BUILD_DIR)/src\n# NONGEN_CXX_SRCS includes all source/header files except those generated\n# automatically (e.g., by proto).\nNONGEN_CXX_SRCS := $(shell find \\\n\tsrc/$(PROJECT) \\\n\tinclude/$(PROJECT) \\\n\texamples \\\n\t-name \"*.cpp\" -or -name \"*.hpp\" -or -name \"*.cu\" -or -name \"*.cuh\")\nLINT_SCRIPT := scripts/cpp_lint.py\nLINT_OUTPUT_DIR := $(BUILD_DIR)/.lint\nLINT_EXT := lint.txt\nLINT_OUTPUTS := $(addsuffix .$(LINT_EXT), $(addprefix $(LINT_OUTPUT_DIR)/, $(NONGEN_CXX_SRCS)))\nEMPTY_LINT_REPORT := $(BUILD_DIR)/.$(LINT_EXT)\nNONEMPTY_LINT_REPORT := $(BUILD_DIR)/$(LINT_EXT)\n\n##############################\n# Derive generated files\n##############################\n# The objects corresponding to the source files\n# These objects will be linked into the final shared library, so we\n# exclude the example objects.\nCXX_OBJS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o})\nCU_OBJS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o})\nOBJS := $(CXX_OBJS) $(CU_OBJS)\n# example objects\nEXAMPLE_OBJS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o})\n# Output files for automatic dependency generation\nDEPS := ${EXAMPLE_OBJS:.o=.d} ${CXX_OBJS:.o=.d} ${CU_OBJS:.o=.d}\nEXAMPLE_BINS := ${EXAMPLE_OBJS:.o=.bin}\n\n##############################\n# Derive compiler warning dump locations\n##############################\nWARNS_EXT := warnings.txt\nCXX_WARNS := $(addprefix $(BUILD_DIR)/, ${CXX_SRCS:.cpp=.o.$(WARNS_EXT)})\nCU_WARNS := $(addprefix $(BUILD_DIR)/cuda/, ${CU_SRCS:.cu=.o.$(WARNS_EXT)})\nEXAMPLE_WARNS := $(addprefix $(BUILD_DIR)/, ${EXAMPLE_SRCS:.cpp=.o.$(WARNS_EXT)})\nALL_CXX_WARNS := $(CXX_WARNS) $(EXAMPLE_WARNS)\nALL_CU_WARNS := $(CU_WARNS)\nALL_WARNS := $(ALL_CXX_WARNS) $(ALL_CU_WARNS)\n\nEMPTY_WARN_REPORT := $(BUILD_DIR)/.$(WARNS_EXT)\nNONEMPTY_WARN_REPORT := $(BUILD_DIR)/$(WARNS_EXT)\n\n##############################\n# Derive include and lib directories\n##############################\nCUDA_INCLUDE_DIR := $(CUDA_DIR)/include\n\nCUDA_LIB_DIR :=\n# add <cuda>/lib64 only if it exists\nifneq (\"$(wildcard $(CUDA_DIR)/lib64)\",\"\")\n\tCUDA_LIB_DIR += $(CUDA_DIR)/lib64\nendif\nCUDA_LIB_DIR += $(CUDA_DIR)/lib\n\nINCLUDE_DIRS += $(BUILD_INCLUDE_DIR) ./src ./include\nifeq ($(USE_CUDA), 1)\n\tINCLUDE_DIRS += $(CUDA_INCLUDE_DIR)\n\tLIBRARY_DIRS += $(CUDA_LIB_DIR)\n\tLIBRARIES += cudart cublas curand\nendif\n\nLIBRARIES += glog gflags m hdf5_hl hdf5\n\n# handle IO dependencies\nUSE_LEVELDB ?= 1\nUSE_LMDB ?= 1\nUSE_OPENCV ?= 1\n\nifeq ($(USE_LEVELDB), 1)\n\tLIBRARIES += leveldb snappy\nendif\nifeq ($(USE_LMDB), 1)\n\tLIBRARIES += lmdb\nendif\nifeq ($(USE_OPENCV), 1)\n\tLIBRARIES += opencv_core opencv_highgui opencv_imgproc opencv_objdetect opencv_video opencv_calib3d\n\n\tifeq ($(OPENCV_VERSION), 3)\n\t\tLIBRARIES += opencv_imgcodecs opencv_videoio\n\t\t# Cuda warping removed for TX2 compatibility (PR #989)\n\t\t# LIBRARIES += opencv_imgcodecs opencv_videoio opencv_cudawarping\n\telse\n\t\tLIBRARIES += opencv_contrib opencv_gpu\n\tendif\n\nendif\n##############################\n# OpenPose extra code: commented\n##############################\n# WARNINGS := -Wall -Wno-sign-compare\n\n##############################\n# Set build directories\n##############################\n\nDISTRIBUTE_DIR ?= distribute\nDISTRIBUTE_SUBDIRS := $(DISTRIBUTE_DIR)/bin $(DISTRIBUTE_DIR)/lib\nDIST_ALIASES := dist\nifneq ($(strip $(DISTRIBUTE_DIR)),distribute)\n\t\tDIST_ALIASES += distribute\nendif\n\nALL_BUILD_DIRS := $(sort $(BUILD_DIR) $(addprefix $(BUILD_DIR)/, $(SRC_DIRS)) \\\n\t$(addprefix $(BUILD_DIR)/cuda/, $(SRC_DIRS)) \\\n\t$(LIB_BUILD_DIR) $(LINT_OUTPUT_DIR))\n\n##############################\n# Set directory for Doxygen-generated documentation\n##############################\nDOXYGEN_CONFIG_FILE ?= ./.Doxyfile\n# should be the same as OUTPUT_DIRECTORY in the .Doxyfile\nDOXYGEN_OUTPUT_DIR ?= ./doxygen\nDOXYGEN_COMMAND ?= doxygen\n# All the files that might have Doxygen documentation.\nDOXYGEN_SOURCES := $(shell find \\\n\tsrc/$(PROJECT) \\\n\tinclude/$(PROJECT) \\\n\texamples \\\n\t-name \"*.cpp\" -or -name \"*.hpp\" -or -name \"*.cu\" -or -name \"*.cuh\")\nDOXYGEN_SOURCES += $(DOXYGEN_CONFIG_FILE)\n\n\n##############################\n# OpenPose extra code: added flags\n##############################\n# Automatic dependency generation (nvcc is handled separately)\nCXXFLAGS += -march=native\n\n# Complete build flags.\nCXXFLAGS += -fopenmp -Wpedantic -Wall -Wextra\nCXXFLAGS += -Wfatal-errors\nCOMMON_FLAGS += -std=c++11\nLINKFLAGS += -fopenmp\n\n\n##############################\n# Configure build\n##############################\n\n# Determine platform\nUNAME := $(shell uname -s)\nifeq ($(UNAME), Linux)\n\tLINUX := 1\nelse ifeq ($(UNAME), Darwin)\n\tOSX := 1\n\tOSX_MAJOR_VERSION := $(shell sw_vers -productVersion | cut -f 1 -d .)\n\tOSX_MINOR_VERSION := $(shell sw_vers -productVersion | cut -f 2 -d .)\nendif\n\n# Linux\nifeq ($(LINUX), 1)\n\tCXX ?= /usr/bin/g++\n\tGCCVERSION := $(shell $(CXX) -dumpversion | cut -f1,2 -d.)\n\t# We will also explicitly add stdc++ to the link target.\n\tLIBRARIES += stdc++\n\tVERSIONFLAGS += -Wl,-soname,$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../lib\nendif\n\n# OS X:\n# clang++ instead of g++\n# libstdc++ for NVCC compatibility on OS X >= 10.9 with CUDA < 7.0\nifeq ($(OSX), 1)\n\tCXX := /usr/bin/clang++\n\tifeq ($(USE_CUDA), 1)\n\t\tCUDA_VERSION := $(shell $(CUDA_DIR)/bin/nvcc -V | grep -o 'release [0-9.]*' | tr -d '[a-z ]')\n\t\tifeq ($(shell echo | awk '{exit $(CUDA_VERSION) < 7.0;}'), 1)\n\t\t\tCXXFLAGS += -stdlib=libstdc++\n\t\t\tLINKFLAGS += -stdlib=libstdc++\n\t\tendif\n\t\t# clang throws this warning for cuda headers\n\t\tWARNINGS += -Wno-unneeded-internal-declaration\n\t\t# 10.11 strips DYLD_* env vars so link CUDA (rpath is available on 10.5+)\n\t\tOSX_10_OR_LATER   := $(shell [ $(OSX_MAJOR_VERSION) -ge 10 ] && echo true)\n\t\tOSX_10_5_OR_LATER := $(shell [ $(OSX_MINOR_VERSION) -ge 5 ] && echo true)\n\t\tifeq ($(OSX_10_OR_LATER),true)\n\t\t\tifeq ($(OSX_10_5_OR_LATER),true)\n\t\t\t\tLDFLAGS += -Wl,-rpath,$(CUDA_LIB_DIR)\n\t\t\tendif\n\t\tendif\n\tendif\n\t# we need to explicitly ask for the rpath to be obeyed\n\tORIGIN := @loader_path\n\tVERSIONFLAGS += -Wl,-install_name,@rpath/$(DYNAMIC_VERSIONED_NAME_SHORT) -Wl,-rpath,$(ORIGIN)/../../build/lib\nelse\n\tORIGIN := \\$$ORIGIN\nendif\n\n# Custom compiler\nifdef CUSTOM_CXX\n\tCXX := $(CUSTOM_CXX)\nendif\n\n# Static linking\nifneq (,$(findstring clang++,$(CXX)))\n\tSTATIC_LINK_COMMAND := -Wl,-force_load $(STATIC_NAME)\nelse ifneq (,$(findstring g++,$(CXX)))\n\tSTATIC_LINK_COMMAND := -Wl,--whole-archive $(STATIC_NAME) -Wl,--no-whole-archive\nelse\n  # The following line must not be indented with a tab, since we are not inside a target\n  $(error Cannot static link with the $(CXX) compiler)\nendif\n\n# Debugging\nifeq ($(DEBUG), 1)\n\tCOMMON_FLAGS += -DDEBUG -g -O0\n\tNVCCFLAGS += -G\nelse\n\tCOMMON_FLAGS += -DNDEBUG -O3\nendif\n\n# configure IO libraries\nifeq ($(USE_OPENCV), 1)\n\tCOMMON_FLAGS += -DUSE_OPENCV\nendif\nifeq ($(USE_LEVELDB), 1)\n\tCOMMON_FLAGS += -DUSE_LEVELDB\nendif\nifeq ($(USE_LMDB), 1)\n\tCOMMON_FLAGS += -DUSE_LMDB\nifeq ($(ALLOW_LMDB_NOLOCK), 1)\n\tCOMMON_FLAGS += -DALLOW_LMDB_NOLOCK\nendif\nendif\n\n# CPU-only configuration\nifeq ($(USE_CUDA), 1)\n\tCOMMON_FLAGS += -DUSE_CUDA\nelse\n\tCOMMON_FLAGS += -DCPU_ONLY # For Caffe\n\tCOMMON_FLAGS += -DUSE_CPU_ONLY\nendif\n\nLIBRARY_DIRS += $(LIB_BUILD_DIR)\n\n# Automatic dependency generation (nvcc is handled separately)\nCXXFLAGS += -MMD -MP\n\n# Complete build flags.\nCOMMON_FLAGS += $(foreach includedir,$(INCLUDE_DIRS),-I$(includedir))\nCXXFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS)\nNVCCFLAGS += -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS)\nLINKFLAGS += -pthread -fPIC $(COMMON_FLAGS) $(WARNINGS)\n\nUSE_PKG_CONFIG ?= 0\nifeq ($(USE_PKG_CONFIG), 1)\n\tPKG_CONFIG := $(shell pkg-config opencv --libs)\nelse\n\tPKG_CONFIG :=\nendif\nLDFLAGS += $(foreach librarydir,$(LIBRARY_DIRS),-L$(librarydir)) $(PKG_CONFIG) \\\n\t\t$(foreach library,$(LIBRARIES),-l$(library))\n\n##############################\n# Define build targets\n##############################\n.PHONY: all lib clean docs linecount lint lintclean examples $(DIST_ALIASES) \\\n\twarn everything\n\nall: lib examples\n\nlib: $(STATIC_NAME) $(DYNAMIC_NAME)\n\neverything: $(EVERYTHING_TARGETS)\n\nlinecount:\n\tcloc --read-lang-def=$(PROJECT).cloc \\\n\t\tsrc/$(PROJECT) include/$(PROJECT) examples\n\nlint: $(EMPTY_LINT_REPORT)\n\nlintclean:\n\t@ $(RM) -r $(LINT_OUTPUT_DIR) $(EMPTY_LINT_REPORT) $(NONEMPTY_LINT_REPORT)\n\ndocs: $(DOXYGEN_OUTPUT_DIR)\n\t@ cd ./docs ; ln -sfn ../$(DOXYGEN_OUTPUT_DIR)/html doxygen\n\n$(DOXYGEN_OUTPUT_DIR): $(DOXYGEN_CONFIG_FILE) $(DOXYGEN_SOURCES)\n\t$(DOXYGEN_COMMAND) $(DOXYGEN_CONFIG_FILE)\n\n$(EMPTY_LINT_REPORT): $(LINT_OUTPUTS) | $(BUILD_DIR)\n\t@ cat $(LINT_OUTPUTS) > $@\n\t@ if [ -s \"$@\" ]; then \\\n\t\tcat $@; \\\n\t\tmv $@ $(NONEMPTY_LINT_REPORT); \\\n\t\techo \"Found one or more lint errors.\"; \\\n\t\texit 1; \\\n\t  fi; \\\n\t  $(RM) $(NONEMPTY_LINT_REPORT); \\\n\t  echo \"No lint errors!\";\n\n$(LINT_OUTPUTS): $(LINT_OUTPUT_DIR)/%.lint.txt : % $(LINT_SCRIPT) | $(LINT_OUTPUT_DIR)\n\t@ mkdir -p $(dir $@)\n\t@ python $(LINT_SCRIPT) $< 2>&1 \\\n\t\t| grep -v \"^Done processing \" \\\n\t\t| grep -v \"^Total errors found: 0\" \\\n\t\t> $@ \\\n\t\t|| true\n\nexamples: $(EXAMPLE_BINS)\n\nwarn: $(EMPTY_WARN_REPORT)\n\n$(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR)\n\t@ cat $(ALL_WARNS) > $@\n\t@ if [ -s \"$@\" ]; then \\\n\t\tcat $@; \\\n\t\tmv $@ $(NONEMPTY_WARN_REPORT); \\\n\t\techo \"Compiler produced one or more warnings.\"; \\\n\t\texit 1; \\\n\t  fi; \\\n\t  $(RM) $(NONEMPTY_WARN_REPORT); \\\n\t  echo \"No compiler warnings!\";\n\n$(ALL_WARNS): %.o.$(WARNS_EXT) : %.o\n\n$(BUILD_DIR_LINK): $(BUILD_DIR)/.linked\n\n# Create a target \".linked\" in this BUILD_DIR to tell Make that the \"build\" link\n# is currently correct, then delete the one in the OTHER_BUILD_DIR in case it\n# exists and $(DEBUG) is toggled later.\n$(BUILD_DIR)/.linked:\n\t@ mkdir -p $(BUILD_DIR)\n\t@ $(RM) $(OTHER_BUILD_DIR)/.linked\n\t@ $(RM) -r $(BUILD_DIR_LINK)\n\t@ ln -s $(BUILD_DIR) $(BUILD_DIR_LINK)\n\t@ touch $@\n\n$(ALL_BUILD_DIRS): | $(BUILD_DIR_LINK)\n\t@ mkdir -p $@\n\n$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)\n\t@ echo LD -o $@\n\t$(Q)$(CXX) -shared -o $@ $(OBJS) $(VERSIONFLAGS) $(LINKFLAGS) $(LDFLAGS)\n\t@ cd $(LIB_BUILD_DIR); rm -f $(DYNAMIC_NAME_SHORT);   ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT)\n\n$(STATIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)\n\t@ echo AR -o $@\n\t$(Q)ar rcs $@ $(OBJS)\n\n$(BUILD_DIR)/%.o: %.cpp | $(ALL_BUILD_DIRS)\n\t@ echo CXX $<\n\t$(Q)$(CXX) $< $(CXXFLAGS) -c -o $@ 2> $@.$(WARNS_EXT) \\\n\t\t|| (cat $@.$(WARNS_EXT); exit 1)\n\t@ cat $@.$(WARNS_EXT)\n\n$(BUILD_DIR)/cuda/%.o: %.cu | $(ALL_BUILD_DIRS)\n\t@ echo NVCC $<\n\t$(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -M $< -o ${@:.o=.d} \\\n\t\t-odir $(@D)\n\t$(Q)$(CUDA_DIR)/bin/nvcc $(NVCCFLAGS) $(CUDA_ARCH) -c $< -o $@ 2> $@.$(WARNS_EXT) \\\n\t\t|| (cat $@.$(WARNS_EXT); exit 1)\n\t@ cat $@.$(WARNS_EXT)\n\n$(EXAMPLE_BINS): %.bin : %.o | $(DYNAMIC_NAME)\n\t@ echo CXX/LD -o $@\n\t$(Q)$(CXX) $< -o $@ $(LINKFLAGS) -l$(LIBRARY_NAME) $(LDFLAGS) \\\n\t\t-Wl,-rpath,$(ORIGIN)/../../lib\n\nclean:\n\t@- $(RM) -rf $(ALL_BUILD_DIRS)\n\t@- $(RM) -rf $(OTHER_BUILD_DIR)\n\t@- $(RM) -rf $(BUILD_DIR_LINK)\n\t@- $(RM) -rf $(DISTRIBUTE_DIR)\n\n$(DIST_ALIASES): $(DISTRIBUTE_DIR)\n\n$(DISTRIBUTE_DIR): all\n\t@ mkdir -p $(DISTRIBUTE_SUBDIRS)\n\t# add include\n\tcp -r include $(DISTRIBUTE_DIR)/\n\t# add example binaries\n\tcp $(EXAMPLE_BINS) $(DISTRIBUTE_DIR)/bin\n\t# add libraries\n\tcp $(STATIC_NAME) $(DISTRIBUTE_DIR)/lib\n\tinstall -m 644 $(DYNAMIC_NAME) $(DISTRIBUTE_DIR)/lib\n\tcd $(DISTRIBUTE_DIR)/lib; rm -f $(DYNAMIC_NAME_SHORT);   ln -s $(DYNAMIC_VERSIONED_NAME_SHORT) $(DYNAMIC_NAME_SHORT)\n\n-include $(DEPS)\n"
  },
  {
    "path": "scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.1.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing Caffe and OpenPose -------------------------\"\necho \"NOTE: This script assumes that just flashed JetPack 3.1 : Ubuntu 16, CUDA 8, cuDNN 6 and OpenCV are already installed on your machine. Otherwise, it might fail.\"\n\n\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\ngit submodule update --init --recursive --remote\nexecuteShInItsFolder \"install_caffe_JetsonTX2_JetPack3.1.sh\" \"./3rdparty/caffe\" \"../..\"\nexitIfError\n\n\n\nexecuteShInItsFolder \"install_openpose_JetsonTX2_JetPack3.1.sh\" \"./scripts/ubuntu/\" \"./\"\nexitIfError\n\n\n\necho \"------------------------- Caffe and OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu/install_caffe_and_openpose_JetsonTX2_JetPack3.3.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing Caffe and OpenPose -------------------------\"\necho \"NOTE: This script assumes that just flashed JetPack 3.3 : Ubuntu 16, CUDA 9, cuDNN 7 and OpenCV are already installed on your machine. Otherwise, it might fail.\"\n\n\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\nrm -rf ./3rdparty/caffe && mkdir ./3rdparty/caffe\ngit submodule update --init --recursive --remote\nexecuteShInItsFolder \"install_caffe_JetsonTX2_JetPack3.3.sh\" \"./3rdparty/caffe\" \"../..\"\nexitIfError\n\n\n\nexecuteShInItsFolder \"./scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh\" \"./\" \"./\"\nexitIfError\n\n\n\necho \"------------------------- Caffe and OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu/install_cuda.sh",
    "content": "#!/bin/bash\n\necho \"NOTE: This script assumes Ubuntu 20 or 18 (Nvidia Graphics card >= 10XX), as well as 16 or 14 (card up to 10XX).\"\necho \"Otherwise, install it by yourself or it might fail.\"\n\nif [[ $CI == true ]]; then\n    WGET_VERBOSE=\"--no-verbose\"\nfi\n\n# Install CUDA 8.0\nUBUNTU_VERSION=\"$(lsb_release -r)\"\nsudo apt-get update && sudo apt-get install wget -y --no-install-recommends\nif [[ $UBUNTU_VERSION == *\"14.\"* ]]; then\n    CUDA_LINK=https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1404-8-0-local-ga2_8.0.61-1_amd64-deb\n    echo \"wget -c \\\"$CUDA_LINK\\\" ${WGET_VERBOSE}\"\n    wget -c \"$CUDA_LINK\" ${WGET_VERBOSE}\n    sudo dpkg --install cuda-repo-ubuntu1404-8-0-local-ga2_8.0.61-1_amd64-deb\n    sudo apt-get update\n    sudo apt-get install cuda-8-0\nelif [[ $UBUNTU_VERSION == *\"16.\"* ]]; then\n    CUDA_LINK=https://developer.nvidia.com/compute/cuda/8.0/Prod2/local_installers/cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb\n    echo \"wget -c \\\"$CUDA_LINK\\\" ${WGET_VERBOSE}\"\n    wget -c \"$CUDA_LINK\" ${WGET_VERBOSE}\n    sudo dpkg --install cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64-deb\n    sudo apt-get update\n    sudo apt-get install cuda-8-0\n# Install CUDA 10.0\nelif [[ $UBUNTU_VERSION == *\"18.\"* ]]; then\n    CUDA_PIN_LINK=https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin\n    CUDA_LINK=http://developer.download.nvidia.com/compute/cuda/10.2/Prod/local_installers/cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb\n    echo \"wget -c \\\"$CUDA_PIN_LINK\\\" ${WGET_VERBOSE}\"\n    wget -c \"$CUDA_PIN_LINK\" ${WGET_VERBOSE}\n    sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600\n    echo \"wget \\\"$CUDA_LINK\\\" ${WGET_VERBOSE}\"\n    wget \"$CUDA_LINK\" ${WGET_VERBOSE}\n    sudo dpkg -i cuda-repo-ubuntu1804-10-2-local-10.2.89-440.33.01_1.0-1_amd64.deb\n    sudo apt-key add /var/cuda-repo-10-2-local-10.2.89-440.33.01/7fa2af80.pub\n    sudo apt-get update\n    sudo apt-get -y install cuda\n# Install CUDA 11.0\nelif [[ $UBUNTU_VERSION == *\"20.\"* ]]; then\n    CUDA_PIN_LINK=https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin\n    CUDA_LINK=https://developer.download.nvidia.com/compute/cuda/11.0.3/local_installers/cuda-repo-ubuntu2004-11-0-local_11.0.3-450.51.06-1_amd64.deb\n    echo \"wget -c \\\"$CUDA_PIN_LINK\\\" ${WGET_VERBOSE}\"\n    wget -c \"$CUDA_PIN_LINK\" ${WGET_VERBOSE}\n    sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600\n    echo \"wget \\\"$CUDA_LINK\\\" ${WGET_VERBOSE}\"\n    wget \"$CUDA_LINK\" ${WGET_VERBOSE}\n    sudo dpkg -i cuda-repo-ubuntu2004-11-0-local_11.0.3-450.51.06-1_amd64.deb\n    sudo apt-key add /var/cuda-repo-ubuntu2004-11-0-local/7fa2af80.pub\n    sudo apt-get update\n    sudo apt-get -y install cuda\nfi\n# sudo apt-get install cuda\n"
  },
  {
    "path": "scripts/ubuntu/install_cudnn_up_to_Ubuntu16.sh",
    "content": "#!/bin/bash\n\necho \"This script assumes Ubuntu 16 or 14 and Nvidia Graphics card up to 10XX. Otherwise, it will fail.\"\n\nif [[ $CI == true ]]; then\n    WGET_VERBOSE=\"--no-verbose\"\nfi\n\n# Install cuDNN 5.1\nUBUNTU_VERSION=\"$(lsb_release -r)\"\nif [[ $UBUNTU_VERSION == *\"14.\"* ]] || [[ $UBUNTU_VERSION == *\"15.\"* ]] || [[ $UBUNTU_VERSION == *\"16.\"* ]]; then\n    CUDNN_URL=\"http://developer.download.nvidia.com/compute/redist/cudnn/v5.1/cudnn-8.0-linux-x64-v5.1.tgz\"\n    echo \"wget -c ${CUDNN_URL} ${WGET_VERBOSE}\"\n    wget -c ${CUDNN_URL} ${WGET_VERBOSE}\n    sudo tar -xzf cudnn-8.0-linux-x64-v5.1.tgz -C /usr/local\n    rm cudnn-8.0-linux-x64-v5.1.tgz && sudo ldconfig\nelse\n    echo \"cuDNN NOT INSTALLED! Ubuntu 16 or 14 not found. Install cuDNN manually from 'https://developer.nvidia.com/cudnn'.\"\nfi\n"
  },
  {
    "path": "scripts/ubuntu/install_deps.sh",
    "content": "#!/bin/bash\n\n### INSTALL PREREQUISITES\n\nUBUNTU_VERSION=\"$(lsb_release -r)\"\n\n# Basic\nsudo apt-get --assume-yes update\nsudo apt-get --assume-yes install build-essential\n# General dependencies\nsudo apt-get --assume-yes install libatlas-base-dev libprotobuf-dev libleveldb-dev libsnappy-dev libhdf5-serial-dev protobuf-compiler\nsudo apt-get --assume-yes install --no-install-recommends libboost-all-dev\n# Remaining dependencies\nsudo apt-get --assume-yes install libgflags-dev libgoogle-glog-dev\n# LMDB is needed for Caffe training, but very likely not for inference-only\nsudo apt-get --assume-yes install liblmdb-dev\n\n# Python2 libs (Official Ubuntu support dropped after Ubuntu 20)\nif [[ $UBUNTU_VERSION == *\"14.\"* ]] || [[ $UBUNTU_VERSION == *\"15.\"* ]] || [[ $UBUNTU_VERSION == *\"16.\"* ]] || [[ $UBUNTU_VERSION == *\"17.\"* ]] || [[ $UBUNTU_VERSION == *\"18.\"* ]]; then\n    echo \"Installing Python2 libs...\"\n    sudo apt-get --assume-yes install python-setuptools python-dev build-essential\n    hash pip2 2> /dev/null || sudo apt-get --assume-yes install python-pip\n    sudo -H python2 -m pip install pip --upgrade\n    if [[ $CI == true ]]; then\n        sudo -H python2 -m pip install --upgrade \"numpy<1.17\" protobuf\n        python2 -m pip install --user \"opencv-python<4.3\"\n    else\n        sudo -H python2 -m pip install --upgrade \"numpy<1.17\" protobuf \"opencv-python<4.3\"\n    fi\nfi\n# Python3 libs\necho \"Installing Python3 libs...\"\nsudo apt-get --assume-yes install python3-setuptools python3-dev build-essential\nhash pip3 2> /dev/null || sudo apt-get --assume-yes install python3-pip\nsudo -H python3 -m pip install pip --upgrade\nif [[ $CI == true ]]; then\n    sudo -H python3 -m pip install --upgrade numpy protobuf\n    python3 -m pip install --user opencv-python\nelse\n    sudo -H python3 -m pip install --upgrade numpy protobuf opencv-python\nfi\n\n# OpenCL Generic (Official OpenPose support dropped after Ubuntu 20)\nif [[ $UBUNTU_VERSION == *\"14.\"* ]] || [[ $UBUNTU_VERSION == *\"15.\"* ]] || [[ $UBUNTU_VERSION == *\"16.\"* ]] || [[ $UBUNTU_VERSION == *\"17.\"* ]] || [[ $UBUNTU_VERSION == *\"18.\"* ]]; then\n\tsudo apt-get --assume-yes install opencl-headers ocl-icd-opencl-dev\n\tsudo apt-get --assume-yes install libviennacl-dev\nfi\n# OpenCV 2.4 -> Added as option\n# # sudo apt-get --assume-yes install libopencv-dev\n"
  },
  {
    "path": "scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing OpenPose -------------------------\"\necho \"NOTE: This script assumes that just flashed JetPack 3.1 : Ubuntu 16, CUDA 8, cuDNN 6 and OpenCV are already installed on your machine. Otherwise, it might fail.\"\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\necho \"------------------------- Checking Ubuntu Version -------------------------\"\n# If you respected the installation assumptions, nothing to do. \necho \"------------------------- Ubuntu Version Checked -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- Compiling OpenPose -------------------------\"\n# Copy Makefile & Makefile.config\ncp scripts/ubuntu/Makefile.example Makefile\ncp scripts/ubuntu/Makefile.config.Ubuntu16_cuda8_JetsonTX2 Makefile.config\n# Compile OpenPose\nmake all -j`nproc`\nexitIfError\necho \"------------------------- OpenPose Compiled -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- Downloading OpenPose Models -------------------------\"\nexecuteShInItsFolder \"getModels.sh\" \"./models\" \"..\"\nexitIfError\necho \"Models downloaded\"\necho \"------------------------- OpenPose Models Downloaded -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing OpenPose -------------------------\"\necho \"NOTE: This script assumes that just flashed JetPack 3.3 : Ubuntu 16, CUDA 9, cuDNN 7 and OpenCV are already installed on your machine. Otherwise, it might fail.\"\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\necho \"------------------------- Compiling OpenPose -------------------------\"\n# Copy Makefile & Makefile.config\ncp scripts/ubuntu/Makefile.example Makefile\ncp scripts/ubuntu/Makefile.config.Ubuntu16_cuda9_JetsonTX2_JetPack33 Makefile.config\n# Compile OpenPose\nmake all -j`nproc`\nexitIfError\necho \"------------------------- OpenPose Compiled -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- Downloading OpenPose Models -------------------------\"\nexecuteShInItsFolder \"getModels.sh\" \"./models\" \"..\"\nexitIfError\necho \"Models downloaded\"\necho \"------------------------- OpenPose Models Downloaded -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda7.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\n# Architectures:\n# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52\n# Deprecated\n# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \\\n# \t\t-gencode arch=compute_20,code=sm_21 \\\n# \t\t-gencode arch=compute_30,code=sm_30 \\\n# \t\t-gencode arch=compute_35,code=sm_35 \\\n# \t\t-gencode arch=compute_50,code=sm_50 \\\n# \t\t-gencode arch=compute_52,code=sm_52\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include\nLIBRARY_DIRS := /usr/local/lib /usr/lib\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_61,code=compute_61\n# Deprecated\n# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \\\n# \t\t-gencode arch=compute_20,code=sm_21 \\\n# \t\t-gencode arch=compute_30,code=sm_30 \\\n# \t\t-gencode arch=compute_35,code=sm_35 \\\n# \t\t-gencode arch=compute_50,code=sm_50 \\\n# \t\t-gencode arch=compute_52,code=sm_52 \\\n# \t\t-gencode arch=compute_60,code=sm_60 \\\n# \t\t-gencode arch=compute_61,code=sm_61 \\\n# \t\t-gencode arch=compute_61,code=compute_61\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include\nLIBRARY_DIRS := /usr/local/lib /usr/lib\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda10.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\n# Architectures:\n# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_62,code=sm_62 \\\n\t\t-gencode arch=compute_70,code=sm_70 \\\n\t\t-gencode arch=compute_72,code=sm_72 \\\n\t\t-gencode arch=compute_75,code=sm_75 \\\n\t\t-gencode arch=compute_75,code=compute_75\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda7.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52\n# Deprecated\n# CUDA_ARCH := -gencode arch=compute_20,code=sm_20 \\\n# \t\t-gencode arch=compute_20,code=sm_21 \\\n# \t\t-gencode arch=compute_30,code=sm_30 \\\n# \t\t-gencode arch=compute_35,code=sm_35 \\\n# \t\t-gencode arch=compute_50,code=sm_50 \\\n# \t\t-gencode arch=compute_52,code=sm_52\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\n# Architectures:\n# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_62,code=sm_62 \\\n\t\t-gencode arch=compute_62,code=compute_62\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda9.example",
    "content": "## Refer to http://caffe.berkeleyvision.org/installation.html\n# Contributions simplifying and improving our build system are welcome!\n\n# CPU-only switch (comment to build without GPU support).\nUSE_CUDA := 1\n\n# uncomment to disable IO dependencies and corresponding data layers\n# USE_OPENCV := 0\n# USE_LEVELDB := 0\n# USE_LMDB := 0\n\n# uncomment to allow MDB_NOLOCK when reading LMDB files (only if necessary)\n#\tYou should not set this flag if you will be reading LMDBs with any\n#\tpossibility of simultaneous read and write\n# ALLOW_LMDB_NOLOCK := 1\n\n# Uncomment if you're using OpenCV 3\n# OPENCV_VERSION := 3\n\n# To customize your choice of compiler, uncomment and set the following.\n# N.B. the default for Linux is g++ and the default for OSX is clang++\n# CUSTOM_CXX := g++\n\n# CUDA directory contains bin/ and lib/ directories that we need.\nCUDA_DIR := /usr/local/cuda\n# On Ubuntu 14.04, if cuda tools are installed via\n# \"sudo apt-get install nvidia-cuda-toolkit\" then use this instead:\n# CUDA_DIR := /usr\n\n# CUDA architecture setting: going with all of them.\n# For CUDA < 6.0, comment the *_50 through *_61 lines for compatibility.\n# For CUDA < 8.0, comment the *_60 and *_61 lines for compatibility.\n# Architectures:\n# http://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/\nCUDA_ARCH := -gencode arch=compute_30,code=sm_30 \\\n\t\t-gencode arch=compute_35,code=sm_35 \\\n\t\t-gencode arch=compute_50,code=sm_50 \\\n\t\t-gencode arch=compute_52,code=sm_52 \\\n\t\t-gencode arch=compute_60,code=sm_60 \\\n\t\t-gencode arch=compute_61,code=sm_61 \\\n\t\t-gencode arch=compute_62,code=sm_62 \\\n\t\t-gencode arch=compute_70,code=sm_70 \\\n\t\t-gencode arch=compute_72,code=sm_72 \\\n\t\t-gencode arch=compute_72,code=compute_72\n\n# Uncomment to enable op::Profiler\n# PROFILER_ENABLED := 1\n\n# DEEP_NET choice:\n# caffe for Caffe (default and only option so far)\nDEEP_NET := caffe\n\n# Caffe directory\nCAFFE_DIR := 3rdparty/caffe/distribute\n\n# Faster GUI display\n# WITH_OPENCV_WITH_OPENGL := 1\n# OpenPose 3-D Reconstruction\n# WITH_3D_RENDERER := 1\n# WITH_CERES := 1\n# WITH_FLIR_CAMERA := 1\n# Eigen directory (Ceres)\n# WITH_EIGEN := 1\nEIGEN_DIR := /usr/include/eigen3/\n# Spinnaker directory\nSPINNAKER_DIR := /usr/include/spinnaker\n\n# Whatever else you find you need goes here.\nINCLUDE_DIRS := /usr/local/include /usr/include/hdf5/serial\nLIBRARY_DIRS := /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial\n\n# If Homebrew is installed at a non standard location (for example your home directory) and you use it for general dependencies\n# INCLUDE_DIRS += $(shell brew --prefix)/include\n# LIBRARY_DIRS += $(shell brew --prefix)/lib\n\n# Uncomment to use `pkg-config` to specify OpenCV library paths.\n# (Usually not necessary -- OpenCV libraries are normally installed in one of the above $LIBRARY_DIRS.)\n# USE_PKG_CONFIG := 1\n\nBUILD_DIR := build\nDISTRIBUTE_DIR := distribute\n\n# Uncomment for debugging. Does not work on OSX due to https://github.com/BVLC/caffe/issues/171\n# DEBUG := 1\n\n# The ID of the GPU that 'make runtest' will use to run unit tests.\nTEST_GPUID := 0\n\n# enable pretty build (comment to see full commands)\nQ ?= @\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/copy_makefile_files.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Preprocessing -------------------------\"\necho \"NOTE: This script assumes that CUDA and cuDNN are already installed on your machine. Otherwise, it might fail.\"\n\n\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\necho \"------------------------- Checking Ubuntu Version -------------------------\"\nubuntu_version=\"$(lsb_release -r)\"\necho \"Ubuntu $ubuntu_version\"\nif [[ $ubuntu_version == *\"14.\"* ]]; then\n    ubuntu_le_14=true\nelif [[ $ubuntu_version == *\"16.\"* || $ubuntu_version == *\"15.\"* || $ubuntu_version == *\"17.\"* || $ubuntu_version == *\"18.\"* ]]; then\n    ubuntu_le_14=false\nelse\n    echo \"Ubuntu release older than version 14. This installation script might fail.\"\n    ubuntu_le_14=true\nfi\nexitIfError\necho \"------------------------- Ubuntu Version Checked -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- Copying Required Files -------------------------\"\n# Copy Makefile & Makefile.config\ncp scripts/ubuntu/Makefile.example Makefile\nif [[ $ubuntu_le_14 == true ]]; then\n    cp scripts/ubuntu_deprecated/Makefile.config.Ubuntu14_cuda8.example Makefile.config\nelse\n    cp scripts/ubuntu_deprecated/Makefile.config.Ubuntu16_cuda8.example Makefile.config\nfi\nexitIfError\necho \"------------------------- Required Files Copied -------------------------\"\n\n\n\necho \"------------------------- Preprocessing Ready -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/install_caffe_and_openpose_if_cuda8.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing Caffe and OpenPose -------------------------\"\necho \"NOTE: This script assumes that CUDA and cuDNN are already installed on your machine. Otherwise, it might fail.\"\n\n\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\ngit submodule update --init --recursive --remote\nexecuteShInItsFolder \"install_caffe_if_cuda8.sh\" \"./3rdparty/caffe\" \"../..\"\nexitIfError\n\n\n\nexecuteShInItsFolder \"./scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh\" \"./\" \"./\"\nexitIfError\n\n\n\necho \"------------------------- Caffe and OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "scripts/ubuntu_deprecated/install_openpose_if_cuda8.sh",
    "content": "#!/bin/bash\n\n\n\necho \"------------------------- Installing OpenPose -------------------------\"\n\n\n\nfunction exitIfError {\n    if [[ $? -ne 0 ]] ; then\n        echo \"\"\n        echo \"------------------------- -------------------------\"\n        echo \"Errors detected. Exiting script. The software might have not been successfully installed.\"\n        echo \"------------------------- -------------------------\"\n        exit 1\n    fi\n}\n\n\n\nfunction executeShInItsFolder {\n    # $1 = sh file name\n    # $2 = folder where the sh file is\n    # $3 = folder to go back\n    cd $2\n    exitIfError\n    sudo chmod +x $1\n    exitIfError\n    bash ./$1\n    exitIfError\n    cd $3\n    exitIfError\n}\n\n\n\nexecuteShInItsFolder \"scripts/ubuntu_deprecated/copy_makefile_files.sh\" \"./\" \"./\"\n\n\n\necho \"------------------------- Compiling OpenPose -------------------------\"\nmake all -j`nproc`\nexitIfError\necho \"------------------------- OpenPose Compiled -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- Downloading OpenPose Models -------------------------\"\nexecuteShInItsFolder \"getModels.sh\" \"./models\" \"..\"\nexitIfError\necho \"Models downloaded\"\necho \"------------------------- OpenPose Models Downloaded -------------------------\"\necho \"\"\n\n\n\necho \"------------------------- OpenPose Installed -------------------------\"\necho \"\"\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "add_subdirectory(openpose)"
  },
  {
    "path": "src/openpose/3d/CMakeLists.txt",
    "content": "set(SOURCES_OP_3D\n    cameraParameterReader.cpp\n    defineTemplates.cpp\n    jointAngleEstimation.cpp\n    poseTriangulation.cpp\n    poseTriangulationPrivate.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_3D_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_3D})\nset(SOURCES_OP_3D_WITH_CP ${SOURCES_OP_3D_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_3D_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_3d ${SOURCES_OP_3D})\n  else ()\n    add_library(openpose_3d ${SOURCES_OP_3D})\n  endif ()\n\n  add_library(caffe SHARED IMPORTED)\n  set_property(TARGET caffe PROPERTY IMPORTED_LOCATION ${Caffe_LIBS})\n  target_link_libraries(openpose_3d caffe openpose_core ${MKL_LIBS})\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_3d openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_3d\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/3d/cameraParameterReader.cpp",
    "content": "#include <openpose/3d/cameraParameterReader.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp> // OPEN_CV_IS_4_OR_HIGHER\n#ifdef OPEN_CV_IS_4_OR_HIGHER\n    #include <opencv2/calib3d.hpp> // cv::initUndistortRectifyMap in OpenCV 4\n#endif\n#include <opencv2/imgproc/imgproc.hpp> // cv::initUndistortRectifyMap (OpenCV <= 3), cv::undistort\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n\nnamespace op\n{\n    struct CameraParameterReader::ImplCameraParameterReader\n    {\n        std::vector<std::string> mSerialNumbers;\n        std::vector<Matrix> mCameraMatrices;\n        std::vector<Matrix> mCameraDistortions;\n        std::vector<Matrix> mCameraIntrinsics;\n        std::vector<Matrix> mCameraExtrinsics;\n        std::vector<Matrix> mCameraExtrinsicsInitial;\n\n        // Undistortion (optional)\n        bool mUndistortImage;\n        std::vector<cv::Mat> mRemoveDistortionMaps1;\n        std::vector<cv::Mat> mRemoveDistortionMaps2;\n\n        ImplCameraParameterReader(const bool undistortImage) :\n            mUndistortImage{undistortImage}\n        {\n        }\n    };\n\n    CameraParameterReader::CameraParameterReader() :\n        spImpl{std::make_shared<ImplCameraParameterReader>(false)}\n    {\n    }\n\n    CameraParameterReader::~CameraParameterReader()\n    {\n    }\n\n    CameraParameterReader::CameraParameterReader(const std::string& serialNumber,\n                                                 const Matrix& cameraIntrinsics,\n                                                 const Matrix& cameraDistortion,\n                                                 const Matrix& cameraExtrinsics,\n                                                 const Matrix& cameraExtrinsicsInitial) :\n        spImpl{std::make_shared<ImplCameraParameterReader>(false)}\n    {\n        try\n        {\n            // Sanity checks\n            if (serialNumber.empty())\n                error(\"Camera serialNumber cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            if (cameraIntrinsics.empty())\n                error(\"Camera intrinsics cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            if (cameraDistortion.empty())\n                error(\"Camera distortion cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            // Add new matrices\n            spImpl->mSerialNumbers.emplace_back(serialNumber);\n            spImpl->mCameraIntrinsics.emplace_back(cameraIntrinsics.clone());\n            spImpl->mCameraDistortions.emplace_back(cameraDistortion.clone());\n            // Add extrinsics if not empty\n            if (!cameraExtrinsics.empty())\n                spImpl->mCameraExtrinsics.emplace_back(cameraExtrinsics.clone());\n            else\n                spImpl->mCameraExtrinsics.emplace_back(Matrix::eye(3, 4, cameraIntrinsics.type()));\n            // Add extrinsics (initial) if not empty\n            if (!cameraExtrinsicsInitial.empty())\n                spImpl->mCameraExtrinsicsInitial.emplace_back(cameraExtrinsicsInitial.clone());\n            // Otherwise, add cv::eye\n            else\n                spImpl->mCameraExtrinsicsInitial.emplace_back(Matrix::eye(3, 4, cameraIntrinsics.type()));;\n            const cv::Mat cvCameraMatrices = OP_OP2CVCONSTMAT(spImpl->mCameraIntrinsics.back()) * OP_OP2CVCONSTMAT(spImpl->mCameraExtrinsics.back());\n            const Matrix opCameraMatrices = OP_CV2OPCONSTMAT(cvCameraMatrices);\n            spImpl->mCameraMatrices.emplace_back(opCameraMatrices);\n            // Undistortion Mats\n            spImpl->mRemoveDistortionMaps1.resize(getNumberCameras());\n            spImpl->mRemoveDistortionMaps2.resize(getNumberCameras());\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void CameraParameterReader::readParameters(const std::string& cameraParameterPath,\n                                               const std::vector<std::string>& serialNumbers)\n    {\n        try\n        {\n            // Serial numbers\n            if (serialNumbers.empty())\n            {\n                spImpl->mSerialNumbers = getFilesOnDirectory(cameraParameterPath, \"xml\");\n                for (auto& serialNumber : spImpl->mSerialNumbers)\n                    serialNumber = getFileNameNoExtension(serialNumber);\n            }\n            else\n                spImpl->mSerialNumbers = serialNumbers;\n\n            // Commong saving/loading\n            const auto dataFormat = DataFormat::Xml;\n            const std::vector<std::string> cvMatNames {\n                \"CameraMatrix\", \"Intrinsics\", \"Distortion\", \"CameraMatrixInitial\"\n            };\n\n            // Load parameters\n            spImpl->mCameraMatrices.clear();\n            spImpl->mCameraDistortions.clear();\n            spImpl->mCameraIntrinsics.clear();\n            spImpl->mCameraExtrinsics.clear();\n            spImpl->mCameraExtrinsicsInitial.clear();\n            // opLog(\"Camera matrices:\");\n            for (auto i = 0ull ; i < spImpl->mSerialNumbers.size() ; i++)\n            {\n                const auto parameterPath = cameraParameterPath + spImpl->mSerialNumbers.at(i);\n                const auto opCameraParameters = loadData(cvMatNames, parameterPath, dataFormat);\n                OP_OP2CVVECTORMAT(cameraParameters, opCameraParameters)\n                // Error if empty element\n                if (cameraParameters.empty() || cameraParameters.at(0).empty()\n                    || cameraParameters.at(1).empty() || cameraParameters.at(2).empty()\n                    || cameraParameters.at(3).empty())\n                {\n                    const std::string errorMessage = \" of the camera with serial number `\" + spImpl->mSerialNumbers[i]\n                                                   + \"` (file: \" + parameterPath + \".\" + dataFormatToString(dataFormat)\n                                                   + \"). Is its format valid? You might want to check the example xml\"\n                                                   + \" file.\";\n                    if (cameraParameters.empty())\n                        error(\"Error at reading the camera parameters\" + errorMessage,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    if (cameraParameters.at(0).empty())\n                        error(\"Error at reading the camera matrix parameters\" + errorMessage,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    if (cameraParameters.at(1).empty())\n                        error(\"Error at reading the camera intrinsics parameters\" + errorMessage,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    if (cameraParameters.at(2).empty())\n                        error(\"Error at reading the camera distortion parameters\" + errorMessage,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    // Commented for back-compatibility\n                    // if (cameraParameters.at(3).empty())\n                    //     error(\"Error at reading the camera distortion parameters\" + errorMessage,\n                    //           __LINE__, __FUNCTION__, __FILE__);\n                }\n                spImpl->mCameraExtrinsics.emplace_back(opCameraParameters.at(0));\n                spImpl->mCameraIntrinsics.emplace_back(opCameraParameters.at(1));\n                spImpl->mCameraDistortions.emplace_back(opCameraParameters.at(2));\n                spImpl->mCameraExtrinsicsInitial.emplace_back(opCameraParameters.at(3));\n                const cv::Mat cvCameraMatrices = OP_OP2CVCONSTMAT(spImpl->mCameraIntrinsics.back()) * OP_OP2CVCONSTMAT(spImpl->mCameraExtrinsics.back());\n                const Matrix opCameraMatrices = OP_CV2OPCONSTMAT(cvCameraMatrices);\n                spImpl->mCameraMatrices.emplace_back(opCameraMatrices);\n                // opLog(cameraParameters.at(0));\n            }\n            // Undistortion Mats\n            spImpl->mRemoveDistortionMaps1.resize(getNumberCameras());\n            spImpl->mRemoveDistortionMaps2.resize(getNumberCameras());\n            // // spImpl->mCameraMatrices\n            // opLog(\"\\nFull camera matrices:\");\n            // for (const auto& cvMat : spImpl->mCameraMatrices)\n            //     opLog(cvMat);\n            // // spImpl->mCameraIntrinsics\n            // opLog(\"\\nCamera intrinsic parameters:\");\n            // for (const auto& cvMat : spImpl->mCameraIntrinsics)\n            //     opLog(cvMat);\n            // // spImpl->mCameraDistortions\n            // opLog(\"\\nCamera distortion parameters:\");\n            // for (const auto& cvMat : spImpl->mCameraDistortions)\n            //     opLog(cvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void CameraParameterReader::readParameters(const std::string& cameraParameterPath,\n                                               const std::string& serialNumber)\n    {\n        try\n        {\n            readParameters(cameraParameterPath, std::vector<std::string>{serialNumber});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void CameraParameterReader::writeParameters(const std::string& cameraParameterPath) const\n    {\n        try\n        {\n            // Sanity check\n            if (spImpl->mSerialNumbers.size() != spImpl->mCameraIntrinsics.size()\n                || spImpl->mSerialNumbers.size() != spImpl->mCameraDistortions.size()\n                || (spImpl->mSerialNumbers.size() != spImpl->mCameraIntrinsics.size()\n                    && !spImpl->mCameraExtrinsics.empty()))\n                error(\"Arguments must have same size (spImpl->mSerialNumbers, spImpl->mCameraIntrinsics, spImpl->mCameraDistortions,\"\n                      \" and spImpl->mCameraExtrinsics).\", __LINE__, __FUNCTION__, __FILE__);\n            // Commong saving/loading\n            const auto dataFormat = DataFormat::Xml;\n            const std::vector<std::string> cvMatNames {\n                \"CameraMatrix\", \"Intrinsics\", \"Distortion\", \"CameraMatrixInitial\"\n            };\n            // Saving\n            for (auto i = 0ull ; i < spImpl->mSerialNumbers.size() ; i++)\n            {\n                std::vector<Matrix> cameraParameters;\n                cameraParameters.emplace_back(spImpl->mCameraExtrinsics[i]);\n                cameraParameters.emplace_back(spImpl->mCameraIntrinsics[i]);\n                cameraParameters.emplace_back(spImpl->mCameraDistortions[i]);\n                cameraParameters.emplace_back(spImpl->mCameraExtrinsicsInitial[i]);\n                saveData(cameraParameters, cvMatNames, cameraParameterPath + spImpl->mSerialNumbers[i], dataFormat);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    unsigned long long CameraParameterReader::getNumberCameras() const\n    {\n        try\n        {\n            return spImpl->mSerialNumbers.size();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0ull;\n        }\n    }\n\n    const std::vector<std::string>& CameraParameterReader::getCameraSerialNumbers() const\n    {\n        try\n        {\n            return spImpl->mSerialNumbers;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mSerialNumbers;\n        }\n    }\n\n    const std::vector<Matrix>& CameraParameterReader::getCameraMatrices() const\n    {\n        try\n        {\n            return spImpl->mCameraMatrices;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mCameraMatrices;\n        }\n    }\n\n    const std::vector<Matrix>& CameraParameterReader::getCameraDistortions() const\n    {\n        try\n        {\n            return spImpl->mCameraDistortions;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mCameraDistortions;\n        }\n    }\n\n    const std::vector<Matrix>& CameraParameterReader::getCameraIntrinsics() const\n    {\n        try\n        {\n            return spImpl->mCameraIntrinsics;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mCameraIntrinsics;\n        }\n    }\n\n    const std::vector<Matrix>& CameraParameterReader::getCameraExtrinsics() const\n    {\n        try\n        {\n            return spImpl->mCameraExtrinsics;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mCameraExtrinsics;\n        }\n    }\n\n    const std::vector<Matrix>& CameraParameterReader::getCameraExtrinsicsInitial() const\n    {\n        try\n        {\n            return spImpl->mCameraExtrinsicsInitial;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mCameraExtrinsicsInitial;\n        }\n    }\n\n    bool CameraParameterReader::getUndistortImage() const\n    {\n        try\n        {\n            return spImpl->mUndistortImage;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void CameraParameterReader::setUndistortImage(const bool undistortImage)\n    {\n        try\n        {\n            spImpl->mUndistortImage = undistortImage;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void CameraParameterReader::undistort(Matrix& frame, const unsigned int cameraIndex)\n    {\n        try\n        {\n            if (spImpl->mUndistortImage)\n            {\n                // Sanity check\n                if (spImpl->mRemoveDistortionMaps1.size() <= cameraIndex\n                    || spImpl->mRemoveDistortionMaps2.size() <= cameraIndex)\n                {\n                    error(\"Variable cameraIndex is out of bounds, it should be smaller than spImpl->mRemoveDistortionMapsX.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Only first time\n                if (spImpl->mRemoveDistortionMaps1[cameraIndex].empty()\n                    || spImpl->mRemoveDistortionMaps2[cameraIndex].empty())\n                {\n                    const auto cvCameraIntrinsics = OP_OP2CVCONSTMAT(spImpl->mCameraIntrinsics.at(0));\n                    const auto cvCameraDistorsions = OP_OP2CVCONSTMAT(spImpl->mCameraDistortions.at(0));\n                    //const auto imageSize = OP_OP2CVMAT(frame).size();\n                    cv::Size imageSize;\n                    OP_CONST_MAT_RETURN_FUNCTION(imageSize, frame, size()); // = frame.size();\n                    // // Option a - 80 ms / 3 images\n                    // // http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#undistort\n                    // cv::undistort(cvMatDistorted, mCvMats[i], cvCameraIntrinsics, cvCameraDistorsions);\n                    // // In OpenCV 2.4, cv::undistort is exactly equal than cv::initUndistortRectifyMap\n                    // (with CV_16SC2) + cv::remap (with LINEAR). I.e., opLog(cv::norm(cvMatMethod1-cvMatMethod2)) = 0.\n                    // Option b - 15 ms / 3 images (LINEAR) or 25 ms (CUBIC)\n                    // Distortion removal - not required and more expensive (applied to the whole image instead of\n                    // only to our interest points)\n                    cv::initUndistortRectifyMap(\n                        cvCameraIntrinsics, cvCameraDistorsions, cv::Mat(),\n                        // cvCameraIntrinsics instead of cv::getOptimalNewCameraMatrix to\n                        // avoid black borders\n                        cvCameraIntrinsics,\n                        // #include <opencv2/calib3d/calib3d.hpp> for next line\n                        // cv::getOptimalNewCameraMatrix(cvCameraIntrinsics,\n                        //                               cvCameraDistorsions,\n                        //                               imageSize, 1,\n                        //                               imageSize, 0),\n                        imageSize,\n                        CV_16SC2, // Faster, less memory\n                        // CV_32FC1, // More accurate\n                        spImpl->mRemoveDistortionMaps1[cameraIndex],\n                        spImpl->mRemoveDistortionMaps2[cameraIndex]);\n                }\n                cv::Mat undistortedCvMat;\n                const cv::Mat cvFrame = OP_OP2CVCONSTMAT(frame);\n                cv::remap(cvFrame, undistortedCvMat,\n                          spImpl->mRemoveDistortionMaps1[cameraIndex], spImpl->mRemoveDistortionMaps2[cameraIndex],\n                          // cv::INTER_NEAREST);\n                          cv::INTER_LINEAR);\n                          // cv::INTER_CUBIC);\n                          // cv::INTER_LANCZOS4); // Smoother, but we do not need this quality & its >>expensive\n                Matrix opUndistortedCvMat = OP_CV2OPMAT(undistortedCvMat);\n                std::swap(opUndistortedCvMat, frame);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/3d/defineTemplates.cpp",
    "content": "#include <openpose/3d/headers.hpp>\n\nnamespace op\n{\n#ifdef USE_3D_ADAM_MODEL\n    DEFINE_TEMPLATE_DATUM(WJointAngleEstimation);\n#endif\n    DEFINE_TEMPLATE_DATUM(WPoseTriangulation);\n}\n"
  },
  {
    "path": "src/openpose/3d/jointAngleEstimation.cpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#include <openpose/3d/jointAngleEstimation.hpp>\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/FitToBody.h>\n    #include <adam/totalmodel.h>\n#endif\n\nnamespace op\n{\n    #ifdef USE_3D_ADAM_MODEL\n        std::shared_ptr<TotalModel> sTotalModel;\n        const int NUMBER_BODY_KEYPOINTS = 20;\n        const int NUMBER_HAND_KEYPOINTS = 21;\n        const int NUMBER_FACE_KEYPOINTS = 70;\n        const int NUMBER_FOOT_KEYPOINTS = 3;\n        // targetJoints: Only for Body, LHand, RHand. No Face, no Foot\n        const int NUMBER_KEYPOINTS = 3*(NUMBER_BODY_KEYPOINTS + 2*NUMBER_HAND_KEYPOINTS);\n\n        const std::shared_ptr<const TotalModel> loadTotalModel(const std::string& mObjectPath,\n                                                               const std::string& mGTotalModelPath,\n                                                               const std::string& mPcaPath,\n                                                               const std::string& mCorrespondencePath)\n        {\n            try\n            {\n                if (sTotalModel == nullptr)\n                {\n                    // Initialize model\n                    sTotalModel = std::make_shared<TotalModel>();\n                    // Load spTotalModel (model + data)\n                    // ~100 milliseconds\n                    LoadTotalModelFromObj(*sTotalModel, mObjectPath);\n                    // ~25 seconds\n                    LoadTotalDataFromJson(*sTotalModel, mGTotalModelPath, mPcaPath, mCorrespondencePath);\n                }\n                // Return result\n                return sTotalModel;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            }\n        }\n\n        void updateKeypoint(Eigen::MatrixXd& targetJoint, const float* const poseKeypoint3D, const int part)\n        {\n            try\n            {\n                // Keypoint found\n                if (poseKeypoint3D[2] > 0.5)\n                {\n                    targetJoint(0, part) = poseKeypoint3D[0];\n                    targetJoint(1, part) = poseKeypoint3D[1];\n                    targetJoint(2, part) = poseKeypoint3D[2];\n                }\n                // Keypoint not found - Keep last known keypoint or 0\n                // Implicitly done with the initial setZero()\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    struct JointAngleEstimation::ImplJointAngleEstimation\n    {\n        #ifdef USE_3D_ADAM_MODEL\n            // Adam model files\n            const std::string mGTotalModelPath;\n            const std::string mPcaPath;\n            const std::string mObjectPath;\n            const std::string mCorrespondencePath;\n\n            // Processing\n            const bool mReturnJacobian;\n            bool mInitialized;\n\n            Eigen::MatrixXd mBodyJoints;\n            Eigen::MatrixXd mFaceJoints;\n            Eigen::MatrixXd mLHandJoints;\n            Eigen::MatrixXd mRHandJoints;\n            Eigen::MatrixXd mLFootJoints;\n            Eigen::MatrixXd mRFootJoints;\n\n            // Other parameters\n            smpl::SMPLParams mFrameParams;\n\n            // Shared parameters\n            Eigen::Matrix<double, Eigen::Dynamic, 1> mVtVec;\n            Eigen::Matrix<double, Eigen::Dynamic, 1> mJ0Vec;\n            const std::shared_ptr<const TotalModel> spTotalModel;\n\n            ImplJointAngleEstimation(const bool returnJacobian) :\n                mGTotalModelPath{\"./model/adam_v1_plus2.json\"},\n                mPcaPath{\"./model/adam_blendshapes_348_delta_norm.json\"},\n                mObjectPath{\"./model/mesh_nofeet.obj\"},\n                mCorrespondencePath{\"./model/correspondences_nofeet.txt\"},\n                mReturnJacobian{returnJacobian},\n                mInitialized{false},\n                mBodyJoints(5, NUMBER_BODY_KEYPOINTS),\n                mFaceJoints(5, NUMBER_FACE_KEYPOINTS),// (3, landmarks_face.size());\n                mLHandJoints(5, NUMBER_HAND_KEYPOINTS),// (3, HandModel::NUM_JOINTS);\n                mRHandJoints(5, NUMBER_HAND_KEYPOINTS),// (3, HandModel::NUM_JOINTS);\n                mLFootJoints(5, 3),// (3, 3);        // Heel, Toe\n                mRFootJoints(5, 3),// (3, 3);        // Heel, Toe\n                spTotalModel{loadTotalModel(mObjectPath, mGTotalModelPath, mPcaPath, mCorrespondencePath)}\n            {\n            }\n        #endif\n    };\n\n    int mapOPToAdam(const int oPPart)\n    {\n        if (oPPart >= 0 && oPPart < 19)\n        {\n            // Nose\n            if (oPPart == 0)\n                return 1;\n            // Neck\n            else if (oPPart == 1)\n                return 0;\n            // Right arm\n            else if (oPPart == 2)\n                return 9;\n            else if (oPPart == 3)\n                return 10;\n            else if (oPPart == 4)\n                return 11;\n            // Left arm\n            else if (oPPart == 5)\n                return 3;\n            else if (oPPart == 6)\n                return 4;\n            else if (oPPart == 7)\n                return 5;\n            // Mid-hip\n            else if (oPPart == 8)\n                return 2;\n            // Right leg\n            else if (oPPart == 9)\n                return 12;\n            else if (oPPart == 10)\n                return 13;\n            else if (oPPart == 11)\n                return 14;\n            // Left leg\n            else if (oPPart == 12)\n                return 6;\n            else if (oPPart == 13)\n                return 7;\n            else if (oPPart == 14)\n                return 8;\n            // Face\n            else if (oPPart == 15)\n                return 17;\n            else if (oPPart == 16)\n                return 15;\n            else if (oPPart == 17)\n                return 18;\n            else if (oPPart == 18)\n                return 16;\n            else\n                error(\"Wrong body part (\" + std::to_string(oPPart) + \").\",\n                          __LINE__, __FUNCTION__, __FILE__);\n        }\n        error(\"Wrong body part (\" + std::to_string(oPPart) + \").\",\n                  __LINE__, __FUNCTION__, __FILE__);\n        return -1;\n    }\n\n    const std::shared_ptr<const TotalModel> JointAngleEstimation::getTotalModel()\n    {\n        try\n        {\n            return sTotalModel;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    JointAngleEstimation::JointAngleEstimation(const bool returnJacobian)\n        #ifdef USE_3D_ADAM_MODEL\n            : spImpl{std::make_shared<ImplJointAngleEstimation>(returnJacobian)}\n        #endif\n    {\n        try\n        {\n            // error(\"JointAngleEstimation (`ik_threads` flag) buggy and not working yet, but we are working on it!\"\n            //       \" No coming soon...\", __LINE__, __FUNCTION__, __FILE__);\n            #ifndef USE_3D_ADAM_MODEL\n                error(\"OpenPose must be compiled with the `USE_3D_ADAM_MODEL` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JointAngleEstimation::~JointAngleEstimation()\n    {\n    }\n\n    void JointAngleEstimation::initializationOnThread()\n    {\n    }\n\n    void JointAngleEstimation::adamFastFit(Eigen::Matrix<double, 62, 3, Eigen::RowMajor>& adamPose,\n                                           Eigen::Vector3d& adamTranslation,\n                                           Eigen::Matrix<double, Eigen::Dynamic, 1>& vtVec,\n                                           Eigen::Matrix<double, Eigen::Dynamic, 1>& j0Vec,\n                                           Eigen::VectorXd& adamFacecoeffsExp,\n                                           const Array<float>& poseKeypoints3D,\n                                           const Array<float>& faceKeypoints3D,\n                                           const std::array<Array<float>, 2>& handKeypoints3D)\n    {\n        try\n        {\n            // Sanity check\n            if (!poseKeypoints3D.empty() && poseKeypoints3D.getSize(1) != 19 && poseKeypoints3D.getSize(1) != 25)\n                error(\"Only working for BODY_19 or BODY_25 (#parts = \"\n                      + std::to_string(poseKeypoints3D.getSize(2)) + \").\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Shorter naming\n            auto& frameParams = spImpl->mFrameParams;\n            // If keypoints detected\n            if (!poseKeypoints3D.empty())\n            {\n                // Reset to 0 all keypoints - Otherwise undefined behavior when fitting\n                // It must be done on every iteration, otherwise errors, e.g., if face\n                // was detected in frame i-1 but not in i\n                spImpl->mBodyJoints.setZero();\n                spImpl->mFaceJoints.setZero();\n                spImpl->mLHandJoints.setZero();\n                spImpl->mRHandJoints.setZero();\n                spImpl->mLFootJoints.setZero();\n                spImpl->mRFootJoints.setZero();\n                // Update body\n                for (auto part = 0 ; part < 19; part++)\n                    updateKeypoint(spImpl->mBodyJoints,\n                                   &poseKeypoints3D[{0, part, 0}],\n                                   mapOPToAdam(part));\n                // Update left/right hand\n                if (poseKeypoints3D.getSize(1) == 65)\n                {\n                    // Wrists\n                    updateKeypoint(spImpl->mLHandJoints,\n                                   &poseKeypoints3D[{0, 7, 0}],\n                                   0);\n                    updateKeypoint(spImpl->mRHandJoints,\n                                   &poseKeypoints3D[{0, 4, 0}],\n                                   0);\n                    // Left\n                    for (auto part = 0 ; part < 20; part++)\n                        updateKeypoint(spImpl->mLHandJoints,\n                                       &poseKeypoints3D[{0, part+25, 0}],\n                                       part+1);\n                    // Right\n                    for (auto part = 0 ; part < 20; part++)\n                        updateKeypoint(spImpl->mRHandJoints,\n                                       &poseKeypoints3D[{0, part+25+20, 0}],\n                                       part+1);\n                }\n                else\n                {\n                    for (auto hand = 0u ; hand < handKeypoints3D.size(); hand++)\n                        if (!handKeypoints3D.at(hand).empty())\n                            for (auto part = 0 ; part < handKeypoints3D[hand].getSize(1); part++)\n                                updateKeypoint((hand == 0 ? spImpl->mLHandJoints : spImpl->mRHandJoints),\n                                               &handKeypoints3D[hand][{0, part, 0}],\n                                               part);\n                }\n                // Update Foot data\n                if (poseKeypoints3D.getSize(1) == 25)\n                {\n                    // Update LFoot\n                    for (auto adamPart = 0 ; adamPart < NUMBER_FOOT_KEYPOINTS; adamPart++)\n                        updateKeypoint(spImpl->mLFootJoints,\n                                       &poseKeypoints3D[{0, adamPart + 19, 0}],\n                                       adamPart);\n                    // Update RFoot\n                    for (auto adamPart = 0 ; adamPart < NUMBER_FOOT_KEYPOINTS; adamPart++)\n                        updateKeypoint(spImpl->mRFootJoints,\n                                       &poseKeypoints3D[{0, adamPart + 19 + NUMBER_FOOT_KEYPOINTS, 0}],\n                                       adamPart);\n                }\n                // Update Face data\n                if (!faceKeypoints3D.empty())\n                    for (auto part = 0 ; part < NUMBER_FACE_KEYPOINTS; part++)\n                        updateKeypoint(spImpl->mFaceJoints,\n                                       &faceKeypoints3D[{0, part, 0}],\n                                       part);\n                // Meters --> cm\n                spImpl->mBodyJoints *= 1e2;\n                if (!handKeypoints3D.at(0).empty() || poseKeypoints3D.getSize(1) == 65)\n                    spImpl->mLHandJoints *= 1e2;\n                if (!handKeypoints3D.at(1).empty() || poseKeypoints3D.getSize(1) == 65)\n                    spImpl->mRHandJoints *= 1e2;\n                if (!faceKeypoints3D.empty())\n                    spImpl->mFaceJoints *= 1e2;\n                spImpl->mLFootJoints *= 1e2;\n                spImpl->mRFootJoints *= 1e2;\n\n                // Initialization (e.g., first frame)\n                const bool fastVersion = false;\n                const bool freezeMissing = true;\n                const bool ceresDisplayReport = false;\n                // Fill Datum\n                if (!spImpl->mInitialized || !fastVersion)\n                {\n                    if (!spImpl->mInitialized)\n                    {\n                        frameParams.m_adam_t(0) = spImpl->mBodyJoints(0, 2);\n                        frameParams.m_adam_t(1) = spImpl->mBodyJoints(1, 2);\n                        frameParams.m_adam_t(2) = spImpl->mBodyJoints(2, 2);\n                        frameParams.m_adam_pose(0, 0) = 3.14159265358979323846264338327950288419716939937510582097494459;\n                        spImpl->mInitialized = true;\n                    }\n                    // We make T-pose start with:\n                    // 1. Root translation similar to current 3-d location of the mid-hip\n                    // 2. x-orientation = 180, i.e., person standing up & looking to the camera\n                    // 3. Because otherwise, if we call Adam_FastFit_Initialize twice (e.g., if a new person appears),\n                    // it would use the latest ones from the last Adam_FastFit\n                    // Fit initialization\n                    // Adam_FastFit_Initialize only changes frameParams\n                    const auto multistageFitting = true;\n                    const auto handEnabled = !handKeypoints3D[0].empty() || !handKeypoints3D[1].empty()\n                        || poseKeypoints3D.getSize(1) == 65;\n                    const auto fitFaceExponents = !faceKeypoints3D.empty();\n                    const auto fastSolver = true;\n                    Adam_FastFit_Initialize(*spImpl->spTotalModel, frameParams, spImpl->mBodyJoints, spImpl->mRFootJoints,\n                                            spImpl->mLFootJoints, spImpl->mRHandJoints, spImpl->mLHandJoints,\n                                            spImpl->mFaceJoints, freezeMissing, ceresDisplayReport,\n                                            multistageFitting, handEnabled, fitFaceExponents, fastSolver);\n                    // The following 2 operations takes ~12 msec\n                    if (spImpl->mReturnJacobian)\n                    {\n                        vtVec = spImpl->spTotalModel->m_meanshape\n                              + spImpl->spTotalModel->m_shapespace_u * frameParams.m_adam_coeffs;\n                        j0Vec = spImpl->spTotalModel->J_mu_ + spImpl->spTotalModel->dJdc_ * frameParams.m_adam_coeffs;\n                        if (fastVersion)\n                        {\n                            spImpl->mVtVec = vtVec;\n                            spImpl->mJ0Vec = j0Vec;\n                        }\n                    }\n                }\n                // Other frames if fastVersion\n                else // if (spImpl->mInitialized && fastVersion)\n                {\n                    // Adam_FastFit only changes frameParams\n                    Adam_FastFit(*spImpl->spTotalModel, frameParams, spImpl->mBodyJoints, spImpl->mRFootJoints,\n                                 spImpl->mLFootJoints, spImpl->mRHandJoints, spImpl->mLHandJoints,\n                                 spImpl->mFaceJoints, ceresDisplayReport);\n                    if (spImpl->mReturnJacobian)\n                    {\n                        vtVec = spImpl->mVtVec;\n                        j0Vec = spImpl->mJ0Vec;\n                    }\n                }\n                adamPose = frameParams.m_adam_pose;\n                adamTranslation = frameParams.m_adam_t;\n                adamFacecoeffsExp = frameParams.m_adam_facecoeffs_exp;\n                // // Not used anymore\n                // frameParams.mouth_open, frameParams.reye_open, frameParams.leye_open, frameParams.dist_root_foot\n            }\n            else\n                spImpl->mInitialized = false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "src/openpose/3d/poseTriangulation.cpp",
    "content": "#include <openpose/3d/poseTriangulation.hpp>\n#include <numeric> // std::accumulate\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/3d/poseTriangulationPrivate.hpp>\n\nnamespace op\n{\n    inline bool isValidKeypoint(const float* const keypointPtr, const Point<int>& imageSize)\n    {\n        try\n        {\n            const auto threshold = 0.35f;\n            return (keypointPtr[2] > threshold\n                    // If keypoint in border --> most probably it is actually out of the image,\n                    // so removed to reduce that noise\n                    && keypointPtr[0] > 8\n                    && keypointPtr[0] < imageSize.x - 8\n                    && keypointPtr[1] > 8\n                    && keypointPtr[1] < imageSize.y - 8);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    bool reconstructArrayThread(\n        Array<float>* keypoints3DPtr, const std::vector<Array<float>>& keypointsVector,\n        const std::vector<cv::Mat>& cameraMatrices, const std::vector<Point<int>>& imageSizes, const int minViews3d)\n    {\n        try\n        {\n            auto& keypoints3D = *keypoints3DPtr;\n\n            // Sanity check\n            if (cameraMatrices.size() < 2)\n                error(\"Only 1 camera detected. The 3-D reconstruction module can only be used with > 1 cameras\"\n                      \" simultaneously. E.g., using FLIR stereo cameras (`--flir_camera`).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Get number body parts and whether at least 2 cameras have keypoints\n            auto detectionMissed = 0;\n            auto numberBodyParts = 0;\n            auto channel0Length = 0;\n            for (const auto& keypoints : keypointsVector)\n            {\n                if (!keypoints.empty())\n                {\n                    ++detectionMissed;\n                    if (detectionMissed > 1)\n                    {\n                        numberBodyParts = keypoints.getSize(1);\n                        channel0Length = keypoints.getSize(2);\n                        break;\n                    }\n                }\n            }\n            // If at least 2 set of keypoints not empty\n            if (numberBodyParts > 0)\n            {\n                // Create x-y vector from high score results\n                std::vector<int> indexesUsed;\n                std::vector<std::vector<cv::Point2d>> xyPoints;\n                std::vector<std::vector<cv::Mat>> cameraMatricesPerPoint;\n                for (auto part = 0; part < numberBodyParts; ++part)\n                {\n                    // Create vector of points\n                    // auto missedPoint = false;\n                    std::vector<cv::Point2d> xyPointsElement;\n                    std::vector<cv::Mat> cameraMatricesElement;\n                    const auto baseIndex = part * channel0Length;\n                    // for (auto& keypoints : keypointsVector)\n                    for (auto i = 0u ; i < keypointsVector.size() ; i++)\n                    {\n                        const auto& keypoints = keypointsVector[i];\n                        if (!keypoints.empty() && isValidKeypoint(&keypoints[baseIndex], imageSizes[i]))\n                        {\n                            xyPointsElement.emplace_back(\n                                cv::Point2d{keypoints[baseIndex], keypoints[baseIndex+1]});\n                            cameraMatricesElement.emplace_back(cameraMatrices[i]);\n                        }\n                    }\n                    const auto minViews3dValue = (minViews3d > 0 ? minViews3d\n                        : fastMax(2u, fastMin(4u, (unsigned int)cameraMatrices.size()-1u)));\n                    // If visible for at least minViews3dValue views\n                    if (minViews3dValue <= xyPointsElement.size())\n                    // Old code\n                    // // If visible from all views (minViews3d < 0) or if visible for at least minViews3d views\n                    // if ((minViews3d < 0 && cameraMatricesElement.size() == cameraMatrices.size())\n                    //     || (minViews3d > 1 && minViews3d <= (int)xyPointsElement.size()))\n                    {\n                        indexesUsed.emplace_back(part);\n                        xyPoints.emplace_back(xyPointsElement);\n                        cameraMatricesPerPoint.emplace_back(cameraMatricesElement);\n                    }\n                }\n                // 3D reconstruction\n                const auto imageRatio = std::sqrt(imageSizes[0].x * imageSizes[0].y / 1310720.);\n                const auto reprojectionMaxAcceptable = 25 * imageRatio;\n                std::vector<double> reprojectionErrors(xyPoints.size());\n                if (!xyPoints.empty())\n                {\n                    keypoints3D.reset({ 1, numberBodyParts, 4 }, 0.f);\n                    // Do 3D reconstruction\n                    std::vector<cv::Point3f> xyzPoints(xyPoints.size());\n                    for (auto i = 0u; i < xyPoints.size(); i++)\n                    {\n                        cv::Mat reconstructedPoint;\n                        reprojectionErrors[i] = triangulateWithOptimization(\n                            reconstructedPoint, cameraMatricesPerPoint[i], xyPoints[i], reprojectionMaxAcceptable);\n                        xyzPoints[i] = cv::Point3d{\n                            reconstructedPoint.at<double>(0), reconstructedPoint.at<double>(1),\n                            reconstructedPoint.at<double>(2)};\n                    }\n                    const auto reprojectionErrorTotal = std::accumulate(\n                        reprojectionErrors.begin(), reprojectionErrors.end(), 0.0) / xyPoints.size();\n\n                    // 3D points to pose\n                    // OpenCV alternative:\n                    // http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#triangulatepoints\n                    // cv::Mat reconstructedPoints{4, firstcv::Points.size(), CV_64F};\n                    // cv::triangulatePoints(cv::Mat::eye(3,4, CV_64F), M_3_1, firstcv::Points, secondcv::Points,\n                    //                           reconstructedcv::Points);\n                    // 20 pixels for 1280x1024 image\n                    bool atLeastOnePointProjected = false;\n                    const auto lastChannelLength = keypoints3D.getSize(2);\n                    for (auto index = 0u; index < indexesUsed.size(); ++index)\n                    {\n                        if (std::isfinite(xyzPoints[index].x) && std::isfinite(xyzPoints[index].y)\n                            && std::isfinite(xyzPoints[index].z)\n                            // Remove outliers\n                            && (reprojectionErrors[index] < 5 * reprojectionErrorTotal\n                                && reprojectionErrors[index] < reprojectionMaxAcceptable))\n                        {\n                            const auto baseIndex = indexesUsed[index] * lastChannelLength;\n                            keypoints3D[baseIndex] = xyzPoints[index].x;\n                            keypoints3D[baseIndex + 1] = xyzPoints[index].y;\n                            keypoints3D[baseIndex + 2] = xyzPoints[index].z;\n                            keypoints3D[baseIndex + 3] = 1.f;\n                            atLeastOnePointProjected = true;\n                        }\n                    }\n                    // Warning\n                    if (reprojectionErrorTotal > 60)\n                        opLog(\"Unusual high re-projection error (averaged over #keypoints) of value \"\n                            + std::to_string(reprojectionErrorTotal) + \" pixels, while the average for a good OpenPose\"\n                            \" detection from 4 cameras is about 2-3 pixels. It might be simply a wrong OpenPose\"\n                            \" detection. However, if this message appears very frequently, your calibration parameters\"\n                            \" might be wrong. Note: If you have introduced your own camera intrinsics, are they an\"\n                            \" upper triangular matrix (as specified in the OpenPose doc/advanced/calibration_module.md\"\n                            \" and doc/advanced/3d_reconstruction_module.md)?\", Priority::High);\n                    // opLog(\"Reprojection error: \" + std::to_string(reprojectionErrorTotal)); // To debug reprojection error\n                    return atLeastOnePointProjected;\n                }\n                return false;\n            }\n            // Keypoints in < 2 images\n            else\n                return true; // True because it is not a 3D problem but rather it is e.g., a scene without people on it\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    PoseTriangulation::PoseTriangulation(const int minViews3d) :\n        mMinViews3d{minViews3d}\n    {\n        try\n        {\n            // Sanity check\n            if (0 <= mMinViews3d && mMinViews3d < 2)\n                error(\"Minimum number of views must be at least 2 (e.g., `--3d_min_views 2`) or negative.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    PoseTriangulation::~PoseTriangulation()\n    {\n    }\n\n    void PoseTriangulation::initializationOnThread()\n    {\n    }\n\n    Array<float> PoseTriangulation::reconstructArray(\n        const std::vector<Array<float>>& keypointsVector, const std::vector<Matrix>& cameraMatrices,\n        const std::vector<Point<int>>& imageSizes) const\n    {\n        try\n        {\n            return reconstructArray(\n                std::vector<std::vector<Array<float>>>{keypointsVector}, cameraMatrices, imageSizes).at(0);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    const std::string sFlirErrorMessage{\n        \" If you are simultaneously using FLIR cameras (`--flir_camera`) and the 3-D reconstruction module\"\n        \" (`--3d), you should also enable `--frame_undistort` so their camera parameters are read.\"};\n    std::vector<Array<float>> PoseTriangulation::reconstructArray(\n        const std::vector<std::vector<Array<float>>>& keypointsVectors,\n        const std::vector<Matrix>& cameraMatrices,\n        const std::vector<Point<int>>& imageSizes) const\n    {\n        try\n        {\n            OP_OP2CVVECTORMAT(cvCameraMatrices, cameraMatrices);\n            // Sanity checks\n            if (cvCameraMatrices.size() < 2)\n                error(\"3-D reconstruction (`--3d`) requires at least 2 camera views, only found \"\n                    + std::to_string(cvCameraMatrices.size()) + \" camera parameter matrices.\" + sFlirErrorMessage,\n                    __LINE__, __FUNCTION__, __FILE__);\n            for (const auto& cameraMatrix : cvCameraMatrices)\n                if (cameraMatrix.empty())\n                    error(\"Camera matrix was found empty during 3-D reconstruction (`--3d`).\" + sFlirErrorMessage,\n                        __LINE__, __FUNCTION__, __FILE__);\n            if (cvCameraMatrices.size() != imageSizes.size())\n                error(\"The camera parameters and number of images must be the same (\"\n                    + std::to_string(cvCameraMatrices.size()) + \" vs. \" + std::to_string(imageSizes.size()) + \").\",\n                    __LINE__, __FUNCTION__, __FILE__);\n            // Run 3-D reconstruction\n            bool keypointsReconstructed = false;\n            std::vector<Array<float>> keypoints3Ds(keypointsVectors.size());\n            // std::vector<std::thread> threads(keypointsVectors.size()-1);\n            for (auto i = 0u; i < keypointsVectors.size()-1; i++)\n            {\n                // // Multi-thread option - ~15% slower\n                // // Ceres seems to be super slow if run concurrently in different threads\n                // threads.at(i) = std::thread{&reconstructArrayThread,\n                //                             &keypoints3Ds[i], keypointsVectors[i], cvCameraMatrices,\n                //                             imageSizes, mMinViews3d};\n                // Single-thread option\n                keypointsReconstructed |= reconstructArrayThread(\n                    &keypoints3Ds[i], keypointsVectors[i], cvCameraMatrices, imageSizes, mMinViews3d);\n            }\n            keypointsReconstructed |= reconstructArrayThread(\n                &keypoints3Ds.back(), keypointsVectors.back(), cvCameraMatrices, imageSizes, mMinViews3d);\n            // // Close threads\n            // for (auto& thread : threads)\n            //     if (thread.joinable())\n            //         thread.join();\n            // Warning\n            if (!keypointsReconstructed)\n                opLog(\"No keypoints were reconstructed on this frame. It might be simply a challenging frame.\"\n                    \" However, if this message appears frequently, OpenPose is facing some unknown issue,\"\n                    \" maybe the calibration parameters are not accurate. Feel free to open a GitHub issue\"\n                    \" (remember to fill all the required information detailed in the GitHub issue template\"\n                    \" when it is created).\", Priority::High);\n            // Return results\n            return keypoints3Ds;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/3d/poseTriangulationPrivate.cpp",
    "content": "#include <openpose_private/3d/poseTriangulationPrivate.hpp>\n#ifdef USE_CERES\n    #include <ceres/ceres.h>\n    #include <ceres/rotation.h>\n#endif\n#include <opencv2/calib3d/calib3d.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    double calcReprojectionError(const cv::Mat& reconstructedPoint, const std::vector<cv::Mat>& cameraMatrices,\n                                 const std::vector<cv::Point2d>& pointsOnEachCamera)\n    {\n        try\n        {\n            auto averageError = 0.;\n            for (auto i = 0u ; i < cameraMatrices.size() ; i++)\n            {\n                cv::Mat imageX = cameraMatrices[i] * reconstructedPoint;\n                imageX /= imageX.at<double>(2,0);\n                const auto error = std::sqrt(std::pow(imageX.at<double>(0,0) -  pointsOnEachCamera[i].x,2)\n                                             + std::pow(imageX.at<double>(1,0) - pointsOnEachCamera[i].y,2));\n                // opLog(\"Error: \" + std::to_string(error));\n                averageError += error;\n            }\n            return averageError / cameraMatrices.size();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1.;\n        }\n    }\n\n    #ifdef USE_CERES\n        // Nonlinear Optimization for 3D Triangulation\n        struct ReprojectionErrorForTriangulation\n        {\n            ReprojectionErrorForTriangulation(const double x, const double y, const double* const param) :\n                observed_x{x},\n                observed_y{y}\n            {\n                memcpy(camParam, param, sizeof(double)*12);\n            }\n\n            template <typename T>\n            bool operator()(const T* const pt,\n                            T* residuals) const ;\n\n            inline virtual bool Evaluate(double const* const* pt,\n                                         double* residuals,\n                                         double** jacobians) const;\n\n            const double observed_x;\n            const double observed_y;\n            double camParam[12];\n        };\n\n        template <typename T>\n        bool ReprojectionErrorForTriangulation::operator()(const T* const pt,\n                                                           T* residuals) const\n        {\n            try\n            {\n                const T predicted[3] = {\n                    T(camParam[0])*pt[0] + T(camParam[1])*pt[1] + T(camParam[2])*pt[2] + T(camParam[3]),\n                    T(camParam[4])*pt[0] + T(camParam[5])*pt[1] + T(camParam[6])*pt[2] + T(camParam[7]),\n                    T(camParam[8])*pt[0] + T(camParam[9])*pt[1] + T(camParam[10])*pt[2] + T(camParam[11])};\n\n                residuals[0] = T(observed_x) - predicted[0] / predicted[2];\n                residuals[1] = T(observed_y) - predicted[1] / predicted[2];\n\n                // residuals[0] = T(pow(predicted[0] - observed_x,2) + pow(predicted[1] - observed_y,2));\n                // residuals[0] = -pow(predicted[0] - T(observed_x),2);\n                // residuals[1] = -pow(predicted[1] - T(observed_y),2);\n\n                return true;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return false;\n            }\n        }\n\n        bool ReprojectionErrorForTriangulation::Evaluate(double const* const* pt,\n            double* residuals,\n            double** jacobians) const\n        {\n            try\n            {\n                UNUSED(jacobians);\n\n                const double predicted[3] = {\n                    camParam[0]*pt[0][0] + camParam[1]*pt[0][1] + camParam[2]*pt[0][2] + camParam[3],\n                    camParam[4]*pt[0][0] + camParam[5]*pt[0][1] + camParam[6]*pt[0][2] + camParam[7],\n                    camParam[8]*pt[0][0] + camParam[9]*pt[0][1] + camParam[10]*pt[0][2] + camParam[11]};\n\n                // residuals[0] = predicted[0] / predicted[2] - observed_x;\n                // residuals[1] = predicted[1] / predicted[2] - observed_y;\n\n                residuals[0] = std::sqrt(std::pow(predicted[0] / predicted[2] - observed_x,2)\n                                         + std::pow(predicted[1] / predicted[2] - observed_y,2));\n\n                // opLog(\"Residuals:\");\n                // residuals[0]= pow(predicted[0] - (observed_x),2);\n                // residuals[1]= pow(predicted[1] - (observed_y),2);\n\n                return true;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return false;\n            }\n        }\n    #endif\n\n    double triangulate(cv::Mat& reconstructedPoint, const std::vector<cv::Mat>& cameraMatrices,\n                       const std::vector<cv::Point2d>& pointsOnEachCamera)\n    {\n        try\n        {\n            // Sanity checks\n            if (cameraMatrices.size() != pointsOnEachCamera.size())\n                error(\"numberCameras.size() != pointsOnEachCamera.size() (\" + std::to_string(cameraMatrices.size())\n                      + \" vs. \" + std::to_string(pointsOnEachCamera.size()) + \").\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (cameraMatrices.empty())\n                error(\"numberCameras.empty()\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Create and fill A for homogeneous equation system Ax = 0\n            const auto numberCameras = (int)cameraMatrices.size();\n            cv::Mat A = cv::Mat::zeros(numberCameras*2, 4, CV_64F);\n            for (auto i = 0 ; i < numberCameras ; i++)\n            {\n                A.rowRange(i*2, i*2+1) = pointsOnEachCamera[i].x*cameraMatrices[i].rowRange(2,3)\n                                       - cameraMatrices[i].rowRange(0,1);\n                A.rowRange(i*2+1, i*2+2) = pointsOnEachCamera[i].y*cameraMatrices[i].rowRange(2,3)\n                                         - cameraMatrices[i].rowRange(1,2);\n            }\n            // Solve x for Ax = 0 --> SVD on A\n            cv::SVD svd{A};\n            svd.solveZ(A,reconstructedPoint);\n            reconstructedPoint /= reconstructedPoint.at<double>(3);\n\n            return calcReprojectionError(reconstructedPoint, cameraMatrices, pointsOnEachCamera);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1.;\n        }\n    }\n\n    double triangulateWithOptimization(\n        cv::Mat& reconstructedPoint, const std::vector<cv::Mat>& cameraMatrices,\n        const std::vector<cv::Point2d>& pointsOnEachCamera, const double reprojectionMaxAcceptable)\n    {\n        try\n        {\n            // Warning\n            if (cameraMatrices.size() >= 8)\n            {\n                error(\"We did not have that many camera views to test the 3D triangulation code, so it might not\"\n                      \" give the desired results here. But we would love to help! Please, share your video/images\"\n                      \" so we can test our code with them and guarantee the desired results even for >= 8\"\n                      \" cameras! Feel free to email them to gines@alumni.cmu.edu.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            }\n\n            // Information for 3 cameras:\n            //     - Speed: triangulate ~0.01 ms vs. optimization ~0.2 ms\n            //     - Accuracy: initial reprojection error ~14-21, reduced ~5% with non-linear optimization\n\n            // Basic triangulation\n            auto projectionError = triangulate(reconstructedPoint, cameraMatrices, pointsOnEachCamera);\n\n            // Basic RANSAC (for >= 4 cameras if the reprojection error is higher than usual)\n            // 1. Run with all cameras (already done)\n            // 2. Run with all but 1 camera for each camera.\n            // 3. Use the one with minimum average reprojection error.\n            // Note: Meant to be used for up to 7-8 views. With more than that, it might not improve much.\n            // Set initial values\n            auto cameraMatricesFinal = cameraMatrices;\n            auto pointsOnEachCameraFinal = pointsOnEachCamera;\n            if (cameraMatrices.size() >= 4\n                && projectionError > 0.5 * reprojectionMaxAcceptable\n                /*&& projectionError < 1.5 * reprojectionMaxAcceptable*/)\n            {\n                // Find best projection\n                auto bestReprojection = projectionError;\n                auto bestReprojectionIndex = -1; // -1 means with all camera views\n                cv::Mat bestReconstructedPoint;\n                for (auto i = 0u; i < cameraMatrices.size(); ++i)\n                {\n                    // Set initial values\n                    auto cameraMatricesSubset = cameraMatrices;\n                    auto pointsOnEachCameraSubset = pointsOnEachCamera;\n                    // Remove camera i\n                    cameraMatricesSubset.erase(cameraMatricesSubset.begin() + i);\n                    pointsOnEachCameraSubset.erase(pointsOnEachCameraSubset.begin() + i);\n                    // Get new triangulation results\n                    cv::Mat reconstructedPointSubset;\n                    const auto projectionErrorSubset = triangulate(\n                        reconstructedPointSubset, cameraMatricesSubset, pointsOnEachCameraSubset);\n                    // If projection doesn't change much, this point is inlier (or all points are bad)\n                    // Thus, save new best results only if considerably better\n                    if (bestReprojection > projectionErrorSubset && projectionErrorSubset < 0.9*projectionError)\n                    {\n                        bestReprojection = projectionErrorSubset;\n                        bestReprojectionIndex = i;\n                        bestReconstructedPoint = reconstructedPointSubset;\n                    }\n                }\n                // Remove noisy camera\n                if (bestReprojectionIndex != -1) // && bestReprojection < 0.5 * reprojectionMaxAcceptable)\n                {\n                    // Remove camera i\n                    cameraMatricesFinal.erase(cameraMatricesFinal.begin() + bestReprojectionIndex);\n                    pointsOnEachCameraFinal.erase(pointsOnEachCameraFinal.begin() + bestReprojectionIndex);\n                    // Update reconstructedPoint & projectionError\n                    reconstructedPoint = bestReconstructedPoint;\n                    projectionError = bestReprojection;\n                }\n            }\n\n            #ifdef USE_CERES\n                // Empirically detected that reprojection error (for 4 cameras) only minimizes the error if initial\n                // project error > ~2.5, and that it improves more the higher that error actually is\n                // Therefore, we disable it for already accurate samples in order to get both:\n                //     - Speed\n                //     - Accuracy for already accurate samples\n                if (projectionError > 3.0\n                    && projectionError < 1.5*reprojectionMaxAcceptable)\n                {\n                    // Slow equivalent: double paramX[3]; paramX[i] = reconstructedPoint.at<double>(i);\n                    double* paramX = (double*)reconstructedPoint.data;\n                    ceres::Problem problem;\n                    for (auto i = 0u; i < cameraMatricesFinal.size(); ++i)\n                    {\n                        // Slow copy equivalent:\n                        //     double camParam[12]; memcpy(camParam, cameraMatricesFinal[i].data, sizeof(double)*12);\n                        const double* const camParam = (double*)cameraMatricesFinal[i].data;\n                        // Each Residual block takes a point and a camera as input and outputs a 2\n                        // dimensional residual. Internally, the cost function stores the observed\n                        // image location and compares the reprojection against the observation.\n                        ceres::CostFunction* cost_function =\n                            new ceres::AutoDiffCostFunction<ReprojectionErrorForTriangulation, 2, 3>(\n                                new ReprojectionErrorForTriangulation(\n                                    pointsOnEachCameraFinal[i].x, pointsOnEachCameraFinal[i].y, camParam));\n                        // Add to problem\n                        problem.AddResidualBlock(cost_function,\n                            //NULL, //squared loss\n                            new ceres::HuberLoss(2.0),\n                            paramX); // paramX[0,1,2]\n                    }\n\n                    ceres::Solver::Options options;\n                    options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;\n                    // options.num_threads = 2; // It does not affect speed\n                    // if (fastVersion)\n                    {\n                        // ~22 ms\n                        // options.function_tolerance = 1e-3; //1e-6\n                        // options.gradient_tolerance = 1e-5; //1e-10\n                        // options.parameter_tolerance = 1e-5; //1e-8\n                        // options.inner_iteration_tolerance = 1e-3; //1e-6\n                        // ~30 ms (~30 FPS)\n                        options.function_tolerance = 1e-4; //1e-6\n                        options.gradient_tolerance = 1e-7; //1e-10\n                        options.parameter_tolerance = 1e-6; //1e-8\n                        options.inner_iteration_tolerance = 1e-4; //1e-6\n                        // Default (none of the above) ~42 ms\n                    }\n                    // options.minimizer_progress_to_stdout = true;\n                    // options.parameter_tolerance = 1e-20;\n                    // options.function_tolerance = 1e-20;\n                    ceres::Solver::Summary summary;\n                    ceres::Solve(options, &problem, &summary);\n                    // if (summary.initial_cost > summary.final_cost)\n                    //     std::cout << summary.FullReport() << \"\\n\";\n\n                    projectionError = calcReprojectionError(reconstructedPoint, cameraMatricesFinal,\n                                                            pointsOnEachCameraFinal);\n                    // const auto reprojectionErrorDecrease = std::sqrt((summary.initial_cost - summary.final_cost)\n                    //                                      / double(cameraMatricesFinal.size()));\n                }\n            #else\n                UNUSED(reprojectionMaxAcceptable);\n            #endif\n            // // This value is always 1\n            // assert(reconstructedPoint.at<double>(3) == 1.);\n\n            // // Check that our implementation gives similar result than OpenCV\n            // // But we apply bundle adjustment + >2 views, so it should be better (and slower) than OpenCV one\n            // if (cameraMatricesFinal.size() == 4)\n            // {\n            //     cv::Mat triangCoords4D;\n            //     cv::triangulatePoints(cameraMatricesFinal.at(0), cameraMatricesFinal.at(3),\n            //                           std::vector<cv::Point2d>{pointsOnEachCameraFinal.at(0)},\n            //                           std::vector<cv::Point2d>{pointsOnEachCameraFinal.at(3)}, triangCoords4D);\n            //     triangCoords4D /= triangCoords4D.at<double>(3);\n            //     std::cout << reconstructedPoint << \"\\n\"\n            //               << triangCoords4D << \"\\n\"\n            //               << cv::norm(reconstructedPoint-triangCoords4D) << \"\\n\" << std::endl;\n            // }\n\n            return projectionError;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1.;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/CMakeLists.txt",
    "content": "include(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nsubdirlist(SUB_DIRS ${CMAKE_CURRENT_SOURCE_DIR})\nforeach (SUB_DIR ${SUB_DIRS})\n  add_subdirectory(${SUB_DIR})\nendforeach (SUB_DIR ${SUB_DIRS})\n\n# make the openpose.so/dll\nfile(GLOB_RECURSE OP_HEADERS_UNFILTERED \"${CMAKE_SOURCE_DIR}/include/openpose/*.h\"\n    \"${CMAKE_SOURCE_DIR}/include/openpose/*.hpp\"\n    \"${CMAKE_SOURCE_DIR}/include/openpose/*.hu\")\n\nset(OP_HEADERS \"\")\n# # Add experimental sub-folders\n# foreach (FILE ${OP_HEADERS_UNFILTERED})\n#   if (NOT FILE MATCHES \"${CMAKE_SOURCE_DIR}/include/openpose/experimental/*\")\n#       list(APPEND OP_HEADERS ${FILE})\n#   endif ()\n# endforeach(FILE ${OP_HEADERS_UNFILTERED})\n\nif (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose ${SOURCES_OPENPOSE} ${OP_HEADERS})\nelse ()\n    add_library(openpose ${SOURCES_OPENPOSE} ${OP_HEADERS})\nendif ()\n\n# Ubuntu\nif (UNIX OR APPLE)\n  target_link_libraries(openpose ${OpenPose_3rdparty_libraries})\n  if (CMAKE_COMPILER_IS_GNUCXX)\n    foreach (SUB_DIR ${SUB_DIRS})\n        set_target_properties(openpose_${SUB_DIR} PROPERTIES COMPILE_FLAGS ${OP_CXX_FLAGS})\n    endforeach (SUB_DIR ${SUB_DIRS})\n    set_target_properties(openpose PROPERTIES COMPILE_FLAGS ${OP_CXX_FLAGS})\n  endif (CMAKE_COMPILER_IS_GNUCXX)\n# Windows\nelseif (WIN32)\n  set_property(TARGET openpose PROPERTY DEBUG_POSTFIX d)\n  target_link_libraries(openpose ${OpenPose_3rdparty_libraries})\n  if (${DL_FRAMEWORK} MATCHES \"CAFFE\")\n    target_compile_definitions(openpose PRIVATE BOOST_ALL_NO_LIB)\n  endif(${DL_FRAMEWORK} MATCHES \"CAFFE\")\n  set_property(TARGET openpose PROPERTY FOLDER \"OpenPose library\")\n\n  foreach (SUB_DIR ${SUB_DIRS})\n    string(TOUPPER ${SUB_DIR} SUB_DIR_UPPERCASE)\n    source_group(\"Source Files\\\\${SUB_DIR}\" FILES ${SOURCES_OP_${SUB_DIR_UPPERCASE}_WITH_CP} \"*\")\n    file(GLOB_RECURSE SUB_MOD_HEADERS \"${CMAKE_SOURCE_DIR}/include/openpose/${SUB_DIR}/*.h\"\n        \"${CMAKE_SOURCE_DIR}/include/openpose/${SUB_DIR}/*.hpp\"\n        \"${CMAKE_SOURCE_DIR}/include/openpose/${SUB_DIR}/*.hu\")\n    source_group(\"Header Files\\\\${SUB_DIR}\" FILES ${SUB_MOD_HEADERS})\n  endforeach (SUB_DIR ${SUB_DIRS})\n  set_target_properties(openpose PROPERTIES COMPILE_FLAGS -DOP_EXPORTS)\n  # Properties->General->Output Directory\n  set_property(TARGET openpose PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n  set_property(TARGET openpose PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))\n\nendif (UNIX OR APPLE)\n\nif (UNIX OR APPLE)\n  add_library(caffe SHARED IMPORTED)\n  set_property(TARGET caffe PROPERTY IMPORTED_LOCATION ${Caffe_LIBS})\n  target_link_libraries(openpose caffe ${Boost_SYSTEM_LIBRARY} ${OpenCL_LIBRARIES})\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose openpose)\n  endif (BUILD_CAFFE)\n\n  set_property(TARGET openpose PROPERTY VERSION ${OpenPose_VERSION})\n\n  install(TARGETS openpose\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/calibration/CMakeLists.txt",
    "content": "set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP;cl)\nset(SOURCES_OP_CALIBRATION\n    cameraParameterEstimation.cpp\n    gridPatternFunctions.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_CALIBRATION_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_CALIBRATION})\nset(SOURCES_OP_CALIBRATION_WITH_CP ${SOURCES_OP_CALIBRATION_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_CALIBRATION_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_calibration ${SOURCES_OP_CALIBRATION})\n  else ()\n    add_library(openpose_calibration ${SOURCES_OP_CALIBRATION})\n  endif ()\n\n  target_link_libraries(openpose_calibration openpose_core)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_calibration openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_calibration\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/calibration/cameraParameterEstimation.cpp",
    "content": "#include <openpose/calibration/cameraParameterEstimation.hpp>\n#include <fstream>\n#include <numeric> // std::accumulate\n#ifdef USE_CERES\n    #include <ceres/ceres.h>\n    #include <ceres/rotation.h>\n#endif\n#ifdef USE_EIGEN\n    #include <Eigen/Dense>\n    #include <opencv2/core/eigen.hpp>\n#endif\n#include <openpose/3d/cameraParameterReader.hpp>\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose_private/3d/poseTriangulationPrivate.hpp>\n#include <openpose_private/calibration/gridPatternFunctions.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    // Private variables\n    const long double PI = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844;\n\n    // Private functions\n    struct Intrinsics\n    {\n        cv::Mat cameraMatrix;\n        cv::Mat distortionCoefficients;\n\n        Intrinsics() :\n            cameraMatrix(cv::Mat::eye(3, 3, CV_64F)),\n            distortionCoefficients(cv::Mat::zeros(14, 1, CV_64F))\n        {\n        }\n\n        Intrinsics(const cv::Mat& cameraMatrix, const cv::Mat& distortionCoefficients) :\n            cameraMatrix{cameraMatrix.clone()}, // cv::Mat::eye(3, 3, CV_64F)\n            distortionCoefficients{distortionCoefficients.clone()} // cv::Mat::zeros(14||12||8||5, 1, CV_64F)\n        {\n        }\n\n        bool empty()\n        {\n            return cameraMatrix.empty() || distortionCoefficients.empty();\n        }\n    };\n\n    #ifdef USE_EIGEN\n        struct Extrinsics\n        {\n            Eigen::Matrix3d Rotation;\n            Eigen::Vector3d translationMm;\n            std::vector<cv::Point2f> points2DVector;\n            std::vector<cv::Point3f> objects3DVector;\n\n            Extrinsics()\n            {\n                Rotation.setIdentity();\n                translationMm.setZero();\n            }\n        };\n    #endif\n\n    std::vector<std::string> getImagePaths(const std::string& imageDirectoryPath)\n    {\n        try\n        {\n            // Get files on directory with the desired extensions\n            const auto imagePaths = getFilesOnDirectory(imageDirectoryPath, Extensions::Images);\n            // Check #files > 0\n            if (imagePaths.empty())\n                error(\"No images were found on `\" + imageDirectoryPath + \"`.\", __LINE__, __FUNCTION__, __FILE__);\n            // Return result\n            return imagePaths;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<std::pair<cv::Mat, std::string>> getImageAndPaths(const std::string& imageDirectoryPath)\n    {\n        try\n        {\n            // Get images on directory\n            const auto imagePaths = getImagePaths(imageDirectoryPath);\n            // Check #files > 0\n            if (imagePaths.empty())\n                error(\"No images were found on `\" + imageDirectoryPath + \"`.\", __LINE__, __FUNCTION__, __FILE__);\n            // Read images\n            std::vector<std::pair<cv::Mat, std::string>> imageAndPaths;\n            for (const auto& imagePath : imagePaths)\n            {\n                imageAndPaths.emplace_back(std::make_pair(cv::imread(imagePath, CV_LOAD_IMAGE_COLOR), imagePath));\n                if (imageAndPaths.back().first.empty())\n                    error(\"Image could not be opened from path `\" + imagePath + \"`.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Return result\n            return imageAndPaths;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::pair<double, std::vector<double>> calcReprojectionErrors(\n        const std::vector<std::vector<cv::Point3f>>& objects3DVectors,\n        const std::vector<std::vector<cv::Point2f>>& points2DVectors, const std::vector<cv::Mat>& rVecs,\n        const std::vector<cv::Mat>& tVecs, const Intrinsics& intrinsics)\n    {\n        try\n        {\n            std::vector<double> perViewErrors(objects3DVectors.size());\n\n            std::vector<cv::Point2f> points2DVectors2;\n            unsigned long long totalPoints = 0;\n            double totalErr = 0.;\n\n            for (auto i = 0ull; i < objects3DVectors.size(); ++i )\n            {\n                cv::projectPoints(\n                    cv::Mat(objects3DVectors.at(i)), rVecs.at(i), tVecs.at(i), intrinsics.cameraMatrix,\n                    intrinsics.distortionCoefficients, points2DVectors2);\n                const auto err = cv::norm(cv::Mat(points2DVectors.at(i)), cv::Mat(points2DVectors2), CV_L2);\n\n                const auto n = objects3DVectors.at(i).size();\n                perViewErrors.at(i) = {std::sqrt(err*err/n)};\n                totalErr        += err*err;\n                totalPoints     += n;\n            }\n            // Return results\n            const auto reprojectionError = std::sqrt(totalErr/totalPoints);\n            return std::make_pair(reprojectionError, perViewErrors);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(0., std::vector<double>{});\n        }\n    }\n\n    Intrinsics calcIntrinsicParameters(\n        const cv::Size& imageSize, const std::vector<std::vector<cv::Point2f>>& points2DVectors,\n        const std::vector<std::vector<cv::Point3f>>& objects3DVectors, const int calibrateCameraFlags)\n    {\n        try\n        {\n            opLog(\"\\nCalibrating camera (intrinsics) with points from \" + std::to_string(points2DVectors.size())\n                + \" images...\", Priority::High);\n\n            //Find intrinsic and extrinsic camera parameters\n            Intrinsics intrinsics;\n            std::vector<cv::Mat> rVecs;\n            std::vector<cv::Mat> tVecs;\n            const auto rms = cv::calibrateCamera(\n                objects3DVectors, points2DVectors, imageSize, intrinsics.cameraMatrix,\n                intrinsics.distortionCoefficients, rVecs, tVecs, calibrateCameraFlags);\n\n            // cv::checkRange checks that every array element is neither NaN nor infinite\n            const auto calibrationIsCorrect = cv::checkRange(intrinsics.cameraMatrix)\n                                            && cv::checkRange(intrinsics.distortionCoefficients);\n            if (!calibrationIsCorrect)\n                error(\"Invalid cameraMatrix and/or distortionCoefficients.\", __LINE__, __FUNCTION__, __FILE__);\n\n            double totalAvgErr;\n            std::vector<double> reprojectionErrors;\n            std::tie(totalAvgErr, reprojectionErrors) = calcReprojectionErrors(\n                objects3DVectors, points2DVectors, rVecs, tVecs, intrinsics);\n\n            opLog(\"\\nIntrinsics:\", Priority::High);\n            opLog(\"Re-projection error - cv::calibrateCamera vs. calcReprojectionErrors:\\t\" + std::to_string(rms)\n                + \" vs. \" + std::to_string(totalAvgErr), Priority::High);\n            opLog(\"Intrinsics_K:\", Priority::High);\n            opLog(intrinsics.cameraMatrix, Priority::High);\n            opLog(\"Intrinsics_distCoeff:\", Priority::High);\n            opLog(intrinsics.distortionCoefficients, Priority::High);\n            opLog(\" \", Priority::High);\n\n            return intrinsics;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Intrinsics{};\n        }\n    }\n\n    double setAngleInRangeZeroTwoPi(const double angle)\n    {\n        try\n        {\n            // Return angle in range [0,2pi)\n            return std::fmod(angle + 2 * PI, 2 * PI);    // floating-point remainder\n            // double result{angle};\n\n            // Return angle in range [0,2pi)\n            // const auto twoPi = 2 * PI;\n            // while (result >= 2*PI)\n            //     result -= twoPi;\n            // while (result < 0)\n            //     result += twoPi;\n\n            // return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    double setAngleInRangePlusMinusPi(const double angle)\n    {\n        try\n        {\n            auto result = setAngleInRangeZeroTwoPi(angle);\n\n            // Return angle in range (-pi,pi]\n            const auto twoPi = 2 * PI;\n            if (result > PI)\n                result -= twoPi;\n\n            // // Return angle in range (-pi,pi]\n            // const auto twoPi = 2 * PI;\n            // while (result > PI)\n            //     result -= twoPi;\n            // while (result <= -PI)\n            //     result += twoPi;\n\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    #ifdef USE_EIGEN\n        cv::Mat getRodriguesVector(const Eigen::Matrix3d& rotationMatrix)\n        {\n            try\n            {\n                // Rotation matrix as cv::Mat\n                cv::Mat rotationMatrixCv;\n                cv::eigen2cv(rotationMatrix, rotationMatrixCv);\n                // Rotation as vector\n                cv::Mat rotationVector;\n                cv::Rodrigues(rotationMatrixCv, rotationVector);\n                return rotationVector;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return cv::Mat();\n            }\n        }\n\n        std::pair<bool, double> estimateAverageAngle(const std::vector<double>& angles)\n        {\n            try\n            {\n                // Idea:\n                    // Average(-40, 40) = 0\n                    // Average(-179, 179) = 180 (not 0!)\n                    // Average(90, 270) = 0 || 180??? We will assume outliers and return false\n\n                // Sanity check\n                if (angles.empty())\n                    error(\"Variables `angles` is empty when calling estimateAverageAngle().\",\n                        __LINE__, __FUNCTION__, __FILE__);\n\n                // angles in range (-pi, pi]\n                auto anglesNormalized = angles;\n                for (auto& angle : anglesNormalized)\n                    angle = setAngleInRangePlusMinusPi(angle);\n\n                // If the difference between them is > 180 degrees, then we turn them in the range [0, 360) (so\n                // now the difference between them is < 180) and return the traditional average. Examples:\n                //     - If one in range [90, 180] and the other in range (-180, -90]\n                //     - If one is 179 degrees and the other one -179 degrees -> average should be 180 no 0! So:\n                //       [179 + (360-179)] / 2 = 180\n                //     - Etc.\n                // Math equivalent:\n                //     We want:         ( maxAngle + (minAngle + 360) )   /2\n                //     Equivalent to:   ( maxAngle + minAngle + 360 )   /2     =   (maxAngle + minAngle) / 2 + 180\n                //                      =   (angleA + angleB) / 2 + 180,   in radians: (angleA + angleB) / 2 + PI\n                auto minElement = *std::min_element(anglesNormalized.begin(), anglesNormalized.end());\n                auto maxElement = *std::max_element(anglesNormalized.begin(), anglesNormalized.end());\n                if (maxElement - minElement >= PI)\n                    for (auto& angle : anglesNormalized)\n                        angle = setAngleInRangeZeroTwoPi(angle);\n\n                // If after normalizing range between min and max is still >180 degrees --> there are outliers\n                minElement = *std::min_element(anglesNormalized.begin(), anglesNormalized.end());\n                maxElement = *std::max_element(anglesNormalized.begin(), anglesNormalized.end());\n                auto resultIsOK = true;\n                if (maxElement - minElement >= PI)\n                {\n                    resultIsOK = {false};\n                    opLog(\"There are outliers in the angles.\", Priority::High);\n                }\n\n                // If the difference between them is <= 180 degrees, then we just return the traditional average.\n                // Examples:\n                //     - If both have the same signs, i.e., both in range [0, 180] or both in range (-180, 0)\n                //     - If one in range [0, 90] and the other in range [-90, 0]\n                //     - Etc.\n                auto average = std::accumulate(anglesNormalized.begin(), anglesNormalized.end(), 0.)\n                             / (double)anglesNormalized.size();\n                average = setAngleInRangePlusMinusPi(average);\n\n                return std::make_pair(resultIsOK, average);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::make_pair(false, 0.);\n            }\n        }\n\n        Eigen::Matrix4d getMAverage(const std::vector<Eigen::Matrix4d>& MsToAverage,\n                                    const Eigen::Matrix4d& noisyApproximatedM = Eigen::Matrix4d::Zero())\n        {\n            try\n            {\n                auto MsToAverageRobust = MsToAverage;\n                // Clean noisy outputs\n                if (noisyApproximatedM.norm() > 0.1)\n                {\n                    MsToAverageRobust.clear();\n                    for (const auto& matrix : MsToAverage)\n                    {\n                        bool addElement = true;\n                        for (auto col = 0 ; col < 3 ; col++)\n                        {\n                            for (auto row = 0 ; row < 3 ; row++)\n                            {\n                                if (std::abs(matrix(col, row) - noisyApproximatedM(col, row)) > 0.25)\n                                {\n                                    addElement = false;\n                                    break;\n                                }\n                            }\n                        }\n                        if (addElement)\n                            MsToAverageRobust.push_back(matrix);\n                    }\n                }\n\n                // Projection matrix\n                Eigen::Matrix4d averagedProjectionMatrix;\n                averagedProjectionMatrix.setIdentity();\n\n                // Average translation\n                for (const auto& matrix : MsToAverageRobust)\n                    averagedProjectionMatrix.block<3,1>(0,3) += matrix.block<3,1>(0,3);\n                averagedProjectionMatrix.block<3,1>(0,3) /= (double)MsToAverageRobust.size();\n\n                // Average rotation\n                std::array<std::vector<double>, 3> rotationVectors;\n                for (const auto& matrix : MsToAverageRobust)\n                {\n                    const auto rVec = getRodriguesVector(matrix.block<3,3>(0,0));\n                    for (auto i = 0u ; i < rotationVectors.size() ; i++)\n                        rotationVectors.at(i).emplace_back(rVec.at<double>(i,0));\n                }\n                cv::Mat rotationVector = cv::Mat::zeros(3, 1, CV_64F);\n                for (auto i = 0u ; i < rotationVectors.size() ; i++)\n                {\n                    const auto pairAverageAngle = estimateAverageAngle(rotationVectors.at(i));\n                    if (!pairAverageAngle.first)\n                        opLog(\"Outlies in the result. Something went wrong when estimating the average of different\"\n                              \" projection matrices.\", Priority::High);\n                    rotationVector.at<double>(i,0) = {pairAverageAngle.second};\n                }\n                cv::Mat rotationMatrix;\n                cv::Rodrigues(rotationVector, rotationMatrix);\n                Eigen::Matrix3d rotEigen;\n                cv::cv2eigen(rotationMatrix, rotEigen);\n                averagedProjectionMatrix.block<3,3>(0,0) = rotEigen;\n\n                // Result\n                return averagedProjectionMatrix;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::Matrix4d{};\n            }\n        }\n\n        Eigen::Matrix4d getMFromRt(const Eigen::Matrix3d& Rot, const Eigen::Vector3d& trans)\n        {\n            try\n            {\n                // projectionMatrix\n                Eigen::Matrix4d projectionMatrix = Eigen::Matrix4d::Identity();\n                projectionMatrix.block<3,3>(0,0) = Rot;\n                projectionMatrix.block<3,1>(0,3) = trans;\n                return projectionMatrix;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::Matrix4d{};\n            }\n        }\n\n        Eigen::Matrix4d getMFromRt(const cv::Mat& Rot, const cv::Mat& trans)\n        {\n            try\n            {\n                if (Rot.cols != 3 || Rot.rows != 3)\n                    error(\"Rotation matrix does not have 3 cols and/or 3 rows.\", __LINE__, __FUNCTION__, __FILE__);\n                if (trans.cols != 1 || trans.rows != 3)\n                    error(\"Translation vector does not have 1 col and/or 3 rows.\", __LINE__, __FUNCTION__, __FILE__);\n\n                Eigen::Matrix3d RotEigen;\n                cv::cv2eigen(Rot, RotEigen);\n                Eigen::Vector3d transEigen;\n                cv::cv2eigen(trans, transEigen);\n\n                // projectionMatrix\n                return getMFromRt(RotEigen, transEigen);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::Matrix4d{};\n            }\n        }\n        std::pair<cv::Mat, cv::Mat> solveCorrespondences2D3D(\n            const cv::Mat& cameraMatrix, const cv::Mat& distortionCoefficients,\n            const std::vector<cv::Point3f>& objects3DVector, const std::vector<cv::Point2f>& points2DVector)\n        {\n            try\n            {\n                // opLog(\"Solving 2D-3D correspondences (extrinsics)\", Priority::High);\n                cv::Mat rVec(3, 1, cv::DataType<double>::type);\n                cv::Mat tVec(3, 1, cv::DataType<double>::type);\n\n                // VERY IMPORTANT\n                // So far, the only one that gives precise results is: cv::SOLVEPNP_DLS without RANSCAC\n\n                // Non-RANSAC mode\n                // It only can use 4 points\n                // cv::solvePnP(fourObjects3DVector, fourPoints2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, cv::SOLVEPNP_P3P);\n                // More robust against outliers\n                // const auto found = cv::solvePnP(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, cv::SOLVEPNP_ITERATIVE);\n                // Default cv::SOLVEPNP_ITERATIVE for OpenCV 3\n                const auto found = cv::solvePnP(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false);\n                // More fragile against outliers\n                // cv::solvePnP(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, cv::SOLVEPNP_EPNP);\n                // More robust against outliers\n                // cv::solvePnP(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, cv::SOLVEPNP_DLS);\n                // More robust against outliers\n                // cv::solvePnP(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, cv::SOLVEPNP_UPNP);\n\n                // RANSAC mode\n                // It gives really bad results\n                // This one is the best, but it doest care about initial guesses\n                // cv::solvePnPRansac(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, 1000, 8.0, 0.99, (int)objects3DVector.size() + 1, cv::noArray(), CV_EPNP);\n                // This one is the best, but it doest care about initial guesses\n                // cv::solvePnPRansac(objects3DVector, points2DVector, cameraMatrix, distortionCoefficients, rVec, tVec, false, 1000, 8.0, 0.99, cv::noArray(), cv::SOLVEPNP_ITERATIVE);\n                if (!found)\n                    error(\"Correspondences could not be found.\", __LINE__, __FUNCTION__, __FILE__);\n\n                return std::make_pair(rVec, tVec);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::make_pair(cv::Mat(), cv::Mat());\n            }\n        }\n\n        std::tuple<cv::Mat, cv::Mat, std::vector<cv::Point2f>, std::vector<cv::Point3f>> calcExtrinsicParametersOpenCV(\n            const cv::Mat& image, const cv::Mat& cameraMatrix, const cv::Mat& distortionCoefficients,\n            const cv::Size& gridInnerCorners, const float gridSquareSizeMm)\n        {\n            try\n            {\n                // Finding accurate chessboard corner positions\n                bool found{false};\n                std::vector<cv::Point2f> points2DVector;\n                std::tie(found, points2DVector) = findAccurateGridCorners(image, gridInnerCorners);\n                if (!found)\n                    return std::make_tuple(cv::Mat(), cv::Mat(), std::vector<cv::Point2f>(),\n                                           std::vector<cv::Point3f>());\n\n                // Reordering points2DVector to have the first point at the top left position (top right in\n                // case the chessboard is mirrored)\n                reorderPoints(points2DVector, gridInnerCorners, image);\n\n                // Generate objects3DVector from gridSquareSizeMm\n                const auto objects3DVector = getObjects3DVector(gridInnerCorners, gridSquareSizeMm);\n\n                // Solving correspondences 2D-3D\n                cv::Mat rVec;\n                cv::Mat tVec;\n                std::tie(rVec, tVec) = solveCorrespondences2D3D(cameraMatrix, distortionCoefficients, objects3DVector,\n                                                                points2DVector);\n\n                return std::make_tuple(rVec, tVec, points2DVector, objects3DVector);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::make_tuple(cv::Mat(), cv::Mat(), std::vector<cv::Point2f>(), std::vector<cv::Point3f>());\n            }\n        }\n\n        std::tuple<bool, Extrinsics> calcExtrinsicParameters(const cv::Mat& image,\n                                                             const cv::Size& gridInnerCorners,\n                                                             const float gridSquareSizeMm,\n                                                             const cv::Mat& cameraMatrix,\n                                                             const cv::Mat& distortionCoefficients)\n        {\n            try\n            {\n                Extrinsics extrinsics;\n                cv::Mat rVecOpenCV;\n                cv::Mat RotOpenCV;\n                cv::Mat tMmOpenCV;\n                std::tie(rVecOpenCV, tMmOpenCV, extrinsics.points2DVector, extrinsics.objects3DVector)\n                        = calcExtrinsicParametersOpenCV(\n                            image, cameraMatrix, distortionCoefficients, gridInnerCorners, gridSquareSizeMm);\n                if (rVecOpenCV.empty())\n                    return std::make_tuple(false, Extrinsics{});\n\n                cv::Rodrigues(rVecOpenCV, RotOpenCV);\n                cv::cv2eigen(RotOpenCV, extrinsics.Rotation);\n                cv::cv2eigen(tMmOpenCV, extrinsics.translationMm);\n\n                return std::make_tuple(true, extrinsics);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::make_tuple(false, Extrinsics{});\n            }\n        }\n\n        std::tuple<bool, Eigen::Matrix3d, Eigen::Vector3d, Eigen::Matrix3d, Eigen::Vector3d> getExtrinsicParameters(\n            const std::vector<std::string>& cameraPaths, const cv::Size& gridInnerCorners, const float gridSquareSizeMm,\n            const bool coutAndPlotGridCorners, const std::vector<cv::Mat>& intrinsics, const std::vector<cv::Mat>& distortions)\n        {\n            try\n            {\n                // Sanity check\n                if (intrinsics.size() != 2 || distortions.size() != 2 || cameraPaths.size() != 2)\n                    error(\"Found that (intrinsics.size() != 2 || distortions.size() != 2 || cameraPaths.size() != 2).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                std::vector<Extrinsics> extrinsicss(2);\n                for (auto i = 0u ; i < cameraPaths.size() ; i++)\n                {\n                    if (coutAndPlotGridCorners)\n                        opLog(\"getExtrinsicParameters(...), iteration with: \" + cameraPaths[i], Priority::High);\n                    // Loading images\n                    const cv::Mat image = cv::imread(cameraPaths[i]);\n                    if (image.empty())\n                        error(\"No image found in the path `\" + cameraPaths[i] + \"`.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    bool valid;\n                    std::tie(valid, extrinsicss[i]) = calcExtrinsicParameters(\n                        image, gridInnerCorners, gridSquareSizeMm, intrinsics.at(i), distortions.at(i));\n                    if (!valid)\n                        return std::make_tuple(false, Eigen::Matrix3d{}, Eigen::Vector3d{}, Eigen::Matrix3d{},\n                                               Eigen::Vector3d{});\n                    if (coutAndPlotGridCorners)\n                        plotGridCorners(gridInnerCorners, extrinsicss[i].points2DVector, cameraPaths[i], image);\n                }\n\n                return std::make_tuple(\n                    true,\n                    extrinsicss.at(0).Rotation,\n                    extrinsicss.at(0).translationMm,\n                    extrinsicss.at(1).Rotation,\n                    extrinsicss.at(1).translationMm\n                );\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return std::make_tuple(\n                    false, Eigen::Matrix3d{}, Eigen::Vector3d{}, Eigen::Matrix3d{}, Eigen::Vector3d{});\n            }\n        }\n\n        Eigen::Matrix4d getMFrom2Ms(const Eigen::Matrix4d& MGridToCam0,\n                                    const Eigen::Matrix4d& MGridToCam1)\n        {\n            try\n            {\n                // MCam1ToGrid\n                // Non-efficient equivalent:\n                    // MCam1ToGrid = MGridToCam1.inverse()\n                // Efficient version:\n                    // M * M.inverse()  =    I\n                    // [R t] [R -R't]   =  [I 0]\n                    // [0 1] [0   1 ]   =  [0 1]\n                    // Conclusion:\n                    //     R_inv = R^-1 = R^T\n                    //     t_inv = -R^T t\n                Eigen::Matrix4d MCam1ToGrid = Eigen::Matrix4d::Identity();\n                MCam1ToGrid.block<3,3>(0,0) = MGridToCam1.block<3,3>(0,0).transpose();\n                MCam1ToGrid.block<3,1>(0,3) = - MCam1ToGrid.block<3,3>(0,0) * MGridToCam1.block<3,1>(0,3);\n                // MCam1ToCam0 = MGridToCam0 * inv(MGridToCam1)\n                // I.e., position of camera 1 w.r.t. camera 0\n                return Eigen::Matrix4d{MGridToCam0 * MCam1ToGrid};\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::Matrix4d{};\n            }\n        }\n\n        Eigen::Matrix4d getMFromCam1ToCam0(const Eigen::Matrix3d& RGridToMainCam0,\n                                           const Eigen::Vector3d& tGridToMainCam0,\n                                           const Eigen::Matrix3d& RGridToMainCam1,\n                                           const Eigen::Vector3d& tGridToMainCam1,\n                                           const bool coutAndImshowVerbose)\n        {\n            const auto MGridToCam0 = getMFromRt(RGridToMainCam0, tGridToMainCam0);\n            const auto MGridToCam1 = getMFromRt(RGridToMainCam1, tGridToMainCam1);\n            // const auto MCam1ToCam0 = getMFrom2Ms(MGridToCam0, MGridToCam1);\n            const auto MCam1ToCam0 = getMFrom2Ms(MGridToCam1, MGridToCam0);\n\n            if (coutAndImshowVerbose)\n            {\n                const Eigen::Vector3d tCam1WrtCam0 = MCam1ToCam0.block<3,1>(0,3) / MCam1ToCam0(3,3);\n                const Eigen::Matrix3d RCam1WrtCam0 = MCam1ToCam0.block<3,3>(0,0);\n                opLog(\"M_gb:\", Priority::High);\n                opLog(MGridToCam1, Priority::High);\n                opLog(\"M_gf:\", Priority::High);\n                opLog(MGridToCam0, Priority::High);\n                opLog(\"M_bf:\", Priority::High);\n                opLog(MCam1ToCam0, Priority::High);\n\n                opLog(\"########## Secondary camera position w.r.t. main camera ##########\", Priority::High);\n                opLog(\"tCam1WrtCam0:\", Priority::High);\n                opLog(tCam1WrtCam0, Priority::High);\n                opLog(\"RCam1WrtCam0:\", Priority::High);\n                opLog(RCam1WrtCam0, Priority::High);\n                opLog(\"MCam0WrtCam1:\", Priority::High);\n                opLog((- RCam1WrtCam0.transpose() * tCam1WrtCam0), Priority::High);\n            }\n\n            return MCam1ToCam0;\n        }\n    #endif\n\n    const int SIFT_NAME = ('S' + ('I' << 8) + ('F' << 16) + ('T' << 24));\n    // const int MSER_NAME = ('M' + ('S' << 8) + ('E' << 16) + ('R' << 24));\n    // const int RECT_NAME = ('R' + ('E' << 8) + ('C' << 16) + ('T' << 24));\n    const int SIFT_VERSION_4 = ('V' + ('4' << 8) + ('.' << 16) + ('0' << 24));\n    const int SIFT_EOF = (0xff + ('E' << 8) + ('O' << 16) + ('F' << 24));\n    void writeVisualSFMSiftGPU(const std::string& fileName, const std::vector<cv::Point2f>& points2DVector)\n    {\n        const int siftName = SIFT_NAME;\n        const int siftVersion = SIFT_VERSION_4;\n        const int keyDimension = 5;\n        const int descDimension = 128;\n        const int siftEOF = SIFT_EOF;\n        const int nSift = (int)points2DVector.size();\n        std::ofstream ofstreamSift;\n        ofstreamSift.open(fileName, std::ios::binary);\n        // Can write\n        if (ofstreamSift.is_open())\n        {\n            ofstreamSift.write(reinterpret_cast<const char*>(&siftName), sizeof(int));\n            ofstreamSift.write(reinterpret_cast<const char*>(&siftVersion), sizeof(int));\n            ofstreamSift.write(reinterpret_cast<const char*>(&nSift), sizeof(int));\n            ofstreamSift.write(reinterpret_cast<const char*>(&keyDimension), sizeof(int));\n            ofstreamSift.write(reinterpret_cast<const char*>(&descDimension), sizeof(int));\n            // for (int j = 0; j < nSift; ++j)\n            for (auto i = 0u; i < points2DVector.size(); i++)\n            {\n                // const float x = KeyPts[4 * j];\n                // const float y = KeyPts[4 * j + 1];\n                const float x = points2DVector[i].x;\n                const float y = points2DVector[i].y;\n                const float dummy = 0.f;\n                const float scale = 1.f;\n                const float orientation = 0.f;\n                ofstreamSift.write(reinterpret_cast<const char*>(&x), sizeof(float));\n                ofstreamSift.write(reinterpret_cast<const char*>(&y), sizeof(float));\n                ofstreamSift.write(reinterpret_cast<const char*>(&dummy), sizeof(float));\n                // ofstreamSift.write(reinterpret_cast<const char*>(&KeyPts[4 * j + 2]), sizeof(float));\n                // ofstreamSift.write(reinterpret_cast<const char*>(&KeyPts[4 * j + 3]), sizeof(float));\n                ofstreamSift.write(reinterpret_cast<const char*>(&scale), sizeof(float));\n                ofstreamSift.write(reinterpret_cast<const char*>(&orientation), sizeof(float));\n            }\n\n            // // Extra argument: const unsigned char* const desc\n            // for (int j = 0; j < nSift; ++j)\n            //     for (int i = 0; i < descDimension; i++)\n            //         ofstreamSift.write(reinterpret_cast<const char*>(&desc[j * descDimension + i]),\n            //                            sizeof(unsigned char));\n            const unsigned char dummy = 0u;\n            for (auto i = 0; i < nSift * descDimension; i++)\n                ofstreamSift.write(reinterpret_cast<const char*>(&dummy), sizeof(unsigned char));\n\n            ofstreamSift.write(reinterpret_cast<const char*>(&siftEOF), sizeof(int));\n            ofstreamSift.close();\n        }\n        // Couldn't write\n        else\n            opLog(\"Cannot write on \" + fileName, Priority::High);\n    }\n\n    std::string getFileNameFromCameraIndex(const int cameraIndex)\n    {\n        try\n        {\n            // Sanity check\n            if (cameraIndex >= 100)\n                error(\"Only implemented for up to 99 cameras.\", __LINE__, __FUNCTION__, __FILE__);\n            // Return result\n            return (cameraIndex < 10 ? \"00_0\" : \"00_\") + std::to_string(cameraIndex);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    void estimateAndSaveSiftFileSubThread(\n        std::vector<cv::Point2f>* points2DExtrinsicPtr, std::vector<unsigned int>* matchIndexesCameraPtr,\n        const int cameraIndex, const int numberCameras, const int numberCorners, const unsigned int numberViews,\n        const bool saveImagesWithCorners, const std::string& imageFolder, const cv::Size& gridInnerCornersCvSize,\n        const cv::Size& imageSize, const std::vector<std::pair<cv::Mat, std::string>>& imageAndPaths,\n        const bool saveSIFTFile)\n    {\n        try\n        {\n            // Sanity checks\n            if (points2DExtrinsicPtr == nullptr || matchIndexesCameraPtr == nullptr)\n                error(\"Make sure than points2DExtrinsicPtr != nullptr && matchIndexesCameraPtr != nullptr.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (!points2DExtrinsicPtr->empty() || !matchIndexesCameraPtr->empty())\n                error(\"Variables points2DExtrinsicPtr and matchIndexesCameraPtr must be empty.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Estimate and save SIFT file\n            std::vector<cv::Point2f>& points2DExtrinsic = *points2DExtrinsicPtr;\n            std::vector<unsigned int>& matchIndexesCamera = *matchIndexesCameraPtr;\n            std::vector<cv::Mat> imagesWithCorners;\n            for (auto viewIndex = 0u ; viewIndex < numberViews ; viewIndex++)\n            {\n                // Get right image\n                const auto& imageAndPath = imageAndPaths.at(viewIndex * numberCameras + cameraIndex);\n                const auto& image = imageAndPath.first;\n\n                if (viewIndex % std::max(1, int(numberViews/4)) == 0)\n                    opLog(\"Camera \" + std::to_string(cameraIndex) + \" - Image view \"\n                        + std::to_string(viewIndex+1) + \"/\" + std::to_string(numberViews),\n                        Priority::High);\n\n                // Sanity check\n                if (imageSize.width != image.cols || imageSize.height != image.rows)\n                    error(\"Detected images with different sizes in `\" + imageFolder + \"` All images\"\n                          \" must have the same resolution.\", __LINE__, __FUNCTION__, __FILE__);\n\n                // Find grid corners\n                bool found;\n                std::vector<cv::Point2f> points2DVector;\n                std::tie(found, points2DVector) = findAccurateGridCorners(image, gridInnerCornersCvSize);\n\n                // Reorder & save 2D pixels points\n                if (found)\n                {\n                    reorderPoints(points2DVector, gridInnerCornersCvSize, image);\n                    for (auto i = 0 ; i < numberCorners ; i++)\n                        matchIndexesCamera.emplace_back(viewIndex * numberCorners + i);\n                }\n                else\n                {\n                    points2DVector.clear();\n                    points2DVector.resize(numberCorners, cv::Point2f{-1.f,-1.f});\n                    opLog(\"Camera \" + std::to_string(cameraIndex) + \" - Image view \"\n                        + std::to_string(viewIndex+1) + \"/\" + std::to_string(numberViews)\n                        + \" - Chessboard not found.\", Priority::High);\n                }\n                points2DExtrinsic.insert(points2DExtrinsic.end(), points2DVector.begin(), points2DVector.end());\n\n                // Show image (with chessboard corners if found)\n                if (saveImagesWithCorners)\n                {\n                    cv::Mat imageToPlot = image.clone();\n                    if (found)\n                        drawGridCorners(imageToPlot, gridInnerCornersCvSize, points2DVector);\n                    imagesWithCorners.emplace_back(imageToPlot);\n                }\n            }\n\n            // Save *.sift file for camera\n            if (saveSIFTFile)\n            {\n                // const auto fileName = getFullFilePathNoExtension(imageAndPaths.at(cameraIndex).second) + \".sift\";\n                const auto fileName = getFileParentFolderPath(imageAndPaths.at(cameraIndex).second)\n                                    + getFileNameFromCameraIndex(cameraIndex) + \".sift\";\n                writeVisualSFMSiftGPU(fileName, points2DExtrinsic);\n            }\n\n            // Save images with corners\n            if (saveImagesWithCorners)\n            {\n                const auto folderWhereSavingImages = imageFolder + \"images_with_corners/\";\n                // Create directory in case it did not exist\n                makeDirectory(folderWhereSavingImages);\n                const auto pathWhereSavingImages = folderWhereSavingImages + std::to_string(cameraIndex) + \"_\";\n                // Save new images\n                const std::string extension{\".png\"};\n                auto fileRemoved = true;\n                for (auto i = 0u ; i < imagesWithCorners.size() || fileRemoved; i++)\n                {\n                    const auto finalPath = pathWhereSavingImages + std::to_string(i+1) + extension;\n                    // remove leftovers/previous files\n                    // Note: If file is not deleted before cv::imwrite, Windows considers that the file\n                    // was \"only\" modified at that time, not created\n                    fileRemoved = {remove(finalPath.c_str()) == 0};\n                    // save images on hhd in the desired place\n                    if (i < imagesWithCorners.size())\n                    {\n                        const auto opMat = OP_CV2OPMAT(imagesWithCorners.at(i));\n                        saveImage(opMat, finalPath);\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    const std::string sEmptyErrorMessage = \"No chessboard was found in any of the images. Are you sure you\"\n        \" are using the right value for `--grid_number_inner_corners`? Remember that it corresponds to the\"\n        \" number of inner corners on the image (not the total number of corners!). I.e., it corresponds to\"\n        \" the number of squares on each side minus 1! (or the number of total corners on each side - 1).\"\n        \" It follows the OpenCV notation.\";\n\n\n\n\n\n    // Public functions\n    void estimateAndSaveIntrinsics(\n        const Point<int>& gridInnerCorners, const float gridSquareSizeMm, const int flags,\n        const std::string& outputParameterFolder, const std::string& imageFolder, const std::string& serialNumber,\n        const bool saveImagesWithCorners)\n    {\n        try\n        {\n            // Point<int> --> cv::Size\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const cv::Size gridInnerCornersCvSize{gridInnerCorners.x, gridInnerCorners.y};\n\n            // Read images in folder\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const auto imageAndPaths = getImageAndPaths(imageFolder);\n\n            // Get 2D grid corners of each image\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            std::vector<std::vector<cv::Point2f>> points2DVectors;\n            std::vector<cv::Mat> imagesWithCorners;\n            const auto imageSize = imageAndPaths.at(0).first.size();\n            for (auto i = 0u ; i < imageAndPaths.size() ; i++)\n            {\n                opLog(\"\\nImage \" + std::to_string(i+1) + \"/\" + std::to_string(imageAndPaths.size()), Priority::High);\n                const auto& image = imageAndPaths.at(i).first;\n\n                // Sanity check\n                if (imageSize.width != image.cols || imageSize.height != image.rows)\n                    error(\"Detected images with different sizes in `\" + imageFolder + \"` All images\"\n                          \" must have the same resolution.\", __LINE__, __FUNCTION__, __FILE__);\n\n                // Find grid corners\n                bool found;\n                std::vector<cv::Point2f> points2DVector;\n                std::tie(found, points2DVector) = findAccurateGridCorners(image, gridInnerCornersCvSize);\n\n                // Reorder & save 2D pixels points\n                if (found)\n                {\n                    // For intrinsics order is irrelevant, so I do not care if it fails\n                    const auto showWarning = false;\n                    reorderPoints(points2DVector, gridInnerCornersCvSize, image, showWarning);\n                    points2DVectors.emplace_back(points2DVector);\n                }\n                else\n                    opLog(\"Chessboard not found in image \" + imageAndPaths.at(i).second + \".\", Priority::High);\n\n                // Debugging (optional) - Show image (with chessboard corners if found)\n                if (saveImagesWithCorners)\n                {\n                    cv::Mat imageToPlot = image.clone();\n                    if (found)\n                        drawGridCorners(imageToPlot, gridInnerCornersCvSize, points2DVector);\n                    // cv::pyrDown(imageToPlot, imageToPlot);\n                    // cv::imshow(\"Image View\", imageToPlot);\n                    // cv::waitKey(delayMilliseconds);\n                    imagesWithCorners.emplace_back(imageToPlot);\n                }\n            }\n            // Sanity check\n            if (points2DVectors.empty())\n                error(sEmptyErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n\n            // Run calibration\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // objects3DVector is the same one for each image\n            const std::vector<std::vector<cv::Point3f>> objects3DVectors(\n                points2DVectors.size(), getObjects3DVector(gridInnerCornersCvSize, gridSquareSizeMm));\n            const auto intrinsics = calcIntrinsicParameters(imageSize, points2DVectors, objects3DVectors, flags);\n\n            // Save intrinsics/results\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            Matrix opCameraMatrix = OP_CV2OPMAT(intrinsics.cameraMatrix);\n            Matrix opDistortionCoefficients = OP_CV2OPMAT(intrinsics.distortionCoefficients);\n            CameraParameterReader cameraParameterReader{\n                serialNumber, opCameraMatrix, opDistortionCoefficients };\n            cameraParameterReader.writeParameters(outputParameterFolder);\n\n            // Debugging (optional) - Save images with corners\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            if (saveImagesWithCorners)\n            {\n                const auto folderWhereSavingImages = imageFolder + \"images_with_corners/\";\n                // Create directory in case it did not exist\n                makeDirectory(folderWhereSavingImages);\n                // Save new images\n                const std::string extension{\".png\"};\n                auto fileRemoved = true;\n                for (auto i = 0u ; i < imagesWithCorners.size() || fileRemoved; i++)\n                {\n                    const auto finalPath = folderWhereSavingImages + std::to_string(i+1) + extension;\n                    // remove leftovers/previous files\n                    // Note: If file is not deleted before cv::imwrite, Windows considers that the file\n                    // was \"only\" modified at that time, not created\n                    fileRemoved = {remove(finalPath.c_str()) == 0};\n                    // save images on hhd in the desired place\n                    if (i < imagesWithCorners.size())\n                    {\n                        const auto opMat = OP_CV2OPMAT(imagesWithCorners.at(i));\n                        saveImage(opMat, finalPath);\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void estimateAndSaveExtrinsics(\n        const std::string& parameterFolder, const std::string& imageFolder, const Point<int>& gridInnerCorners,\n        const float gridSquareSizeMm, const int index0, const int index1, const bool imagesAreUndistorted,\n        const bool combineCam0Extrinsics)\n    {\n        try\n        {\n            #ifdef USE_EIGEN\n                // For debugging\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto coutResults = false;\n                // const auto coutResults = true;\n                const bool coutAndImshowVerbose = false;\n\n                // Point<int> --> cv::Size\n                const cv::Size gridInnerCornersCvSize{gridInnerCorners.x, gridInnerCorners.y};\n\n                // Load intrinsic parameters\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                CameraParameterReader cameraParameterReader;\n                cameraParameterReader.readParameters(parameterFolder);\n                const auto cameraSerialNumbers = cameraParameterReader.getCameraSerialNumbers();\n                const auto opRealCameraDistortions = cameraParameterReader.getCameraDistortions();\n                OP_OP2CVVECTORMAT(realCameraDistortions, opRealCameraDistortions)\n                auto opCameraIntrinsicsSubset = cameraParameterReader.getCameraIntrinsics();\n                OP_OP2CVVECTORMAT(cameraIntrinsicsSubset, opCameraIntrinsicsSubset)\n                auto cameraDistortionsSubset = (imagesAreUndistorted ?\n                    std::vector<cv::Mat>{realCameraDistortions.size()}\n                    : realCameraDistortions);\n                // Only use the 2 desired ones\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                cameraIntrinsicsSubset = {cameraIntrinsicsSubset.at(index0), cameraIntrinsicsSubset.at(index1)};\n                cameraDistortionsSubset = {cameraDistortionsSubset.at(index0), cameraDistortionsSubset.at(index1)};\n                // Base extrinsics\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                cv::Mat extrinsicsCam0 = cv::Mat::eye(4, 4, realCameraDistortions.at(0).type());\n                bool cam0IsOrigin = true;\n                if (combineCam0Extrinsics)\n                {\n                    const cv::Mat cameraExtrinsicsAtIndex0 = OP_OP2CVCONSTMAT(\n                        cameraParameterReader.getCameraExtrinsics().at(index0));\n                    cameraExtrinsicsAtIndex0.copyTo(extrinsicsCam0(cv::Rect{0,0,4,3}));\n                    cam0IsOrigin = cv::norm(extrinsicsCam0 - cv::Mat::eye(4, 4, extrinsicsCam0.type())) < 1e-9;\n                }\n\n                // Number cameras and image paths\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto numberCameras = cameraParameterReader.getNumberCameras();\n                opLog(\"\\nDetected \" + std::to_string(numberCameras) + \" cameras from your XML files on:\\n\"\n                    + parameterFolder + \"\\nRemove wrong/extra XML files if this number of cameras does not\"\n                    + \" correspond with the number of cameras recorded in:\\n\" + imageFolder + \"\\n\",\n                    Priority::High);\n                const auto imagePaths = getImagePaths(imageFolder);\n                // Sanity check\n                if (imagePaths.size() % numberCameras != 0)\n                    error(\"You indicated that there are \" + std::to_string(numberCameras)\n                          + \" cameras. However, we found a total of \" + std::to_string(imagePaths.size())\n                          + \" images, which should be possible to divide into the number of cameras with no\"\n                          \" remainder.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                // Estimate extrinsic parameters per image\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                opLog(\"Calibrating camera \" + cameraSerialNumbers.at(index1) + \" with respect to camera \"\n                    + cameraSerialNumbers.at(index0) + \"...\", Priority::High);\n                const auto numberViews = imagePaths.size() / numberCameras;\n                auto counterValidImages = 0u;\n                std::vector<Eigen::Matrix4d> MCam1ToCam0s;\n                for (auto i = 0u ; i < imagePaths.size() ; i+=numberCameras)\n                {\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    const auto pathCam0 = imagePaths[i+index0];\n                    const auto pathCam1 = imagePaths[i+index1];\n                    if (coutResults || i/numberCameras % int(numberViews/10) == 0)\n                        opLog(\"It \" + std::to_string(i/numberCameras+1) + \"/\" + std::to_string(numberViews) + \": \"\n                            + getFileNameAndExtension(pathCam0) + \" & \"\n                            + getFileNameAndExtension(pathCam1) + \"...\", Priority::High);\n\n                    // Extrinsic parameters extractor\n                    Eigen::Matrix3d RGridToMainCam0;\n                    Eigen::Matrix3d RGridToMainCam1;\n                    Eigen::Vector3d tGridToMainCam0;\n                    Eigen::Vector3d tGridToMainCam1;\n                    bool valid = true;\n                    std::tie(valid, RGridToMainCam0, tGridToMainCam0, RGridToMainCam1, tGridToMainCam1)\n                        = getExtrinsicParameters({pathCam0, pathCam1}, gridInnerCornersCvSize, gridSquareSizeMm,\n                                                 false,\n                                                 // coutAndImshowVerbose, // It'd display all images with grid\n                                                 cameraIntrinsicsSubset, cameraDistortionsSubset);\n                    if (valid)\n                    {\n                        counterValidImages++;\n                        if (coutAndImshowVerbose)\n                        {\n                            opLog(\"########## Extrinsic parameters extractor ##########\", Priority::High);\n                            opLog(\"R_gf\", Priority::High);\n                            opLog(RGridToMainCam0, Priority::High);\n                            opLog(\"t_gf\", Priority::High);\n                            opLog(tGridToMainCam0, Priority::High);\n                            opLog(\"R_gb\", Priority::High);\n                            opLog(RGridToMainCam1, Priority::High);\n                            opLog(\"t_gb\", Priority::High);\n                            opLog(tGridToMainCam1, Priority::High);\n                            opLog(\"\\n\", Priority::High);\n                        }\n\n                        // MCam1ToCam0 - Projection matrix estimator\n                        if (coutAndImshowVerbose)\n                            opLog(\"########## Projection Matrix from secondary camera to main camera ##########\",\n                                Priority::High);\n                        MCam1ToCam0s.emplace_back(\n                            getMFromCam1ToCam0(RGridToMainCam0, tGridToMainCam0, RGridToMainCam1, tGridToMainCam1,\n                                coutAndImshowVerbose));\n                        if (coutResults)\n                        {\n                            if (coutAndImshowVerbose)\n                                opLog(\"M_bg:\", Priority::High);\n                            opLog(MCam1ToCam0s.back(), Priority::High);\n                            opLog(\" \", Priority::High);\n                        }\n                    }\n                    else\n                    {\n                        if (coutResults)\n                            opLog(\"Invalid frame (chessboard not found).\", Priority::High);\n                    }\n                }\n                // Sanity check\n                if (MCam1ToCam0s.empty())\n                    error(sEmptyErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n                opLog(\"Finished processing images.\", Priority::High);\n\n                // Pseudo RANSAC calibration\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto MCam1ToCam0Noisy = getMAverage(MCam1ToCam0s);\n                opLog(\"Estimated initial (noisy?) projection matrix.\", Priority::High);\n                auto MCam1ToCam0 = getMAverage(MCam1ToCam0s, MCam1ToCam0Noisy);\n                while ((MCam1ToCam0 - getMAverage(MCam1ToCam0s, MCam1ToCam0)).norm() > 1e-3)\n                {\n                    if (coutResults)\n                        opLog(\"Repeated robustness method...\", Priority::High);\n                    MCam1ToCam0 = getMAverage(MCam1ToCam0s, MCam1ToCam0);\n                }\n                opLog(\"Estimated robust projection matrix.\", Priority::High);\n                opLog(\"norm(M_robust-M_noisy): \" + std::to_string((MCam1ToCam0Noisy - MCam1ToCam0).norm()),\n                    Priority::High);\n\n\n\n                // Show errors\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                if (coutAndImshowVerbose)\n                {\n                    opLog(\"\\n-----------------------------------------------------------------------------------\"\n                        \"-------------------\\nErrors:\", Priority::High);\n                    // Errors\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    for (auto i = 0u ; i < MCam1ToCam0s.size() ; i++)\n                    {\n                        opLog(\"tCam1WrtCam0:\", Priority::High);\n                        opLog(MCam1ToCam0s.at(i).block<3,1>(0,3).transpose(), Priority::High);\n                    }\n                    opLog(\" \", Priority::High);\n\n                    opLog(\"tCam1WrtCam0:\", Priority::High);\n                    opLog(MCam1ToCam0.block<3,1>(0,3).transpose(), Priority::High);\n                    opLog(\" \", Priority::High);\n\n                    // Rotation matrix in degrees Rodrigues(InputArray src, OutputArray dst\n                    opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    const auto rad2deg = 180 / PI;\n                    for (auto i = 0u ; i < MCam1ToCam0s.size() ; i++)\n                    {\n                        Eigen::Matrix3d R_secondaryToMain = MCam1ToCam0s.at(i).block<3,3>(0,0);\n                        opLog(\"rodrigues:\", Priority::High);\n                        opLog((getRodriguesVector(R_secondaryToMain).t() * rad2deg), Priority::High);\n                    }\n                    Eigen::Matrix3d R_secondaryToMain = MCam1ToCam0.block<3,3>(0,0);\n                    opLog(\"rodrigues:\", Priority::High);\n                    opLog((getRodriguesVector(R_secondaryToMain).t() * rad2deg), Priority::High);\n                }\n\n                // Show final result\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                if (coutResults)\n                {\n                    opLog(\"\\n\\n\\n---------------------------------------------------------------------------\"\n                        \"---------------------------\", Priority::High);\n                    opLog(std::to_string(counterValidImages) + \" valid images.\", Priority::High);\n                    opLog(\"Initial (noisy?) projection matrix:\", Priority::High);\n                    opLog(MCam1ToCam0Noisy, Priority::High);\n                    opLog(\"\\nFinal projection matrix (mm):\", Priority::High);\n                    opLog(MCam1ToCam0, Priority::High);\n                    opLog(\" \", Priority::High);\n                }\n\n                // mm --> m\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                MCam1ToCam0.block<3,1>(0,3) *= 1e-3;\n\n                // Eigen --> cv::Mat\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                cv::Mat cvMatExtrinsics;\n                Eigen::MatrixXd eigenExtrinsics = MCam1ToCam0.block<3,4>(0,0);\n                cv::eigen2cv(eigenExtrinsics, cvMatExtrinsics);\n\n                // pos_target_origen = pos_target_cam1 * pos_cam1_origin\n                // Example: pos_31 = pos_32 * pos_21\n                if (!cam0IsOrigin)\n                    cvMatExtrinsics *= extrinsicsCam0;\n\n                // Final projection matrix\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                opLog(\"\\nFinal projection matrix w.r.t. global origin (meters):\", Priority::High);\n                opLog(cvMatExtrinsics, Priority::High);\n                opLog(\" \", Priority::High);\n\n                // Save result\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                CameraParameterReader cameraParameterReaderFinal{\n                    cameraSerialNumbers.at(index1),\n                    OP_CV2OPMAT(cameraIntrinsicsSubset.at(1)),\n                    OP_CV2OPMAT(realCameraDistortions.at(index1)),\n                    OP_CV2OPMAT(cvMatExtrinsics)\n                };\n                cameraParameterReaderFinal.writeParameters(parameterFolder);\n\n                // Let the rendered image to be displayed\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                if (coutAndImshowVerbose)\n                    cv::waitKey(0);\n            #else\n                UNUSED(parameterFolder);\n                UNUSED(imageFolder);\n                UNUSED(gridInnerCorners);\n                UNUSED(gridSquareSizeMm);\n                UNUSED(index0);\n                UNUSED(index1);\n                UNUSED(imagesAreUndistorted);\n                UNUSED(combineCam0Extrinsics);\n                error(\"CMake flag `USE_EIGEN` required when compiling OpenPose`.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    #if defined(USE_CERES) && defined(USE_EIGEN)\n        double computeReprojectionErrorInPixels(\n            const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, const Eigen::MatrixXd& BAValid,\n            const Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D, const std::vector<cv::Mat> cameraExtrinsics,\n            const std::vector<cv::Mat> cameraIntrinsics, const bool verbose = true)\n        {\n            try\n            {\n                // compute the average reprojection error\n                const unsigned int numberCameras = cameraIntrinsics.size();\n                const unsigned int numberPoints = points2DVectorsExtrinsic[0].size();\n                double sumError = 0.;\n                int sumPoint = 0;\n                double maxError = 0.;\n                int maxCamIdx = -1;\n                int maxPtIdx = -1;\n                for (auto cameraIndex = 0u; cameraIndex < numberCameras; cameraIndex++)\n                {\n                    const cv::Mat cameraMatrix = cameraIntrinsics[cameraIndex] * cameraExtrinsics[cameraIndex];\n                    for (auto i = 0u; i < numberPoints; i++)\n                    {\n                        if (!BAValid(cameraIndex, i))\n                            continue;\n                        const auto& point3d = &points3D.data()[3*i];\n                        const double KX = cameraMatrix.at<double>(0, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(0, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(0, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(0, 3);\n                        const double KY = cameraMatrix.at<double>(1, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(1, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(1, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(1, 3);\n                        const double KZ = cameraMatrix.at<double>(2, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(2, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(2, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(2, 3);\n                        const double xDiff = KX / KZ - points2DVectorsExtrinsic[cameraIndex][i].x;\n                        const double yDiff = KY / KZ - points2DVectorsExtrinsic[cameraIndex][i].y;\n                        const double error = sqrt(xDiff*xDiff + yDiff*yDiff);\n                        sumError += error;\n                        sumPoint++;\n                        if (error > maxError)\n                        {\n                            maxError = error;\n                            maxPtIdx = i;\n                            maxCamIdx = cameraIndex;\n                        }\n                    }\n                }\n                if (sumPoint == 0)\n                    error(\"Number of inlier points is 0 (with \" + std::to_string(numberCameras)\n                          + \" cameras and \" + std::to_string(numberPoints) + \" total points).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // Debugging\n                if (verbose)\n                    opLog(\"Reprojection Error info: Max error: \" + std::to_string(maxError) + \";\\t in cam idx \"\n                        + std::to_string(maxCamIdx) + \" with pt idx: \" + std::to_string(maxPtIdx) + \" & pt 2D: \"\n                        + std::to_string(points2DVectorsExtrinsic[maxCamIdx][maxPtIdx].x) + \"x\"\n                        + std::to_string(points2DVectorsExtrinsic[maxCamIdx][maxPtIdx].y), Priority::High);\n                return sumError / sumPoint;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n        }\n\n        void removeOutliersReprojectionError(\n            std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, Eigen::MatrixXd& BAValid,\n            const Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D, const std::vector<cv::Mat> cameraExtrinsics,\n            const std::vector<cv::Mat> cameraIntrinsics, const double errorThreshold = 5.)\n        {\n            try\n            {\n                std::vector<unsigned int> indexesToRemove;\n                const unsigned int numberCameras = cameraIntrinsics.size();\n                const unsigned int numberPoints = points2DVectorsExtrinsic[0].size();\n                for (auto cameraIndex = 0u; cameraIndex < numberCameras; cameraIndex++)\n                {\n                    const cv::Mat cameraMatrix = cameraIntrinsics[cameraIndex] * cameraExtrinsics[cameraIndex];\n                    for (auto i = 0u; i < numberPoints; i++)\n                    {\n                        if (!BAValid(cameraIndex, i))\n                            continue;\n                        const auto& point3d = &points3D.data()[3*i];\n                        const double KX = cameraMatrix.at<double>(0, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(0, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(0, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(0, 3);\n                        const double KY = cameraMatrix.at<double>(1, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(1, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(1, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(1, 3);\n                        const double KZ = cameraMatrix.at<double>(2, 0) * point3d[0]\n                                        + cameraMatrix.at<double>(2, 1) * point3d[1]\n                                        + cameraMatrix.at<double>(2, 2) * point3d[2]\n                                        + cameraMatrix.at<double>(2, 3);\n                        const double xDiff = KX / KZ - points2DVectorsExtrinsic[cameraIndex][i].x;\n                        const double yDiff = KY / KZ - points2DVectorsExtrinsic[cameraIndex][i].y;\n                        const double error = sqrt(xDiff*xDiff + yDiff*yDiff);\n                        if (error > errorThreshold)\n                        {\n                            indexesToRemove.emplace_back(i);\n                            BAValid(cameraIndex, i) = 0;\n                        }\n                    }\n                }\n                // Sort + Remove duplicates\n                std::sort(indexesToRemove.begin(), indexesToRemove.end());\n                indexesToRemove.erase(\n                    std::unique(indexesToRemove.begin(), indexesToRemove.end()), indexesToRemove.end());\n                // Sanity check\n                if (numberPoints <= indexesToRemove.size())\n                    error(\"All samples are considered outliers, no images left (\"\n                          + std::to_string(numberPoints) + \" total points vs. \"\n                          + std::to_string(indexesToRemove.size()) + \" outliers).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // Pros / cons:\n                // - Pros: It reduces the size of points (faster).\n                // - Cons: Scaling does not work.\n                // // Remove outliers (if any)\n                // if (!indexesToRemove.empty())\n                // {\n                //     const unsigned int numberPointsRansac = numberPoints - indexesToRemove.size();\n                //     std::vector<std::vector<cv::Point2f>> points2DVectorsExtrinsicRansac(\n                //         numberCameras, std::vector<cv::Point2f>(numberPointsRansac));\n                //     Eigen::Matrix<double, 3, Eigen::Dynamic> points3DRansac(3, numberPointsRansac);\n                //     Eigen::MatrixXd BAValidRansac = Eigen::MatrixXd::Zero(numberCameras, numberPointsRansac);\n                //     auto counterRansac = 0u;\n                //     for (auto i = 0u ; i < indexesToRemove.size()+1 ; i++)\n                //     {\n                //         // Otherwise, it would not get the points after the last outlier\n                //         const auto& indexToRemove = (\n                //             i < indexesToRemove.size() ? indexesToRemove[i] : numberPoints);\n                //         while (counterRansac < indexToRemove && counterRansac < numberPoints)\n                //         {\n                //             // Fill 2D coordinate\n                //             for (auto cameraIndex = 0u; cameraIndex < numberCameras; cameraIndex++)\n                //                 points2DVectorsExtrinsicRansac[cameraIndex][counterRansac-i]\n                //                     = points2DVectorsExtrinsic[cameraIndex][counterRansac];\n                //                 // points2DVectorsExtrinsicRansac.at(cameraIndex).at(counterRansac-i)\n                //                 //     = points2DVectorsExtrinsic.at(cameraIndex).at(counterRansac);\n                //             // Fill 3D coordinate\n                //             const auto* const point3D = &points3D.data()[3*counterRansac];\n                //             auto* point3DRansac = &points3DRansac.data()[3*(counterRansac-i)];\n                //             point3DRansac[0] = point3D[0];\n                //             point3DRansac[1] = point3D[1];\n                //             point3DRansac[2] = point3D[2];\n                //             // Fill BAValidRansac\n                //             BAValidRansac.col(counterRansac-i) = BAValid.col(counterRansac);\n                //             // Update counter\n                //             counterRansac++;\n                //         }\n                //         counterRansac++;\n                //     }\n                //     // Assign back\n                //     std::swap(points2DVectorsExtrinsic, points2DVectorsExtrinsicRansac);\n                //     std::swap(points3D, points3DRansac);\n                //     std::swap(BAValid, BAValidRansac);\n                // }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        Eigen::MatrixXd getInlierAndOutliers(\n            const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic)\n        {\n            try\n            {\n                const auto numberCameras = points2DVectorsExtrinsic.size();\n                // Update inliers & outliers\n                // This is a valid reprojection term\n                Eigen::MatrixXd BAValid = Eigen::MatrixXd::Zero(numberCameras, points2DVectorsExtrinsic[0].size());\n                for (auto i = 0u; i < points2DVectorsExtrinsic[0].size(); i++)\n                {\n                    auto visibleViewCounter = 0u;\n                    // std::vector<cv::Mat> pointCameraMatrices;\n                    for (auto cameraIndex = 0u ; cameraIndex < numberCameras ; cameraIndex++)\n                    {\n                        if (points2DVectorsExtrinsic[cameraIndex][i].x >= 0)  // visible in this camera\n                        {\n                            visibleViewCounter++;\n                            if (visibleViewCounter > 1u)\n                                break;\n                        }\n                    }\n                    // If visible in >1 camera, point used in bundle adjustment\n                    if (visibleViewCounter > 1u)\n                        for (auto cameraIndex = 0u ; cameraIndex < numberCameras ; cameraIndex++)\n                            if (points2DVectorsExtrinsic[cameraIndex][i].x >= 0)\n                                BAValid(cameraIndex, i) = 1;\n                }\n                return BAValid;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::MatrixXd{};\n            }\n        }\n\n        void removeOutliersReprojectionErrorIterative(\n            std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, Eigen::MatrixXd& BAValid,\n            const Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D, const std::vector<cv::Mat> cameraExtrinsics,\n            const std::vector<cv::Mat> cameraIntrinsics, const double errorThresholdRelative = 5.)\n        {\n            try\n            {\n                // Outlier removal\n                auto reprojectionError = computeReprojectionErrorInPixels(\n                    points2DVectorsExtrinsic, BAValid, points3D, cameraExtrinsics, cameraIntrinsics, false);\n                auto reprojectionErrorPrevious = reprojectionError+1;\n                while (reprojectionError != reprojectionErrorPrevious)\n                {\n                    reprojectionErrorPrevious = reprojectionError;\n                    // 1 pixels is a lot for HD images...\n                    const auto errorThreshold = fastMax(2*reprojectionError, errorThresholdRelative);\n                    removeOutliersReprojectionError(\n                        points2DVectorsExtrinsic, BAValid, points3D, cameraExtrinsics, cameraIntrinsics,\n                        errorThreshold);\n                    reprojectionError = computeReprojectionErrorInPixels(\n                        points2DVectorsExtrinsic, BAValid, points3D, cameraExtrinsics, cameraIntrinsics);\n                    // Verbose\n                    opLog(\"Reprojection Error (after outlier removal iteration): \"\n                        + std::to_string(reprojectionError) + \" pixels,\\twith error threshold of \"\n                        + std::to_string(errorThreshold) + \" pixels.\", Priority::High);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        Eigen::Matrix<double, 3, Eigen::Dynamic> reconstruct3DPoints(\n            const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic,\n            const std::vector<cv::Mat>& cameraIntrinsics, const std::vector<cv::Mat>& cameraExtrinsics,\n            const int numberCameras, const cv::Size& imageSize)\n        {\n            try\n            {\n                // Initialize to 0\n                Eigen::Matrix<double, 3, Eigen::Dynamic> points3D(3, points2DVectorsExtrinsic[0].size());\n                points3D.setZero();\n                // Compute the initial camera matrices\n                std::vector<cv::Mat> cameraMatrices(numberCameras);\n                for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n                    cameraMatrices[cameraIndex] = cameraIntrinsics[cameraIndex] * cameraExtrinsics[cameraIndex];\n                const auto imageRatio = std::sqrt(imageSize.area() / 1310720.);\n                const auto reprojectionMaxAcceptable = 25 * imageRatio;\n                for (auto i = 0u; i < points2DVectorsExtrinsic[0].size(); i++)\n                {\n                    std::vector<cv::Mat> pointCameraMatrices;\n                    std::vector<cv::Point2d> pointsOnEachCamera;\n                    for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n                    {\n                        if (points2DVectorsExtrinsic[cameraIndex][i].x >= 0)  // visible in this camera\n                        {\n                            pointCameraMatrices.emplace_back(cameraMatrices[cameraIndex]);\n                            const auto& point2D = points2DVectorsExtrinsic[cameraIndex][i];\n                            // cv::Point2f --> cv::Point2d\n                            pointsOnEachCamera.emplace_back(cv::Point2d{point2D.x, point2D.y});\n                        }\n                    }\n                    // if visible in one camera, no triangulation and not used in bundle adjustment.\n                    if (pointCameraMatrices.size() > 1u)\n                    {\n                        cv::Mat reconstructedPoint;\n                        triangulateWithOptimization(\n                            reconstructedPoint, pointCameraMatrices, pointsOnEachCamera, reprojectionMaxAcceptable);\n                        auto* points3DPtr = &points3D.data()[3*i];\n                        points3DPtr[0] = reconstructedPoint.at<double>(0, 0) / reconstructedPoint.at<double>(3, 0);\n                        points3DPtr[1] = reconstructedPoint.at<double>(1, 0) / reconstructedPoint.at<double>(3, 0);\n                        points3DPtr[2] = reconstructedPoint.at<double>(2, 0) / reconstructedPoint.at<double>(3, 0);\n                    }\n                }\n                return points3D;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Eigen::Matrix<double, 3, Eigen::Dynamic>();\n            }\n        }\n\n        // // BundleAdjustmentCost not used because it was slower than differentiation by parts\n        // struct BundleAdjustmentCost\n        // {\n        //     BundleAdjustmentCost(const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic,\n        //                          const std::vector<cv::Mat>& cameraIntrinsicsCvMat,\n        //                          const Eigen::MatrixXd& BAValid) :\n        //         points2DVectorsExtrinsic(points2DVectorsExtrinsic), BAValid(BAValid)\n        //     {\n        //         numberCameras = cameraIntrinsicsCvMat.size();\n        //         if (points2DVectorsExtrinsic.size() != numberCameras)\n        //             error(\"#view of points != #camera intrinsics.\", __LINE__, __FUNCTION__, __FILE__);\n        //         numberPoints = points2DVectorsExtrinsic[0].size();\n        //         numberProjection = BAValid.sum();\n        //         for (auto cameraIndex = 0u; cameraIndex < numberCameras; cameraIndex++)\n        //         {\n        //             if (cameraIntrinsicsCvMat[cameraIndex].cols!=3 || cameraIntrinsicsCvMat[cameraIndex].rows!=3)\n        //                 error(\"Intrinsics passed in are not 3 x 3.\", __LINE__, __FUNCTION__, __FILE__);\n        //             cameraIntrinsics.resize(numberCameras);\n        //             for (auto x = 0; x < 3; x++)\n        //                 for (auto y = 0; y < 3; y++)\n        //                     cameraIntrinsics[cameraIndex](x,y) = cameraIntrinsicsCvMat[cameraIndex].at<double>(x,y);\n        //         }\n        //     }\n\n        //     template <typename T>\n        //     bool operator()(T const* const* parameters, T* residuals) const;\n\n        //     const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic;\n        //     const Eigen::MatrixXd& BAValid;\n        //     std::vector<Eigen::Matrix<double, 3, 3>> cameraIntrinsics;\n        //     uint numberCameras, numberPoints, numberProjection;\n        // };\n\n        // template <typename T>\n        // bool BundleAdjustmentCost::operator()(T const* const* parameters, T* residuals) const\n        // {\n        //     // cameraExtrinsics: angle axis + translation (6 x (#Cam - 1)), camera 0 is always [I | 0]\n        //     // pt3D: 3D points (3 x #Points)\n        //     const T* cameraExtrinsics = parameters[0];\n        //     const T* pt3D = parameters[1];\n        //     const Eigen::Map< const Eigen::Matrix<T, 3, Eigen::Dynamic> > pt3DWorld(pt3D, 3, numberPoints);\n        //     uint countProjection = 0u;\n        //     for (auto cameraIndex = 0u; cameraIndex < numberCameras; cameraIndex++)\n        //     {\n        //         Eigen::Matrix<T, 3, Eigen::Dynamic> pt3DCamera = pt3DWorld;\n        //         if (cameraIndex > 0u)\n        //         {\n        //             const Eigen::Map< const Eigen::Matrix<T, 3, 1> > translation(\n        //             cameraExtrinsics + 6 * (cameraIndex - 1) + 3);  // minus 1!\n        //             Eigen::Matrix<T, 3, 3> rotation;\n        //             ceres::AngleAxisToRotationMatrix(cameraExtrinsics + 6 * (cameraIndex - 1), rotation.data());//-1!\n        //             pt3DCamera = rotation * pt3DCamera;\n        //             pt3DCamera.colwise() += translation;\n        //         }\n        //         const Eigen::Matrix<T, 3, Eigen::Dynamic> pt2DHomogeneous = cameraIntrinsics[cameraIndex].cast<T>()\n        //                                                                   * pt3DCamera;\n        //         const Eigen::Matrix<T, 1, Eigen::Dynamic> ptx = pt2DHomogeneous.row(0).cwiseQuotient(\n        //             pt2DHomogeneous.row(2));\n        //         const Eigen::Matrix<T, 1, Eigen::Dynamic> pty = pt2DHomogeneous.row(1).cwiseQuotient(\n        //             pt2DHomogeneous.row(2));\n        //         for (auto i = 0u; i < numberPoints; i++)\n        //         {\n        //             if (!BAValid(cameraIndex, i))   // no data for this point\n        //                 continue;\n        //             residuals[2 * countProjection + 0] = ptx(0, i) - T(points2DVectorsExtrinsic[cameraIndex][i].x);\n        //             residuals[2 * countProjection + 1] = pty(0, i) - T(points2DVectorsExtrinsic[cameraIndex][i].y);\n        //             countProjection++;\n        //         }\n        //     }\n        //     // sanity check\n        //     if (countProjection != numberProjection)\n        //         error(\"Wrong number of constraints in bundle adjustment\", __LINE__, __FUNCTION__, __FILE__);\n        //     return true;\n        // }\n\n        struct BundleAdjustmentUnit\n        {\n            BundleAdjustmentUnit(const cv::Point2f& pt2d, const cv::Mat& intrinsics) :\n                pt2d{pt2d},\n                intrinsics{intrinsics}\n            {\n                if (intrinsics.cols != 3 || intrinsics.rows != 3)\n                    error(\"Intrinsics passed in are not 3 x 3.\", __LINE__, __FUNCTION__, __FILE__);\n                if (intrinsics.type() != CV_64FC1)\n                    error(\"Intrinsics passed in must be in double.\", __LINE__, __FUNCTION__, __FILE__);\n                cv::Mat pt2DHomogeneous(3, 1, CV_64FC1);\n                pt2DHomogeneous.at<double>(0, 0) = pt2d.x;\n                pt2DHomogeneous.at<double>(1, 0) = pt2d.y;\n                pt2DHomogeneous.at<double>(2, 0) = 1;\n                const cv::Mat calibrated = intrinsics.inv() * pt2DHomogeneous;\n                pt2dCalibrated.x = calibrated.at<double>(0, 0) / calibrated.at<double>(2, 0);\n                pt2dCalibrated.y = calibrated.at<double>(1, 0) / calibrated.at<double>(2, 0);\n            }\n            const cv::Point2f& pt2d;\n            const cv::Mat& intrinsics;\n            cv::Point2f pt2dCalibrated;\n\n            template <typename T>\n            bool operator()(const T* camera, const T* point, T* residuals) const\n            {\n                // camera (6): angle axis + translation4\n                // point (3): X, Y, Z\n                // residuals (2): x, y\n                T P[3];\n                ceres::AngleAxisRotatePoint(camera, point, P);\n                Eigen::Matrix<T, 3, 3, Eigen::ColMajor> R;\n                P[0] += camera[3]; P[1] += camera[4]; P[2] += camera[5];\n\n                residuals[0] = P[0] / P[2] - T(pt2dCalibrated.x);\n                residuals[1] = P[1] / P[2] - T(pt2dCalibrated.y);\n                return true;\n            }\n\n            template <typename T>\n            bool operator()(const T* point, T* residuals) const\n            {\n                // point (3): X, Y, Z\n                // residuals (2): x, y\n\n                residuals[0] = point[0] / point[2] - T(pt2dCalibrated.x);\n                residuals[1] = point[1] / point[2] - T(pt2dCalibrated.y);\n                return true;\n            }\n        };\n\n        // // Compute the Jacobian of rotation matrix w.r.t angle axis (rotation matrix in column major order)\n        // void AngleAxisToRotationMatrixDerivative(const double* pose, double* dR_data, const int idj = 0,\n        //                                          const int numberColumns = 3)\n        // {\n        //     Eigen::Map< Eigen::Matrix<double, 9, Eigen::Dynamic, Eigen::RowMajor> > dR(\n        //         dR_data, 9, numberColumns);\n        //     std::fill(dR_data, dR_data + 9 * numberColumns, 0.0);\n        //     const double theta2 = pose[0] * pose[0] + pose[1] * pose[1] + pose[2] * pose[2];\n        //     if (theta2 > std::numeric_limits<double>::epsilon())\n        //     {\n        //         const double theta = sqrt(theta2);\n        //         const double s = sin(theta);\n        //         const double c = cos(theta);\n        //         const Eigen::Map< const Eigen::Matrix<double, 3, 1> > u(pose);\n        //         Eigen::VectorXd e(3);\n        //         e[0] = pose[0] / theta; e[1] = pose[1] / theta; e[2] = pose[2] / theta;\n\n        //         // dR / dtheta\n        //         Eigen::Matrix<double, 9, 1> dRdth(9, 1);\n        //         Eigen::Map< Eigen::Matrix<double, 3, 3, Eigen::RowMajor> > dRdth_(dRdth.data());\n        //         // skew symmetric\n        //         dRdth_ << 0.0, -e[2], e[1],\n        //                   e[2], 0.0, -e[0],\n        //                   -e[1], e[0], 0.0;\n        //         // dRdth_ = dRdth_ * c - Matrix<double, 3, 3>::Identity() * s + s * e * e.transpose();\n        //         dRdth_ = - dRdth_ * c - Eigen::Matrix<double, 3, 3>::Identity() * s + s * e * e.transpose();\n\n        //         // dR / de\n        //         Eigen::Matrix<double, 9, 3, Eigen::RowMajor> dRde(9, 3);\n        //         // d(ee^T) / de\n        //         dRde <<\n        //             2 * e[0], 0., 0.,\n        //             e[1], e[0], 0.,\n        //             e[2], 0., e[0],\n        //             e[1], e[0], 0.,\n        //             0., 2 * e[1], 0.,\n        //             0., e[2], e[1],\n        //             e[2], 0., e[0],\n        //             0., e[2], e[1],\n        //             0., 0., 2 * e[2];\n        //         Eigen::Matrix<double, 9, 3, Eigen::RowMajor> dexde(9, 3);\n        //         dexde <<\n        //             0, 0, 0,\n        //             0, 0, -1,\n        //             0, 1, 0,\n        //             0, 0, 1,\n        //             0, 0, 0,\n        //             -1, 0, 0,\n        //             0, -1, 0,\n        //             1, 0, 0,\n        //             0, 0, 0;\n        //         // dRde = dRde * (1. - c) + c * dexde;\n        //         dRde = dRde * (1. - c) - s * dexde;\n        //         Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> dedu\n        //             = Eigen::Matrix<double, 3, 3>::Identity() / theta - u * u.transpose() / theta2 / theta;\n\n        //         dR.block(0, 3 * idj, 9, 3) = dRdth * e.transpose() + dRde * dedu;\n        //     }\n        //     else\n        //     {\n        //         dR(1, 3 * idj + 2) = 1;\n        //         dR(2, 3 * idj + 1) = -1;\n        //         dR(3, 3 * idj + 2) = -1;\n        //         dR(5, 3 * idj) = 1;\n        //         dR(6, 3 * idj + 1) = 1;\n        //         dR(7, 3 * idj) = -1;\n        //     }\n        // }\n\n        // // Compute the derivative w.r.t AB from dA\n        // void SparseProductDerivative(const double* const dA_data, const double* const B_data,\n        //                              const std::vector<int>& parentIndexes, double* dAB_data,\n        //                              const int numberColumns = 3)\n        // {\n        //     // d(AB) = AdB + (dA)B\n        //     // Sparse for loop form\n        //     std::fill(dAB_data, dAB_data + 3 * numberColumns, 0.0);\n        //     for (int r = 0; r < 3; r++)\n        //     {\n        //         const int baseIndex = 3*r;\n        //         for (const auto& parentIndex : parentIndexes)\n        //         {\n        //             const auto parentOffset = 3*parentIndex;\n        //             for (int subIndex = 0; subIndex < 3; subIndex++)\n        //             {\n        //                 const auto finalOffset = parentOffset + subIndex;\n        //                 dAB_data[numberColumns*r + finalOffset] +=\n        //                     B_data[0] * dA_data[numberColumns*baseIndex + finalOffset]\n        //                     + B_data[1] * dA_data[numberColumns*(baseIndex+1) + finalOffset]\n        //                     + B_data[2] * dA_data[numberColumns*(baseIndex+2) + finalOffset];\n        //             }\n        //         }\n        //     }\n        // }\n\n        // // BundleAdjustmentUnitJacobian not used because it was slower than automatic differentiation\n        // class BundleAdjustmentUnitJacobian : public ceres::CostFunction\n        // {\n        // public:\n        //     BundleAdjustmentUnitJacobian(const cv::Point2f& pt2d, const cv::Mat& intrinsics, const bool solveExt) :\n        //         pt2d(pt2d), intrinsics(intrinsics), solveExt(solveExt)\n        //     {\n        //         if (intrinsics.cols != 3 || intrinsics.rows != 3)\n        //             error(\"Intrinsics passed in are not 3 x 3.\", __LINE__, __FUNCTION__, __FILE__);\n        //         if (intrinsics.type() != CV_64FC1)\n        //             error(\"Intrinsics passed in must be in double.\", __LINE__, __FUNCTION__, __FILE__);\n\n        //         cv::Mat pt2DHomogeneous(3, 1, CV_64FC1);\n        //         pt2DHomogeneous.at<double>(0, 0) = pt2d.x;\n        //         pt2DHomogeneous.at<double>(1, 0) = pt2d.y;\n        //         pt2DHomogeneous.at<double>(2, 0) = 1;\n        //         const cv::Mat calibrated = intrinsics.inv() * pt2DHomogeneous;\n        //         pt2dCalibrated.x = calibrated.at<double>(0, 0) / calibrated.at<double>(2, 0);\n        //         pt2dCalibrated.y = calibrated.at<double>(1, 0) / calibrated.at<double>(2, 0);\n\n        //         CostFunction::set_num_residuals(2);\n        //         auto parameter_block_sizes = CostFunction::mutable_parameter_block_sizes();\n        //         parameter_block_sizes->clear();\n        //         if (solveExt) parameter_block_sizes->push_back(6); // camera extrinsics\n        //         parameter_block_sizes->push_back(3);  // 3D points\n        //     }\n\n        //     virtual bool Evaluate(double const* const* parameters, double* residuals, double** jacobians) const\n        //     {\n        //         double P[3];\n        //         const double* ptr = solveExt ? P : parameters[0];\n        //         if (solveExt)\n        //         {\n        //             const double* camera = parameters[0];\n        //             ceres::AngleAxisRotatePoint(camera, parameters[1], P);\n        //             P[0] += camera[3]; P[1] += camera[4]; P[2] += camera[5];\n        //         }\n\n        //         residuals[0] = ptr[0] / ptr[2] - pt2dCalibrated.x;\n        //         residuals[1] = ptr[1] / ptr[2] - pt2dCalibrated.y;\n\n        //         if (jacobians)\n        //         {\n        //             // Q = RP + t, L = [Lx ; Ly], Lx = Qx / Qz, Ly = Qy / Qz\n        //             Eigen::Matrix<double, 2, 3, Eigen::RowMajor> dQ;\n        //             // x = X / Z -> dx/dX = 1/Z, dx/dY = 0, dx/dZ = -X / Z^2;\n        //             dQ.data()[0] = 1 / ptr[2];\n        //             dQ.data()[1] = 0;\n        //             dQ.data()[2] = -ptr[0] / ptr[2] / ptr[2];\n        //             // y = Y / Z -> dy/dX = 0, dy/dY = 1/Z, dy/dZ = -Y / Z^2;\n        //             dQ.data()[3] = 0;\n        //             dQ.data()[4] = 1 / ptr[2];\n        //             dQ.data()[5] = -ptr[1] / ptr[2] / ptr[2];\n\n        //             if (solveExt)\n        //             {\n        //                 if (jacobians[0])   // Jacobian of output [x, y] w.r.t. input [angle axis, translation]\n        //                 {\n        //                     Eigen::Map< Eigen::Matrix<double, 2, 6, Eigen::RowMajor> > dRt(jacobians[0]);\n        //                     // dt\n        //                     dRt.block<2, 3>(0, 3) = dQ;\n        //                     // dL/dR = dL/dQ * dQ/dR * dR/d(\\theta)\n        //                     Eigen::Matrix<double, 9, 3, Eigen::RowMajor> dRdtheta;\n        //                     AngleAxisToRotationMatrixDerivative(parameters[0], dRdtheta.data());\n        //                     // switch from column major (R) to row major\n        //                     Eigen::Matrix<double, 1, 3> tmp = dRdtheta.row(1);\n        //                     dRdtheta.row(1) = dRdtheta.row(3);\n        //                     dRdtheta.row(3) = tmp;\n        //                     tmp = dRdtheta.row(2);\n        //                     dRdtheta.row(2) = dRdtheta.row(6);\n        //                     dRdtheta.row(6) = tmp;\n        //                     tmp = dRdtheta.row(5);\n        //                     dRdtheta.row(5) = dRdtheta.row(7);\n        //                     dRdtheta.row(7) = tmp;\n        //                     Eigen::Matrix<double, 3, 3, Eigen::RowMajor> dQdtheta;\n        //                     SparseProductDerivative(\n        //                         dRdtheta.data(), parameters[1], std::vector<int>(1, 0), dQdtheta.data());\n        //                     dRt.block<2, 3>(0, 0) = dQ * dQdtheta;\n        //                 }\n        //                 if (jacobians[1])   // Jacobian of output [x, y] w.r.t input [X, Y, Z]\n        //                 {\n        //                     // dL/dP = dL/dQ * dQ/dP = dL/dQ * R\n        //                     Eigen::Matrix<double, 3, 3> R;\n        //                     ceres::AngleAxisToRotationMatrix(parameters[0], R.data());\n        //                     Eigen::Map< Eigen::Matrix<double, 2, 3, Eigen::RowMajor> > dP(jacobians[1]);\n        //                     dP = dQ * R;\n        //                 }\n        //             }\n        //             else\n        //             {\n        //                 if (jacobians[0])   // Jacobian of output [x, y] w.r.t input [X, Y, Z]\n        //                     std::copy(dQ.data(), dQ.data() + 6, jacobians[0]);\n        //             }\n        //         }\n        //         return true;\n        //     }\n        // private:\n        //     const cv::Point2f& pt2d;\n        //     cv::Point2f pt2dCalibrated;\n        //     const cv::Mat& intrinsics;\n        //     const bool solveExt;\n        // };\n\n        void runBundleAdjustment(\n            std::vector<cv::Mat>& refinedExtrinsics, Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D,\n            const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, const Eigen::MatrixXd& BAValid,\n            const std::vector<cv::Mat>& cameraIntrinsics, const int numberCameras)\n        {\n            try\n            {\n                // Sanity check\n                auto normCam0Identity = cv::norm(\n                    refinedExtrinsics[0] - cv::Mat::eye(3, 4, refinedExtrinsics[0].type()));\n                if (normCam0Identity > 1e-9) // std::cout prints exactly 0\n                    error(\"Camera 0 should be [I, 0] for this algorithm to run. Norm cam0-[I,0] = \"\n                          + std::to_string(normCam0Identity), __LINE__, __FUNCTION__, __FILE__);\n                // Prepare the camera extrinsics\n                Eigen::Matrix<double, 6, Eigen::Dynamic> cameraRt(6, numberCameras); // Angle axis + translation\n                for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n                {\n                    cameraRt.data()[6 * cameraIndex + 3] = refinedExtrinsics[cameraIndex].at<double>(0, 3);\n                    cameraRt.data()[6 * cameraIndex + 4] = refinedExtrinsics[cameraIndex].at<double>(1, 3);\n                    cameraRt.data()[6 * cameraIndex + 5] = refinedExtrinsics[cameraIndex].at<double>(2, 3);\n                    Eigen::Matrix<double, 3, 3> rotation;   // Column major!\n                    for (auto x = 0; x < 3; x++)\n                        for (auto y = 0; y < 3; y++)\n                            rotation(x, y) = refinedExtrinsics[cameraIndex].at<double>(x, y);\n                    ceres::RotationMatrixToAngleAxis(rotation.data(), cameraRt.data() + 6 * cameraIndex);\n                }\n                ceres::Problem problem;\n                ceres::Solver::Options options;\n                // options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;\n                // options.linear_solver_type = ceres::DENSE_QR;\n                options.linear_solver_type = ceres::DENSE_SCHUR;\n                options.use_nonmonotonic_steps = true;\n                options.minimizer_progress_to_stdout = true;\n                options.num_threads = 1;\n                // // Option 1/3) Computing things together\n                // const int numResiduals = 2 * BAValid.sum();  // x and y\n                // BundleAdjustmentCost* ptr_BA = new BundleAdjustmentCost(\n                //     points2DVectorsExtrinsic, cameraIntrinsics, BAValid);\n                // ceres::DynamicAutoDiffCostFunction<BundleAdjustmentCost>* costFunction\n                //     = new ceres::DynamicAutoDiffCostFunction<BundleAdjustmentCost>(ptr_BA);\n                // costFunction->AddParameterBlock(6 * (numberCameras - 1));  // R + t\n                // costFunction->AddParameterBlock(3 * points2DVectorsExtrinsic[0].size());\n                // costFunction->SetNumResiduals(numResiduals);\n                // problem.AddResidualBlock(\n                //     costFunction, new ceres::HuberLoss(2.0), cameraRt.data() + 6, points3D.data());\n                // Option 2/3) Computing things separately (automatic differentiation)\n                for (auto cameraIndex = 0; cameraIndex < numberCameras; cameraIndex++)\n                {\n                    if (cameraIndex != 0u)\n                    {\n                        for (auto i = 0u; i < points2DVectorsExtrinsic[cameraIndex].size(); i++)\n                        {\n                            if (!BAValid(cameraIndex, i)) continue;\n                            BundleAdjustmentUnit* ptr_BA = new BundleAdjustmentUnit(\n                                points2DVectorsExtrinsic[cameraIndex][i], cameraIntrinsics[cameraIndex]);\n                            auto* costFunction = new ceres::AutoDiffCostFunction<BundleAdjustmentUnit, 2, 6, 3>(\n                                ptr_BA);\n                            problem.AddResidualBlock(\n                                costFunction, new ceres::HuberLoss(2.0), cameraRt.data() + 6 * cameraIndex,\n                                points3D.data() + 3 * i);\n                        }\n                    }\n                    else\n                    {\n                        for (auto i = 0u; i < points2DVectorsExtrinsic[cameraIndex].size(); i++)\n                        {\n                            if (!BAValid(cameraIndex, i)) continue;\n                            BundleAdjustmentUnit* ptr_BA = new BundleAdjustmentUnit(\n                                points2DVectorsExtrinsic[cameraIndex][i], cameraIntrinsics[cameraIndex]);\n                            auto* costFunction = new ceres::AutoDiffCostFunction<BundleAdjustmentUnit, 2, 3>(ptr_BA);\n                            problem.AddResidualBlock(costFunction, new ceres::HuberLoss(2.0), points3D.data() + 3 * i);\n                        }\n                    }\n                }\n                // No need to delete ptr_BA or costFunction; Ceres::Problem takes care of them.\n                // // Option 3/3) Computing things separately (manual differentiation)\n                // for (auto cameraIndex = 0; cameraIndex < numberCameras; cameraIndex++)\n                // {\n                //     if (cameraIndex != 0u)\n                //         for (auto i = 0u; i < points2DVectorsExtrinsic[cameraIndex].size(); i++)\n                //         {\n                //             if (!BAValid(cameraIndex, i)) continue;\n                //             ceres::CostFunction* costFunction = new BundleAdjustmentUnitJacobian(\n                //                 points2DVectorsExtrinsic[cameraIndex][i], cameraIntrinsics[cameraIndex], true);\n                //             problem.AddResidualBlock(\n                //                 costFunction, new ceres::HuberLoss(2.0), cameraRt.data() + 6 * cameraIndex,\n                //                 points3D.data() + 3 * i);\n                //         }\n                //     else\n                //         for (auto i = 0u; i < points2DVectorsExtrinsic[cameraIndex].size(); i++)\n                //         {\n                //             if (!BAValid(cameraIndex, i)) continue;\n                //             ceres::CostFunction* costFunction = new BundleAdjustmentUnitJacobian(\n                //                 points2DVectorsExtrinsic[cameraIndex][i], cameraIntrinsics[cameraIndex], false);\n                //             problem.AddResidualBlock(costFunction, new ceres::HuberLoss(2.0), points3D.data() + 3 * i);\n                //         }\n                // }\n                // Ceres verbose\n                ceres::Solver::Summary summary;\n                ceres::Solve(options, &problem, &summary);\n                opLog(summary.FullReport(), Priority::High);\n                // Sanity check\n                normCam0Identity = cv::norm(\n                    refinedExtrinsics[0] - cv::Mat::eye(3, 4, refinedExtrinsics[0].type()));\n                if (normCam0Identity > 1e-9) // std::cout prints exactly 0\n                    error(\"Camera 0 should not be modified by our implementation of bundle adjustment, notify us!\"\n                          \" Norm: \" + std::to_string(normCam0Identity), __LINE__, __FUNCTION__, __FILE__);\n                // The first one should be [I | 0] and it is not modified by our Ceres optimization\n                for (auto cameraIndex = 1 ; cameraIndex < numberCameras ; cameraIndex++)\n                {\n                    cv::Mat extrinsics(3, 4, refinedExtrinsics[0].type());\n                    extrinsics.at<double>(0, 3) = cameraRt.data()[6 * cameraIndex + 3];\n                    extrinsics.at<double>(1, 3) = cameraRt.data()[6 * cameraIndex + 4];\n                    extrinsics.at<double>(2, 3) = cameraRt.data()[6 * cameraIndex + 5];\n                    Eigen::Matrix<double, 3, 3> rotation;\n                    ceres::AngleAxisToRotationMatrix(cameraRt.data() + 6 * cameraIndex, rotation.data());\n                    for (auto x = 0; x < 3; x++)\n                        for (auto y = 0; y < 3; y++)\n                            extrinsics.at<double>(x, y) = rotation(x, y);\n                    refinedExtrinsics[cameraIndex] = extrinsics;\n                }\n                const auto reprojectionError = computeReprojectionErrorInPixels(\n                    points2DVectorsExtrinsic, BAValid, points3D, refinedExtrinsics, cameraIntrinsics);\n                opLog(\"Reprojection Error (after Bundle Adjustment): \" + std::to_string(reprojectionError)\n                    + \" pixels.\", Priority::High);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void rescaleExtrinsicsAndPoints3D(\n            std::vector<cv::Mat>& refinedExtrinsics, Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D,\n            const std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, const Eigen::MatrixXd& BAValid,\n            const std::vector<cv::Mat>& cameraIntrinsics, const int numberCameras, const int numberCorners,\n            const float gridSquareSizeMm, const Point<int>& gridInnerCorners)\n        {\n            try\n            {\n                // Rescale the 3D points and translation based on the grid size\n                if (points2DVectorsExtrinsic[0].size() % numberCorners != 0)\n                    error(\"The number of points should be divided by number of corners in the image.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                const int numTimeStep = points2DVectorsExtrinsic[0].size() / numberCorners;\n                double sumLength = 0.;\n                double sumSquareLength = 0.;\n                double maxLength = -1.;\n                double minLength = std::numeric_limits<double>::max();\n                for (auto t = 0; t < numTimeStep; t++)\n                {\n                    // Horizontal edges\n                    for (auto x = 0; x < gridInnerCorners.x - 1; x++)\n                        for (auto y = 0; y < gridInnerCorners.y; y++)\n                        {\n                            const int startPerFrame = x + y * gridInnerCorners.x;\n                            const int startIndex = startPerFrame + t * numberCorners;\n                            const int endPerFrame = x + 1 + y * gridInnerCorners.x;\n                            const int endIndex = endPerFrame + t * numberCorners;\n                            // These points are used for BA, must have been constructed.\n                            if (BAValid.col(startIndex).any() && BAValid.col(endIndex).any())\n                            {\n                                const double length = (points3D.col(startIndex) - points3D.col(endIndex)).norm();\n                                sumSquareLength += length * length;\n                                sumLength += length;\n                                if (length < minLength)\n                                    minLength = length;\n                                if (length > maxLength)\n                                    maxLength = length;\n                            }\n                        }\n\n                    // Vertical edges\n                    for (auto x = 0; x < gridInnerCorners.x; x++)\n                        for (auto y = 0; y < gridInnerCorners.y - 1; y++)\n                        {\n                            const int startPerFrame = x + y * gridInnerCorners.x;\n                            const int startIndex = startPerFrame + t * numberCorners;\n                            const int endPerFrame = x + (y + 1) * gridInnerCorners.x;\n                            const int endIndex = endPerFrame + t * numberCorners;\n                            // These points are used for BA, must have been constructed.\n                            if (BAValid.col(startIndex).any() && BAValid.col(endIndex).any())\n                            {\n                                const double length = (points3D.col(startIndex) - points3D.col(endIndex)).norm();\n                                sumSquareLength += length * length;\n                                sumLength += length;\n                                if (length < minLength)\n                                    minLength = length;\n                                if (length > maxLength)\n                                    maxLength = length;\n                            }\n                        }\n                }\n                const double scalingFactor = 0.001f * gridSquareSizeMm * sumLength / sumSquareLength;\n                opLog(\"Scaling factor: \" + std::to_string(scalingFactor) + \",\\tMin grid length: \"\n                    + std::to_string(minLength) + \",\\tMax grid length: \" + std::to_string(maxLength), Priority::High);\n                // Scale extrinsics: Scale the translation (and the 3D point)\n                for (auto cameraIndex = 1; cameraIndex < numberCameras; cameraIndex++)\n                {\n                    refinedExtrinsics[cameraIndex].at<double>(0, 3) *= scalingFactor;\n                    refinedExtrinsics[cameraIndex].at<double>(1, 3) *= scalingFactor;\n                    refinedExtrinsics[cameraIndex].at<double>(2, 3) *= scalingFactor;\n                }\n                // Scale 3D points\n                points3D *= scalingFactor;\n                // Final reprojection error\n                const auto reprojectionError = computeReprojectionErrorInPixels(\n                    points2DVectorsExtrinsic, BAValid, points3D, refinedExtrinsics, cameraIntrinsics);\n                opLog(\"Reprojection Error (after rescaling): \" + std::to_string(reprojectionError) + \" pixels.\",\n                    Priority::High);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void runBundleAdjustmentWithOutlierRemoval(\n            std::vector<cv::Mat>& refinedExtrinsics, Eigen::Matrix<double, 3, Eigen::Dynamic>& points3D,\n            std::vector<std::vector<cv::Point2f>>& points2DVectorsExtrinsic, Eigen::MatrixXd& BAValid,\n            const std::vector<cv::Mat>& cameraIntrinsics, const int numberCameras, const double pixelThreshold,\n            const bool printInitialReprojection)\n        {\n            try\n            {\n                // Update inliers & outliers\n                BAValid = getInlierAndOutliers(points2DVectorsExtrinsic);\n\n                // Initial reprojection error\n                if (printInitialReprojection)\n                {\n                    const auto reprojectionError = computeReprojectionErrorInPixels(\n                        points2DVectorsExtrinsic, BAValid, points3D, refinedExtrinsics, cameraIntrinsics);\n                    opLog(\"Reprojection Error (initial): \" + std::to_string(reprojectionError), Priority::High);\n                    opLog(\" \", Priority::High);\n                }\n\n                // Outlier removal\n                opLog(\"Applying outlier removal...\", Priority::High);\n                removeOutliersReprojectionErrorIterative(\n                    points2DVectorsExtrinsic, BAValid, points3D, refinedExtrinsics, cameraIntrinsics, pixelThreshold);\n                opLog(\" \", Priority::High);\n\n                // Bundle Adjustment\n                opLog(\"Running bundle adjustment...\", Priority::High);\n                runBundleAdjustment(\n                    refinedExtrinsics, points3D, points2DVectorsExtrinsic, BAValid, cameraIntrinsics, numberCameras);\n                opLog(\" \", Priority::High);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void cameraXAsOrigin(\n            std::vector<cv::Mat>& cameraExtrinsics, cv::Mat& cameraOriginInv, const cv::Mat& cameraOrigin)\n        {\n            try\n            {\n                // Extrinsics = cameraOrigin will turn into [I | 0]\n                // All the others are transformed accordingly by multiplying them by inv(cameraOrigin)\n                cameraOriginInv = cv::Mat::eye(4, 4, cameraOrigin.type());\n                for (auto i = 0 ; i < 3 ; i++)\n                    for (auto j = 0 ; j < 4 ; j++)\n                        cameraOriginInv.at<double>(i, j) = cameraOrigin.at<double>(i, j);\n                cameraOriginInv = cameraOriginInv.inv();\n                for (auto& cameraExtrinsic : cameraExtrinsics)\n                    cameraExtrinsic = cameraExtrinsic * cameraOriginInv;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    void refineAndSaveExtrinsics(\n        const std::string& parameterFolder, const std::string& imageFolder, const Point<int>& gridInnerCorners,\n        const float gridSquareSizeMm, const int numberCameras, const bool imagesAreUndistorted,\n        const bool saveImagesWithCorners)\n    {\n        try\n        {\n            #if defined(USE_CERES) && defined(USE_EIGEN)\n                // Debugging\n                const auto saveVisualSFMFiles = false;\n                // const auto saveVisualSFMFiles = true;\n\n                // Sanity check\n                if (!imagesAreUndistorted)\n                    error(\"This mode assumes that the images are already undistorted (add flag `--omit_distortion`).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                opLog(\"Loading images...\", Priority::High);\n                const auto imageAndPaths = getImageAndPaths(imageFolder);\n                opLog(\"Images loaded.\", Priority::High);\n\n                // Point<int> --> cv::Size\n                const cv::Size gridInnerCornersCvSize{gridInnerCorners.x, gridInnerCorners.y};\n\n                // Load parameters (distortion, intrinsics, initial extrinsics)\n                opLog(\"Loading parameters...\", Priority::High);\n                CameraParameterReader cameraParameterReader;\n                cameraParameterReader.readParameters(parameterFolder);\n                const auto opCameraExtrinsicsInitial = cameraParameterReader.getCameraExtrinsicsInitial();\n                // Sanity check\n                if (opCameraExtrinsicsInitial.empty())\n                    error(\"Camera intrinsics could not be loaded from \" + parameterFolder\n                        + \". Are they in the right path? Remember than the XML must contain the right intrinsic\"\n                        + \" parameters before using this function. \", __LINE__, __FUNCTION__, __FILE__);\n                bool initialEmpty = false;\n                for (const auto& cameraExtrinsicInitial : opCameraExtrinsicsInitial)\n                {\n                    if (cameraExtrinsicInitial.empty())\n                    {\n                        initialEmpty = true;\n                        break;\n                    }\n                }\n                opLog(\"Parameters loaded.\", Priority::High);\n                // Camera extrinsics\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                auto opCameraExtrinsics = (initialEmpty\n                    ? cameraParameterReader.getCameraExtrinsics() : opCameraExtrinsicsInitial);\n                OP_OP2CVVECTORMAT(cameraExtrinsics, opCameraExtrinsics)\n                // The first one should be [I | 0]: Multiply them all by inv(camera 0 extrinsics)\n                cv::Mat cameraOriginInv;\n                cameraXAsOrigin(cameraExtrinsics, cameraOriginInv, cameraExtrinsics.at(0).clone());\n                // Camera intrinsics and distortion\n                const auto opCameraIntrinsics = cameraParameterReader.getCameraIntrinsics();\n                OP_OP2CVVECTORMAT(cameraIntrinsics, opCameraIntrinsics);\n                const auto cameraDistortions = (\n                    imagesAreUndistorted\n                    ? std::vector<Matrix>{cameraIntrinsics.size()} : cameraParameterReader.getCameraDistortions());\n                // Read images in folder\n                opLog(\"Reading images in folder...\", Priority::High);\n                const auto numberCorners = gridInnerCorners.area();\n                std::vector<std::vector<cv::Point2f>> points2DVectorsExtrinsic(numberCameras); // camera - keypoints\n                std::vector<std::vector<unsigned int>> matchIndexes(numberCameras); // camera - indixes found\n                if (imageAndPaths.empty())\n                    error(\"imageAndPaths.empty()!.\", __LINE__, __FUNCTION__, __FILE__);\n                opLog(\"Images read.\", Priority::High);\n                // Get 2D grid corners of each image\n                std::vector<cv::Mat> imagesWithCorners;\n                const auto imageSize = imageAndPaths.at(0).first.size();\n                const auto numberViews = (unsigned int)(imageAndPaths.size() / numberCameras);\n                opLog(\"Processing cameras...\", Priority::High);\n                std::vector<std::thread> threads;\n                for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n                {\n                    auto* points2DExtrinsic = &points2DVectorsExtrinsic[cameraIndex];\n                    auto* matchIndexesCamera = &matchIndexes[cameraIndex];\n                    // Threaded version\n                    threads.emplace_back(estimateAndSaveSiftFileSubThread, points2DExtrinsic,\n                                         matchIndexesCamera, cameraIndex, numberCameras,\n                                         numberCorners, numberViews, saveImagesWithCorners, imageFolder,\n                                         gridInnerCornersCvSize, imageSize, imageAndPaths, saveVisualSFMFiles);\n                    // // Non-threaded version\n                    // estimateAndSaveSiftFileSubThread(points2DExtrinsic, matchIndexesCamera, cameraIndex, numberCameras,\n                    //                                  numberCorners, numberViews, saveImagesWithCorners, imageFolder,\n                    //                                  gridInnerCornersCvSize, imageSize, imageAndPaths,\n                    //                                  saveVisualSFMFiles);\n                }\n                // Threaded version\n                for (auto& thread : threads)\n                    if (thread.joinable())\n                        thread.join();\n\n                // Matching file\n                if (saveVisualSFMFiles)\n                {\n                    std::ofstream ofstreamMatches{\n                        getFileParentFolderPath(imageAndPaths.at(0).second) + \"FeatureMatches.txt\"};\n                    for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n                    {\n                        for (auto cameraIndex2 = cameraIndex+1 ; cameraIndex2 < numberCameras ; cameraIndex2++)\n                        {\n                            std::vector<unsigned int> matchIndexesIntersection;\n                            std::set_intersection(matchIndexes[cameraIndex].begin(), matchIndexes[cameraIndex].end(),\n                                                  matchIndexes[cameraIndex2].begin(), matchIndexes[cameraIndex2].end(),\n                                                  std::back_inserter(matchIndexesIntersection));\n\n                            ofstreamMatches << getFileNameFromCameraIndex(cameraIndex) << \".jpg\"\n                                            << \" \" << getFileNameFromCameraIndex(cameraIndex2) << \".jpg\"\n                            // ofstreamMatches << getFileNameAndExtension(imageAndPaths.at(cameraIndex).second)\n                            //                 << \" \" << getFileNameAndExtension(imageAndPaths.at(cameraIndex2).second)\n                                            << \" \" << matchIndexesIntersection.size() << \"\\n\";\n                            for (auto reps = 0 ; reps < 2 ; reps++)\n                            {\n                                for (auto i = 0u ; i < matchIndexesIntersection.size() ; i++)\n                                    ofstreamMatches << matchIndexesIntersection[i] << \" \";\n                                ofstreamMatches << \"\\n\";\n                            }\n                            ofstreamMatches << \"\\n\";\n                        }\n                    }\n                }\n                // ofstreamMatches.close();\n                opLog(\"Number points (i.e., timestamps) fully obtained: \"\n                    + std::to_string(points2DVectorsExtrinsic[0].size()), Priority::High);\n                opLog(\"Number views (i.e., cameras) fully obtained: \"\n                    + std::to_string(points2DVectorsExtrinsic[0].size() / numberCorners), Priority::High);\n                opLog(\" \", Priority::High);\n\n                // Sanity check\n                for (auto i = 1 ; i < numberCameras ; i++)\n                    if (points2DVectorsExtrinsic[i].size() != points2DVectorsExtrinsic[0].size())\n                        error(\"Something went wrong. Notify us:\"\n                              \" points2DVectorsExtrinsic[i].size() != points2DVectorsExtrinsic[0].size().\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                // Note:\n                // Extrinsics for each camera: std::vector<cv::Mat> cameraExtrinsics (translation in meters)\n                // Intrinsics for each camera: std::vector<cv::Mat> cameraIntrinsics\n                // Distortions assumed to be 0 (for now...)\n                // 3D coordinates: gridSquareSizeMm (in mm not meters!) is the size of each chessboard square side\n                // 2D coordinates:\n                //     - matchIndexes[cameraIndex] are the coordinates matched (so found) in camera cameraIndex.\n                //     - matchIndexesIntersection shows you how to get the intersection of 2 pair of cameras.\n                //     - points2DVectorsExtrinsic[cameraIndex] has the 2D coordinates of the chessboard for camera\n                //       cameraIndex.\n                // Please, do not make changes to the code above this line (unless you ask me first), given that this code\n                // is the same than VisualSFM uses, so we can easily compare results with both of them. If you wanna\n                // re-write the 2D matching format, just modify it or duplicate it, but do not remove or edit\n                // `matchIndexesIntersection`.\n                // Last note: For quick debugging, set saveVisualSFMFiles = true and check the generated FeatureMatches.txt\n                // (note that *.sift files are actually in binary format, so quite hard to read.)\n\n                opLog(\"Estimating initial 3D points...\", Priority::High);\n                // Run triangulation to obtain the initial 3D points\n                const auto initialPoints3D = reconstruct3DPoints(\n                    points2DVectorsExtrinsic, cameraIntrinsics, cameraExtrinsics, numberCameras, imageSize);\n\n                auto refinedExtrinsics = cameraExtrinsics;\n                auto points3D = initialPoints3D;\n                Eigen::MatrixXd BAValid;\n\n                // Update inliers & outliers + Outlier removal + Bundle Adjustment with 1.0 threshold\n                runBundleAdjustmentWithOutlierRemoval(\n                    refinedExtrinsics, points3D, points2DVectorsExtrinsic, BAValid, cameraIntrinsics,\n                    numberCameras, 1.0, true);\n\n                // Update inliers & outliers + Outlier removal + Bundle Adjustment with 0.5 threshold\n                runBundleAdjustmentWithOutlierRemoval(\n                    refinedExtrinsics, points3D, points2DVectorsExtrinsic, BAValid, cameraIntrinsics,\n                    numberCameras, 0.5, false);\n\n                // Rescale the 3D points and translation based on the grid size\n                rescaleExtrinsicsAndPoints3D(\n                    refinedExtrinsics, points3D, points2DVectorsExtrinsic, BAValid, cameraIntrinsics, numberCameras,\n                    numberCorners, gridSquareSizeMm, gridInnerCorners);\n\n                // Revert back to refinedExtrinsics[0] = cameraExtrinsics[0] (rather than [I,0])\n                // Note: Given that inv([R,t;0,1]) is another [R',t';0,1], scaling is maintained\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                cv::Mat cameraOriginInv2;\n                cameraXAsOrigin(refinedExtrinsics, cameraOriginInv2, cameraOriginInv);\n                // Sanity check\n                auto normCam0Identity = cv::norm(refinedExtrinsics[0] - cameraExtrinsics[0]);\n                if (normCam0Identity > 1e-9) // std::cout prints exactly 0\n                    error(\"Unexpected error, notify us. Norm difference: \"\n                          + std::to_string(normCam0Identity), __LINE__, __FUNCTION__, __FILE__);\n\n                // Final projection matrix\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                opLog(\"\\nFinal projection matrix w.r.t. global origin (meters):\", Priority::High);\n                for (auto cameraIndex = 0; cameraIndex < numberCameras; cameraIndex++)\n                {\n                    opLog(\"Camera \" + std::to_string(cameraIndex) + \":\", Priority::High);\n                    opLog(refinedExtrinsics[cameraIndex], Priority::High);\n                    // opLog(\"Initial camera \" + std::to_string(cameraIndex) + \":\", Priority::High);\n                    // opLog(cameraExtrinsics[cameraIndex], Priority::High);\n                    const auto normDifference = cv::norm(\n                        refinedExtrinsics[cameraIndex] - cameraExtrinsics[cameraIndex]);\n                    opLog(\"Norm difference w.r.t. original extrinsics: \" + std::to_string(normDifference),\n                        Priority::High);\n                }\n\n                // Save new extrinsics\n                opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                const auto cameraSerialNumbers = cameraParameterReader.getCameraSerialNumbers();\n                const auto opRealCameraDistortions = cameraParameterReader.getCameraDistortions();\n                for (auto i = 0 ; i < numberCameras ; i++)\n                {\n                    CameraParameterReader cameraParameterReaderFinal{\n                        cameraSerialNumbers.at(i),\n                        OP_CV2OPCONSTMAT(cameraIntrinsics.at(i)),\n                        opRealCameraDistortions.at(i),\n                        OP_CV2OPCONSTMAT(refinedExtrinsics.at(i)),\n                        (initialEmpty ? OP_CV2OPCONSTMAT(cameraExtrinsics.at(i)) : opCameraExtrinsicsInitial.at(i))};\n                    cameraParameterReaderFinal.writeParameters(parameterFolder);\n                }\n                opLog(\" \", Priority::High);\n            #else\n                UNUSED(parameterFolder);\n                UNUSED(imageFolder);\n                UNUSED(gridInnerCorners);\n                UNUSED(gridSquareSizeMm);\n                UNUSED(numberCameras);\n                UNUSED(imagesAreUndistorted);\n                UNUSED(saveImagesWithCorners);\n                error(\"CMake flags `USE_CERES` and `USE_EIGEN` required when compiling OpenPose`.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void estimateAndSaveSiftFile(const Point<int>& gridInnerCorners, const std::string& imageFolder,\n                                 const int numberCameras, const bool saveImagesWithCorners)\n    {\n        try\n        {\n            opLog(\"Loading images...\", Priority::High);\n            const auto imageAndPaths = getImageAndPaths(imageFolder);\n            opLog(\"Images loaded.\", Priority::High);\n\n            // Point<int> --> cv::Size\n            const cv::Size gridInnerCornersCvSize{gridInnerCorners.x, gridInnerCorners.y};\n\n            // Read images in folder\n            const auto numberCorners = gridInnerCorners.area();\n            std::vector<std::vector<cv::Point2f>> points2DVectorsExtrinsic(numberCameras); // camera - keypoints\n            std::vector<std::vector<unsigned int>> matchIndexes(numberCameras); // camera - indixes found\n            if (imageAndPaths.empty())\n                error(\"imageAndPaths.empty()!.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Get 2D grid corners of each image\n            std::vector<cv::Mat> imagesWithCorners;\n            const auto imageSize = imageAndPaths.at(0).first.size();\n            const auto numberViews = (unsigned int)(imageAndPaths.size() / numberCameras);\n            opLog(\"Processing cameras...\", Priority::High);\n            std::vector<std::thread> threads;\n            for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n            {\n                auto* points2DExtrinsic = &points2DVectorsExtrinsic[cameraIndex];\n                auto* matchIndexesCamera = &matchIndexes[cameraIndex];\n                // Threaded version\n                const auto saveSIFTFile = true;\n                threads.emplace_back(estimateAndSaveSiftFileSubThread, points2DExtrinsic,\n                                     matchIndexesCamera, cameraIndex, numberCameras,\n                                     numberCorners, numberViews, saveImagesWithCorners, imageFolder,\n                                     gridInnerCornersCvSize, imageSize, imageAndPaths, saveSIFTFile);\n                // // Non-threaded version\n                // estimateAndSaveSiftFileSubThread(points2DExtrinsic, matchIndexesCamera, cameraIndex, numberCameras,\n                //                                  numberCorners, numberViews, saveImagesWithCorners, imageFolder,\n                //                                  gridInnerCornersCvSize, imageSize, imageAndPaths, saveSIFTFile);\n            }\n            // Threaded version\n            for (auto& thread : threads)\n                if (thread.joinable())\n                    thread.join();\n\n            // Matching file\n            std::ofstream ofstreamMatches{getFileParentFolderPath(imageAndPaths.at(0).second) + \"FeatureMatches.txt\"};\n            for (auto cameraIndex = 0 ; cameraIndex < numberCameras ; cameraIndex++)\n            {\n                for (auto cameraIndex2 = cameraIndex+1 ; cameraIndex2 < numberCameras ; cameraIndex2++)\n                {\n                    std::vector<unsigned int> matchIndexesIntersection;\n                    std::set_intersection(matchIndexes[cameraIndex].begin(), matchIndexes[cameraIndex].end(),\n                                          matchIndexes[cameraIndex2].begin(), matchIndexes[cameraIndex2].end(),\n                                          std::back_inserter(matchIndexesIntersection));\n\n                    ofstreamMatches << getFileNameFromCameraIndex(cameraIndex) << \".jpg\"\n                                    << \" \" << getFileNameFromCameraIndex(cameraIndex2) << \".jpg\"\n                    // ofstreamMatches << getFileNameAndExtension(imageAndPaths.at(cameraIndex).second)\n                    //                 << \" \" << getFileNameAndExtension(imageAndPaths.at(cameraIndex2).second)\n                                    << \" \" << matchIndexesIntersection.size() << \"\\n\";\n                    for (auto reps = 0 ; reps < 2 ; reps++)\n                    {\n                        for (auto i = 0u ; i < matchIndexesIntersection.size() ; i++)\n                            ofstreamMatches << matchIndexesIntersection[i] << \" \";\n                        ofstreamMatches << \"\\n\";\n                    }\n                    ofstreamMatches << \"\\n\";\n                }\n            }\n            ofstreamMatches.close();\n            opLog(\"Number points fully obtained: \" + std::to_string(points2DVectorsExtrinsic[0].size()), Priority::High);\n            opLog(\"Number views fully obtained: \" + std::to_string(points2DVectorsExtrinsic[0].size() / numberCorners),\n                Priority::High);\n            // Sanity check\n            for (auto i = 1 ; i < numberCameras ; i++)\n                if (points2DVectorsExtrinsic[i].size() != points2DVectorsExtrinsic[0].size())\n                    error(\"Something went wrong. Notify us.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/calibration/gridPatternFunctions.cpp",
    "content": "#include <openpose_private/calibration/gridPatternFunctions.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    // Private functions\n    void improveCornersPositionsAtSubPixelLevel(std::vector<cv::Point2f>& points2DVector, const cv::Mat& image)\n    {\n        try\n        {\n            if (!image.empty() && points2DVector.size() > 1)\n            {\n                // cv::Mat imageGray;\n                // cv::cvtColor(image, imageGray, CV_BGR2GRAY);\n                const auto winSize = std::max(5,\n                    (int)std::round(cv::norm(cv::Mat(points2DVector.at(0) - points2DVector.at(1)), cv::NORM_INF) / 4));\n                cv::cornerSubPix(\n                    image, points2DVector,\n                    cv::Size{winSize, winSize}, // Depending on the chessboard size;\n                    // cv::Size{11,11}, // Default in code I got, used above one\n                    cv::Size{-1,-1},\n                    cv::TermCriteria{ CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 1000, 1e-9 });\n                    // cv::TermCriteria{ CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 });  // Default\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::pair<bool, std::vector<cv::Point2f>> tryToFindGridCorners(const cv::Mat& image,\n                                                                   const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            std::vector<cv::Point2f> points2DVector;\n            // CALIB_CB_FAST_CHECK -> faster but more false negatives\n            const auto chessboardFound = cv::findChessboardCorners(\n                image, gridInnerCorners, points2DVector,\n                CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE | CV_CALIB_CB_FILTER_QUADS);\n\n            return std::make_pair(chessboardFound, points2DVector);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(false, std::vector<cv::Point2f>());\n        }\n    }\n\n    std::pair<bool, std::vector<cv::Point2f>> mediumlyTryToFindGridCorners(const cv::Mat& image,\n                                                                           const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            bool chessboardFound{false};\n            std::vector<cv::Point2f> points2DVector;\n\n            if (!image.empty())\n            {\n                std::tie(chessboardFound, points2DVector) = tryToFindGridCorners(image, gridInnerCorners);\n\n                if (!chessboardFound)\n                {\n                    std::tie(chessboardFound, points2DVector) = tryToFindGridCorners(image, gridInnerCorners);\n                    if (!chessboardFound)\n                    {\n                        // If not chessboardFound -> try sharpening the image\n                        cv::Mat sharperedImage;\n                        // hardcoded filter size, to be tested on 50 mm lens\n                        cv::GaussianBlur(image, sharperedImage, cv::Size{0,0}, 105);\n                        // hardcoded weight, to be tested.\n                        cv::addWeighted(image, 1.8, sharperedImage, -0.8, 0, sharperedImage);\n                        std::tie(chessboardFound, points2DVector) = tryToFindGridCorners(\n                            sharperedImage, gridInnerCorners);\n                    }\n                }\n            }\n\n            return std::make_pair(chessboardFound, points2DVector);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(false, std::vector<cv::Point2f>());\n        }\n    }\n\n    std::pair<bool, std::vector<cv::Point2f>> heavilyTryToFindGridCorners(const cv::Mat& image,\n                                                                          const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            bool chessboardFound{false};\n            std::vector<cv::Point2f> points2DVector;\n\n            // Loading images\n            if (!image.empty())\n            {\n                std::tie(chessboardFound, points2DVector) = mediumlyTryToFindGridCorners(image, gridInnerCorners);\n\n                if (!chessboardFound)\n                {\n                    cv::Mat tempImage;\n                    auto counter = 0;\n                    while (!chessboardFound && counter <= 2) // 3 pyrdown max\n                    {\n                        cv::pyrDown((!tempImage.empty() ? tempImage : image), tempImage);\n                        std::tie(chessboardFound, points2DVector) = mediumlyTryToFindGridCorners(\n                            tempImage, gridInnerCorners);\n                        counter++;\n\n                        // After next pyrDown if will be area > 5000 < 71 x 71 px image\n                        if (tempImage.size().area() <= 20e3)\n                            break;\n                    }\n                    if (chessboardFound && image.size().width != tempImage.size().width)\n                    {\n                        opLog(\"Chessboard found at lower resolution (\" + std::to_string(tempImage.cols) + \"x\"\n                            + std::to_string(tempImage.rows) + \").\", Priority::High);\n                        for (auto& point : points2DVector)\n                            point *= (image.size().width / tempImage.size().width);\n                    }\n                }\n            }\n\n            return std::make_pair(chessboardFound, points2DVector);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(false, std::vector<cv::Point2f>());\n        }\n    }\n\n    Points2DOrigin getPoints2DOrigin(const cv::Size& gridInnerCorners,\n                                     const std::vector<cv::Point2f>& points2DVector)\n    {\n        try\n        {\n            Points2DOrigin points2DOrigin;\n\n            const auto outterCornerIndices = getOutterCornerIndices(points2DVector, gridInnerCorners);\n            const std::vector<cv::Point2f> fourPointsVector{\n                points2DVector.at(outterCornerIndices.at(0)),\n                points2DVector.at(outterCornerIndices.at(1)),\n                points2DVector.at(outterCornerIndices.at(2)),\n                points2DVector.at(outterCornerIndices.at(3))\n            };\n            auto fourPointsVectorXSorted = fourPointsVector;\n            std::sort(fourPointsVectorXSorted.begin(), fourPointsVectorXSorted.end(),\n                      [](cv::Point2f const& l, cv::Point2f const& r) { return l.x < r.x; });\n\n            // If point is in the left\n            if (points2DVector.at(0) == fourPointsVectorXSorted.at(0)\n                || points2DVector.at(0) == fourPointsVectorXSorted.at(1))\n            {\n                if (points2DVector.at(0).y >= fourPointsVectorXSorted.at(0).y\n                    && points2DVector.at(0).y >= fourPointsVectorXSorted.at(1).y)\n                    points2DOrigin = {Points2DOrigin::BottomLeft};\n                else\n                    points2DOrigin = {Points2DOrigin::TopLeft};\n            }\n\n            // If point is in the right\n            else\n            {\n                if (points2DVector.at(0).y >= fourPointsVectorXSorted.at(2).y\n                    && points2DVector.at(0).y >= fourPointsVectorXSorted.at(3).y)\n                    points2DOrigin = {Points2DOrigin::BottomRight};\n                else\n                    points2DOrigin = {Points2DOrigin::TopRight};\n            }\n\n            return points2DOrigin;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Points2DOrigin::TopLeft;\n        }\n    }\n\n    void invertXPositionsIndices(std::vector<cv::Point2f>& points2DVector, const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            // Invert points orientation within each row\n            for (auto x = 0 ; x < gridInnerCorners.width / 2 ; x++)\n            {\n                for (auto y = 0 ; y < gridInnerCorners.height ; y++)\n                {\n                    const auto rowComponent = gridInnerCorners.width * y;\n                    std::swap(points2DVector.at(rowComponent + x),\n                              points2DVector.at(rowComponent + (gridInnerCorners.width - 1) - x));\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n\n\n    // Public functions\n    std::pair<bool, std::vector<cv::Point2f>> findAccurateGridCorners(\n        const cv::Mat& image, const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            // Grayscale for speeding up\n            cv::Mat imageGray;\n            cv::cvtColor(image, imageGray, CV_BGR2GRAY);\n\n            // Find chessboard corners\n            auto foundGridCornersAndLocations = heavilyTryToFindGridCorners(imageGray, gridInnerCorners);\n\n            // Increase accuracy\n            if (foundGridCornersAndLocations.first)\n                improveCornersPositionsAtSubPixelLevel(foundGridCornersAndLocations.second, imageGray);\n\n            // return final result\n            return foundGridCornersAndLocations;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(false, std::vector<cv::Point2f>());\n        }\n    }\n\n    std::vector<cv::Point3f> getObjects3DVector(\n        const cv::Size& gridInnerCorners, const float gridSquareSizeMm)\n    {\n        try\n        {\n            std::vector<cv::Point3f> objects3DVector;\n\n            for (auto x = 0 ; x < gridInnerCorners.height ; x++)\n                for (auto y = 0 ; y < gridInnerCorners.width ; y++)\n                    objects3DVector.emplace_back(cv::Point3f{x*gridSquareSizeMm,\n                                                             y*gridSquareSizeMm,\n                                                             0.f});\n            // for (int i = 0; i < gridInnerCorners.height; i++)\n            //     for (int j = 0; j < gridInnerCorners.width; j++)\n            //         corners.emplace_back(cv::Point3f(float( j*squareSize ), float( i*squareSize ), 0));\n\n            return objects3DVector;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    void drawGridCorners(cv::Mat& image, const cv::Size& gridInnerCorners,\n                         const std::vector<cv::Point2f>& points2DVector)\n    {\n        try\n        {\n            // Draw every corner\n            cv::drawChessboardCorners(image, gridInnerCorners, cv::Mat(points2DVector), true/*found*/);\n            // Draw 4 outer corners\n            const auto radiusAndThickness = std::max(5,\n                                                     (int)std::round(std::sqrt(image.cols * image.rows) / 100));\n            const auto outterCornerIndices = getOutterCornerIndices(points2DVector, gridInnerCorners);\n            cv::circle(image, points2DVector.at(outterCornerIndices.at(0)), radiusAndThickness,\n                       cv::Scalar{0, 0, 255, 1}, radiusAndThickness);\n            cv::circle(image, points2DVector.at(outterCornerIndices.at(1)), radiusAndThickness,\n                       cv::Scalar{0, 255, 0, 1}, radiusAndThickness);\n            cv::circle(image, points2DVector.at(outterCornerIndices.at(2)), radiusAndThickness,\n                       cv::Scalar{255, 0, 0, 1}, radiusAndThickness);\n            cv::circle(image, points2DVector.at(outterCornerIndices.at(3)), radiusAndThickness,\n                       cv::Scalar{0, 0, 0, 1}, radiusAndThickness);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::array<unsigned int, 4> getOutterCornerIndices(\n        const std::vector<cv::Point2f>& points2DVector, const cv::Size& gridInnerCorners)\n    {\n        try\n        {\n            std::array<unsigned int, 4> result{\n                0u,\n                (unsigned int)(gridInnerCorners.width - 1),\n                (unsigned int)points2DVector.size() - gridInnerCorners.width,\n                (unsigned int)points2DVector.size() - 1\n            };\n\n            for (const auto& value : result)\n                if (value >= points2DVector.size())\n                    error(\"Vector `points2DVector` is smaller than expected. Were all corners found?\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::array<unsigned int, 4>();\n        }\n    }\n\n    void reorderPoints(std::vector<cv::Point2f>& points2DVector, const cv::Size& gridInnerCorners,\n                       const cv::Mat& image, const bool showWarning)\n    {\n        try\n        {\n            const auto debugging = false;\n            // gridInnerCorners is 2 even\n            // In this case, there will be 2 black corners in diagonal, and 2 white ones in the opposite diagonal\n            // No way to get absolute orientation.\n            // OR\n            // gridInnerCorners is 2 odd\n            // In this case, there will be all black (or white) corners in diagonal, and 2 white ones in the opposite\n            // diagonal\n            // No way to get absolute orientation.\n            if ((gridInnerCorners.width % 2 == 0 && gridInnerCorners.height % 2 == 0)\n                || (gridInnerCorners.width % 2 == 1 && gridInnerCorners.height % 2 == 1))\n            {\n                // Warning\n                if (showWarning)\n                    opLog(\"For maximum multi-view accuracy: The number of corners of the chessboard should be even in\"\n                        \" 1 dimension and odd in the other (e.g., 1x2, 2x1, 1x4, 3x8, 6x9, 9x6, etc.). Otherwise,\"\n                        \" extrinsics calibration results might be affected.\", Priority::High);\n                // Old method\n                const auto points2DOriginCurrent = getPoints2DOrigin(gridInnerCorners, points2DVector);\n                // // No mirrored image\n                // if (points2DOriginDesired == Points2DOrigin::TopLeft)\n                // {\n                    if (points2DOriginCurrent == Points2DOrigin::TopRight)\n                        invertXPositionsIndices(points2DVector, gridInnerCorners);\n                    else if (points2DOriginCurrent == Points2DOrigin::BottomLeft)\n                    {\n                        std::reverse(points2DVector.begin(), points2DVector.end());\n                        invertXPositionsIndices(points2DVector, gridInnerCorners);\n                    }\n                    else if (points2DOriginCurrent == Points2DOrigin::BottomRight)\n                        std::reverse(points2DVector.begin(), points2DVector.end());\n                // }\n                // // Mirrored image\n                // else if (points2DOriginDesired == Points2DOrigin::TopRight)\n                // {\n                //     if (points2DOriginCurrent == Points2DOrigin::TopLeft)\n                //         invertXPositionsIndices(points2DVector, gridInnerCorners);\n                //     else if (points2DOriginCurrent == Points2DOrigin::BottomLeft)\n                //         std::reverse(points2DVector.begin(), points2DVector.end());\n                //     else if (points2DOriginCurrent == Points2DOrigin::BottomRight)\n                //     {\n                //         std::reverse(points2DVector.begin(), points2DVector.end());\n                //         invertXPositionsIndices(points2DVector, gridInnerCorners);\n                //     }\n                // }\n            }\n            // gridInnerCorners is 1 even, 1 odd\n            // In this case, there will be 2 consecutive white and 2 consecutive black corners.\n            // Easy to get absolute orientation: We detect the 2 black corners. Then, we pick as main one the black\n            // one whose left is white and right is black (only 1 satisfies this) by cross product properties.\n            else\n            {\n                const auto outterCornerIndices = getOutterCornerIndices(points2DVector, gridInnerCorners);\n                const std::vector<cv::Point2f> fourPointsVector{\n                    points2DVector.at(outterCornerIndices.at(0)),\n                    points2DVector.at(outterCornerIndices.at(1)),\n                    points2DVector.at(outterCornerIndices.at(2)),\n                    points2DVector.at(outterCornerIndices.at(3))\n                };\n                const auto point01 = fourPointsVector.at(0)-fourPointsVector.at(1);\n                const auto point01Norm = cv::norm(point01);\n                const auto point02 = fourPointsVector.at(0)-fourPointsVector.at(2);\n                const auto point02Norm = cv::norm(point02);\n                const auto point13 = fourPointsVector.at(1)-fourPointsVector.at(3);\n                const auto point13Norm = cv::norm(point13);\n                const auto averageSquareSizePx =\n                    (point01Norm/gridInnerCorners.width\n                    + point02Norm/gridInnerCorners.height\n                    + point13Norm/gridInnerCorners.height\n                    + cv::norm(fourPointsVector.at(3)-fourPointsVector.at(2))/gridInnerCorners.width)\n                    / 4.;\n                // Debugging\n                if (debugging)\n                    opLog(\"\\naverageSquareSizePx: \" + std::to_string(averageSquareSizePx));\n                // How many pixels does the outer square has?\n                // 0.67 is a threshold to be safe\n                const auto diagonalLength = 0.67 * std::sqrt(2) * averageSquareSizePx;\n                // Debugging\n                if (debugging)\n                    opLog(\"diagonalLength: \" + std::to_string(diagonalLength));\n\n                // In which direction do I have to look?\n                // Normal vector between corners 0-1, 0-2, 1-3?\n                const auto point01Direction = 1. / point01Norm * point01;\n                const auto point02Direction = 1. / point02Norm * point02;\n                const auto point13Direction = 1. / point13Norm * point13;\n                // Debugging\n                if (debugging)\n                {\n                    opLog(\"\\npoint01Direction:\");\n                    opLog(point01Direction);\n                    opLog(\"point02Direction:\");\n                    opLog(point02Direction);\n                    opLog(\"point13Direction:\");\n                    opLog(point13Direction);\n                    opLog(\" \");\n                }\n\n                auto pointDirection = fourPointsVector; // Initialization\n                pointDirection[0] = 1. / cv::norm(point01Direction + point02Direction)\n                                  * (point01Direction + point02Direction);\n                pointDirection[1] = pointDirection[0];\n                pointDirection[1].y *= -1;\n                pointDirection[2] = pointDirection[0];\n                pointDirection[2].x *= -1;\n                pointDirection[3] = -pointDirection[0];\n                // Debugging\n                if (debugging)\n                {\n                    for (auto i = 0u ; i < fourPointsVector.size() ; i++)\n                    {\n                        opLog(\"pointDirection[\" + std::to_string(i) + \"]:\");\n                        opLog(pointDirection[i]);\n                    }\n                    opLog(\" \");\n                }\n\n                // Get line to check whether outer grid color is black\n                auto pointLimit = fourPointsVector; // Initialization\n                for (auto i = 0u ; i < fourPointsVector.size() ; i++)\n                    pointLimit[i] = fourPointsVector[i] + diagonalLength * pointDirection[i];\n\n                // Line search to see if white or black\n                std::vector<double> meanPxValues(fourPointsVector.size());\n                const auto numberPointsInLine = 25;\n                const auto imageSize = image.size();\n                for (auto i = 0u ; i < fourPointsVector.size() ; i++)\n                {\n                    auto sum = 0.;\n                    auto count = 0u;\n                    for (auto lm = 0; lm < numberPointsInLine; lm++)\n                    {\n                        const auto mX = fastMax(\n                            0, fastMin(\n                                imageSize.width-1, positiveIntRound(fourPointsVector[i].x + lm*pointDirection[i].x)));\n                        const auto mY = fastMax(\n                            0, fastMin(\n                                imageSize.height-1, positiveIntRound(fourPointsVector[i].y + lm*pointDirection[i].y)));\n                        const cv::Vec3b bgrValue = image.at<cv::Vec3b>(mY, mX);\n                        sum += (bgrValue.val[0] + bgrValue.val[1] + bgrValue.val[2])/3;\n                        count++;\n                    }\n                    meanPxValues[i] = sum/count;\n                // Debugging\n                if (debugging)\n                    opLog(\"meanPxValues[\" + std::to_string(i) + \"]: \" + std::to_string(meanPxValues[i]));\n                }\n\n                // Get black indexes\n                const bool blackIs0 = meanPxValues[0] < meanPxValues[3];\n                bool blackIs1 = meanPxValues[1] < meanPxValues[2];\n\n                // Debugging\n                if (debugging)\n                {\n                    // Plotting visually results\n                    auto imageToPlot = image.clone();\n                    for (auto i = 0u ; i < fourPointsVector.size() ; i++)\n                    cv::line(imageToPlot, fourPointsVector[i], pointLimit[i], cv::Scalar{0,0,255}, 10);\n                    // Black indexes\n                    opLog(\" \");\n                    opLog(\"blackIs0: \" + std::to_string(blackIs0));\n                    opLog(\"blackIs1: \" + std::to_string(blackIs1));\n                    // Plotting results\n                    // Chessboard before\n                    drawGridCorners(imageToPlot, gridInnerCorners, points2DVector);\n                    cv::pyrDown(imageToPlot, imageToPlot);\n                    cv::imshow(\"image_before\", imageToPlot);\n                }\n\n                // Apply transformations\n                // For simplicity, we assume 0 is black\n                if (!blackIs0)\n                {\n                    std::reverse(points2DVector.begin(), points2DVector.end());\n                    blackIs1 = !blackIs1;\n                    // Debugging\n                    if (debugging)\n                        opLog(\"Swapping 0 and 3 so 0 is black.\");\n                }\n                // Lead is 0 or 1||2 (depending on blackIs1)?\n                const auto outterCornerIndicesAfter = getOutterCornerIndices(points2DVector, gridInnerCorners);\n                const auto middle = 0.25f*(\n                    fourPointsVector[0] + fourPointsVector[1] + fourPointsVector[2] + fourPointsVector[3]);\n                const std::vector<cv::Point2f> fourPointsVectorAfter{\n                    points2DVector.at(outterCornerIndicesAfter.at(0)) - middle,\n                    points2DVector.at(outterCornerIndicesAfter.at(1)) - middle,\n                    points2DVector.at(outterCornerIndicesAfter.at(2)) - middle,\n                    points2DVector.at(outterCornerIndicesAfter.at(3)) - middle\n                };\n                const auto crossProduct = fourPointsVectorAfter[0].cross(fourPointsVectorAfter[(blackIs1 ? 1 : 2)]);\n                // Debugging\n                if (debugging)\n                    opLog(\"crossProduct: \" + std::to_string(crossProduct));\n                const auto leadIs0 = crossProduct < 0;\n                // Second transformation\n                if (!leadIs0)\n                {\n                    // Debugging\n                    if (debugging)\n                        opLog(\"Lead is not 0.\");\n                    // Second black is 1\n                    if (blackIs1)\n                    {\n                        // Debugging\n                        if (debugging)\n                            opLog(\"Lead was 1.\");\n                        invertXPositionsIndices(points2DVector, gridInnerCorners); // 1->0\n                    }\n                    // Second black is 2\n                    else\n                    {\n                        // Debugging\n                        if (debugging)\n                            opLog(\"Lead was 2.\");\n                        std::reverse(points2DVector.begin(), points2DVector.end()); // 2->3\n                        invertXPositionsIndices(points2DVector, gridInnerCorners); // 3->0\n                    }\n                }\n\n                // Debugging\n                if (debugging)\n                {\n                    // Chessboard after\n                    plotGridCorners(gridInnerCorners, points2DVector, \"image_after.jpg\", image);\n                    cv::waitKey(0);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void plotGridCorners(\n        const cv::Size& gridInnerCorners, const std::vector<cv::Point2f>& points2DVector,\n        const std::string& imagePath, const cv::Mat& image)\n    {\n        try\n        {\n            cv::Mat imageToPlot = image.clone();\n            // Draw corners\n            drawGridCorners(imageToPlot, gridInnerCorners, points2DVector);\n            // Plotting results\n            const std::string windowName = getFileNameAndExtension(imagePath);\n            cv::pyrDown(imageToPlot, imageToPlot);\n            cv::imshow(windowName, imageToPlot);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/CMakeLists.txt",
    "content": "set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP;cl)\nset(SOURCES_OP_CORE\n    array.cpp\n    arrayCpuGpu.cpp\n    cvMatToOpInput.cpp\n    cvMatToOpOutput.cpp\n    datum.cpp\n    defineTemplates.cpp\n    gpuRenderer.cpp\n    keepTopNPeople.cpp\n    keypointScaler.cpp\n    matrix.cpp\n    opOutputToCvMat.cpp\n    point.cpp\n    rectangle.cpp\n    renderer.cpp\n    scaleAndSizeExtractor.cpp\n    string.cpp\n    verbosePrinter.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_CORE_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_CORE})\nset(SOURCES_OP_CORE_WITH_CP ${SOURCES_OP_CORE_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_CORE_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_core ${SOURCES_OP_CORE})\n  else ()\n    add_library(openpose_core ${SOURCES_OP_CORE})\n  endif ()\n\n  if (APPLE)\n    target_link_libraries(openpose_core openpose caffe  ${OpenCV_LIBS} ${Caffe_LIBS} ${GLUT_LIBRARY} ${SPINNAKER_LIB} ${OpenCL_LIBRARIES}\n          ${GLOG_LIBRARY} ${OpenCV_LIBS} ${Caffe_LIBS} ${GFLAGS_LIBRARY} ${GLOG_LIBRARY} ${MKL_LIBS} ${GLUT_LIBRARY} ${SPINNAKER_LIB})\n    add_library(caffe SHARED IMPORTED)\n    set_property(TARGET caffe PROPERTY IMPORTED_LOCATION ${Caffe_LIBS})\n  endif (APPLE)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_core openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_core\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/core/array.cpp",
    "content": "#include <openpose/core/array.hpp>\n#include <typeinfo> // typeid\n#include <numeric> // std::accumulate\n#include <opencv2/core/core.hpp> // cv::Mat\n#include <openpose_private/utilities/avx.hpp>\n\n// Note: std::shared_ptr not (fully) supported for array pointers:\n// http://stackoverflow.com/questions/8947579/\n// Solutions:\n// 1) Using boost::shared_ptr from <boost/shared_ptr.hpp>: Very easy but requires Boost.\n// 2) Using std::unique_ptr from <memory>: Same behaviour than 1, but only `unique`.\n// 3) Using std::shared_ptr from <memory>: Harder to use, but benefits of 1 & 2. Solutions to its problems:\n//     a) Accessing elements:\n//        https://stackoverflow.com/questions/30780262/accessing-array-of-shared-ptr\n//     b) Default delete:\n//        https://stackoverflow.com/questions/13061979/shared-ptr-to-an-array-should-it-be-used\n\nnamespace op\n{\n    /**\n     * Private auxiliary function that sets the cv::Mat wrapper and makes it point to the same data than\n     * std::shared_ptr points to.\n     */\n    template<typename T>\n    void setCvMatFromPtr(std::pair<bool, Matrix>& cvMatData, T* const dataPtr, const std::vector<int>& sizes)\n    {\n        try\n        {\n            cvMatData.first = true;\n            cvMatData.second = Matrix();\n            // BGR image\n            if (sizes.size() == 3 && sizes[2] == 3)\n            {\n                // Prepare cv::Mat\n                auto cvFormat = CV_32FC3;\n                if (typeid(T) == typeid(float))\n                    cvFormat = CV_32FC3;\n                else if (typeid(T) == typeid(double))\n                    cvFormat = CV_64FC3;\n                else if (typeid(T) == typeid(unsigned char))\n                    cvFormat = CV_8UC3;\n                else if (typeid(T) == typeid(signed char))\n                    cvFormat = CV_8SC3;\n                else if (typeid(T) == typeid(int))\n                    cvFormat = CV_32SC3;\n                else\n                    cvMatData.first = false;\n\n                if (cvMatData.first)\n                {\n                    cv::Mat cvMat(sizes[0], sizes[1], cvFormat, dataPtr);\n                    cvMatData.second = OP_CV2OPMAT(cvMat);\n                }\n            }\n            // Any other type\n            else\n            {\n                // Prepare cv::Mat\n                auto cvFormat = CV_32FC1;\n                if (typeid(T) == typeid(float))\n                    cvFormat = CV_32FC1;\n                else if (typeid(T) == typeid(double))\n                    cvFormat = CV_64FC1;\n                else if (typeid(T) == typeid(unsigned char))\n                    cvFormat = CV_8UC1;\n                else if (typeid(T) == typeid(signed char))\n                    cvFormat = CV_8SC1;\n                else if (typeid(T) == typeid(int))\n                    cvFormat = CV_32SC1;\n                else\n                    cvMatData.first = false;\n\n                if (cvMatData.first)\n                {\n                    cv::Mat cvMat((int)sizes.size(), sizes.data(), cvFormat, dataPtr);\n                    cvMatData.second = OP_CV2OPMAT(cvMat);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const int size)\n    {\n        try\n        {\n            reset(size);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const std::vector<int>& sizes)\n    {\n        try\n        {\n            reset(sizes);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const int size, const T value)\n    {\n        try\n        {\n            reset(size, value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const std::vector<int>& sizes, const T value)\n    {\n        try\n        {\n            reset(sizes, value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const int size, T* const dataPtr)\n    {\n        try\n        {\n            reset(size, dataPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const std::vector<int>& sizes, T* const dataPtr)\n    {\n        try\n        {\n            reset(sizes, dataPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const Array<T>& array, const int index, const bool noCopy)\n    {\n        try\n        {\n            // Sanity check\n            if (array.getSize(0) <= index)\n                error(\"Index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n            // Define new size\n            auto sizes = array.getSize();\n            sizes[0] = 1;\n            // Move --> Temporary Array<T> as long as `array` is in scope\n            if (noCopy)\n                resetAuxiliary(sizes, array.getPseudoConstPtr() + index*array.getVolume(1));\n            // Copy --> Slower but it will always stay in scope\n            else\n            {\n                // Allocate memory\n                reset(sizes);\n                // Copy desired index\n                const auto arrayArea = (int)array.getVolume(1);\n                const auto keypointsIndex = index*arrayArea;\n                std::copy(&array[keypointsIndex], &array[keypointsIndex]+arrayArea, pData);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(const Array<T>& array) :\n        mSize{array.mSize},\n        mVolume{array.mVolume},\n        spData{array.spData},\n        pData{array.pData},\n        mCvMatData{array.mCvMatData}\n    {\n    }\n\n    template<typename T>\n    Array<T>& Array<T>::operator=(const Array<T>& array)\n    {\n        try\n        {\n            mSize = array.mSize;\n            mVolume = array.mVolume;\n            spData = array.spData;\n            pData = array.pData;\n            mCvMatData = array.mCvMatData;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Array<T>::Array(Array<T>&& array) :\n        mSize{array.mSize},\n        mVolume{array.mVolume}\n    {\n        try\n        {\n            std::swap(spData, array.spData);\n            std::swap(pData, array.pData);\n            std::swap(mCvMatData, array.mCvMatData);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Array<T>& Array<T>::operator=(Array<T>&& array)\n    {\n        try\n        {\n            mSize = array.mSize;\n            mVolume = array.mVolume;\n            std::swap(spData, array.spData);\n            std::swap(pData, array.pData);\n            std::swap(mCvMatData, array.mCvMatData);\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Array<T> Array<T>::clone() const\n    {\n        try\n        {\n            // Constructor\n            Array<T> array{mSize};\n            // Clone data\n            // Equivalent: std::copy(spData.get(), spData.get() + mVolume, array.spData.get());\n            std::copy(pData, pData + mVolume, array.pData);\n            // Return\n            return array;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<T>{};\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const int size)\n    {\n        try\n        {\n            if (size > 0)\n                reset(std::vector<int>{size});\n            else\n                reset(std::vector<int>{});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const std::vector<int>& sizes)\n    {\n        try\n        {\n            resetAuxiliary(sizes);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const int sizes, const T value)\n    {\n        try\n        {\n            reset(sizes);\n            setTo(value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const std::vector<int>& sizes, const T value)\n    {\n        try\n        {\n            reset(sizes);\n            setTo(value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const int size, T* const dataPtr)\n    {\n        try\n        {\n            if (size > 0)\n                resetAuxiliary(std::vector<int>{size}, dataPtr);\n            else\n                error(\"Size cannot be less than 1.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::reset(const std::vector<int>& sizes, T* const dataPtr)\n    {\n        try\n        {\n            if (!sizes.empty())\n                resetAuxiliary(sizes, dataPtr);\n            else\n                error(\"Size cannot be empty or less than 1.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::setFrom(const Matrix& cvMat)\n    {\n        try\n        {\n            if (!cvMat.empty())\n            {\n                // New size\n                std::vector<int> newSize(cvMat.dims(),0);\n                for (auto i = 0u ; i < newSize.size() ; i++)\n                    newSize[i] = cvMat.size(i);\n                // Reset data & volume\n                reset(newSize);\n                // Integrity checks\n                if (!mCvMatData.first || mCvMatData.second.type() != cvMat.type())\n                    error(\"Array<T>: T type and cvMat type are different.\", __LINE__, __FUNCTION__, __FILE__);\n                // Fill data\n                cvMat.copyTo(mCvMatData.second);\n            }\n            else\n                reset();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void Array<T>::setTo(const T value)\n    {\n        try\n        {\n            if (mVolume > 0)\n            {\n                // OpenCV is efficient on copying (AVX, SSE, etc.)\n                if (mCvMatData.first)\n                    mCvMatData.second.setTo((double)value);\n                else\n                    for (auto i = 0u ; i < mVolume ; i++)\n                        operator[](i) = value;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    int Array<T>::getSize(const int index) const\n    {\n        try\n        {\n            // Matlab style:\n                // If empty -> return 0\n                // If index >= # dimensions -> return 1\n            if ((unsigned int)index < mSize.size() && 0 <= index)\n                return mSize[index];\n            // Long version:\n            // else if (mSize.empty())\n            //     return 0;\n            // else // if mSize.size() <= (unsigned int)index\n            //     return 1;\n            // Equivalent to:\n            else\n                return (!mSize.empty());\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    template<typename T>\n    std::string Array<T>::printSize() const\n    {\n        try\n        {\n            auto counter = 0u;\n            std::string sizeString = \"[ \";\n            for (const auto& i : mSize)\n            {\n                sizeString += std::to_string(i);\n                if (++counter < mSize.size())\n                    sizeString += \" x \";\n            }\n            sizeString += \" ]\";\n            return sizeString;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    template<typename T>\n    size_t Array<T>::getVolume(const int indexA, const int indexB) const\n    {\n        try\n        {\n            const auto indexBFinal = (indexB != -1 ? indexB : (int)mSize.size()-1);\n            if (indexA < indexBFinal)\n            {\n                // 0 <= indexA < indexBFinal < mSize.size()\n                if (0 <= indexA && (unsigned int)indexBFinal < mSize.size())\n                    return std::accumulate(\n                        mSize.begin()+indexA, mSize.begin()+indexBFinal+1, 1ull, std::multiplies<size_t>());\n                else\n                {\n                    error(\"Indexes out of dimension.\", __LINE__, __FUNCTION__, __FILE__);\n                    return 0;\n                }\n            }\n            else if (indexA == indexBFinal)\n                return mSize.at(indexA);\n            else // if (indexA > indexBFinal)\n            {\n                error(\"indexA > indexB.\", __LINE__, __FUNCTION__, __FILE__);\n                return 0;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    template<typename T>\n    std::vector<int> Array<T>::getStride() const\n    {\n        try\n        {\n            std::vector<int> strides(mSize.size());\n            if (!strides.empty())\n            {\n                strides.back() = sizeof(T);\n                for (auto i = (int)strides.size()-2 ; i > -1 ; i--)\n                    strides[i] = strides[i+1] * mSize[i+1];\n            }\n            return strides;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    template<typename T>\n    int Array<T>::getStride(const int index) const\n    {\n        try\n        {\n            return getStride()[index];\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    const Matrix& Array<T>::getConstCvMat() const\n    {\n        try\n        {\n            if (!mCvMatData.first)\n                error(\"Array<T>: Matrix functions only valid for T types defined by OpenCV: unsigned char,\"\n                      \" signed char, int, float & double\", __LINE__, __FUNCTION__, __FILE__);\n            return mCvMatData.second;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return mCvMatData.second;\n        }\n    }\n\n    template<typename T>\n    Matrix& Array<T>::getCvMat()\n    {\n        try\n        {\n            if (!mCvMatData.first)\n                error(\"Array<T>: Matrix functions only valid for T types defined by OpenCV: unsigned char,\"\n                      \" signed char, int, float & double\", __LINE__, __FUNCTION__, __FILE__);\n            return mCvMatData.second;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return mCvMatData.second;\n        }\n    }\n\n    template<typename T>\n    const std::string Array<T>::toString() const\n    {\n        try\n        {\n            // Initial value\n            std::string string{\"Array<T>::toString():\\n\"};\n            // Add each element\n            for (auto i = 0u ; i < mVolume ; i++)\n            {\n                // Adding element separated by a space\n                string += std::to_string(pData[i]) + \" \";\n                // Introduce an enter for each dimension change\n                // If commented, all values will be printed in the same line\n                auto multiplier = 1;\n                for (auto dimension = (int)(mSize.size() - 1u) ; dimension > 0\n                      && (int(i/multiplier) % getSize(dimension) == getSize(dimension)-1) ; dimension--)\n                {\n                    string += \"\\n\";\n                    multiplier *= getSize(dimension);\n                }\n            }\n            // Return string\n            return string;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    template<typename T>\n    int Array<T>::getIndex(const std::vector<int>& indexes) const\n    {\n        try\n        {\n            auto index = 0;\n            auto accumulated = 1;\n            for (auto i = (int)indexes.size() - 1 ; i >= 0  ; i--)\n            {\n                index += accumulated * indexes[i];\n                accumulated *= mSize[i];\n            }\n            return index;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    template<typename T>\n    int Array<T>::getIndexAndCheck(const std::vector<int>& indexes) const\n    {\n        try\n        {\n            if (indexes.size() != mSize.size())\n                error(\"Requested indexes size is different than Array size.\", __LINE__, __FUNCTION__, __FILE__);\n            return getIndex(indexes);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    template<typename T>\n    T& Array<T>::commonAt(const int index) const\n    {\n        try\n        {\n            if (0 <= index && (size_t)index < mVolume)\n                return pData[index]; // spData.get()[index]\n            else\n            {\n                error(\"Index out of bounds: 0 <= index && index < mVolume\", __LINE__, __FUNCTION__, __FILE__);\n                return pData[0]; // spData.get()[0]\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return pData[0]; // spData.get()[0]\n        }\n    }\n\n    template<typename T>\n    void Array<T>::resetAuxiliary(const std::vector<int>& sizes, T* const dataPtr)\n    {\n        try\n        {\n            if (!sizes.empty())\n            {\n                // New size & volume\n                mSize = sizes;\n                mVolume = {std::accumulate(sizes.begin(), sizes.end(), std::size_t(1), std::multiplies<size_t>())};\n                // Prepare shared_ptr\n                if (dataPtr == nullptr)\n                {\n                    #ifdef WITH_AVX\n                        spData = aligned_shared_ptr<T>(mVolume);\n                    #else\n                        spData.reset(new T[mVolume], std::default_delete<T[]>());\n                    #endif\n                    pData = spData.get();\n                    // Sanity check\n                    if (pData == nullptr)\n                        error(\"Shared pointer could not be allocated for Array data storage.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                }\n                else\n                {\n                    spData.reset();\n                    pData = dataPtr;\n                }\n                setCvMatFromPtr(mCvMatData, pData, mSize); // spData.get()\n            }\n            else\n            {\n                mSize = {};\n                mVolume = 0ul;\n                spData.reset();\n                pData = nullptr;\n                // Matrix available but empty\n                mCvMatData = std::make_pair(true, Matrix());\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_BASIC_TYPES_CLASS(Array);\n}\n"
  },
  {
    "path": "src/openpose/core/arrayCpuGpu.cpp",
    "content": "#include <openpose/core/arrayCpuGpu.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    template<typename T>\n    struct ArrayCpuGpu<T>::ImplArrayCpuGpu\n    {\n        #ifdef USE_CAFFE\n            #ifdef NV_CAFFE\n                std::unique_ptr<caffe::TBlob<T>> upCaffeBlobT;\n                caffe::TBlob<T>* pCaffeBlobT;\n            #else\n                std::unique_ptr<caffe::Blob<T>> upCaffeBlobT;\n                caffe::Blob<T>* pCaffeBlobT;\n            #endif\n        #endif\n    };\n\n    const std::string constructorErrorMessage = \"ArrayCpuGpu class only implemented for Caffe DL framework (enable\"\n        \" `USE_CAFFE` in CMake-GUI).\";\n    template<typename T>\n    ArrayCpuGpu<T>::ArrayCpuGpu()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Construct spImpl\n                spImpl.reset(new ImplArrayCpuGpu{});\n                #ifdef NV_CAFFE\n                    spImpl->upCaffeBlobT.reset(new caffe::TBlob<T>{});\n                #else\n                    spImpl->upCaffeBlobT.reset(new caffe::Blob<T>{});\n                #endif\n                spImpl->pCaffeBlobT = spImpl->upCaffeBlobT.get();\n            #else\n                error(constructorErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    ArrayCpuGpu<T>::ArrayCpuGpu(const void* caffeBlobTPtr)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Construct spImpl\n                spImpl.reset(new ImplArrayCpuGpu{});\n                #ifdef NV_CAFFE\n                    spImpl->pCaffeBlobT = (caffe::TBlob<T>*)caffeBlobTPtr;\n                #else\n                    spImpl->pCaffeBlobT = (caffe::Blob<T>*)caffeBlobTPtr;\n                #endif\n            #else\n                UNUSED(caffeBlobTPtr);\n                error(constructorErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    ArrayCpuGpu<T>::ArrayCpuGpu(const Array<T>& array, const bool copyFromGpu)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Get updated size\n                std::vector<int> arraySize;\n                // If batch size = 1 --> E.g., array.getSize() == {78, 368, 368}\n                if (array.getNumberDimensions() == 3)\n                    // Add 1: arraySize = {1}\n                    arraySize.emplace_back(1);\n                // Add {78, 368, 368}: arraySize = {1, 78, 368, 368}\n                for (const auto& sizeI : array.getSize())\n                    arraySize.emplace_back(sizeI);\n                // Construct spImpl\n                spImpl.reset(new ImplArrayCpuGpu{});\n                #ifdef NV_CAFFE\n                    spImpl->upCaffeBlobT.reset(new caffe::TBlob<T>{arraySize});\n                #else\n                    spImpl->upCaffeBlobT.reset(new caffe::Blob<T>{arraySize});\n                #endif\n                spImpl->pCaffeBlobT = spImpl->upCaffeBlobT.get();\n                // Copy data\n                // CPU copy\n                if (!copyFromGpu)\n                {\n                    const auto* const arrayPtr = array.getConstPtr();\n                    std::copy(arrayPtr, arrayPtr + array.getVolume(), spImpl->pCaffeBlobT->mutable_cpu_data());\n                }\n                // GPU copy\n                else\n                    error(\"Not implemented yet. Let us know you are interested on this function.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(array);\n                UNUSED(copyFromGpu);\n                error(constructorErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    ArrayCpuGpu<T>::ArrayCpuGpu(const int num, const int channels, const int height, const int width)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Construct spImpl\n                spImpl.reset(new ImplArrayCpuGpu{});\n                #ifdef NV_CAFFE\n                    spImpl->upCaffeBlobT.reset(new caffe::TBlob<T>{num, channels, height, width});\n                #else\n                    spImpl->upCaffeBlobT.reset(new caffe::Blob<T>{num, channels, height, width});\n                #endif\n                spImpl->pCaffeBlobT = spImpl->upCaffeBlobT.get();\n            #else\n                UNUSED(num);\n                UNUSED(channels);\n                UNUSED(height);\n                UNUSED(width);\n                error(constructorErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // template<typename T>\n    // ArrayCpuGpu<T>::ArrayCpuGpu(const std::vector<int>& shape)\n    // {\n    //     try\n    //     {\n    //         #ifdef USE_CAFFE\n    //             spImpl.reset(new ImplArrayCpuGpu{});\n    //             spImpl->upCaffeBlobT.reset(new caffe::Blob<T>{shape});\n    //             spImpl->pCaffeBlobT = spImpl->upCaffeBlobT.get();\n    //         #else\n    //             error(constructorErrorMessage, __LINE__, __FUNCTION__, __FILE__);\n    //         #endif\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //     }\n    // }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::Reshape(const int num, const int channels, const int height, const int width)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->Reshape(num, channels, height, width);\n            #else\n                UNUSED(num);\n                UNUSED(channels);\n                UNUSED(height);\n                UNUSED(width);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::Reshape(const std::vector<int>& shape)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->Reshape(shape);\n            #else\n                UNUSED(shape);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    std::string ArrayCpuGpu<T>::shape_string() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->shape_string();\n            #else\n                return \"\";\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::vector<int> DUMB_VECTOR;\n    template<typename T>\n    const std::vector<int>& ArrayCpuGpu<T>::shape() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->shape();\n            #else\n                return DUMB_VECTOR;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return DUMB_VECTOR;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::shape(const int index) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->shape(index);\n            #else\n                UNUSED(index);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::num_axes() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->num_axes();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::count() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->count();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::count(const int start_axis, const int end_axis) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->count(start_axis, end_axis);\n            #else\n                UNUSED(start_axis);\n                UNUSED(end_axis);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::count(const int start_axis) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->count(start_axis);\n            #else\n                UNUSED(start_axis);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::CanonicalAxisIndex(const int axis_index) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->CanonicalAxisIndex(axis_index);\n            #else\n                UNUSED(axis_index);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::num() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->num();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::channels() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->channels();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::height() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->height();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::width() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->width();\n            #else\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::LegacyShape(const int index) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->LegacyShape(index);\n            #else\n                UNUSED(index);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    template<typename T>\n    int ArrayCpuGpu<T>::offset(const int n, const int c, const int h, const int w) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->offset(n, c, h, w);\n            #else\n                UNUSED(n);\n                UNUSED(c);\n                UNUSED(h);\n                UNUSED(w);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    // template<typename T>\n    // int ArrayCpuGpu<T>::offset(const std::vector<int>& indices) const\n    // {\n    //     try\n    //     {\n    //         #ifdef USE_CAFFE\n    //             return spImpl->pCaffeBlobT->offset(indices);\n    //         #else\n    //             UNUSED(indices);\n    //             return -1;\n    //         #endif\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //         return -1;\n    //     }\n    // }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::data_at(const int n, const int c, const int h, const int w) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->data_at(n, c, h, w);\n            #else\n                UNUSED(n);\n                UNUSED(c);\n                UNUSED(h);\n                UNUSED(w);\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::diff_at(const int n, const int c, const int h, const int w) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->diff_at(n, c, h, w);\n            #else\n                UNUSED(n);\n                UNUSED(c);\n                UNUSED(h);\n                UNUSED(w);\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    // template<typename T>\n    // T ArrayCpuGpu<T>::data_at(const std::vector<int>& index) const\n    // {\n    //     try\n    //     {\n    //         #ifdef USE_CAFFE\n    //             return spImpl->pCaffeBlobT->data_at(index);\n    //         #else\n    //             UNUSED(index);\n    //             return T{0};\n    //         #endif\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //         return T{0};\n    //     }\n    // }\n\n    // template<typename T>\n    // T ArrayCpuGpu<T>::diff_at(const std::vector<int>& index) const\n    // {\n    //     try\n    //     {\n    //         #ifdef USE_CAFFE\n    //             return spImpl->pCaffeBlobT->diff_at(index);\n    //         #else\n    //             UNUSED(index);\n    //             return T{0};\n    //         #endif\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //         return T{0};\n    //     }\n    // }\n\n    template<typename T>\n    const T* ArrayCpuGpu<T>::cpu_data() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->cpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::set_cpu_data(T* data)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->set_cpu_data(data);\n            #else\n                UNUSED(data);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    const int* ArrayCpuGpu<T>::gpu_shape() const\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                return spImpl->pCaffeBlobT->gpu_shape();\n            #else\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    const T* ArrayCpuGpu<T>::gpu_data() const\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                return spImpl->pCaffeBlobT->gpu_data();\n            #else\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::set_gpu_data(T* data)\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                spImpl->pCaffeBlobT->set_gpu_data(data);\n            #else\n                UNUSED(data);\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    const T* ArrayCpuGpu<T>::cpu_diff() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->cpu_diff();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    const T* ArrayCpuGpu<T>::gpu_diff() const\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                return spImpl->pCaffeBlobT->gpu_diff();\n            #else\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    T* ArrayCpuGpu<T>::mutable_cpu_data()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->mutable_cpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    T* ArrayCpuGpu<T>::mutable_gpu_data()\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                return spImpl->pCaffeBlobT->mutable_gpu_data();\n            #else\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    T* ArrayCpuGpu<T>::mutable_cpu_diff()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->mutable_cpu_diff();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    T* ArrayCpuGpu<T>::mutable_gpu_diff()\n    {\n        try\n        {\n            #if defined(USE_CAFFE) && (defined(USE_CUDA) || defined(USE_OPENCL))\n                return spImpl->pCaffeBlobT->mutable_gpu_diff();\n            #else\n                error(\"Required `USE_CAFFE` and `USE_CUDA` flags enabled.\", __LINE__, __FUNCTION__, __FILE__);\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::Update()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->Update();\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::asum_data() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->asum_data();\n            #else\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::asum_diff() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->asum_diff();\n            #else\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::sumsq_data() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->sumsq_data();\n            #else\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    template<typename T>\n    T ArrayCpuGpu<T>::sumsq_diff() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return spImpl->pCaffeBlobT->sumsq_diff();\n            #else\n                return T{0};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T{0};\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::scale_data(const T scale_factor)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->scale_data(scale_factor);\n            #else\n                UNUSED(scale_factor);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    void ArrayCpuGpu<T>::scale_diff(const T scale_factor)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                spImpl->pCaffeBlobT->scale_diff(scale_factor);\n            #else\n                UNUSED(scale_factor);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_FLOATING_INT_TYPES_CLASS(ArrayCpuGpu);\n}\n"
  },
  {
    "path": "src/openpose/core/cvMatToOpInput.cpp",
    "content": "#include <openpose/core/cvMatToOpInput.hpp>\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n    #include <openpose/net/resizeAndMergeBase.hpp>\n    #include <openpose_private/gpu/cuda.hu>\n#endif\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvPrivate.hpp>\n\nnamespace op\n{\n    CvMatToOpInput::CvMatToOpInput(const PoseModel poseModel, const bool gpuResize) :\n        mPoseModel{poseModel},\n        mGpuResize{gpuResize},\n        pInputImageCuda{nullptr},\n        pInputImageReorderedCuda{nullptr},\n        pOutputImageCuda{nullptr},\n        pInputMaxSize{0ull},\n        pOutputMaxSize{0ull}\n    {\n        #ifndef USE_CUDA\n            if (mGpuResize)\n                error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                    __LINE__, __FUNCTION__, __FILE__);\n        #endif\n    }\n\n    CvMatToOpInput::~CvMatToOpInput()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (mGpuResize)\n                {\n                    // Free temporary memory\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    if (pInputImageCuda != nullptr)\n                    {\n                        cudaFree(pInputImageCuda);\n                        pInputImageCuda = nullptr;\n                    }\n                    if (pOutputImageCuda != nullptr)\n                    {\n                        cudaFree(pOutputImageCuda);\n                        pOutputImageCuda = nullptr;\n                    }\n                    if (pInputImageReorderedCuda != nullptr)\n                    {\n                        cudaFree(pInputImageReorderedCuda);\n                        pInputImageReorderedCuda = nullptr;\n                    }\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::vector<Array<float>> CvMatToOpInput::createArray(\n        const Matrix& inputData, const std::vector<double>& scaleInputToNetInputs,\n        const std::vector<Point<int>>& netInputSizes)\n    {\n        try\n        {\n            // Sanity checks\n            if (inputData.empty())\n                error(\"Wrong input element (empty inputData).\", __LINE__, __FUNCTION__, __FILE__);\n            if (inputData.channels() != 3)\n                error(\"Input images must be 3-channel BGR.\", __LINE__, __FUNCTION__, __FILE__);\n            if (scaleInputToNetInputs.size() != netInputSizes.size())\n                error(\"scaleInputToNetInputs.size() != netInputSizes.size().\", __LINE__, __FUNCTION__, __FILE__);\n            // inputNetData - Reescale keeping aspect ratio and transform to float the input deep net image\n            const auto numberScales = (int)scaleInputToNetInputs.size();\n            std::vector<Array<float>> inputNetData(numberScales);\n            cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData);\n            for (auto i = 0u ; i < inputNetData.size() ; i++)\n            {\n                // CPU version (faster if #Gpus <= 3 and relatively small images)\n                if (!mGpuResize)\n                {\n                    cv::Mat frameWithNetSize;\n                    resizeFixedAspectRatio(frameWithNetSize, cvInputData, scaleInputToNetInputs[i], netInputSizes[i]);\n                    // Fill inputNetData[i]\n                    inputNetData[i].reset({1, 3, netInputSizes.at(i).y, netInputSizes.at(i).x});\n                    uCharCvMatToFloatPtr(\n                        inputNetData[i].getPtr(), OP_CV2OPMAT(frameWithNetSize),\n                        (mPoseModel == PoseModel::BODY_19N ? 2 : 1));\n\n                    // // OpenCV equivalent\n                    // const auto scale = 1/255.;\n                    // const cv::Scalar mean{128,128,128};\n                    // const cv::Size outputSize{netInputSizes[i].x, netInputSizes[i].y};\n                    // // cv::Mat cvMat;\n                    // cv::dnn::blobFromImage(\n                    //     // frameWithNetSize, cvMat, scale, outputSize, mean);\n                    //     frameWithNetSize, inputNetData[i].getCvMat(), scale, outputSize, mean);\n                    // // opLog(cv::norm(cvMat - inputNetData[i].getCvMat())); // ~0.25\n                }\n                // CUDA version (if #Gpus > n)\n                else\n                {\n                    // Note: This version reduces the global accuracy about 0.1%, so it is disabled for now\n                    error(\"This version reduces the global accuracy about 0.1%, so it is disabled for now.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n                    #ifdef USE_CUDA\n                        // (Re)Allocate temporary memory\n                        const unsigned int inputImageSize = 3 * cvInputData.rows * cvInputData.cols;\n                        const unsigned int outputImageSize = 3 * netInputSizes[i].x * netInputSizes[i].y;\n                        if (pInputMaxSize < inputImageSize)\n                        {\n                            pInputMaxSize = inputImageSize;\n                            // Free temporary memory\n                            cudaFree(pInputImageCuda);\n                            cudaFree(pInputImageReorderedCuda);\n                            // Re-allocate memory\n                            cudaMalloc((void**)&pInputImageCuda, sizeof(unsigned char) * inputImageSize);\n                            cudaMalloc((void**)&pInputImageReorderedCuda, sizeof(float) * inputImageSize);\n                        }\n                        if (pOutputMaxSize < outputImageSize)\n                        {\n                            pOutputMaxSize = outputImageSize;\n                            // Free temporary memory\n                            cudaFree(pOutputImageCuda);\n                            // Re-allocate memory\n                            cudaMalloc((void**)&pOutputImageCuda, sizeof(float) * outputImageSize);\n                        }\n                        // Copy image to GPU\n                        cudaMemcpy(\n                            pInputImageCuda, cvInputData.data, sizeof(unsigned char) * inputImageSize,\n                            cudaMemcpyHostToDevice);\n                        // Resize image on GPU\n                        reorderAndNormalize(\n                            pInputImageReorderedCuda, pInputImageCuda, cvInputData.cols, cvInputData.rows, 3);\n                        resizeAndPadRbgGpu(\n                            pOutputImageCuda, pInputImageReorderedCuda, cvInputData.cols, cvInputData.rows,\n                            netInputSizes[i].x, netInputSizes[i].y, (float)scaleInputToNetInputs[i]);\n                        // Copy back to CPU\n                        inputNetData[i].reset({1, 3, netInputSizes.at(i).y, netInputSizes.at(i).x});\n                        cudaMemcpy(\n                            inputNetData[i].getPtr(), pOutputImageCuda, sizeof(float) * outputImageSize,\n                            cudaMemcpyDeviceToHost);\n                    #else\n                        error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                            __LINE__, __FUNCTION__, __FILE__);\n                    #endif\n                }\n            }\n            return inputNetData;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/cvMatToOpOutput.cpp",
    "content": "#include <openpose/core/cvMatToOpOutput.hpp>\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n    #include <openpose/net/resizeAndMergeBase.hpp>\n    #include <openpose_private/gpu/cuda.hu>\n#endif\n#include <openpose_private/utilities/openCvPrivate.hpp>\n\nnamespace op\n{\n    CvMatToOpOutput::CvMatToOpOutput(const bool gpuResize) :\n        mGpuResize{gpuResize},\n        pInputImageCuda{nullptr},\n        spOutputImageCuda{std::make_shared<float*>()},\n        pInputMaxSize{0ull},\n        spOutputMaxSize{std::make_shared<unsigned long long>(0ull)},\n        spGpuMemoryAllocated{std::make_shared<bool>(false)}\n    {\n        try\n        {\n            #ifndef USE_CUDA\n                if (mGpuResize)\n                    error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    CvMatToOpOutput::~CvMatToOpOutput()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (mGpuResize)\n                {\n                    // Free temporary memory\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    if (pInputImageCuda != nullptr)\n                    {\n                        cudaFree(pInputImageCuda);\n                        pInputImageCuda = nullptr;\n                    }\n                    if (*spOutputImageCuda != nullptr)\n                    {\n                        cudaFree(*spOutputImageCuda);\n                        *spOutputImageCuda = nullptr;\n                    }\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<unsigned long long>>\n        CvMatToOpOutput::getSharedParameters()\n    {\n        try\n        {\n            return std::make_tuple(spOutputImageCuda, spGpuMemoryAllocated, spOutputMaxSize);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_tuple(nullptr, nullptr, nullptr);\n        }\n    }\n\n    Array<float> CvMatToOpOutput::createArray(\n         const Matrix& inputData, const double scaleInputToOutput, const Point<int>& outputResolution)\n    {\n        try\n        {\n            cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData);\n            // Sanity checks\n            if (cvInputData.empty())\n                error(\"Wrong input element (empty cvInputData).\", __LINE__, __FUNCTION__, __FILE__);\n            if (cvInputData.channels() != 3)\n                error(\"Input images must be 3-channel BGR.\", __LINE__, __FUNCTION__, __FILE__);\n            if (cvInputData.cols <= 0 || cvInputData.rows <= 0)\n                error(\"Input images has 0 area.\", __LINE__, __FUNCTION__, __FILE__);\n            if (outputResolution.x <= 0 || outputResolution.y <= 0)\n                error(\"Output resolution has 0 area.\", __LINE__, __FUNCTION__, __FILE__);\n            // outputData - Reescale keeping aspect ratio and transform to float the output image\n            Array<float> outputData({outputResolution.y, outputResolution.x, 3}); // This size is used everywhere\n            // CPU version (faster if #Gpus <= 3 and relatively small images)\n            if (!mGpuResize)\n            {\n                cv::Mat frameWithOutputSize;\n                resizeFixedAspectRatio(frameWithOutputSize, cvInputData, scaleInputToOutput, outputResolution);\n                // Equivalent: frameWithOutputSize.convertTo(outputData.getCvMat(), CV_32FC3);\n                cv::Mat cvOutputData = OP_OP2CVMAT(outputData.getCvMat());\n                frameWithOutputSize.convertTo(cvOutputData, CV_32FC3);\n            }\n            // CUDA version (if #Gpus > 3)\n            else\n            {\n                #ifdef USE_CUDA\n                    // Input image can be shared between this one and cvMatToOpInput.hpp\n                    // However, that version reduces the global accuracy a bit\n                    // (Free and re-)Allocate temporary memory\n                    const unsigned int inputImageSize = 3 * cvInputData.rows * cvInputData.cols;\n                    if (pInputMaxSize < inputImageSize)\n                    {\n                        pInputMaxSize = inputImageSize;\n                        cudaFree(pInputImageCuda);\n                        cudaMalloc((void**)&pInputImageCuda, sizeof(unsigned char) * inputImageSize);\n                    }\n                    // (Free and re-)Allocate temporary memory\n                    const unsigned int outputImageSize = 3 * outputResolution.x * outputResolution.y;\n                    if (*spOutputMaxSize < outputImageSize)\n                    {\n                        *spOutputMaxSize = outputImageSize;\n                        cudaFree(*spOutputImageCuda);\n                        cudaMalloc((void**)spOutputImageCuda.get(), sizeof(float) * outputImageSize);\n                    }\n                    // Copy original image to GPU\n                    cudaMemcpy(\n                        pInputImageCuda, cvInputData.data, sizeof(unsigned char) * inputImageSize, cudaMemcpyHostToDevice);\n                    // Resize output image on GPU\n                    resizeAndPadRbgGpu(\n                        *spOutputImageCuda, pInputImageCuda, cvInputData.cols, cvInputData.rows, outputResolution.x,\n                        outputResolution.y, (float)scaleInputToOutput);\n                    *spGpuMemoryAllocated = true;\n                    // // No need to copy output image back to CPU\n                    // cudaMemcpy(\n                    //     outputData.getPtr(), *spOutputImageCuda, sizeof(float) * outputImageSize,\n                    //     cudaMemcpyDeviceToHost);\n                #else\n                    error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            // Return result\n            return outputData;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/datum.cpp",
    "content": "#include <openpose/core/datum.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    Datum::Datum() :\n        id{std::numeric_limits<unsigned long long>::max()},\n        subId{0},\n        subIdMax{0},\n        poseIds{-1}\n    {\n    }\n\n    // Copy constructor\n    Datum::Datum(const Datum& datum) :\n        // ID\n        id{datum.id},\n        subId{datum.subId},\n        subIdMax{datum.subIdMax},\n        name{datum.name},\n        frameNumber{datum.frameNumber},\n        // Input image and rendered version\n        cvInputData{datum.cvInputData},\n        inputNetData{datum.inputNetData},\n        outputData{datum.outputData},\n        cvOutputData{datum.cvOutputData},\n        // Resulting Array<float> data parameters\n        poseKeypoints{datum.poseKeypoints},\n        poseIds{datum.poseIds},\n        poseScores{datum.poseScores},\n        poseHeatMaps{datum.poseHeatMaps},\n        poseCandidates{datum.poseCandidates},\n        faceRectangles{datum.faceRectangles},\n        faceKeypoints{datum.faceKeypoints},\n        faceHeatMaps{datum.faceHeatMaps},\n        handRectangles{datum.handRectangles},\n        handKeypoints(datum.handKeypoints), // Parentheses instead of braces to avoid error in GCC 4.8\n        handHeatMaps(datum.handHeatMaps), // Parentheses instead of braces to avoid error in GCC 4.8\n        // 3-D Reconstruction parameters\n        poseKeypoints3D{datum.poseKeypoints3D},\n        faceKeypoints3D{datum.faceKeypoints3D},\n        handKeypoints3D(datum.handKeypoints3D), // Parentheses instead of braces to avoid error in GCC 4.8\n        cameraMatrix{datum.cameraMatrix},\n        // Other parameters\n        scaleInputToNetInputs{datum.scaleInputToNetInputs},\n        netInputSizes{datum.netInputSizes},\n        scaleInputToOutput{datum.scaleInputToOutput},\n        scaleNetToOutput{datum.scaleNetToOutput},\n        elementRendered{datum.elementRendered}\n        // 3D/Adam parameters\n        #ifdef USE_3D_ADAM_MODEL\n            ,\n            // Adam/Unity params\n            adamPosePtr{datum.adamPosePtr},\n            adamPoseRows{datum.adamPoseRows},\n            adamTranslationPtr{datum.adamTranslationPtr},\n            // Adam params (Jacobians)\n            vtVecPtr{datum.vtVecPtr},\n            vtVecRows{datum.vtVecRows},\n            j0VecPtr{datum.j0VecPtr},\n            j0VecRows{datum.j0VecRows},\n            adamFaceCoeffsExpPtr{datum.adamFaceCoeffsExpPtr},\n            adamFaceCoeffsExpRows{datum.adamFaceCoeffsExpRows}\n            #ifdef USE_EIGEN\n                ,\n                // Adam/Unity params\n                adamPose{datum.adamPose},\n                adamTranslation{datum.adamTranslation},\n                // Adam params (Jacobians)\n                vtVec{datum.vtVec},\n                j0Vec{datum.j0Vec},\n                adamFaceCoeffsExp{datum.adamFaceCoeffsExp}\n            #endif\n        #endif\n    {\n    }\n\n    // Copy assignment\n    Datum& Datum::operator=(const Datum& datum)\n    {\n        try\n        {\n            // ID\n            id = datum.id;\n            subId = datum.subId;\n            subIdMax = datum.subIdMax;\n            name = datum.name;\n            frameNumber = datum.frameNumber;\n            // Input image and rendered version\n            cvInputData = datum.cvInputData;\n            inputNetData = datum.inputNetData;\n            outputData = datum.outputData;\n            cvOutputData = datum.cvOutputData;\n            // Resulting Array<float> data parameters\n            poseKeypoints = datum.poseKeypoints;\n            poseIds = datum.poseIds,\n            poseScores = datum.poseScores,\n            poseHeatMaps = datum.poseHeatMaps,\n            poseCandidates = datum.poseCandidates,\n            faceRectangles = datum.faceRectangles,\n            faceKeypoints = datum.faceKeypoints,\n            faceHeatMaps = datum.faceHeatMaps,\n            handRectangles = datum.handRectangles,\n            handKeypoints = datum.handKeypoints,\n            handHeatMaps = datum.handHeatMaps,\n            // 3-D Reconstruction parameters\n            poseKeypoints3D = datum.poseKeypoints3D,\n            faceKeypoints3D = datum.faceKeypoints3D,\n            handKeypoints3D = datum.handKeypoints3D,\n            cameraMatrix = datum.cameraMatrix;\n            // Other parameters\n            scaleInputToNetInputs = datum.scaleInputToNetInputs;\n            netInputSizes = datum.netInputSizes;\n            scaleInputToOutput = datum.scaleInputToOutput;\n            scaleNetToOutput = datum.scaleNetToOutput;\n            elementRendered = datum.elementRendered;\n            // 3D/Adam parameters\n            #ifdef USE_3D_ADAM_MODEL\n                // Adam/Unity params\n                adamPosePtr = datum.adamPosePtr;\n                adamPoseRows = datum.adamPoseRows;\n                adamTranslationPtr = datum.adamTranslationPtr;\n                // Adam params (Jacobians)\n                vtVecPtr = datum.vtVecPtr;\n                vtVecRows = datum.vtVecRows;\n                j0VecPtr = datum.j0VecPtr;\n                j0VecRows = datum.j0VecRows;\n                adamFaceCoeffsExpPtr = datum.adamFaceCoeffsExpPtr;\n                adamFaceCoeffsExpRows = datum.adamFaceCoeffsExpRows;\n                #ifdef USE_EIGEN\n                    // Adam/Unity params\n                    adamPose = datum.adamPose;\n                    adamTranslation = datum.adamTranslation;\n                    // Adam params (Jacobians)\n                    vtVec = datum.vtVec;\n                    j0Vec = datum.j0Vec;\n                    adamFaceCoeffsExp = datum.adamFaceCoeffsExp;\n                #endif\n            #endif\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    // Move constructor\n    Datum::Datum(Datum&& datum) :\n        // ID\n        id{datum.id},\n        subId{datum.subId},\n        subIdMax{datum.subIdMax},\n        frameNumber{datum.frameNumber},\n        // Other parameters\n        scaleInputToOutput{datum.scaleInputToOutput},\n        scaleNetToOutput{datum.scaleNetToOutput}\n    {\n        try\n        {\n            // ID\n            std::swap(name, datum.name);\n            // Input image and rendered version\n            std::swap(cvInputData, datum.cvInputData);\n            std::swap(inputNetData, datum.inputNetData);\n            std::swap(outputData, datum.outputData);\n            std::swap(cvOutputData, datum.cvOutputData);\n            // Resulting Array<float> data parameters\n            std::swap(poseKeypoints, datum.poseKeypoints);\n            std::swap(poseIds, datum.poseIds);\n            std::swap(poseScores, datum.poseScores);\n            std::swap(poseHeatMaps, datum.poseHeatMaps);\n            std::swap(poseCandidates, datum.poseCandidates);\n            std::swap(faceRectangles, datum.faceRectangles);\n            std::swap(faceKeypoints, datum.faceKeypoints);\n            std::swap(faceHeatMaps, datum.faceHeatMaps);\n            std::swap(handRectangles, datum.handRectangles);\n            std::swap(handKeypoints, datum.handKeypoints);\n            std::swap(handHeatMaps, datum.handHeatMaps);\n            // 3-D Reconstruction parameters\n            std::swap(poseKeypoints3D, datum.poseKeypoints3D);\n            std::swap(faceKeypoints3D, datum.faceKeypoints3D);\n            std::swap(handKeypoints3D, datum.handKeypoints3D);\n            std::swap(cameraMatrix, datum.cameraMatrix);\n            // Other parameters\n            std::swap(scaleInputToNetInputs, datum.scaleInputToNetInputs);\n            std::swap(netInputSizes, datum.netInputSizes);\n            std::swap(elementRendered, datum.elementRendered);\n            // 3D/Adam parameters\n            #ifdef USE_3D_ADAM_MODEL\n                // Adam/Unity params\n                std::swap(adamPosePtr, datum.adamPosePtr);\n                adamPoseRows = datum.adamPoseRows;\n                std::swap(adamTranslationPtr, datum.adamTranslationPtr);\n                // Adam params (Jacobians)\n                std::swap(vtVecPtr, datum.vtVecPtr);\n                vtVecRows = datum.vtVecRows;\n                std::swap(j0VecPtr, datum.j0VecPtr);\n                j0VecRows = datum.j0VecRows;\n                std::swap(adamFaceCoeffsExpPtr, datum.adamFaceCoeffsExpPtr);\n                adamFaceCoeffsExpRows = datum.adamFaceCoeffsExpRows;\n                #ifdef USE_EIGEN\n                    // Adam/Unity params\n                    std::swap(adamPose, datum.adamPose);\n                    std::swap(adamTranslation, datum.adamTranslation);\n                    // Adam params (Jacobians)\n                    std::swap(vtVec, datum.vtVec);\n                    std::swap(j0Vec, datum.j0Vec);\n                    std::swap(adamFaceCoeffsExp, datum.adamFaceCoeffsExp);\n                #endif\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // Move assignment\n    Datum& Datum::operator=(Datum&& datum)\n    {\n        try\n        {\n            // ID\n            id = datum.id;\n            subId = datum.subId;\n            subIdMax = datum.subIdMax;\n            std::swap(name, datum.name);\n            frameNumber = datum.frameNumber;\n            // Input image and rendered version\n            std::swap(cvInputData, datum.cvInputData);\n            std::swap(inputNetData, datum.inputNetData);\n            std::swap(outputData, datum.outputData);\n            std::swap(cvOutputData, datum.cvOutputData);\n            // Resulting Array<float> data parameters\n            std::swap(poseKeypoints, datum.poseKeypoints);\n            std::swap(poseIds, datum.poseIds);\n            std::swap(poseScores, datum.poseScores);\n            std::swap(poseHeatMaps, datum.poseHeatMaps);\n            std::swap(poseCandidates, datum.poseCandidates);\n            std::swap(faceRectangles, datum.faceRectangles);\n            std::swap(faceKeypoints, datum.faceKeypoints);\n            std::swap(faceHeatMaps, datum.faceHeatMaps);\n            std::swap(handRectangles, datum.handRectangles);\n            std::swap(handKeypoints, datum.handKeypoints);\n            std::swap(handHeatMaps, datum.handHeatMaps);\n            // 3-D Reconstruction parameters\n            std::swap(poseKeypoints3D, datum.poseKeypoints3D);\n            std::swap(faceKeypoints3D, datum.faceKeypoints3D);\n            std::swap(handKeypoints3D, datum.handKeypoints3D);\n            std::swap(cameraMatrix, datum.cameraMatrix);\n            // Other parameters\n            std::swap(scaleInputToNetInputs, datum.scaleInputToNetInputs);\n            std::swap(netInputSizes, datum.netInputSizes);\n            std::swap(elementRendered, datum.elementRendered);\n            // 3D/Adam parameters\n            #ifdef USE_3D_ADAM_MODEL\n                // Adam/Unity params\n                std::swap(adamPosePtr, datum.adamPosePtr);\n                adamPoseRows = datum.adamPoseRows;\n                std::swap(adamTranslationPtr, datum.adamTranslationPtr);\n                // Adam params (Jacobians)\n                std::swap(vtVecPtr, datum.vtVecPtr);\n                vtVecRows = datum.vtVecRows;\n                std::swap(j0VecPtr, datum.j0VecPtr);\n                j0VecRows = datum.j0VecRows;\n                std::swap(adamFaceCoeffsExpPtr, datum.adamFaceCoeffsExpPtr);\n                adamFaceCoeffsExpRows = datum.adamFaceCoeffsExpRows;\n                #ifdef USE_EIGEN\n                    // Adam/Unity params\n                    std::swap(adamPose, datum.adamPose);\n                    std::swap(adamTranslation, datum.adamTranslation);\n                    // Adam params (Jacobians)\n                    std::swap(vtVec, datum.vtVec);\n                    std::swap(j0Vec, datum.j0Vec);\n                    std::swap(adamFaceCoeffsExp, datum.adamFaceCoeffsExp);\n                #endif\n            #endif\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    Datum::~Datum()\n    {\n    }\n\n    Datum Datum::clone() const\n    {\n        try\n        {\n            // Constructor\n            Datum datum;\n            // ID\n            datum.id = id;\n            datum.subId = subId;\n            datum.subIdMax = subIdMax;\n            datum.name = name;\n            datum.frameNumber = frameNumber;\n            // Input image and rendered version\n            datum.cvInputData = cvInputData.clone();\n            datum.inputNetData.resize(inputNetData.size());\n            for (auto i = 0u ; i < datum.inputNetData.size() ; i++)\n                datum.inputNetData[i] = inputNetData[i].clone();\n            datum.outputData = outputData.clone();\n            datum.cvOutputData = cvOutputData.clone();\n            // Resulting Array<float> data parameters\n            datum.poseKeypoints = poseKeypoints.clone();\n            datum.poseIds = poseIds.clone();\n            datum.poseScores = poseScores.clone();\n            datum.poseHeatMaps = poseHeatMaps.clone();\n            datum.poseCandidates = poseCandidates;\n            datum.faceRectangles = faceRectangles;\n            datum.faceKeypoints = faceKeypoints.clone();\n            datum.faceHeatMaps = faceHeatMaps.clone();\n            datum.handRectangles = handRectangles;\n            for (auto i = 0u ; i < datum.handKeypoints.size() ; i++)\n                datum.handKeypoints[i] = handKeypoints[i].clone();\n            for (auto i = 0u ; i < datum.handKeypoints.size() ; i++)\n                datum.handHeatMaps[i] = handHeatMaps[i].clone();\n            // 3-D Reconstruction parameters\n            datum.poseKeypoints3D = poseKeypoints3D.clone();\n            datum.faceKeypoints3D = faceKeypoints3D.clone();\n            for (auto i = 0u ; i < datum.handKeypoints.size() ; i++)\n                datum.handKeypoints3D[i] = handKeypoints3D[i].clone();\n            datum.cameraMatrix = cameraMatrix.clone();\n            // Other parameters\n            datum.scaleInputToNetInputs = scaleInputToNetInputs;\n            datum.netInputSizes = netInputSizes;\n            datum.scaleInputToOutput = scaleInputToOutput;\n            datum.scaleNetToOutput = scaleNetToOutput;\n            datum.elementRendered = elementRendered;\n            // 3D/Adam parameters\n            #ifdef USE_3D_ADAM_MODEL\n                // Adam/Unity params\n                datum.adamPosePtr = adamPosePtr;\n                datum.adamPoseRows = adamPoseRows;\n                datum.adamTranslationPtr = adamTranslationPtr;\n                // Adam params (Jacobians)\n                datum.vtVecPtr = vtVecPtr;\n                datum.vtVecRows = vtVecRows;\n                datum.j0VecPtr = j0VecPtr;\n                datum.j0VecRows = j0VecRows;\n                datum.adamFaceCoeffsExpPtr = adamFaceCoeffsExpPtr;\n                datum.adamFaceCoeffsExpRows = adamFaceCoeffsExpRows;\n                #ifdef USE_EIGEN\n                    // Adam/Unity params\n                    datum.adamPose = adamPose;\n                    datum.adamTranslation = adamTranslation;\n                    // Adam params (Jacobians)\n                    datum.vtVec = vtVec;\n                    datum.j0Vec = j0Vec;\n                    datum.adamFaceCoeffsExp = adamFaceCoeffsExp;\n                #endif\n            #endif\n            // Return\n            return datum;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Datum{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/defineTemplates.cpp",
    "content": "#include <openpose/core/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WCvMatToOpInput);\n    DEFINE_TEMPLATE_DATUM(WCvMatToOpOutput);\n    DEFINE_TEMPLATE_DATUM(WKeepTopNPeople);\n    DEFINE_TEMPLATE_DATUM(WKeypointScaler);\n    DEFINE_TEMPLATE_DATUM(WOpOutputToCvMat);\n    DEFINE_TEMPLATE_DATUM(WScaleAndSizeExtractor);\n    DEFINE_TEMPLATE_DATUM(WVerbosePrinter);\n}\n"
  },
  {
    "path": "src/openpose/core/gpuRenderer.cpp",
    "content": "#include <openpose/core/gpuRenderer.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime_api.h>\n#endif\n\nnamespace op\n{\n    #ifdef USE_CUDA\n        void checkAndIncreaseGpuMemory(\n            std::shared_ptr<float*>& gpuMemoryPtr, std::shared_ptr<unsigned long long>& currentVolumePtr,\n            const unsigned long long memoryVolume)\n        {\n            try\n            {\n                if (*currentVolumePtr < memoryVolume)\n                {\n                    *currentVolumePtr = memoryVolume;\n                    cudaFree(*gpuMemoryPtr);\n                    cudaMalloc((void**)gpuMemoryPtr.get(), *currentVolumePtr * sizeof(float));\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n    }\n    #endif\n\n    GpuRenderer::GpuRenderer(\n        const float renderThreshold, const float alphaKeypoint, const float alphaHeatMap,\n        const bool blendOriginalFrame, const unsigned int elementToRender, const unsigned int numberElementsToRender) :\n        Renderer{renderThreshold, alphaKeypoint, alphaHeatMap, blendOriginalFrame, elementToRender,\n                 numberElementsToRender},\n        spGpuMemory{std::make_shared<float*>()},\n        spVolume{std::make_shared<unsigned long long>(0)},\n        mIsFirstRenderer{true},\n        mIsLastRenderer{true},\n        spGpuMemoryAllocated{std::make_shared<bool>(false)}\n    {\n    }\n\n    GpuRenderer::~GpuRenderer()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (mIsLastRenderer && spGpuMemory != nullptr)\n                {\n                    cudaFree(*spGpuMemory);\n                    *spGpuMemory = nullptr;\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,\n               std::shared_ptr<unsigned long long>, std::shared_ptr<const unsigned int>>\n               GpuRenderer::getSharedParameters()\n    {\n        try\n        {\n            mIsLastRenderer = false;\n            return std::make_tuple(\n                spGpuMemory, spGpuMemoryAllocated, spElementToRender, spVolume, spNumberElementsToRender);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_tuple(nullptr, nullptr, nullptr, nullptr, nullptr);\n        }\n    }\n\n    void GpuRenderer::setSharedParametersAndIfLast(\n        const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<std::atomic<unsigned int>>,\n            std::shared_ptr<unsigned long long>, std::shared_ptr<const unsigned int>>& tuple,\n        const bool isLast)\n    {\n        try\n        {\n            mIsFirstRenderer = false;\n            mIsLastRenderer = isLast;\n            spGpuMemory = std::get<0>(tuple);\n            spGpuMemoryAllocated = std::get<1>(tuple);\n            spElementToRender = std::get<2>(tuple);\n            spVolume = std::get<3>(tuple);\n            spNumberElementsToRender = std::get<4>(tuple);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void GpuRenderer::setSharedParameters(\n        const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<unsigned long long>>& tuple)\n    {\n        try\n        {\n            mIsFirstRenderer = false;\n            mIsLastRenderer = false;\n            spGpuMemory = std::get<0>(tuple);\n            spGpuMemoryAllocated = std::get<1>(tuple);\n            spVolume = std::get<2>(tuple);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void GpuRenderer::cpuToGpuMemoryIfNotCopiedYet(const float* const cpuMemory, const unsigned long long memoryVolume)\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (!*spGpuMemoryAllocated)\n                {\n                    checkAndIncreaseGpuMemory(spGpuMemory, spVolume, memoryVolume);\n                    cudaMemcpy(*spGpuMemory, cpuMemory, memoryVolume * sizeof(float), cudaMemcpyHostToDevice);\n                    *spGpuMemoryAllocated = true;\n                }\n            #else\n                UNUSED(cpuMemory);\n                UNUSED(memoryVolume);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void GpuRenderer::gpuToCpuMemoryIfLastRenderer(float* cpuMemory, const unsigned long long memoryVolume)\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (*spGpuMemoryAllocated && mIsLastRenderer)\n                {\n                    if (*spVolume < memoryVolume)\n                        error(\"CPU is asking for more memory than it was copied into GPU.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    cudaMemcpy(cpuMemory, *spGpuMemory, memoryVolume * sizeof(float), cudaMemcpyDeviceToHost);\n                    *spGpuMemoryAllocated = false;\n                }\n            #else\n                UNUSED(cpuMemory);\n                UNUSED(memoryVolume);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/keepTopNPeople.cpp",
    "content": "#include <openpose/core/keepTopNPeople.hpp>\n#include <algorithm> // std::sort\n#include <cmath> // std::sqrt\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    KeepTopNPeople::KeepTopNPeople(const int numberPeopleMax) :\n        mNumberPeopleMax{numberPeopleMax}\n    {\n    }\n\n    KeepTopNPeople::~KeepTopNPeople()\n    {\n    }\n\n    Array<float> KeepTopNPeople::keepTopPeople(const Array<float>& peopleArray, const Array<float>& poseScores) const\n    {\n        try\n        {\n            // Remove people if #people > mNumberPeopleMax\n            if (peopleArray.getSize(0) > mNumberPeopleMax && mNumberPeopleMax > 0)\n            {\n                // Sanity checks\n                if (poseScores.getVolume() != (unsigned int) poseScores.getSize(0))\n                    error(\"The poseFinalScores variable should be a Nx1 vector, not a multidimensional array.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                if (peopleArray.getNumberDimensions() != 3)\n                    error(\"The peopleArray variable should be a 3 dimensional array.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                // Get poseFinalScores\n                auto poseFinalScores = poseScores.clone();\n                for (auto person = 0 ; person < (int)poseFinalScores.getVolume() ; person ++)\n                    poseFinalScores[person] *= std::sqrt(getKeypointsArea(peopleArray, person, 0.05f));\n\n                // Get threshold\n                auto poseScoresSorted = poseFinalScores.clone();\n                std::sort(poseScoresSorted.getPtr(), poseScoresSorted.getPtr() + poseScoresSorted.getSize(0),\n                          std::greater<float>());\n                const auto threshold = poseScoresSorted[mNumberPeopleMax-1];\n\n                // Get number people above threshold\n                auto numberPeopleAboveThreshold = 0;\n                for (auto person = 0 ; person < (int)poseFinalScores.getVolume() ; person ++)\n                    if (poseFinalScores[person] > threshold)\n                        numberPeopleAboveThreshold++;\n\n                // Remove extra people - Fill topPeopleArray\n                // assignedPeopleOnThreshold avoids that people with repeated threshold remove higher elements.\n                // In our case, it will keep the first N people with score = threshold, while keeping all the\n                // people with higher scores.\n                // E.g., poseFinalScores = [0, 0.5, 0.5, 0.5, 1.0]; mNumberPeopleMax = 2\n                // Naively, we could accidentally keep the first 2x 0.5 and remove the 1.0 threshold.\n                // Our method keeps the first 0.5 and 1.0.\n                Array<float> topPeopleArray({mNumberPeopleMax, peopleArray.getSize(1), peopleArray.getSize(2)});\n                const auto personArea = (int)peopleArray.getVolume(1, 2);\n                auto assignedPeopleOnThreshold = 0;\n                auto nextPersonIndex = 0;\n                const auto numberPeopleOnThresholdToBeAdded = mNumberPeopleMax - numberPeopleAboveThreshold;\n                for (auto person = 0 ; person < (int)poseFinalScores.getVolume() ; person++)\n                {\n                    if (poseFinalScores[person] >= threshold)\n                    {\n                        // Check we don't copy 2 values in the threshold\n                        if (poseFinalScores[person] == threshold)\n                            assignedPeopleOnThreshold++;\n\n                        // Copy person into people array\n                        if (poseFinalScores[person] > threshold\n                            || assignedPeopleOnThreshold <= numberPeopleOnThresholdToBeAdded)\n                        {\n                            const auto peopleArrayIndex = personArea*person;\n                            const auto topArrayIndex = personArea*nextPersonIndex++;\n                            std::copy(&peopleArray[peopleArrayIndex], &peopleArray[peopleArrayIndex]+personArea,\n                                      &topPeopleArray[topArrayIndex]);\n                        }\n                    }\n                }\n\n                return topPeopleArray;\n            }\n            // If no changes required\n            else\n                return peopleArray;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/keypointScaler.cpp",
    "content": "#include <openpose/core/keypointScaler.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    Rectangle<float> getScaleAndOffset(const ScaleMode scaleMode, const double scaleInputToOutput,\n                                       const double scaleNetToOutput, const Point<int>& producerSize)\n    {\n        try\n        {\n            // OutputResolution\n            if (scaleMode == ScaleMode::OutputResolution)\n                return Rectangle<float>{0.f, 0.f, float(scaleInputToOutput), float(scaleInputToOutput)};\n            // NetOutputResolution\n            else if (scaleMode == ScaleMode::NetOutputResolution)\n                return Rectangle<float>{0.f, 0.f, float(1./scaleNetToOutput),\n                                        float(1./scaleNetToOutput)};\n            // [0,1]\n            else if (scaleMode == ScaleMode::ZeroToOne)\n                return Rectangle<float>{0.f, 0.f, 1.f / ((float)producerSize.x - 1.f),\n                                        1.f / ((float)producerSize.y - 1.f)};\n            // [0,1]\n            else if (scaleMode == ScaleMode::ZeroToOneFixedAspect)\n            {\n                const float invMaxProducerSize = 1.f / ((float)fastMax(producerSize.x, producerSize.y) - 1.f);\n                return Rectangle<float>{0.f, 0.f, invMaxProducerSize, invMaxProducerSize};\n            }\n            // [-1,1]\n            else if (scaleMode == ScaleMode::PlusMinusOne)\n                return Rectangle<float>{-1.f, -1.f, 2.f / ((float)producerSize.x - 1.f),\n                                        2.f / ((float)producerSize.y - 1.f)};\n            // [-1,1]\n            else if (scaleMode == ScaleMode::PlusMinusOneFixedAspect)\n            {\n                const float invMaxProducerSize = 2.f / ((float)fastMax(producerSize.x, producerSize.y) - 1.f);\n                return Rectangle<float>{-1.f, -1.f, invMaxProducerSize, invMaxProducerSize};\n            }\n            // InputResolution\n            else if (scaleMode == ScaleMode::InputResolution)\n                return Rectangle<float>{0.f, 0.f, 1.f, 1.f};\n            // Unknown\n            error(\"Unknown ScaleMode selected.\", __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<float>{};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<float>{};\n        }\n    }\n\n    KeypointScaler::KeypointScaler(const ScaleMode scaleMode) :\n        mScaleMode{scaleMode}\n    {\n    }\n\n\n    KeypointScaler::~KeypointScaler()\n    {\n    }\n\n    void KeypointScaler::scale(Array<float>& arrayToScale, const double scaleInputToOutput,\n                               const double scaleNetToOutput, const Point<int>& producerSize) const\n    {\n        try\n        {\n            std::vector<Array<float>> arrayToScalesToScale{arrayToScale};\n            scale(arrayToScalesToScale, scaleInputToOutput, scaleNetToOutput, producerSize);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void KeypointScaler::scale(std::vector<Array<float>>& arrayToScalesToScale, const double scaleInputToOutput,\n                               const double scaleNetToOutput, const Point<int>& producerSize) const\n    {\n        try\n        {\n            if (mScaleMode != ScaleMode::InputResolution)\n            {\n                // Get scale and offset\n                const auto scaleAndOffset = getScaleAndOffset(mScaleMode, scaleInputToOutput, scaleNetToOutput,\n                                                              producerSize);\n                // Only scaling\n                if (scaleAndOffset.x == 0 && scaleAndOffset.y == 0)\n                    for (auto& arrayToScale : arrayToScalesToScale)\n                        scaleKeypoints2d(arrayToScale, scaleAndOffset.width, scaleAndOffset.height);\n                // Scaling + offset\n                else\n                    for (auto& arrayToScale : arrayToScalesToScale)\n                        scaleKeypoints2d(arrayToScale, scaleAndOffset.width, scaleAndOffset.height,\n                                         scaleAndOffset.x, scaleAndOffset.y);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void KeypointScaler::scale(std::vector<std::vector<std::array<float,3>>>& poseCandidates,\n                               const double scaleInputToOutput, const double scaleNetToOutput,\n                               const Point<int>& producerSize) const\n    {\n        try\n        {\n            if (mScaleMode != ScaleMode::InputResolution)\n            {\n                // Get scale and offset\n                const auto scaleAndOffset = getScaleAndOffset(mScaleMode, scaleInputToOutput, scaleNetToOutput,\n                                                              producerSize);\n                // Only scaling\n                if (scaleAndOffset.x == 0 && scaleAndOffset.y == 0)\n                {\n                    for (auto& partCandidates : poseCandidates)\n                    {\n                        for (auto& candidate : partCandidates)\n                        {\n                            candidate[0] *= scaleAndOffset.width;\n                            candidate[1] *= scaleAndOffset.height;\n                        }\n                    }\n                }\n                // Scaling + offset\n                else\n                {\n                    for (auto& partCandidates : poseCandidates)\n                    {\n                        for (auto& candidate : partCandidates)\n                        {\n                            candidate[0] = candidate[0]*scaleAndOffset.width + scaleAndOffset.x;\n                            candidate[1] = candidate[1]*scaleAndOffset.height + scaleAndOffset.y;\n                        }\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/matrix.cpp",
    "content": "#include <openpose/core/matrix.hpp>\n#include <opencv2/core/core.hpp> // cv::Mat\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    struct Matrix::ImplMatrix\n    {\n        cv::Mat mCvMat;\n    };\n\n    void Matrix::splitCvMatIntoVectorMatrix(std::vector<Matrix>& matrixesResized, const void* const cvMatPtr)\n    {\n        try\n        {\n            const auto numberImagesStackedHorizontally = matrixesResized.size();\n            // Sanity check\n            if (numberImagesStackedHorizontally < 1)\n                error(\"matrixesResized.size() must be greater than 0.\", __LINE__, __FUNCTION__, __FILE__);\n            // Split cv::Mat\n            cv::Mat matConcatenated = *((cv::Mat*) cvMatPtr);\n            const auto individualWidth = matConcatenated.cols/numberImagesStackedHorizontally;\n            for (auto i = 0u ; i < numberImagesStackedHorizontally ; i++)\n            {\n                cv::Mat cvMat(\n                    matConcatenated,\n                    cv::Rect{\n                        (int)(i*individualWidth), 0,\n                        (int)individualWidth, (int)matConcatenated.rows });\n                matrixesResized[i] = OP_CV2OPMAT(cvMat);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix::Matrix() :\n        spImpl{std::make_shared<ImplMatrix>()}\n    {\n    }\n\n    Matrix::Matrix(const void* cvMatPtr) :\n        spImpl{std::make_shared<ImplMatrix>()}\n    {\n        try\n        {\n            spImpl->mCvMat = *((cv::Mat*) cvMatPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix::Matrix(const int rows, const int cols, const int type) :\n        spImpl{std::make_shared<ImplMatrix>()}\n    {\n        try\n        {\n            spImpl->mCvMat = cv::Mat(rows, cols, type);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix::Matrix(const int rows, const int cols, const int type, void* cvMatPtr) :\n        spImpl{std::make_shared<ImplMatrix>()}\n    {\n        try\n        {\n            spImpl->mCvMat = cv::Mat(rows, cols, type, cvMatPtr);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix Matrix::clone() const\n    {\n        try\n        {\n            Matrix matrix;\n            matrix.spImpl->mCvMat = spImpl->mCvMat.clone();\n            return matrix;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    void* Matrix::getCvMat()\n    {\n        try\n        {\n            return (void*)(&spImpl->mCvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    const void* Matrix::getConstCvMat() const\n    {\n        try\n        {\n            return (const void*)(&spImpl->mCvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    unsigned char* Matrix::data()\n    {\n        try\n        {\n            return spImpl->mCvMat.data;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    const unsigned char* Matrix::dataConst() const\n    {\n        try\n        {\n            return spImpl->mCvMat.data;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    unsigned char* Matrix::dataPseudoConst() const\n    {\n        try\n        {\n            return spImpl->mCvMat.data;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    Matrix Matrix::eye(const int rows, const int cols, const int type)\n    {\n        try\n        {\n            Matrix matrix;\n            matrix.spImpl->mCvMat = cv::Mat::eye(rows, cols, type);\n            return matrix;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    int Matrix::cols() const\n    {\n        try\n        {\n            return spImpl->mCvMat.cols;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int Matrix::rows() const\n    {\n        try\n        {\n            return spImpl->mCvMat.rows;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int Matrix::size(const int dimension) const\n    {\n        try\n        {\n            return spImpl->mCvMat.size[dimension];\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int Matrix::dims() const\n    {\n        try\n        {\n            return spImpl->mCvMat.dims;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    bool Matrix::isContinuous() const\n    {\n        try\n        {\n            return spImpl->mCvMat.isContinuous();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    bool Matrix::isSubmatrix() const\n    {\n        try\n        {\n            return spImpl->mCvMat.isSubmatrix();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n    size_t Matrix::elemSize() const\n    {\n        try\n        {\n            return spImpl->mCvMat.elemSize();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return size_t(-1);\n        }\n    }\n\n    size_t Matrix::elemSize1() const\n    {\n        try\n        {\n            return spImpl->mCvMat.elemSize();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return size_t(-1);\n        }\n    }\n\n    int Matrix::type() const\n    {\n        try\n        {\n            return spImpl->mCvMat.type();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int Matrix::depth() const\n    {\n        try\n        {\n            return spImpl->mCvMat.depth();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n\n    int Matrix::channels() const\n    {\n        try\n        {\n            return spImpl->mCvMat.channels();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    size_t Matrix::step1(const int i) const\n    {\n        try\n        {\n            return spImpl->mCvMat.step1(i);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return size_t(-1);\n        }\n    }\n\n    bool Matrix::empty() const\n    {\n        try\n        {\n            return spImpl->mCvMat.empty();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    size_t Matrix::total() const\n    {\n        try\n        {\n            return spImpl->mCvMat.total();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return size_t(-1);\n        }\n    }\n\n    int Matrix::checkVector(const int elemChannels, const int depth, const bool requireContinuous) const\n    {\n        try\n        {\n            return spImpl->mCvMat.checkVector(elemChannels, depth, requireContinuous);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    void Matrix::setTo(const double value)\n    {\n        try\n        {\n            spImpl->mCvMat.setTo(value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Matrix::copyTo(Matrix& outputMat) const\n    {\n        try\n        {\n            spImpl->mCvMat.copyTo(outputMat.spImpl->mCvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/opOutputToCvMat.cpp",
    "content": "#include <openpose/core/opOutputToCvMat.hpp>\n#include <opencv2/core/core.hpp> // cv::Mat\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n    #include <openpose_private/gpu/cuda.hu>\n#endif\n#include <openpose/utilities/openCv.hpp>\n\nnamespace op\n{\n    OpOutputToCvMat::OpOutputToCvMat(const bool gpuResize) :\n        mGpuResize{gpuResize},\n        spOutputImageFloatCuda{std::make_shared<float*>()},\n        spOutputMaxSize{std::make_shared<unsigned long long>(0ull)},\n        spGpuMemoryAllocated{std::make_shared<bool>(false)},\n        pOutputImageUCharCuda{nullptr},\n        mOutputMaxSizeUChar{0ull}\n    {\n        try\n        {\n            #ifndef USE_CUDA\n                if (mGpuResize)\n                    error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    OpOutputToCvMat::~OpOutputToCvMat()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                if (mGpuResize)\n                {\n                    // Free temporary memory\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    if (*spOutputImageFloatCuda != nullptr)\n                    {\n                        cudaFree(*spOutputImageFloatCuda);\n                        *spOutputImageFloatCuda = nullptr;\n                    }\n                    if (pOutputImageUCharCuda != nullptr)\n                    {\n                        cudaFree(pOutputImageUCharCuda);\n                        pOutputImageUCharCuda = nullptr;\n                    }\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void OpOutputToCvMat::setSharedParameters(\n            const std::tuple<std::shared_ptr<float*>, std::shared_ptr<bool>, std::shared_ptr<unsigned long long>>& tuple)\n    {\n        try\n        {\n            spOutputImageFloatCuda = std::get<0>(tuple);\n            spGpuMemoryAllocated = std::get<1>(tuple);\n            spOutputMaxSize = std::get<2>(tuple);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix OpOutputToCvMat::formatToCvMat(const Array<float>& outputData)\n    {\n        try\n        {\n            // Sanity check\n            if (outputData.empty())\n                error(\"Wrong input element (empty outputData).\", __LINE__, __FUNCTION__, __FILE__);\n            // Final result\n            cv::Mat cvMat;\n            // CPU version\n            if (!mGpuResize)\n            {\n                // outputData to cvMat\n                // Equivalent: outputData.getConstCvMat().convertTo(cvMat, CV_8UC3);\n                const cv::Mat constCvMat = OP_OP2CVCONSTMAT(outputData.getConstCvMat());\n                constCvMat.convertTo(cvMat, CV_8UC3);\n            }\n            // CUDA version\n            else\n            {\n                #ifdef USE_CUDA\n                    // (Free and re-)Allocate temporary memory\n                    if (mOutputMaxSizeUChar < *spOutputMaxSize)\n                    {\n                        mOutputMaxSizeUChar = *spOutputMaxSize;\n                        cudaFree(pOutputImageUCharCuda);\n                        cudaMalloc((void**)&pOutputImageUCharCuda, sizeof(unsigned char) * mOutputMaxSizeUChar);\n                    }\n                    // Float ptr --> unsigned char ptr\n                    const auto volume = (int)outputData.getVolume();\n                    uCharImageCast(pOutputImageUCharCuda, *spOutputImageFloatCuda, volume);\n                    // Allocate cvMat\n                    cvMat = cv::Mat(outputData.getSize(0), outputData.getSize(1), CV_8UC3);\n                    // CUDA --> CPU: Copy output image back to CPU\n                    cudaMemcpy(\n                        cvMat.data, pOutputImageUCharCuda, sizeof(unsigned char) * volume,\n                        cudaMemcpyDeviceToHost);\n                    // Indicate memory was copied out\n                    *spGpuMemoryAllocated = false;\n                #else\n                    error(\"You need to compile OpenPose with CUDA support in order to use GPU resize.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            // Return cvMat\n            const Matrix opMat = OP_CV2OPMAT(cvMat);\n            return opMat;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/point.cpp",
    "content": "#include <openpose/core/point.hpp>\n#include <ostream>\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    template<typename T>\n    Point<T>::Point(const T x_, const T y_) :\n        x{x_},\n        y{y_}\n    {\n    }\n\n    template<typename T>\n    Point<T>::Point(const Point<T>& point)\n    {\n        try\n        {\n            x = point.x;\n            y = point.y;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator=(const Point<T>& point)\n    {\n        try\n        {\n            x = point.x;\n            y = point.y;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T>::Point(Point<T>&& point)\n    {\n        try\n        {\n            x = point.x;\n            y = point.y;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator=(Point<T>&& point)\n    {\n        try\n        {\n            x = point.x;\n            y = point.y;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    std::string Point<T>::toString() const\n    {\n        try\n        {\n            return '[' + std::to_string(x) + \", \" + std::to_string(y) + ']';\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator+=(const Point<T>& point)\n    {\n        try\n        {\n            x += point.x;\n            y += point.y;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator+(const Point<T>& point) const\n    {\n        try\n        {\n            return Point<T>{T(x + point.x), T(y + point.y)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator+=(const T value)\n    {\n        try\n        {\n            x += value;\n            y += value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator+(const T value) const\n    {\n        try\n        {\n            return Point<T>{T(x + value), T(y + value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator-=(const Point<T>& point)\n    {\n        try\n        {\n            x -= point.x;\n            y -= point.y;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator-(const Point<T>& point) const\n    {\n        try\n        {\n            return Point<T>{T(x - point.x), T(y - point.y)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator-=(const T value)\n    {\n        try\n        {\n            x -= value;\n            y -= value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator-(const T value) const\n    {\n        try\n        {\n            return Point<T>{T(x - value), T(y - value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator*=(const T value)\n    {\n        try\n        {\n            x *= value;\n            y *= value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator*(const T value) const\n    {\n        try\n        {\n            return Point<T>{T(x * value), T(y * value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T>& Point<T>::operator/=(const T value)\n    {\n        try\n        {\n            x /= value;\n            y /= value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Point<T>::operator/(const T value) const\n    {\n        try\n        {\n            return Point<T>{T(x / value), T(y / value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(Point);\n}\n"
  },
  {
    "path": "src/openpose/core/rectangle.cpp",
    "content": "#include <openpose/core/rectangle.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    template<typename T>\n    Rectangle<T>::Rectangle(const T x_, const T y_, const T width_, const T height_) :\n        x{x_},\n        y{y_},\n        width{width_},\n        height{height_}\n    {\n    }\n\n    template<typename T>\n    Rectangle<T>::Rectangle(const Rectangle<T>& rectangle)\n    {\n        try\n        {\n            x = rectangle.x;\n            y = rectangle.y;\n            width = rectangle.width;\n            height = rectangle.height;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Rectangle<T>& Rectangle<T>::operator=(const Rectangle<T>& rectangle)\n    {\n        try\n        {\n            x = rectangle.x;\n            y = rectangle.y;\n            width = rectangle.width;\n            height = rectangle.height;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Rectangle<T>::Rectangle(Rectangle<T>&& rectangle)\n    {\n        try\n        {\n            x = rectangle.x;\n            y = rectangle.y;\n            width = rectangle.width;\n            height = rectangle.height;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    Rectangle<T>& Rectangle<T>::operator=(Rectangle<T>&& rectangle)\n    {\n        try\n        {\n            x = rectangle.x;\n            y = rectangle.y;\n            width = rectangle.width;\n            height = rectangle.height;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Point<T> Rectangle<T>::center() const\n    {\n        try\n        {\n            return Point<T>{T(x + width / 2), T(y + height / 2)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    Point<T> Rectangle<T>::bottomRight() const\n    {\n        try\n        {\n            return Point<T>{T(x + width), T(y + height)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<T>{};\n        }\n    }\n\n    template<typename T>\n    void Rectangle<T>::recenter(const T newWidth, const T newHeight)\n    {\n        try\n        {\n            const auto centerPoint = center();\n            x = centerPoint.x - T(newWidth / 2.f);\n            y = centerPoint.y - T(newHeight / 2.f);\n            width = newWidth;\n            height = newHeight;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template<typename T>\n    std::string Rectangle<T>::toString() const\n    {\n        try\n        {\n            return '[' + std::to_string(x) + \", \" + std::to_string(y) + \", \" + std::to_string(width) + \", \" + std::to_string(height) + ']';\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    template<typename T>\n    Rectangle<T>& Rectangle<T>::operator*=(const T value)\n    {\n        try\n        {\n            x *= value;\n            y *= value;\n            width *= value;\n            height *= value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Rectangle<T> Rectangle<T>::operator*(const T value) const\n    {\n        try\n        {\n            return Rectangle<T>{T(x * value), T(y * value), T(width * value), T(height * value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<T>{};\n        }\n    }\n\n    template<typename T>\n    Rectangle<T>& Rectangle<T>::operator/=(const T value)\n    {\n        try\n        {\n            x /= value;\n            y /= value;\n            width /= value;\n            height /= value;\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    template<typename T>\n    Rectangle<T> Rectangle<T>::operator/(const T value) const\n    {\n        try\n        {\n            return Rectangle<T>{T(x / value), T(y / value), T(width / value), T(height / value)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<T>{};\n        }\n    }\n\n    COMPILE_TEMPLATE_BASIC_TYPES_STRUCT(Rectangle);\n\n\n\n    // Static methods\n    template<typename T>\n    Rectangle<T> recenter(const Rectangle<T>& rectangle, const T newWidth, const T newHeight)\n    {\n        try\n        {\n            Rectangle<T> result;\n            const auto centerPoint = rectangle.center();\n            result.x = centerPoint.x - T(newWidth / 2.f);\n            result.y = centerPoint.y - T(newHeight / 2.f);\n            result.width = newWidth;\n            result.height = newHeight;\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<T>{};\n        }\n    }\n\n    template Rectangle<char> recenter(const Rectangle<char>& rectangle, const char newWidth, const char newHeight);\n    template Rectangle<signed char> recenter(const Rectangle<signed char>& rectangle, const signed char newWidth, const signed char newHeight);\n    template Rectangle<short> recenter(const Rectangle<short>& rectangle, const short newWidth, const short newHeight);\n    template Rectangle<int> recenter(const Rectangle<int>& rectangle, const int newWidth, const int newHeight);\n    template Rectangle<long> recenter(const Rectangle<long>& rectangle, const long newWidth, const long newHeight);\n    template Rectangle<long long> recenter(const Rectangle<long long>& rectangle, const long long newWidth, const long long newHeight);\n    template Rectangle<unsigned char> recenter(const Rectangle<unsigned char>& rectangle, const unsigned char newWidth, const unsigned char newHeight);\n    template Rectangle<unsigned short> recenter(const Rectangle<unsigned short>& rectangle, const unsigned short newWidth, const unsigned short newHeight);\n    template Rectangle<unsigned int> recenter(const Rectangle<unsigned int>& rectangle, const unsigned int newWidth, const unsigned int newHeight);\n    template Rectangle<unsigned long> recenter(const Rectangle<unsigned long>& rectangle, const unsigned long newWidth, const unsigned long newHeight);\n    template Rectangle<unsigned long long> recenter(const Rectangle<unsigned long long>& rectangle, const unsigned long long newWidth, const unsigned long long newHeight);\n    template Rectangle<float> recenter(const Rectangle<float>& rectangle, const float newWidth, const float newHeight);\n    template Rectangle<double> recenter(const Rectangle<double>& rectangle, const double newWidth, const double newHeight);\n    template Rectangle<long double> recenter(const Rectangle<long double>& rectangle, const long double newWidth, const long double newHeight);\n}\n"
  },
  {
    "path": "src/openpose/core/renderer.cpp",
    "content": "#include <openpose/core/renderer.hpp>\n\nnamespace op\n{\n    Renderer::Renderer(const float renderThreshold, const float alphaKeypoint,\n                       const float alphaHeatMap, const bool blendOriginalFrame,\n                       const unsigned int elementToRender, const unsigned int numberElementsToRender) :\n        mRenderThreshold{renderThreshold},\n        mBlendOriginalFrame{blendOriginalFrame},\n        spElementToRender{std::make_shared<std::atomic<unsigned int>>(elementToRender)},\n        spNumberElementsToRender{std::make_shared<const unsigned int>(numberElementsToRender)},\n        mShowGooglyEyes{false},\n        mAlphaKeypoint{alphaKeypoint},\n        mAlphaHeatMap{alphaHeatMap}\n    {\n        try\n        {\n            // Sanity checks\n            if (mAlphaKeypoint < 0.f || mAlphaKeypoint > 1.f)\n                error(\"The value of mAlphaKeypoint (flag `--alpha_pose`) must be between 0 and 1.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (mAlphaHeatMap < 0.f || mAlphaHeatMap > 1.f)\n                error(\"The value of mAlphaHeatMap (flag `--alpha_heatmap`) must be between 0 and 1.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Renderer::~Renderer()\n    {\n    }\n\n    void Renderer::increaseElementToRender(const int increment)\n    {\n        try\n        {\n            // Sanity check\n            if (*spNumberElementsToRender == 0)\n                error(\"Number elements to render cannot be 0 for this function.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Get current element to be rendered\n            auto elementToRender = (((int)(*spElementToRender) + increment) % (int)(*spNumberElementsToRender));\n            // Handling negative increments\n            while (elementToRender < 0)\n                elementToRender += *spNumberElementsToRender;\n            // Update final value\n            *spElementToRender = elementToRender;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Renderer::setElementToRender(const int elementToRender)\n    {\n        try\n        {\n            *spElementToRender = elementToRender % *spNumberElementsToRender;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Renderer::setElementToRender(const ElementToRender elementToRender)\n    {\n        try\n        {\n            if (elementToRender == ElementToRender::Skeleton)\n                *spElementToRender = 0;\n            else if (elementToRender == ElementToRender::Background)\n                *spElementToRender = 1;\n            else if (elementToRender == ElementToRender::AddKeypoints)\n                *spElementToRender = 2;\n            else if (elementToRender == ElementToRender::AddPAFs)\n                *spElementToRender = 3;\n            else\n                error(\"Unknown ElementToRender value.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    float Renderer::getAlphaKeypoint() const\n    {\n        try\n        {\n            return mAlphaKeypoint;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    void Renderer::setAlphaKeypoint(const float alphaKeypoint)\n    {\n        try\n        {\n            mAlphaKeypoint = alphaKeypoint;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    float Renderer::getAlphaHeatMap() const\n    {\n        try\n        {\n            return mAlphaHeatMap;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    void Renderer::setAlphaHeatMap(const float alphaHeatMap)\n    {\n        try\n        {\n            mAlphaHeatMap = alphaHeatMap;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool Renderer::getBlendOriginalFrame() const\n    {\n        try\n        {\n            return mBlendOriginalFrame;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void Renderer::setBlendOriginalFrame(const bool blendOriginalFrame)\n    {\n        try\n        {\n            mBlendOriginalFrame = blendOriginalFrame;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool Renderer::getShowGooglyEyes() const\n    {\n        try\n        {\n            return mShowGooglyEyes;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void Renderer::setShowGooglyEyes(const bool showGooglyEyes)\n    {\n        try\n        {\n            mShowGooglyEyes = showGooglyEyes;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/scaleAndSizeExtractor.cpp",
    "content": "#include <openpose/core/scaleAndSizeExtractor.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/openCv.hpp> // resizeGetScaleFactor\n\nnamespace op\n{\n    ScaleAndSizeExtractor::ScaleAndSizeExtractor(const Point<int>& netInputResolution,\n        const float netInputResolutionDynamicBehavior, const Point<int>& outputResolution, const int scaleNumber,\n        const double scaleGap) :\n        mNetInputResolution{netInputResolution},\n        mNetInputResolutionDynamicBehavior{netInputResolutionDynamicBehavior},\n        mOutputSize{outputResolution},\n        mScaleNumber{scaleNumber},\n        mScaleGap{scaleGap}\n    {\n        try\n        {\n            // Sanity checks\n            if ((netInputResolution.x > 0 && netInputResolution.x % 16 != 0)\n                || (netInputResolution.y > 0 && netInputResolution.y % 16 != 0))\n                error(\"Net input resolution must be multiples of 16.\", __LINE__, __FUNCTION__, __FILE__);\n            if (scaleNumber < 1)\n                error(\"There must be at least 1 scale.\", __LINE__, __FUNCTION__, __FILE__);\n            if (scaleGap <= 0.)\n                error(\"The gap between scales must be strictly positive.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    ScaleAndSizeExtractor::~ScaleAndSizeExtractor()\n    {\n    }\n\n    std::tuple<std::vector<double>, std::vector<Point<int>>, double, Point<int>> ScaleAndSizeExtractor::extract(\n        const Point<int>& inputResolution) const\n    {\n        try\n        {\n            // Sanity check\n            if (inputResolution.area() <= 0)\n                error(\"Wrong input element (empty cvInputData).\", __LINE__, __FUNCTION__, __FILE__);\n            // Set poseNetInputSize\n            auto poseNetInputSize = mNetInputResolution;\n            if (poseNetInputSize.x <= 0 || poseNetInputSize.y <= 0)\n            {\n                // Sanity check\n                if (poseNetInputSize.x <= 0 && poseNetInputSize.y <= 0)\n                    error(\"Only 1 of the dimensions of net input resolution can be <= 0.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // mNetInputResolutionDynamicBehavior limiting maximum\n                if (mNetInputResolutionDynamicBehavior > 0)\n                {\n                    if (poseNetInputSize.x <= 0)\n                        poseNetInputSize.x = 16 * positiveIntRound(1 / 16.f *\n                            fastMin(poseNetInputSize.y * mNetInputResolutionDynamicBehavior * 16.f / 9.f, poseNetInputSize.y * inputResolution.x / (float)inputResolution.y));\n                    else // if (poseNetInputSize.y <= 0)\n                        poseNetInputSize.y = 16 * positiveIntRound(1 / 16.f *\n                            fastMin(poseNetInputSize.x * mNetInputResolutionDynamicBehavior * 9.f / 16.f, poseNetInputSize.x * inputResolution.y / (float)inputResolution.x));\n                }\n                else // No mNetInputResolutionDynamicBehavior behavior\n                {\n                    if (poseNetInputSize.x <= 0)\n                        poseNetInputSize.x = 16 * positiveIntRound(1 / 16.f * poseNetInputSize.y * inputResolution.x / (float)inputResolution.y);\n                    else // if (poseNetInputSize.y <= 0)\n                        poseNetInputSize.y = 16 * positiveIntRound(1 / 16.f * poseNetInputSize.x * inputResolution.y / (float)inputResolution.x);\n                }\n            }\n            // scaleInputToNetInputs & netInputSizes - Reescale keeping aspect ratio\n            std::vector<double> scaleInputToNetInputs(mScaleNumber, 1.f);\n            std::vector<Point<int>> netInputSizes(mScaleNumber);\n            for (auto i = 0; i < mScaleNumber; i++)\n            {\n                const auto currentScale = 1. - i*mScaleGap;\n                if (currentScale < 0. || 1. < currentScale)\n                    error(\"All scales must be in the range [0, 1], i.e., 0 <= 1-scale_number*scale_gap <= 1\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                const auto targetWidth = fastTruncate(\n                    positiveIntRound(poseNetInputSize.x * currentScale) / 16 * 16, 1, poseNetInputSize.x);\n                const auto targetHeight = fastTruncate(\n                    positiveIntRound(poseNetInputSize.y * currentScale) / 16 * 16, 1, poseNetInputSize.y);\n                const Point<int> targetSize{targetWidth, targetHeight};\n                scaleInputToNetInputs[i] = resizeGetScaleFactor(inputResolution, targetSize);\n                netInputSizes[i] = targetSize;\n            }\n            // scaleInputToOutput - Scale between input and desired output size\n            Point<int> outputResolution;\n            double scaleInputToOutput;\n            // Output = mOutputSize3D size\n            if (mOutputSize.x > 0 && mOutputSize.y > 0)\n            {\n                outputResolution = mOutputSize;\n                scaleInputToOutput = resizeGetScaleFactor(inputResolution, outputResolution);\n            }\n            // Output = input size\n            else\n            {\n                outputResolution = inputResolution;\n                scaleInputToOutput = 1.;\n            }\n            // Return result\n            return std::make_tuple(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_tuple(std::vector<double>{}, std::vector<Point<int>>{}, 1., Point<int>{});\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/string.cpp",
    "content": "#include <openpose/core/string.hpp>\n#include <openpose/utilities/errorAndLog.hpp>\n\nnamespace op\n{\n    struct String::ImplString\n    {\n        std::string mString;\n\n        ImplString()\n        {\n        }\n\n        ImplString(const char* charPtr) :\n            mString{charPtr}\n        {\n        }\n    };\n\n    String::String() :\n        spImpl{std::make_shared<ImplString>()}\n    {\n    }\n\n    String::String(const char* charPtr) :\n        spImpl{std::make_shared<ImplString>(charPtr)}\n    {\n    }\n\n    String::String(const std::string& string) :\n        spImpl{std::make_shared<ImplString>(string.c_str())}\n    {\n    }\n\n    const std::string& String::getStdString() const\n    {\n        try\n        {\n            return spImpl->mString;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return spImpl->mString;\n        }\n    }\n\n    bool String::empty() const\n    {\n        try\n        {\n            return spImpl->mString.empty();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/core/verbosePrinter.cpp",
    "content": "#include <openpose/core/verbosePrinter.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    VerbosePrinter::VerbosePrinter(const double verbose, const unsigned long long numberFrames) :\n    mNumberFrames{numberFrames},\n    mNumberFramesString{\"/\" + std::to_string(numberFrames) + \"...\"},\n    mVerbose{verbose}\n    {\n        try\n        {\n            if (mVerbose > 0. && mVerbose < 1. && mNumberFrames <= 0.)\n                error(\"Number of total frames could not be retrieved from the frames producer. Disable\"\n                      \" `--verbose` or use a frames producer with known number of frames.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    VerbosePrinter::~VerbosePrinter()\n    {\n    }\n\n    void VerbosePrinter::printVerbose(const unsigned long long frameNumber) const\n    {\n        try\n        {\n            // If verbose enabled\n            if (mVerbose > 0.)\n            {\n                bool plotResults = false;\n                // If first or last frame\n                if (frameNumber == 0 || frameNumber >= mNumberFrames-1)\n                    plotResults = true;\n                // mVerbose = (0,1) --> Percentage --> Every mVerbose*numberFrames frames\n                else if (mVerbose < 1.)\n                    plotResults = ((frameNumber+1) % uLongLongRound(mVerbose*mNumberFrames) == 0);\n                // mVerbose = integer >= 1 --> Every mVerbose frames\n                else\n                    plotResults = ((frameNumber+1) % uLongLongRound(mVerbose) == 0);\n                // Plot results\n                if (plotResults)\n                    opLog(\"Processing frame \" + std::to_string(frameNumber+1) + mNumberFramesString);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/CMakeLists.txt",
    "content": "set(SOURCES_OP_FACE\n    defineTemplates.cpp\n    faceDetector.cpp\n    faceDetectorOpenCV.cpp\n    faceExtractorCaffe.cpp\n    faceExtractorNet.cpp\n    faceCpuRenderer.cpp\n    faceGpuRenderer.cpp\n    faceRenderer.cpp\n    renderFace.cpp\n    renderFace.cu)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_FACE_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_FACE})\nset(SOURCES_OP_FACE_WITH_CP ${SOURCES_OP_FACE_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_FACE_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_face ${SOURCES_OP_FACE})\n  else ()\n    add_library(openpose_face ${SOURCES_OP_FACE})\n  endif ()\n\n  target_link_libraries(openpose_face openpose_core)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_face openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_face\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/face/defineTemplates.cpp",
    "content": "#include <openpose/face/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WFaceDetector);\n    DEFINE_TEMPLATE_DATUM(WFaceExtractorNet);\n    DEFINE_TEMPLATE_DATUM(WFaceRenderer);\n    DEFINE_TEMPLATE_DATUM(WFaceDetectorOpenCV);\n}\n"
  },
  {
    "path": "src/openpose/face/faceCpuRenderer.cpp",
    "content": "#include <openpose/face/faceCpuRenderer.hpp>\n#include <openpose/face/renderFace.hpp>\n\nnamespace op\n{\n    FaceCpuRenderer::FaceCpuRenderer(const float renderThreshold, const float alphaKeypoint,\n                                     const float alphaHeatMap) :\n        Renderer{renderThreshold, alphaKeypoint, alphaHeatMap}\n    {\n    }\n\n    FaceCpuRenderer::~FaceCpuRenderer()\n    {\n    }\n\n    void FaceCpuRenderer::renderFaceInherited(Array<float>& outputData, const Array<float>& faceKeypoints)\n    {\n        try\n        {\n            // CPU rendering\n            renderFaceKeypointsCpu(outputData, faceKeypoints, mRenderThreshold);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceDetector.cpp",
    "content": "#include <openpose/face/faceDetector.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    FaceDetector::FaceDetector(const PoseModel poseModel) :\n        mNeck{poseBodyPartMapStringToKey(poseModel, \"Neck\")},\n        mNose{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{\"Nose\", \"Head\"})},\n        mLEar{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{\"LEar\", \"Head\"})},\n        mREar{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{\"REar\", \"Head\"})},\n        mLEye{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{\"LEye\", \"Head\"})},\n        mREye{poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{\"REye\", \"Head\"})}\n    {\n    }\n\n    FaceDetector::~FaceDetector()\n    {\n    }\n\n    inline Rectangle<float> getFaceFromPoseKeypoints(const Array<float>& poseKeypoints, const unsigned int personIndex,\n                                                     const unsigned int neck, const unsigned int headNose,\n                                                     const unsigned int lEar, const unsigned int rEar,\n                                                     const unsigned int lEye, const unsigned int rEye,\n                                                     const float threshold)\n    {\n        try\n        {\n            Point<float> pointTopLeft{0.f, 0.f};\n            auto faceSize = 0.f;\n\n            const auto* posePtr = &poseKeypoints.at(personIndex*poseKeypoints.getSize(1)*poseKeypoints.getSize(2));\n            const auto neckScoreAbove = (posePtr[neck*3+2] > threshold);\n            const auto headNoseScoreAbove = (posePtr[headNose*3+2] > threshold);\n            const auto lEarScoreAbove = (posePtr[lEar*3+2] > threshold);\n            const auto rEarScoreAbove = (posePtr[rEar*3+2] > threshold);\n            const auto lEyeScoreAbove = (posePtr[lEye*3+2] > threshold);\n            const auto rEyeScoreAbove = (posePtr[rEye*3+2] > threshold);\n\n            auto counter = 0;\n            // Face and neck given (e.g., MPI)\n            if (headNose == lEar && lEar == rEar)\n            {\n                if (neckScoreAbove && headNoseScoreAbove)\n                {\n                    pointTopLeft.x = posePtr[headNose*3];\n                    pointTopLeft.y = posePtr[headNose*3+1];\n                    faceSize = 1.33f * getDistance(poseKeypoints, personIndex, neck, headNose);\n                }\n            }\n            // Face as average between different body keypoints (e.g., COCO)\n            else\n            {\n                // factor * dist(neck, headNose)\n                if (neckScoreAbove && headNoseScoreAbove)\n                {\n                    // If profile (i.e., only 1 eye and ear visible) --> avg(headNose, eye & ear position)\n                    if ((lEyeScoreAbove) == (lEarScoreAbove)\n                        && (rEyeScoreAbove) == (rEarScoreAbove)\n                        && (lEyeScoreAbove) != (rEyeScoreAbove))\n                    {\n                        if (lEyeScoreAbove)\n                        {\n                            pointTopLeft.x += (posePtr[lEye*3] + posePtr[lEar*3] + posePtr[headNose*3]) / 3.f;\n                            pointTopLeft.y += (posePtr[lEye*3+1] + posePtr[lEar*3+1] + posePtr[headNose*3+1]) / 3.f;\n                            faceSize += 0.85f * (getDistance(poseKeypoints, personIndex, headNose, lEye)\n                                                 + getDistance(poseKeypoints, personIndex, headNose, lEar)\n                                                 + getDistance(poseKeypoints, personIndex, neck, headNose));\n                        }\n                        else // if(lEyeScoreAbove)\n                        {\n                            pointTopLeft.x += (posePtr[rEye*3] + posePtr[rEar*3] + posePtr[headNose*3]) / 3.f;\n                            pointTopLeft.y += (posePtr[rEye*3+1] + posePtr[rEar*3+1] + posePtr[headNose*3+1]) / 3.f;\n                            faceSize += 0.85f * (getDistance(poseKeypoints, personIndex, headNose, rEye)\n                                                 + getDistance(poseKeypoints, personIndex, headNose, rEar)\n                                                 + getDistance(poseKeypoints, personIndex, neck, headNose));\n                        }\n                    }\n                    // else --> 2 * dist(neck, headNose)\n                    else\n                    {\n                        pointTopLeft.x += (posePtr[neck*3] + posePtr[headNose*3]) / 2.f;\n                        pointTopLeft.y += (posePtr[neck*3+1] + posePtr[headNose*3+1]) / 2.f;\n                        faceSize += 2.f * getDistance(poseKeypoints, personIndex, neck, headNose);\n                    }\n                    counter++;\n                }\n                // 3 * dist(lEye, rEye)\n                if (lEyeScoreAbove && rEyeScoreAbove)\n                {\n                    pointTopLeft.x += (posePtr[lEye*3] + posePtr[rEye*3]) / 2.f;\n                    pointTopLeft.y += (posePtr[lEye*3+1] + posePtr[rEye*3+1]) / 2.f;\n                    faceSize += 3.f * getDistance(poseKeypoints, personIndex, lEye, rEye);\n                    counter++;\n                }\n                // 2 * dist(lEar, rEar)\n                if (lEarScoreAbove && rEarScoreAbove)\n                {\n                    pointTopLeft.x += (posePtr[lEar*3] + posePtr[rEar*3]) / 2.f;\n                    pointTopLeft.y += (posePtr[lEar*3+1] + posePtr[rEar*3+1]) / 2.f;\n                    faceSize += 2.f * getDistance(poseKeypoints, personIndex, lEar, rEar);\n                    counter++;\n                }\n                // Average (if counter > 0)\n                if (counter > 0)\n                {\n                    pointTopLeft /= (float)counter;\n                    faceSize /= counter;\n                }\n            }\n            return Rectangle<float>{pointTopLeft.x - faceSize / 2, pointTopLeft.y - faceSize / 2, faceSize, faceSize};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<float>{};\n        }\n    }\n\n    std::vector<Rectangle<float>> FaceDetector::detectFaces(const Array<float>& poseKeypoints) const\n    {\n        try\n        {\n            const auto numberPeople = poseKeypoints.getSize(0);\n            std::vector<Rectangle<float>> faceRectangles(numberPeople);\n            const auto threshold = 0.25f;\n            // If no poseKeypoints detected -> no way to detect face location\n            // Otherwise, get face position(s)\n            if (!poseKeypoints.empty())\n                for (auto person = 0 ; person < numberPeople ; person++)\n                    faceRectangles.at(person) = getFaceFromPoseKeypoints(\n                        poseKeypoints, person, mNeck, mNose, mLEar, mREar, mLEye, mREye, threshold);\n            return faceRectangles;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceDetectorOpenCV.cpp",
    "content": "#include <openpose/face/faceDetectorOpenCV.hpp>\n#include <opencv2/objdetect/objdetect.hpp> // cv::CascadeClassifier\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    struct FaceDetectorOpenCV::ImplFaceDetectorOpenCV\n    {\n        cv::CascadeClassifier mFaceCascade;\n    };\n\n    FaceDetectorOpenCV::FaceDetectorOpenCV(const std::string& modelFolder) :\n        upImpl{new ImplFaceDetectorOpenCV{}}\n    {\n        try\n        {\n            const std::string faceDetectorModelPath{modelFolder + \"face/haarcascade_frontalface_alt.xml\"};\n            if (!upImpl->mFaceCascade.load(faceDetectorModelPath))\n                error(\"Face detector model not found at: \" + faceDetectorModelPath, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FaceDetectorOpenCV::~FaceDetectorOpenCV()\n    {\n    }\n\n    std::vector<Rectangle<float>> FaceDetectorOpenCV::detectFaces(const Matrix& inputData)\n    {\n        try\n        {\n            cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData);\n            // Image to grey and pyrDown\n            cv::Mat frameGray;\n            cv::cvtColor(cvInputData, frameGray, cv::COLOR_BGR2GRAY);\n            auto multiplier = 1.f;\n            while (frameGray.cols * frameGray.rows > 640*360)\n            {\n                cv::pyrDown(frameGray, frameGray);\n                multiplier *= 2.f;\n            }\n            // Face detection - Example from:\n            // http://docs.opencv.org/2.4/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html\n            std::vector<cv::Rect> detectedFaces;\n            upImpl->mFaceCascade.detectMultiScale(frameGray, detectedFaces, 1.2, 3, 0|CV_HAAR_SCALE_IMAGE);\n            // Rescale rectangles\n            std::vector<Rectangle<float>> faceRectangles(detectedFaces.size());\n            for(auto i = 0u; i < detectedFaces.size(); i++)\n            {\n                // Enlarge detected rectangle by 1.5x, so that it covers the whole face\n                faceRectangles.at(i).x = detectedFaces.at(i).x - 0.25f*detectedFaces.at(i).width;\n                faceRectangles.at(i).y = detectedFaces.at(i).y - 0.25f*detectedFaces.at(i).height;\n                faceRectangles.at(i).width = 1.5f*detectedFaces.at(i).width;\n                faceRectangles.at(i).height = 1.5f*detectedFaces.at(i).height;\n                faceRectangles.at(i) *= multiplier;\n            }\n            return faceRectangles;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceExtractorCaffe.cpp",
    "content": "#include <openpose/face/faceExtractorCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/net/maximumCaffe.hpp>\n#include <openpose/net/netCaffe.hpp>\n#include <openpose/net/resizeAndMergeCaffe.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    struct FaceExtractorCaffe::ImplFaceExtractorCaffe\n    {\n        #ifdef USE_CAFFE\n            bool netInitialized;\n            const int mGpuId;\n            std::shared_ptr<NetCaffe> spNetCaffe;\n            std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;\n            std::shared_ptr<MaximumCaffe<float>> spMaximumCaffe;\n            // Init with thread\n            std::shared_ptr<ArrayCpuGpu<float>> spCaffeNetOutputBlob;\n            std::shared_ptr<ArrayCpuGpu<float>> spHeatMapsBlob;\n            std::shared_ptr<ArrayCpuGpu<float>> spPeaksBlob;\n\n            ImplFaceExtractorCaffe(const std::string& modelFolder, const int gpuId, const bool enableGoogleLogging) :\n                netInitialized{false},\n                mGpuId{gpuId},\n                spNetCaffe{std::make_shared<NetCaffe>(modelFolder + FACE_PROTOTXT, modelFolder + FACE_TRAINED_MODEL,\n                                                      gpuId, enableGoogleLogging)},\n                spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},\n                spMaximumCaffe{std::make_shared<MaximumCaffe<float>>()}\n            {\n            }\n        #endif\n    };\n\n    #ifdef USE_CAFFE\n        void updateFaceHeatMapsForPerson(\n            Array<float>& heatMaps, const int person, const ScaleMode heatMapScaleMode, const float* heatMapsGpuPtr)\n        {\n            try\n            {\n                // Copy memory\n                const auto channelOffset = heatMaps.getVolume(2, 3);\n                const auto volumeBodyParts = FACE_NUMBER_PARTS * channelOffset;\n                auto totalOffset = 0u;\n                auto* heatMapsPtr = &heatMaps.getPtr()[person*volumeBodyParts];\n                // Copy face parts\n                #ifdef USE_CUDA\n                    cudaMemcpy(heatMapsPtr, heatMapsGpuPtr, volumeBodyParts * sizeof(float), cudaMemcpyDeviceToHost);\n                #else\n                    //std::memcpy(heatMapsPtr, heatMapsGpuPtr, volumeBodyParts * sizeof(float));\n                    std::copy(heatMapsGpuPtr, heatMapsGpuPtr + volumeBodyParts, heatMapsPtr);\n                #endif\n                // Change from [0,1] to [-1,1]\n                if (heatMapScaleMode == ScaleMode::PlusMinusOne\n                    || heatMapScaleMode == ScaleMode::PlusMinusOneFixedAspect)\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]) * 2.f - 1.f;\n                // [0, 255]\n                else if (heatMapScaleMode == ScaleMode::UnsignedChar)\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = (float)positiveIntRound(fastTruncate(heatMapsPtr[i]) * 255.f);\n                // Avoid values outside original range\n                else\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]);\n                totalOffset += (unsigned int)volumeBodyParts;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        inline void reshapeFaceExtractorCaffe(std::shared_ptr<ResizeAndMergeCaffe<float>>& resizeAndMergeCaffe,\n                                              std::shared_ptr<MaximumCaffe<float>>& maximumCaffe,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& caffeNetOutputBlob,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& heatMapsBlob,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& peaksBlob,\n                                              const int gpuID)\n        {\n            try\n            {\n                // HeatMaps extractor blob and layer\n                const bool mergeFirstDimension = true;\n                resizeAndMergeCaffe->Reshape(\n                    std::vector<ArrayCpuGpu<float>*>{caffeNetOutputBlob.get()},\n                    std::vector<ArrayCpuGpu<float>*>{heatMapsBlob.get()},\n                    FACE_CCN_DECREASE_FACTOR, 1.f, mergeFirstDimension, gpuID);\n                // Pose extractor blob and layer\n                maximumCaffe->Reshape({heatMapsBlob.get()}, {peaksBlob.get()});\n                // Cuda check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    FaceExtractorCaffe::FaceExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                           const std::string& modelFolder, const int gpuId,\n                                           const std::vector<HeatMapType>& heatMapTypes,\n                                           const ScaleMode heatMapScaleMode, const bool enableGoogleLogging) :\n        FaceExtractorNet{netInputSize, netOutputSize, heatMapTypes, heatMapScaleMode}\n        #ifdef USE_CAFFE\n        , upImpl{new ImplFaceExtractorCaffe{modelFolder, gpuId, enableGoogleLogging}}\n        #endif\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                UNUSED(netInputSize);\n                UNUSED(netOutputSize);\n                UNUSED(modelFolder);\n                UNUSED(gpuId);\n                UNUSED(heatMapTypes);\n                UNUSED(heatMapScaleMode);\n                UNUSED(enableGoogleLogging);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n            #ifdef COMMERCIAL_LICENSE\n                error(\"Face is not included in the commercial version of OpenPose yet. We might include it in the future after some\"\n                      \" commercial issues have been solved. Thanks!\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FaceExtractorCaffe::~FaceExtractorCaffe()\n    {\n    }\n\n    void FaceExtractorCaffe::netInitializationOnThread()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Logging\n                opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Initialize Caffe net\n                upImpl->spNetCaffe->initializationOnThread();\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Initialize blobs\n                upImpl->spCaffeNetOutputBlob = upImpl->spNetCaffe->getOutputBlobArray();\n                upImpl->spHeatMapsBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                upImpl->spPeaksBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Logging\n                opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FaceExtractorCaffe::forwardPass(\n        const std::vector<Rectangle<float>>& faceRectangles, const Matrix& inputData)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (mEnabled && !faceRectangles.empty())\n                {\n                    const cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData);\n\n                    // Sanity check\n                    if (cvInputData.empty())\n                        error(\"Empty cvInputData.\", __LINE__, __FUNCTION__, __FILE__);\n\n                    // Fix parameters\n                    const auto netInputSide = fastMin(mNetOutputSize.x, mNetOutputSize.y);\n\n                    // Set face size\n                    const auto numberPeople = (int)faceRectangles.size();\n                    mFaceKeypoints.reset({numberPeople, (int)FACE_NUMBER_PARTS, 3}, 0.f);\n\n                    // HeatMaps: define size\n                    if (!mHeatMapTypes.empty())\n                        mHeatMaps.reset({numberPeople, (int)FACE_NUMBER_PARTS, mNetOutputSize.y, mNetOutputSize.x});\n\n                    // // Debugging\n                    // cv::Mat cvInputDataCopy = cvInputData.clone();\n                    // Extract face keypoints for each person\n                    for (auto person = 0 ; person < numberPeople ; person++)\n                    {\n                        const auto& faceRectangle = faceRectangles.at(person);\n                        // Sanity check\n                        if (faceRectangle.width != faceRectangle.height)\n                            error(\"Face rectangle for face keypoint estimation must be squared, i.e.,\"\n                                  \" width = height (\" + std::to_string(faceRectangle.width) + \" vs. \"\n                                  + std::to_string(faceRectangle.height) + \").\", __LINE__, __FUNCTION__, __FILE__);\n                        // Only consider faces with a minimum pixel area\n                        const auto minFaceSize = fastMin(faceRectangle.width, faceRectangle.height);\n                        // // Debugging -> red rectangle\n                        // opLog(std::to_string(cvInputData.cols) + \" \" + std::to_string(cvInputData.rows));\n                        // cv::rectangle(cvInputDataCopy,\n                        //               cv::Point{(int)faceRectangle.x, (int)faceRectangle.y},\n                        //               cv::Point{(int)faceRectangle.bottomRight().x,\n                        //                         (int)faceRectangle.bottomRight().y},\n                        //               cv::Scalar{0,0,255}, 2);\n                        // Get parts\n                        if (minFaceSize > 40)\n                        {\n                            // // Debugging -> green rectangle overwriting red one\n                            // opLog(std::to_string(cvInputData.cols) + \" \" + std::to_string(cvInputData.rows));\n                            // cv::rectangle(cvInputDataCopy,\n                            //               cv::Point{(int)faceRectangle.x, (int)faceRectangle.y},\n                            //               cv::Point{(int)faceRectangle.bottomRight().x,\n                            //                         (int)faceRectangle.bottomRight().y},\n                            //               cv::Scalar{0,255,0}, 2);\n                            // Resize and shift image to face rectangle positions\n                            const auto faceSize = fastMax(faceRectangle.width, faceRectangle.height);\n                            const double scaleFace = faceSize / (double)netInputSide;\n                            cv::Mat Mscaling = cv::Mat::eye(2, 3, CV_64F);\n                            Mscaling.at<double>(0,0) = scaleFace;\n                            Mscaling.at<double>(1,1) = scaleFace;\n                            Mscaling.at<double>(0,2) = faceRectangle.x;\n                            Mscaling.at<double>(1,2) = faceRectangle.y;\n\n                            cv::Mat faceImage;\n                            cv::warpAffine(cvInputData, faceImage, Mscaling,\n                                           cv::Size{mNetOutputSize.x, mNetOutputSize.y},\n                                           CV_INTER_LINEAR | CV_WARP_INVERSE_MAP,\n                                           cv::BORDER_CONSTANT, cv::Scalar(0,0,0));\n\n                            // cv::Mat -> float*\n                            uCharCvMatToFloatPtr(mFaceImageCrop.getPtr(), OP_CV2OPMAT(faceImage), true);\n\n                            // // Debugging\n                            // if (person < 5)\n                            // cv::imshow(\"faceImage\" + std::to_string(person), faceImage);\n\n                            // 1. Caffe deep network\n                            upImpl->spNetCaffe->forwardPass(mFaceImageCrop);\n\n                            // Reshape blobs\n                            if (!upImpl->netInitialized)\n                            {\n                                upImpl->netInitialized = true;\n                                reshapeFaceExtractorCaffe(\n                                    upImpl->spResizeAndMergeCaffe, upImpl->spMaximumCaffe,\n                                    upImpl->spCaffeNetOutputBlob, upImpl->spHeatMapsBlob,\n                                    upImpl->spPeaksBlob, upImpl->mGpuId);\n                            }\n\n                            // 2. Resize heat maps + merge different scales\n                            upImpl->spResizeAndMergeCaffe->Forward(\n                                {upImpl->spCaffeNetOutputBlob.get()}, {upImpl->spHeatMapsBlob.get()});\n\n                            // 3. Get peaks by Non-Maximum Suppression\n                            upImpl->spMaximumCaffe->Forward(\n                                {upImpl->spHeatMapsBlob.get()}, {upImpl->spPeaksBlob.get()});\n\n                            const auto* facePeaksPtr = upImpl->spPeaksBlob->mutable_cpu_data();\n                            for (auto part = 0 ; part < mFaceKeypoints.getSize(1) ; part++)\n                            {\n                                const auto xyIndex = part * mFaceKeypoints.getSize(2);\n                                const auto x = facePeaksPtr[xyIndex];\n                                const auto y = facePeaksPtr[xyIndex + 1];\n                                const auto score = facePeaksPtr[xyIndex + 2];\n                                const auto baseIndex = mFaceKeypoints.getSize(2)\n                                                     * (part + person * mFaceKeypoints.getSize(1));\n                                mFaceKeypoints[baseIndex] = float(\n                                    Mscaling.at<double>(0,0) * x + Mscaling.at<double>(0,1) * y\n                                    + Mscaling.at<double>(0,2));\n                                mFaceKeypoints[baseIndex+1] = float(\n                                    Mscaling.at<double>(1,0) * x + Mscaling.at<double>(1,1) * y\n                                    + Mscaling.at<double>(1,2));\n                                mFaceKeypoints[baseIndex+2] = score;\n                            }\n                            // HeatMaps: storing\n                            if (!mHeatMapTypes.empty())\n                            {\n                                updateFaceHeatMapsForPerson(\n                                    mHeatMaps, person, mHeatMapScaleMode,\n                                    #ifdef USE_CUDA\n                                        upImpl->spHeatMapsBlob->gpu_data()\n                                    #else\n                                        upImpl->spHeatMapsBlob->cpu_data()\n                                    #endif\n                                );\n                            }\n                        }\n                    }\n                    // // Debugging\n                    // cv::imshow(\"AcvInputDataCopy\", cvInputDataCopy);\n                }\n                else\n                    mFaceKeypoints.reset();\n\n                // 5. CUDA sanity check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            #else\n                UNUSED(faceRectangles);\n                UNUSED(cvInputData);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceExtractorNet.cpp",
    "content": "#include <openpose/face/faceExtractorNet.hpp>\n#include <openpose/utilities/check.hpp>\n\nnamespace op\n{\n    FaceExtractorNet::FaceExtractorNet(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                       const std::vector<HeatMapType>& heatMapTypes,\n                                       const ScaleMode heatMapScaleMode) :\n        mNetOutputSize{netOutputSize},\n        mFaceImageCrop{{1, 3, mNetOutputSize.y, mNetOutputSize.x}},\n        mHeatMapScaleMode{heatMapScaleMode},\n        mHeatMapTypes{heatMapTypes},\n        mEnabled{true}\n    {\n        try\n        {\n            // Error check\n            if (mHeatMapScaleMode != ScaleMode::ZeroToOne\n                && mHeatMapScaleMode != ScaleMode::ZeroToOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOne\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::UnsignedChar)\n                error(\"The ScaleMode heatMapScaleMode must be ZeroToOne(FixedAspect), PlusMinusOne(FixedAspect)\"\n                    \" or UnsignedChar.\", __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netOutputSize.x, netInputSize.x, \"Net input and output size must be equal.\",\n                __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netOutputSize.y, netInputSize.y, \"Net input and output size must be equal.\",\n                __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netInputSize.x, netInputSize.y, \"Net input size must be squared.\",\n                __LINE__, __FUNCTION__, __FILE__);\n            // Warnings\n            if (!mHeatMapTypes.empty())\n                opLog(\"Note that only the keypoint heatmaps are available with face heatmaps (no background nor PAFs).\",\n                    Priority::High);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FaceExtractorNet::~FaceExtractorNet()\n    {\n    }\n\n    void FaceExtractorNet::initializationOnThread()\n    {\n        try\n        {\n            // Get thread id\n            mThreadId = {std::this_thread::get_id()};\n            // Deep net initialization\n            netInitializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Array<float> FaceExtractorNet::getFaceKeypoints() const\n    {\n        try\n        {\n            checkThread();\n            return mFaceKeypoints;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    bool FaceExtractorNet::getEnabled() const\n    {\n        try\n        {\n            return mEnabled;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void FaceExtractorNet::setEnabled(const bool enabled)\n    {\n        try\n        {\n            mEnabled = enabled;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Array<float> FaceExtractorNet::getHeatMaps() const\n    {\n        try\n        {\n            checkThread();\n            return mHeatMaps;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    void FaceExtractorNet::checkThread() const\n    {\n        try\n        {\n            if (mThreadId != std::this_thread::get_id())\n                error(\"The CPU/GPU pointer data cannot be accessed from a different thread.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceGpuRenderer.cpp",
    "content": "#include <openpose/face/faceGpuRenderer.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime_api.h>\n#endif\n#include <openpose/face/renderFace.hpp>\n#include <openpose/gpu/cuda.hpp>\n\nnamespace op\n{\n    FaceGpuRenderer::FaceGpuRenderer(const float renderThreshold, const float alphaKeypoint,\n                                     const float alphaHeatMap) :\n        GpuRenderer{renderThreshold, alphaKeypoint, alphaHeatMap},\n        pGpuFace{nullptr},\n        pMaxPtr{nullptr},\n        pMinPtr{nullptr},\n        pScalePtr{nullptr}\n    {\n    }\n\n    FaceGpuRenderer::~FaceGpuRenderer()\n    {\n        try\n        {\n            // Free CUDA pointers - Note that if pointers are 0 (i.e., nullptr), no operation is performed.\n            #ifdef USE_CUDA\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                if (pGpuFace != nullptr)\n                {\n                    cudaFree(pGpuFace);\n                    pGpuFace = nullptr;\n                }\n                if (pMaxPtr != nullptr)\n                {\n                    cudaFree(pMaxPtr);\n                    pMaxPtr = nullptr;\n                }\n                if (pMinPtr != nullptr)\n                {\n                    cudaFree(pMinPtr);\n                    pMinPtr = nullptr;\n                }\n                if (pScalePtr != nullptr)\n                {\n                    cudaFree(pScalePtr);\n                    pScalePtr = nullptr;\n                }\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FaceGpuRenderer::initializationOnThread()\n    {\n        try\n        {\n            opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // GPU memory allocation for rendering\n            #ifdef USE_CUDA\n                cudaMalloc((void**)(&pGpuFace), POSE_MAX_PEOPLE * FACE_NUMBER_PARTS * 3 * sizeof(float));\n                cudaMalloc((void**)&pMaxPtr, sizeof(float) * 2 * FACE_NUMBER_PARTS);\n                cudaMalloc((void**)&pMinPtr, sizeof(float) * 2 * FACE_NUMBER_PARTS);\n                cudaMalloc((void**)&pScalePtr, sizeof(float) * FACE_NUMBER_PARTS);\n            #endif\n            opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FaceGpuRenderer::renderFaceInherited(Array<float>& outputData, const Array<float>& faceKeypoints)\n    {\n        try\n        {\n            // GPU rendering\n            #ifdef USE_CUDA\n                // I prefer std::round(T&) over positiveIntRound(T) for std::atomic\n                const auto elementRendered = spElementToRender->load();\n                const auto numberPeople = faceKeypoints.getSize(0);\n                const Point<unsigned int> frameSize{(unsigned int)outputData.getSize(1), (unsigned int)outputData.getSize(0)};\n                if (numberPeople > 0 && elementRendered == 0)\n                {\n                    // Draw faceKeypoints\n                    cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr(), outputData.getVolume());\n                    cudaMemcpy(pGpuFace, faceKeypoints.getConstPtr(),\n                               faceKeypoints.getSize(0) * FACE_NUMBER_PARTS * 3 * sizeof(float),\n                               cudaMemcpyHostToDevice);\n                    renderFaceKeypointsGpu(\n                        *spGpuMemory, pMaxPtr, pMinPtr, pScalePtr, frameSize, pGpuFace, faceKeypoints.getSize(0),\n                        mRenderThreshold, getAlphaKeypoint());\n                    // CUDA check\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n                // GPU memory to CPU if last renderer\n                gpuToCpuMemoryIfLastRenderer(outputData.getPtr(), outputData.getVolume());\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(outputData);\n                UNUSED(faceKeypoints);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/faceRenderer.cpp",
    "content": "#include <openpose/face/faceRenderer.hpp>\n#include <openpose/face/renderFace.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    void FaceRenderer::renderFace(Array<float>& outputData, const Array<float>& faceKeypoints,\n                                  const float scaleInputToOutput)\n    {\n        try\n        {\n            // Sanity check\n            if (outputData.empty())\n                error(\"Empty Array<float> outputData.\", __LINE__, __FUNCTION__, __FILE__);\n            // Rescale keypoints to output size\n            auto faceKeypointsRescaled = faceKeypoints.clone();\n            scaleKeypoints(faceKeypointsRescaled, scaleInputToOutput);\n            // CPU/GPU rendering\n            renderFaceInherited(outputData, faceKeypointsRescaled);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/renderFace.cpp",
    "content": "#include <openpose/face/renderFace.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    void renderFaceKeypointsCpu(Array<float>& frameArray, const Array<float>& faceKeypoints,\n                                const float renderThreshold)\n    {\n        try\n        {\n            if (!frameArray.empty())\n            {\n                // Parameters\n                const auto thicknessCircleRatio = 1.f/75.f;\n                const auto thicknessLineRatioWRTCircle = 0.334f;\n                const auto& pairs = FACE_PAIRS_RENDER;\n                const auto& scales = FACE_SCALES_RENDER;\n\n                // Render keypoints\n                renderKeypointsCpu(frameArray, faceKeypoints, pairs, FACE_COLORS_RENDER, thicknessCircleRatio,\n                                   thicknessLineRatioWRTCircle, scales, renderThreshold);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/face/renderFace.cu",
    "content": "#include <openpose/face/renderFace.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose_private/gpu/cuda.hu>\n#include <openpose_private/utilities/render.hu>\n\nnamespace op\n{\n    __constant__ const unsigned int PART_PAIRS_GPU[] = {FACE_PAIRS_RENDER_GPU};\n    __constant__ const float SCALES[] = {FACE_SCALES_RENDER_GPU};\n    __constant__ const float COLORS[] = {FACE_COLORS_RENDER_GPU};\n\n    __global__ void getBoundingBoxPerPersonFace(\n        float* maxPtr, float* minPtr, float* scalePtr,const int targetWidth, const int targetHeight,\n        const float* const keypointsPtr, const int numberPeople, const int numberParts, const float threshold)\n    {\n        getBoundingBoxPerPerson(\n            maxPtr, minPtr, scalePtr, targetWidth, targetHeight, keypointsPtr, numberPeople, numberParts, threshold);\n    }\n\n    __global__ void renderFaceParts(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const int targetWidth, const int targetHeight,\n        const float* const facePtr, const int numberPeople, const float threshold, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float sharedMins[2*FACE_MAX_FACES];\n        __shared__ float sharedMaxs[2*FACE_MAX_FACES];\n        __shared__ float sharedScaleF[FACE_MAX_FACES];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(SCALES) / sizeof(SCALES[0]);\n        const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 120.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 250.f;\n\n        // Render key points\n        renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, maxPtr, minPtr, scalePtr, globalIdx, x, y, targetWidth,\n            targetHeight, facePtr, PART_PAIRS_GPU, numberPeople, FACE_NUMBER_PARTS, numberPartPairs, COLORS,\n            numberColors, radius, lineWidth, SCALES, numberScales, threshold, alphaColorToAdd);\n    }\n\n    void renderFaceKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point<unsigned int>& frameSize,\n        const float* const facePtr, const int numberPeople, const float renderThreshold, const float alphaColorToAdd)\n    {\n        try\n        {\n            if (numberPeople > 0)\n            {\n                // Get bounding boxes\n                const dim3 threadsPerBlockBoundBox = {1, 1, 1};\n                const dim3 numBlocksBox{getNumberCudaBlocks(POSE_MAX_PEOPLE, threadsPerBlockBoundBox.x)};\n                getBoundingBoxPerPersonFace<<<threadsPerBlockBoundBox, numBlocksBox>>>(\n                    maxPtr, minPtr, scalePtr, frameSize.x, frameSize.y, facePtr, numberPeople,\n                    FACE_NUMBER_PARTS, renderThreshold);\n                // Draw hands\n                dim3 threadsPerBlock;\n                dim3 numBlocks;\n                getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n                renderFaceParts<<<threadsPerBlock, numBlocks>>>(\n                    framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, facePtr, numberPeople,\n                    renderThreshold, alphaColorToAdd);\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/CMakeLists.txt",
    "content": "set(SOURCES_OP_FILESTREAM bvhSaver.cpp\n    cocoJsonSaver.cpp\n    defineTemplates.cpp\n    fileSaver.cpp\n    fileStream.cpp\n    heatMapSaver.cpp\n    imageSaver.cpp\n    jsonOfstream.cpp\n    keypointSaver.cpp\n    peopleJsonSaver.cpp\n    udpSender.cpp\n    videoSaver.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_FILESTREAM_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_FILESTREAM})\nset(SOURCES_OP_FILESTREAM_WITH_CP ${SOURCES_OP_FILESTREAM_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_FILESTREAM_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  add_library(openpose_filestream ${SOURCES_OP_FILESTREAM})\n\n  target_link_libraries(openpose_filestream openpose_core)\n\n  install(TARGETS openpose_filestream\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/filestream/bvhSaver.cpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#include <openpose/filestream/bvhSaver.hpp>\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/BVHWriter.h>\n#endif\n\nnamespace op\n{\n    struct BvhSaver::ImplBvhSaver\n    {\n        #ifdef USE_3D_ADAM_MODEL\n            // Write BVH file\n            const std::string mBvhFilePath;\n            const double mFps;\n            std::unique_ptr<BVHWriter> spBvhWriter;\n            // Record the translation across frames\n            std::vector<Eigen::Matrix<double, 3, 1>> mTranslations;\n            // Record the pose change\n            std::vector<Eigen::Matrix<double, TotalModel::NUM_JOINTS, 3, Eigen::RowMajor>> mPoses;\n            Eigen::Matrix<double, Eigen::Dynamic, 1> mJ0VecFrame0;\n            bool mInitialized;\n\n            // Shared parameters\n            const std::shared_ptr<const TotalModel> spTotalModel;\n\n            ImplBvhSaver(const std::string bvhFilePath, const std::shared_ptr<const TotalModel>& totalModel,\n                         const double fps) :\n                mBvhFilePath{bvhFilePath},\n                mFps{fps},\n                mInitialized{false},\n                spTotalModel{totalModel}\n            {\n                try\n                {\n                    // Sanity check\n                    if (!mBvhFilePath.empty() && spTotalModel == nullptr)\n                        error(\"Given totalModel is a nullptr.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n\n            void writeBvhOnDisk()\n            {\n                try\n                {\n                    if (!mBvhFilePath.empty())\n                    {\n                        const auto secondsPerFrame = 1./mFps;\n                        const bool unityCompatible = true;\n                        spBvhWriter.reset(new BVHWriter{spTotalModel->m_parent, unityCompatible});\n                        spBvhWriter->parseInput(mJ0VecFrame0, mTranslations, mPoses);\n                        spBvhWriter->writeBVH(mBvhFilePath, secondsPerFrame);\n                    }\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        #endif\n    };\n\n    BvhSaver::BvhSaver(const std::string bvhFilePath, const std::shared_ptr<const TotalModel>& totalModel,\n                       const double fps) :\n        spImpl{std::make_shared<ImplBvhSaver>(bvhFilePath, totalModel, fps)}\n    {\n        try\n        {\n            #ifndef USE_3D_ADAM_MODEL\n                UNUSED(bvhFilePath);\n                UNUSED(totalModel);\n                UNUSED(fps);\n                error(\"OpenPose CMake must be compiled with the `USE_3D_ADAM_MODEL` flag in order to use the\"\n                      \" Adam visualization renderer. Alternatively, set 2-D/3-D rendering with `--display 2`\"\n                      \" or `--display 3`.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    BvhSaver::~BvhSaver()\n    {\n        try\n        {\n            #ifdef USE_3D_ADAM_MODEL\n                spImpl->writeBvhOnDisk();\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void BvhSaver::initializationOnThread()\n    {\n    }\n\n    void BvhSaver::updateBvh(const Eigen::Matrix<double, 62, 3, Eigen::RowMajor>& adamPose,\n                             const Eigen::Vector3d& adamTranslation,\n                             const Eigen::Matrix<double, Eigen::Dynamic, 1>& j0Vec)\n    {\n        try\n        {\n            #ifdef USE_3D_ADAM_MODEL\n                // BVH-Unity generation\n                spImpl->mPoses.push_back(adamPose);\n                spImpl->mTranslations.push_back(adamTranslation);\n                if (!spImpl->mInitialized)\n                {\n                    spImpl->mJ0VecFrame0 = j0Vec;\n                    spImpl->mInitialized = true;\n                }\n            #else\n                UNUSED(adamPose);\n                UNUSED(adamTranslation);\n                UNUSED(j0Vec);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n\n#endif\n"
  },
  {
    "path": "src/openpose/filestream/cocoJsonSaver.cpp",
    "content": "#include <openpose/filestream/cocoJsonSaver.hpp>\n#include <numeric> // std::iota\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/string.hpp>\n\nnamespace op\n{\n    int getLastNumberWithErrorMessage(const std::string& imageName, const CocoJsonFormat cocoJsonFormat)\n    {\n        try\n        {\n            return (int)getLastNumber(imageName);\n        }\n        catch (const std::exception& e)\n        {\n            const std::string errorMessage = \"`--write_coco_json` is to be used with the original \"\n                + std::string(cocoJsonFormat == CocoJsonFormat::Car ? \"car\" : \"COCO\")\n                + \" dataset images. If you are not\"\n                \" applying those, OpenPose cannot obtain the ID from their file names. Image name:\\n\"\n                + imageName + \"\\n Error details: \"\n                + e.what();\n            error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    CocoJsonSaver::CocoJsonSaver(const std::string& filePathToSave, const PoseModel poseModel,\n                                 const bool humanReadable, const int cocoJsonVariants,\n                                 const CocoJsonFormat cocoJsonFormat, const int cocoJsonVariant) :\n        mPoseModel{poseModel},\n        mCocoJsonVariant{cocoJsonVariant}\n    {\n        try\n        {\n            // Sanity checks\n            if (filePathToSave.empty())\n                error(\"Empty path given as output file path for saving COCO JSON format.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (cocoJsonVariants >= 32)\n                error(\"Unknown value for cocoJsonFormat (flag `--write_coco_json_variants`).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Open mJsonOfstreams\n            const auto filePath = getFullFilePathNoExtension(filePathToSave);\n            const auto extension = getFileExtension(filePathToSave);\n            // Body/cars\n            if (cocoJsonVariants % 2 == 1 || cocoJsonVariants < 1)\n                mJsonOfstreams.emplace_back(\n                    std::make_tuple(JsonOfstream{filePathToSave, humanReadable}, cocoJsonFormat, false));\n            // Foot\n            if ((cocoJsonVariants/2) % 2 == 1 || cocoJsonVariants < 1)\n                mJsonOfstreams.emplace_back(\n                    std::make_tuple(JsonOfstream{filePath+\"_foot.\"+extension, humanReadable}, CocoJsonFormat::Foot,\n                        false));\n            // Face\n            if ((cocoJsonVariants/4) % 2 == 1 || cocoJsonVariants < 1)\n                mJsonOfstreams.emplace_back(\n                    std::make_tuple(JsonOfstream{filePath+\"_face.\"+extension, humanReadable}, CocoJsonFormat::Face,\n                        false));\n            // Hand21\n            if ((cocoJsonVariants/8) % 2 == 1 || cocoJsonVariants < 1)\n                mJsonOfstreams.emplace_back(\n                    std::make_tuple(JsonOfstream{filePath+\"_hand21.\"+extension, humanReadable}, CocoJsonFormat::Hand21,\n                        false));\n            // Hand42\n            if ((cocoJsonVariants/16) % 2 == 1 || cocoJsonVariants < 1)\n                mJsonOfstreams.emplace_back(\n                    std::make_tuple(JsonOfstream{filePath+\"_hand42.\"+extension, humanReadable}, CocoJsonFormat::Hand42,\n                        false));\n            // Open array\n            for (auto& jsonOfstream : mJsonOfstreams)\n                std::get<0>(jsonOfstream).arrayOpen();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    CocoJsonSaver::~CocoJsonSaver()\n    {\n        try\n        {\n            for (auto& jsonOfstream : mJsonOfstreams)\n                std::get<0>(jsonOfstream).arrayClose();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void CocoJsonSaver::record(\n        const Array<float>& poseKeypoints, const Array<float>& poseScores, const std::string& imageName,\n        const unsigned long long frameNumber)\n    {\n        try\n        {\n            // Sanity check\n            if ((size_t)poseKeypoints.getSize(0) != poseScores.getVolume())\n                error(\"Dimension mismatch between poseKeypoints and poseScores.\", __LINE__, __FUNCTION__, __FILE__);\n            // Fixed variables\n            const auto numberPeople = poseKeypoints.getSize(0);\n            if (numberPeople > 0)\n            {\n                const auto numberBodyParts = poseKeypoints.getSize(1);\n                // Iterate over all JsonOfstreams\n                for (auto& jsonOfstreamAndFormat : mJsonOfstreams)\n                {\n                    auto& jsonOfstream = std::get<0>(jsonOfstreamAndFormat);\n                    const auto cocoJsonFormat = std::get<1>(jsonOfstreamAndFormat);\n                    auto& firstElementAdded = std::get<2>(jsonOfstreamAndFormat);\n                    // Get indexesInCocoOrder\n                    std::vector<int> indexesInCocoOrder;\n                    // Body/car\n                    auto imageId = frameNumber;\n                    if (cocoJsonFormat == CocoJsonFormat::Body)\n                    {\n                        imageId = getLastNumberWithErrorMessage(imageName, CocoJsonFormat::Body);\n                        // Body\n                        if (numberBodyParts == 23)\n                            indexesInCocoOrder = std::vector<int>{\n                                0, 14,13,16,15,    4,1,5,2,6,    3,10,7,11, 8,    12, 9};\n                        else if (numberBodyParts == 18)\n                            indexesInCocoOrder = std::vector<int>{\n                                0, 15,14,17,16,    5,2,6,3,7,    4,11,8,12, 9,    13,10};\n                        else if (mPoseModel == PoseModel::BODY_25B || mPoseModel == PoseModel::BODY_135)\n                        {\n                            indexesInCocoOrder = std::vector<int>(17);\n                            std::iota(indexesInCocoOrder.begin(), indexesInCocoOrder.end(), 0);\n                        }\n                        else if (numberBodyParts == 19 || numberBodyParts == 25 || numberBodyParts == 59)\n                            indexesInCocoOrder = std::vector<int>{\n                                0, 16,15,18,17,    5,2,6,3,7,    4,12,9,13,10,    14,11};\n                        // else if (numberBodyParts == 23)\n                        //     indexesInCocoOrder = std::vector<int>{\n                        //         18,21,19,22,20,    4,1,5,2,6,    3,13,8,14, 9,    15,10};\n                    }\n                    // Foot\n                    else if (cocoJsonFormat == CocoJsonFormat::Foot)\n                    {\n                        imageId = getLastNumberWithErrorMessage(imageName, CocoJsonFormat::Foot);\n                        if (numberBodyParts == 25 || numberBodyParts > 60)\n                            indexesInCocoOrder = std::vector<int>{19,20,21, 22,23,24};\n                        else if (numberBodyParts == 23)\n                            indexesInCocoOrder = std::vector<int>{17,18,19, 20,21,22};\n                    }\n                    // Face\n                    else if (cocoJsonFormat == CocoJsonFormat::Face)\n                    {\n                        if (numberBodyParts == 135)\n                        {\n                            indexesInCocoOrder = std::vector<int>(68);\n                            std::iota(indexesInCocoOrder.begin(), indexesInCocoOrder.end(), F135);\n                        }\n                    }\n                    // Hand21\n                    else if (cocoJsonFormat == CocoJsonFormat::Hand21)\n                    {\n                        if (numberBodyParts == 135)\n                        {\n                            indexesInCocoOrder = std::vector<int>(21);\n                            indexesInCocoOrder[0] = 10;\n                            std::iota(indexesInCocoOrder.begin()+1, indexesInCocoOrder.end(), H135+20);\n                        }\n                    }\n                    // Hand42\n                    else if (cocoJsonFormat == CocoJsonFormat::Hand42)\n                    {\n                        if (numberBodyParts == 135)\n                        {\n                            indexesInCocoOrder = std::vector<int>(42);\n                            indexesInCocoOrder[0] = 9;\n                            std::iota(indexesInCocoOrder.begin()+1, indexesInCocoOrder.end(), H135);\n                            indexesInCocoOrder[21] = 10;\n                            std::iota(indexesInCocoOrder.begin()+22, indexesInCocoOrder.end(), H135+20);\n                        }\n                    }\n                    // Car\n                    else if (cocoJsonFormat == CocoJsonFormat::Car)\n                    {\n                        imageId = getLastNumberWithErrorMessage(imageName, CocoJsonFormat::Car);\n                        // Car12\n                        if (numberBodyParts == 12)\n                            indexesInCocoOrder = std::vector<int>{0,1,2,3, 4,5,6,7, 8, 8,9,10,11, 11};\n                        // Car22\n                        else if (numberBodyParts == 22)\n                        {\n                            // Dataset 1\n                            if (mCocoJsonVariant == 0)\n                                indexesInCocoOrder = std::vector<int>{0,1,2,3, 6,7, 12,13,14,15, 16,17};\n                            // Dataset 2\n                            else if (mCocoJsonVariant == 1)\n                                indexesInCocoOrder = std::vector<int>{0,1,2,3, 6,7, 12,13,14,15, 20,21};\n                            // Dataset 3\n                            else if (mCocoJsonVariant == 2)\n                                for (auto i = 0 ; i < 20 ; i++)\n                                    indexesInCocoOrder.emplace_back(i);\n                        }\n                    }\n                    // Sanity check\n                    if (indexesInCocoOrder.empty())\n                        error(\"Invalid number of body parts (\" + std::to_string(numberBodyParts) + \").\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    // Save on JSON file\n                    for (auto person = 0 ; person < numberPeople ; person++)\n                    {\n                        // At least 1 valid keypoint?\n                        // Reason: When saving any combination of Body + Foot + Face + Hand, the others might be empty\n                        bool foundAtLeast1Keypoint = false;\n                        for (auto bodyPart = 0u ; bodyPart < indexesInCocoOrder.size() ; bodyPart++)\n                        {\n                            const auto finalIndex = 3*(person*numberBodyParts + indexesInCocoOrder.at(bodyPart));\n                            const auto validPoint = (poseKeypoints[finalIndex+2] > 0.f);\n                            if (validPoint)\n                            {\n                                foundAtLeast1Keypoint = true;\n                                break;\n                            }\n                        }\n\n                        if (foundAtLeast1Keypoint)\n                        {\n                            // Comma at any moment but first element\n                            if (firstElementAdded)\n                            {\n                                jsonOfstream.comma();\n                                jsonOfstream.enter();\n                            }\n                            else\n                                firstElementAdded = true;\n\n                            // New element\n                            jsonOfstream.objectOpen();\n\n                            // image_id\n                            jsonOfstream.key(\"image_id\");\n                            jsonOfstream.plainText(imageId);\n                            jsonOfstream.comma();\n\n                            // category_id\n                            jsonOfstream.key(\"category_id\");\n                            jsonOfstream.plainText(\"1\");\n                            jsonOfstream.comma();\n\n                            // keypoints - i.e., poseKeypoints\n                            jsonOfstream.key(\"keypoints\");\n                            jsonOfstream.arrayOpen();\n                            for (auto bodyPart = 0u ; bodyPart < indexesInCocoOrder.size() ; bodyPart++)\n                            {\n                                const auto finalIndex = 3*(person*numberBodyParts + indexesInCocoOrder.at(bodyPart));\n                                const auto validPoint = (poseKeypoints[finalIndex+2] > 0.f);\n                                jsonOfstream.plainText(validPoint ? poseKeypoints[finalIndex] : -1.f);\n                                jsonOfstream.comma();\n                                jsonOfstream.plainText(validPoint ? poseKeypoints[finalIndex+1] : -1.f);\n                                jsonOfstream.comma();\n                                jsonOfstream.plainText(validPoint ? 1 : 0);\n                                // jsonOfstream.plainText(poseKeypoints[finalIndex+2]); // For debugging\n                                if (bodyPart < indexesInCocoOrder.size() - 1u)\n                                    jsonOfstream.comma();\n                            }\n                            jsonOfstream.arrayClose();\n                            jsonOfstream.comma();\n\n                            // score\n                            jsonOfstream.key(\"score\");\n                            jsonOfstream.plainText(poseScores[person]);\n\n                            jsonOfstream.objectClose();\n                        }\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/defineTemplates.cpp",
    "content": "#include <openpose/filestream/headers.hpp>\n\nnamespace op\n{\n#ifdef USE_3D_ADAM_MODEL\n    DEFINE_TEMPLATE_DATUM(WBvhSaver);\n#endif\n    DEFINE_TEMPLATE_DATUM(WCocoJsonSaver);\n    DEFINE_TEMPLATE_DATUM(WFaceSaver);\n    DEFINE_TEMPLATE_DATUM(WHandSaver);\n    DEFINE_TEMPLATE_DATUM(WHeatMapSaver);\n    DEFINE_TEMPLATE_DATUM(WImageSaver);\n    DEFINE_TEMPLATE_DATUM(WPeopleJsonSaver);\n    DEFINE_TEMPLATE_DATUM(WPoseSaver);\n    DEFINE_TEMPLATE_DATUM(WUdpSender);\n    DEFINE_TEMPLATE_DATUM(WVideoSaver);\n    DEFINE_TEMPLATE_DATUM(WVideoSaver3D);\n}\n"
  },
  {
    "path": "src/openpose/filestream/fileSaver.cpp",
    "content": "#include <openpose/filestream/fileSaver.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n\nnamespace op\n{\n    FileSaver::FileSaver(const std::string& directoryPath) :\n        mDirectoryPath{formatAsDirectory(directoryPath)}\n    {\n        try\n        {\n            makeDirectory(mDirectoryPath);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FileSaver::~FileSaver()\n    {\n    }\n\n    std::string FileSaver::getNextFileName(const unsigned long long index) const\n    {\n        try\n        {\n            const auto stringLength = 12u;\n            return mDirectoryPath + toFixedLengthString(index, stringLength);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string FileSaver::getNextFileName(const std::string& fileName) const\n    {\n        try\n        {\n            return mDirectoryPath + fileName;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/fileStream.cpp",
    "content": "#include <openpose/filestream/fileStream.hpp>\n#include <fstream> // std::ifstream, std::ofstream\n#include <opencv2/highgui/highgui.hpp> // cv::imread\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/string.hpp>\n#include <openpose/filestream/jsonOfstream.hpp>\n\nnamespace op\n{\n    // Private class (on *.cpp)\n    const auto errorMessage = \"Json format only implemented in OpenCV for versions >= 3.0. Check savePoseJson\"\n                              \" instead.\";\n\n    std::string getFullName(const std::string& fileNameNoExtension, const DataFormat dataFormat)\n    {\n        return fileNameNoExtension + \".\" + dataFormatToString(dataFormat);\n    }\n\n    void addKeypointsToJson(\n        JsonOfstream& jsonOfstream, const std::vector<std::pair<Array<float>, std::string>>& keypointVector)\n    {\n        try\n        {\n            // Sanity check\n            for (const auto& keypointPair : keypointVector)\n                if (!keypointPair.first.empty() && keypointPair.first.getNumberDimensions() != 3\n                    && keypointPair.first.getNumberDimensions() != 1)\n                    error(\"keypointVector.getNumberDimensions() != 1 && != 3.\", __LINE__, __FUNCTION__, __FILE__);\n            // Add people keypoints\n            jsonOfstream.key(\"people\");\n            jsonOfstream.arrayOpen();\n            // Ger max numberPeople\n            auto numberPeople = 0;\n            for (auto vectorIndex = 0u ; vectorIndex < keypointVector.size() ; vectorIndex++)\n                numberPeople = fastMax(numberPeople, keypointVector[vectorIndex].first.getSize(0));\n            for (auto person = 0 ; person < numberPeople ; person++)\n            {\n                jsonOfstream.objectOpen();\n                for (auto vectorIndex = 0u ; vectorIndex < keypointVector.size() ; vectorIndex++)\n                {\n                    const auto& keypoints = keypointVector[vectorIndex].first;\n                    const auto& keypointName = keypointVector[vectorIndex].second;\n                    const auto numberElementsPerRaw = keypoints.getSize(1) * keypoints.getSize(2);\n                    jsonOfstream.key(keypointName);\n                    jsonOfstream.arrayOpen();\n                    // Body parts\n                    if (numberElementsPerRaw > 0)\n                    {\n                        const auto finalIndex = person*numberElementsPerRaw;\n                        for (auto element = 0 ; element < numberElementsPerRaw - 1 ; element++)\n                        {\n                            jsonOfstream.plainText(keypoints[finalIndex + element]);\n                            jsonOfstream.comma();\n                        }\n                        // Last element (no comma)\n                        jsonOfstream.plainText(keypoints[finalIndex + numberElementsPerRaw - 1]);\n                    }\n                    // Close array\n                    jsonOfstream.arrayClose();\n                    if (vectorIndex < keypointVector.size()-1)\n                        jsonOfstream.comma();\n                }\n                jsonOfstream.objectClose();\n                if (person < numberPeople-1)\n                {\n                    jsonOfstream.comma();\n                    jsonOfstream.enter();\n                }\n            }\n            // Close bodies array\n            jsonOfstream.arrayClose();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void addCandidatesToJson(\n        JsonOfstream& jsonOfstream, const std::vector<std::vector<std::array<float,3>>>& candidates)\n    {\n        try\n        {\n            // Add body part candidates\n            jsonOfstream.key(\"part_candidates\");\n            jsonOfstream.arrayOpen();\n            // Ger max numberParts\n            const auto numberParts = candidates.size();\n            jsonOfstream.objectOpen();\n            for (auto part = 0u ; part < numberParts ; part++)\n            {\n                // Open array\n                jsonOfstream.key(std::to_string(part));\n                jsonOfstream.arrayOpen();\n                // Iterate over part candidates\n                const auto& partCandidates = candidates[part];\n                const auto numberPartCandidates = partCandidates.size();\n                // Body part candidates\n                for (auto bodyPart = 0u ; bodyPart < numberPartCandidates ; bodyPart++)\n                {\n                    const auto& candidate = partCandidates[bodyPart];\n                    jsonOfstream.plainText(candidate[0]);\n                    jsonOfstream.comma();\n                    jsonOfstream.plainText(candidate[1]);\n                    jsonOfstream.comma();\n                    jsonOfstream.plainText(candidate[2]);\n                    if (bodyPart < numberPartCandidates-1)\n                        jsonOfstream.comma();\n                }\n                jsonOfstream.arrayClose();\n                if (part < numberParts-1)\n                    jsonOfstream.comma();\n            }\n            jsonOfstream.objectClose();\n            // Close array\n            jsonOfstream.arrayClose();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n\n\n\n\n    // Public classes (on *.hpp)\n    std::string dataFormatToString(const DataFormat dataFormat)\n    {\n        try\n        {\n            if (dataFormat == DataFormat::Json)\n                return \"json\";\n            else if (dataFormat == DataFormat::Xml)\n                return \"xml\";\n            else if (dataFormat == DataFormat::Yaml)\n                return \"yaml\";\n            else if (dataFormat == DataFormat::Yml)\n                return \"yml\";\n            else\n            {\n                error(\"Undefined DataFormat.\", __LINE__, __FUNCTION__, __FILE__);\n                return \"\";\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    DataFormat stringToDataFormat(const std::string& dataFormat)\n    {\n        try\n        {\n            if (dataFormat == \"json\")\n                return DataFormat::Json;\n            else if (dataFormat == \"xml\")\n                return DataFormat::Xml;\n            else if (dataFormat == \"yaml\")\n                return DataFormat::Yaml;\n            else if (dataFormat == \"yml\")\n                return DataFormat::Yml;\n            else\n            {\n                error(\"String does not correspond to any known format (json, xml, yaml, yml)\",\n                      __LINE__, __FUNCTION__, __FILE__);\n                return DataFormat::Json;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return DataFormat::Json;\n        }\n    }\n\n    void saveFloatArray(const Array<float>& array, const std::string& fullFilePath)\n    {\n        try\n        {\n            // Open file\n            std::ofstream outputFile;\n            outputFile.open(fullFilePath, std::ios::binary);\n            // Save #dimensions\n            const auto numberDimensions = (float)(array.getNumberDimensions());\n            outputFile.write((char*)&numberDimensions, sizeof(float));\n            // Save dimensions\n            for (const auto& sizeI : array.getSize())\n            {\n                const float sizeIFloat = (float) sizeI;\n                outputFile.write((char*)&sizeIFloat, sizeof(float));\n            }\n            // Save each value\n            outputFile.write((char*)&array[0], array.getVolume() * sizeof(float));\n            // Close file\n            outputFile.close();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void saveData(const std::vector<Matrix>& opMats, const std::vector<std::string>& cvMatNames,\n                  const std::string& fileNameNoExtension, const DataFormat dataFormat)\n    {\n        try\n        {\n            OP_OP2CVVECTORMAT(cvMats, opMats)\n            // Sanity checks\n            if (dataFormat == DataFormat::Json && CV_MAJOR_VERSION < 3)\n                error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n            if (cvMats.size() != cvMatNames.size())\n                error(\"cvMats.size() != cvMatNames.size() (\" + std::to_string(cvMats.size())\n                      + \" vs. \" + std::to_string(cvMatNames.size()) + \")\", __LINE__, __FUNCTION__, __FILE__);\n            // Save cv::Mat data\n            cv::FileStorage fileStorage{getFullName(fileNameNoExtension, dataFormat), cv::FileStorage::WRITE};\n            for (auto i = 0u ; i < cvMats.size() ; i++)\n                fileStorage << cvMatNames[i] << (cvMats[i].empty() ? cv::Mat() : cvMats[i]);\n            // Release file\n            fileStorage.release();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void saveData(const Matrix& opMat, const std::string cvMatName, const std::string& fileNameNoExtension,\n                  const DataFormat dataFormat)\n    {\n        try\n        {\n            saveData(std::vector<Matrix>{opMat}, std::vector<std::string>{cvMatName}, fileNameNoExtension,\n                     dataFormat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::vector<Matrix> loadData(const std::vector<std::string>& cvMatNames, const std::string& fileNameNoExtension,\n                                  const DataFormat dataFormat)\n    {\n        try\n        {\n            // Sanity check\n            if (dataFormat == DataFormat::Json && CV_MAJOR_VERSION < 3)\n                error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n            // File name\n            const auto fileName = getFullName(fileNameNoExtension, dataFormat);\n            // Sanity check\n            if (!existFile(fileName))\n                error(\"File to be read does not exist: \" + fileName + \".\", __LINE__, __FUNCTION__, __FILE__);\n            // Read file\n            cv::FileStorage fileStorage{fileName, cv::FileStorage::READ};\n            std::vector<cv::Mat> cvMats(cvMatNames.size());\n            for (auto i = 0u ; i < cvMats.size() ; i++)\n                fileStorage[cvMatNames[i]] >> cvMats[i];\n            fileStorage.release();\n            OP_CV2OPVECTORMAT(opMats, cvMats)\n            return opMats;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    Matrix loadData(const std::string& cvMatName, const std::string& fileNameNoExtension, const DataFormat dataFormat)\n    {\n        try\n        {\n            return OP_CV2OPMAT(loadData(std::vector<std::string>{cvMatName}, fileNameNoExtension, dataFormat)[0]);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    void savePeopleJson(\n        const Array<float>& keypoints, const std::vector<std::vector<std::array<float,3>>>& candidates,\n        const std::string& keypointName, const std::string& fileName, const bool humanReadable)\n    {\n        try\n        {\n            savePeopleJson(\n                std::vector<std::pair<Array<float>, std::string>>{std::make_pair(keypoints, keypointName)},\n                candidates, fileName, humanReadable\n            );\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void savePeopleJson(\n        const std::vector<std::pair<Array<float>, std::string>>& keypointVector,\n        const std::vector<std::vector<std::array<float,3>>>& candidates, const std::string& fileName,\n        const bool humanReadable)\n    {\n        try\n        {\n            // Sanity check\n            for (const auto& keypointPair : keypointVector)\n                if (!keypointPair.first.empty() && keypointPair.first.getNumberDimensions() != 3\n                    && keypointPair.first.getNumberDimensions() != 1)\n                    error(\"keypointVector.getNumberDimensions() != 1 && != 3.\", __LINE__, __FUNCTION__, __FILE__);\n            // Record frame on desired path\n            JsonOfstream jsonOfstream{fileName, humanReadable};\n            jsonOfstream.objectOpen();\n            // Add version\n            // Version 0.1: Body keypoints (2-D)\n            // Version 1.0: Added face and hands (2-D)\n            // Version 1.1: Added candidates\n            // Version 1.2: Added body, face, and hands (3-D)\n            // Version 1.3: Added person ID (for temporal consistency)\n            jsonOfstream.version(\"1.3\");\n            jsonOfstream.comma();\n            // Add people keypoints\n            addKeypointsToJson(jsonOfstream, keypointVector);\n            // Add body part candidates\n            if (!candidates.empty())\n            {\n                jsonOfstream.comma();\n                addCandidatesToJson(jsonOfstream, candidates);\n            }\n            // Close object\n            jsonOfstream.objectClose();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void saveImage(const Matrix& matrix, const std::string& fullFilePath,\n                   const std::vector<int>& openCvCompressionParams)\n    {\n        try\n        {\n            const cv::Mat cvMat = OP_OP2CVCONSTMAT(matrix);\n            if (!cv::imwrite(fullFilePath, cvMat, openCvCompressionParams))\n                error(\"Image could not be saved on \" + fullFilePath + \".\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix loadImage(const std::string& fullFilePath, const int openCvFlags)\n    {\n        try\n        {\n            cv::Mat cvMat = cv::imread(fullFilePath, openCvFlags);\n            if (cvMat.empty())\n                opLog(\"Empty image on path: \" + fullFilePath + \".\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n            return OP_CV2OPMAT(cvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<std::array<Rectangle<float>, 2>> loadHandDetectorTxt(const std::string& txtFilePath)\n    {\n        try\n        {\n            std::vector<std::array<Rectangle<float>, 2>> handRectangles;\n\n            std::string line;\n            std::ifstream jsonFile{txtFilePath};\n            if (jsonFile.is_open())\n            {\n                while (std::getline(jsonFile, line))\n                {\n                    const auto splittedStrings = splitString(line, \" \");\n                    std::vector<float> splittedInts;\n                    for (auto splittedString : splittedStrings)\n                        splittedInts.emplace_back(std::stof(splittedString));\n                    if (splittedInts.size() != 4u)\n                        error(\"splittedInts.size() != 4, but splittedInts.size() = \"\n                              + std::to_string(splittedInts.size()) + \".\", __LINE__, __FUNCTION__, __FILE__);\n                    const Rectangle<float> handRectangleZero;\n                    const Rectangle<float> handRectangle{splittedInts[0], splittedInts[1], splittedInts[2],\n                                                         splittedInts[3]};\n                    if (getFileNameNoExtension(txtFilePath).back() == 'l')\n                        handRectangles.emplace_back(std::array<Rectangle<float>, 2>{handRectangle, handRectangleZero});\n                    else\n                        handRectangles.emplace_back(std::array<Rectangle<float>, 2>{handRectangleZero, handRectangle});\n                }\n                jsonFile.close();\n            }\n            else\n                error(\"Unable to open file \" + txtFilePath + \".\", __LINE__, __FUNCTION__, __FILE__);\n\n            return handRectangles;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/heatMapSaver.cpp",
    "content": "#include <openpose/filestream/heatMapSaver.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose/filestream/fileStream.hpp>\n\nnamespace op\n{\n    HeatMapSaver::HeatMapSaver(const std::string& directoryPath, const std::string& imageFormat) :\n        FileSaver{directoryPath},\n        mImageFormat{imageFormat}\n    {\n        try\n        {\n            if (mImageFormat.empty())\n                error(\"The string imageFormat should not be empty.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    HeatMapSaver::~HeatMapSaver()\n    {\n    }\n\n    void HeatMapSaver::saveHeatMaps(const std::vector<Array<float>>& heatMaps, const std::string& fileName) const\n    {\n        try\n        {\n            // Record cv::mat\n            if (!heatMaps.empty())\n            {\n                // File path (no extension)\n                const auto fileNameNoExtension = getNextFileName(fileName);\n\n                // Get names for each heatMap\n                std::vector<std::string> fileNames(heatMaps.size());\n                for (auto i = 0u; i < fileNames.size(); i++)\n                    fileNames[i] = {fileNameNoExtension + (i != 0 ? \"_\" + std::to_string(i) : \"\") + \".\" + mImageFormat};\n\n                // Saving on custom floating type \"float\". Format it:\n                // First, the number of dimensions of the array.\n                // Next elements: the size of each dimension.\n                // Next: all the elements.\n                if (mImageFormat == \"float\")\n                {\n                    if (heatMaps.size() > 1)\n                        error(\"Float only implemented for heatMaps.size() == 1.\", __LINE__, __FUNCTION__, __FILE__);\n                    for (auto i = 0u; i < heatMaps.size(); i++)\n                        saveFloatArray(heatMaps[i], fileNames[i]);\n                }\n                // Saving on integer type (jpg, png, etc.)\n                else\n                {\n                    // heatMaps -> cvOutputDatas\n                    std::vector<Matrix> cvOutputDatas(heatMaps.size());\n                    for (auto i = 0u; i < cvOutputDatas.size(); i++)\n                        unrollArrayToUCharCvMat(cvOutputDatas[i], heatMaps[i]);\n                    // Save each heatMap\n                    for (auto i = 0u; i < cvOutputDatas.size(); i++)\n                        saveImage(cvOutputDatas[i], fileNames[i]);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/imageSaver.cpp",
    "content": "#include <openpose/filestream/imageSaver.hpp>\n#include <openpose/filestream/fileStream.hpp>\n\nnamespace op\n{\n    ImageSaver::ImageSaver(const std::string& directoryPath, const std::string& imageFormat) :\n        FileSaver{directoryPath},\n        mImageFormat{imageFormat}\n    {\n        try\n        {\n            if (mImageFormat.empty())\n                error(\"The string imageFormat should not be empty.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    ImageSaver::~ImageSaver()\n    {\n    }\n\n    void ImageSaver::saveImages(const Matrix& cvOutputData, const std::string& fileName) const\n    {\n        try\n        {\n            saveImages(std::vector<Matrix>{cvOutputData}, fileName);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void ImageSaver::saveImages(const std::vector<Matrix>& matOutputDatas, const std::string& fileName) const\n    {\n        try\n        {\n            // Record cv::mat\n            if (!matOutputDatas.empty())\n            {\n                // File path (no extension)\n                const auto fileNameNoExtension = getNextFileName(fileName) + \"_rendered\";\n\n                // Get names for each image\n                std::vector<std::string> fileNames(matOutputDatas.size());\n                for (auto i = 0u; i < fileNames.size(); i++)\n                    fileNames[i] = {fileNameNoExtension + (i != 0 ? \"_\" + std::to_string(i) : \"\") + \".\" + mImageFormat};\n\n                // Save each image\n                for (auto i = 0u; i < matOutputDatas.size(); i++)\n                    saveImage(matOutputDatas[i], fileNames[i]);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/jsonOfstream.cpp",
    "content": "#include <openpose/filestream/jsonOfstream.hpp>\n\nnamespace op\n{\n    void enterAndTab(std::ofstream& ofstream, const bool humanReadable, const long long bracesCounter,\n                     const long long bracketsCounter)\n    {\n        try\n        {\n            if (humanReadable)\n            {\n                ofstream << \"\\n\";\n                for (auto i = 0ll ; i < bracesCounter + bracketsCounter ; i++)\n                    ofstream << \"\\t\";\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    JsonOfstream::JsonOfstream(const std::string& filePath, const bool humanReadable) :\n        mHumanReadable{humanReadable},\n        mBracesCounter{0},\n        mBracketsCounter{0},\n        upOfstream{new std::ofstream{filePath}}\n    {\n        try\n        {\n            if (!filePath.empty() && !upOfstream->is_open())\n                error(\"Json file \" + filePath + \" could not be opened.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    JsonOfstream::JsonOfstream(JsonOfstream&& jsonOfstream) :\n        mHumanReadable{jsonOfstream.mHumanReadable},\n        mBracesCounter{jsonOfstream.mBracesCounter},\n        mBracketsCounter{jsonOfstream.mBracketsCounter}\n    {\n        try\n        {\n            upOfstream = std::move(jsonOfstream.upOfstream);\n            // std::swap(upOfstream, jsonOfstream.upOfstream);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    JsonOfstream& JsonOfstream::operator=(JsonOfstream&& jsonOfstream)\n    {\n        try\n        {\n            mHumanReadable = jsonOfstream.mHumanReadable;\n            mBracesCounter = jsonOfstream.mBracesCounter;\n            mBracketsCounter = jsonOfstream.mBracketsCounter;\n            upOfstream = std::move(jsonOfstream.upOfstream);\n            // std::swap(upOfstream, jsonOfstream.upOfstream);\n            // Return\n            return *this;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return *this;\n        }\n    }\n\n    JsonOfstream::~JsonOfstream()\n    {\n        try\n        {\n            // Moved(std::unique_ptr) will be a nullptr in the old one\n            if (upOfstream != nullptr)\n            {\n                enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n\n                if (mBracesCounter != 0 || mBracketsCounter != 0)\n                {\n                    std::string errorMessage = \"Json file wronly generated\";\n                    if (mBracesCounter != 0)\n                        errorMessage += \", number \\\"{\\\" != number \\\"}\\\": \" + std::to_string(mBracesCounter) + \".\";\n                    else if (mBracketsCounter != 0)\n                        errorMessage += \", number \\\"[\\\" != number \\\"]\\\": \" + std::to_string(mBracketsCounter) + \".\";\n                    else\n                        errorMessage += \".\";\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::objectOpen()\n    {\n        try\n        {\n            mBracesCounter++;\n            *upOfstream << \"{\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::objectClose()\n    {\n        try\n        {\n            mBracesCounter--;\n            enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n            *upOfstream << \"}\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::arrayOpen()\n    {\n        try\n        {\n            mBracketsCounter++;\n            *upOfstream << \"[\";\n            enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::arrayClose()\n    {\n        try\n        {\n            mBracketsCounter--;\n            enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n            *upOfstream << \"]\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::version(const std::string& version)\n    {\n        try\n        {\n            key(\"version\");\n            plainText(version);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::key(const std::string& string)\n    {\n        try\n        {\n            enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n            *upOfstream << \"\\\"\" + string + \"\\\":\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void JsonOfstream::enter()\n    {\n        try\n        {\n            enterAndTab(*upOfstream, mHumanReadable, mBracesCounter, mBracketsCounter);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/keypointSaver.cpp",
    "content": "#include <openpose/filestream/keypointSaver.hpp>\n#include <openpose/filestream/fileStream.hpp>\n\nnamespace op\n{\n    KeypointSaver::KeypointSaver(const std::string& directoryPath, const DataFormat format) :\n        FileSaver{directoryPath},\n        mFormat{format}\n    {\n    }\n\n    KeypointSaver::~KeypointSaver()\n    {\n    }\n\n    void KeypointSaver::saveKeypoints(const std::vector<Array<float>>& keypointVector, const std::string& fileName, const std::string& keypointName) const\n    {\n        try\n        {\n            if (!keypointVector.empty())\n            {\n                // File path (no extension)\n                const auto fileNameNoExtension = getNextFileName(fileName) + \"_\" + keypointName;\n\n                // Get vector of people poses\n                std::vector<Matrix> matPoses(keypointVector.size());\n                for (auto i = 0u; i < keypointVector.size(); i++)\n                    matPoses[i] = keypointVector[i].getConstCvMat();\n\n                // Get names inside file\n                std::vector<std::string> keypointVectorNames(matPoses.size());\n                for (auto i = 0u; i < matPoses.size(); i++)\n                    keypointVectorNames[i] = {keypointName + \"_\" + std::to_string(i)};\n\n                // Record people poses in desired format\n                saveData(matPoses, keypointVectorNames, fileNameNoExtension, mFormat);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/peopleJsonSaver.cpp",
    "content": "#include <openpose/filestream/peopleJsonSaver.hpp>\n#include <openpose/filestream/fileStream.hpp>\n\nnamespace op\n{\n    PeopleJsonSaver::PeopleJsonSaver(const std::string& directoryPath) :\n        FileSaver{directoryPath}\n    {\n    }\n\n    PeopleJsonSaver::~PeopleJsonSaver()\n    {\n    }\n\n    void PeopleJsonSaver::save(\n        const std::vector<std::pair<Array<float>, std::string>>& keypointVector,\n        const std::vector<std::vector<std::array<float,3>>>& candidates, const std::string& fileName,\n        const bool humanReadable) const\n    {\n        try\n        {\n            // Record json\n            const auto finalFileName = getNextFileName(fileName) + \".json\";\n            savePeopleJson(keypointVector, candidates, finalFileName, humanReadable);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/udpSender.cpp",
    "content": "#include <openpose/filestream/udpSender.hpp>\n#ifdef USE_ASIO\n    #include <iostream>\n    #include <asio.hpp>\n#endif\n#ifdef USE_EIGEN\n    #include <Eigen/Core>\n#endif\n#include <openpose/filestream/fileStream.hpp>\n\nnamespace op\n{\n    #ifdef USE_ASIO\n        class UdpClient\n        {\n        public:\n            UdpClient(const std::string& host, const std::string& port) :\n                mIoService{},\n                mUdpSocket{mIoService, asio::ip::udp::endpoint(asio::ip::udp::v4(), 0)}\n            {\n                try\n                {\n                    asio::ip::udp::resolver resolver{mIoService};\n                    asio::ip::udp::resolver::query query{asio::ip::udp::v4(), host, port};\n                    asio::ip::udp::resolver::iterator iter = resolver.resolve(query);\n                    mUdpEndpoint = *iter;\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n\n            ~UdpClient()\n            {\n                try\n                {\n                    mUdpSocket.close();\n                }\n                catch (const std::exception& e)\n                {\n                    errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n\n            void send(const std::string& msg)\n            {\n                try\n                {\n                    mUdpSocket.send_to(asio::buffer(msg, msg.size()), mUdpEndpoint);\n                    // std::cout << \"sent data: \" << msg << std::endl;\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n\n        private:\n            asio::io_service mIoService;\n            asio::ip::udp::socket mUdpSocket;\n            asio::ip::udp::endpoint mUdpEndpoint;\n        };\n\n\n        std::string vectorToJson(const float x, const float y, const float z)\n        {\n            return std::string{\"{\"} +\n                \"\\\"x\\\":\" + std::to_string(x) + \",\" +\n                \"\\\"y\\\":\" + std::to_string(y) + \",\" +\n                \"\\\"z\\\":\" + std::to_string(z) + \"}\";\n        }\n    #endif\n\n    struct UdpSender::ImplUdpSender\n    {\n        #ifdef USE_ASIO\n            // Used when increasing spCaffeNets\n            UdpClient mUdpClient;\n\n            ImplUdpSender(const std::string& udpHost, const std::string& udpPort) :\n                mUdpClient(udpHost, udpPort)\n            {\n            }\n        #endif\n    };\n\n    UdpSender::UdpSender(const std::string& udpHost, const std::string& udpPort)\n        #ifdef USE_ASIO\n            : spImpl{new ImplUdpSender{udpHost, udpPort}}\n        #endif\n    {\n        try\n        {\n            // error(\"UdpSender (`--udp_host` and `--udp_port` flags) buggy and not working yet, but we are\"\n            //       \"working on it! Coming soon!\", __LINE__, __FUNCTION__, __FILE__);\n            #if !defined(USE_ASIO) || !defined(USE_EIGEN)\n                error(\"Both `WITH_ASIO` and `WITH_EIGEN` flags must be enabled in CMake for UDP sender.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n                UNUSED(udpHost);\n                UNUSED(udpPort);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    UdpSender::~UdpSender()\n    {\n    }\n\n    void UdpSender::sendJointAngles(const double* const adamPosePtr, const int adamPoseRows,\n                                    const double* const adamTranslationPtr,\n                                    const double* const adamFaceCoeffsExpPtr, const int faceCoeffRows)\n    {\n        #if defined(USE_ASIO) && defined(USE_EIGEN)\n            try\n            {\n                if (adamPosePtr != nullptr && adamTranslationPtr != nullptr && adamFaceCoeffsExpPtr != nullptr)\n                {\n                    const Eigen::Map<const Eigen::Vector3d> adamTranslation(adamTranslationPtr);\n                    const Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> adamPose(\n                        adamPosePtr, adamPoseRows, 3);\n                    const Eigen::Map<const Eigen::VectorXd> adamFaceCoeffsExp(adamFaceCoeffsExpPtr, faceCoeffRows);\n\n                    const std::string prefix = \"AnimData:\";\n                    const std::string totalPositionString = \"\\\"totalPosition\\\":\"\n                        + vectorToJson(adamTranslation(0), adamTranslation(1), adamTranslation(2));\n                    std::string jointAnglesString = \"\\\"jointAngles\\\":[\";\n                    for (int i = 0; i < adamPoseRows; i++)\n                    {\n                        jointAnglesString += vectorToJson(adamPose(i, 0), adamPose(i, 1), adamPose(i, 2));\n                        if (i != adamPoseRows - 1)\n                        {\n                            jointAnglesString += \",\";\n                        }\n                    }\n                    jointAnglesString += \"]\";\n\n                    std::string facialParamsString = \"\\\"facialParams\\\":[\";\n                    for (int i = 0; i < faceCoeffRows; i++)\n                    {\n                        facialParamsString += std::to_string(adamFaceCoeffsExp(i));\n                        if (i != faceCoeffRows - 1)\n                        {\n                            facialParamsString += \",\";\n                        }\n                    }\n                    facialParamsString += \"]\";\n\n                    // facialParamsString + std::to_string(mouth_open) + \",\" + std::to_string(leye_open) + \",\" + std::to_string(reye_open) + \"]\";\n\n                    // std::string rootHeightString = \"\\\"rootHeight\\\":\" + std::to_string(dist_root_foot);\n\n                    const std::string data = prefix + \"{\" + facialParamsString\n                                           + \",\" + totalPositionString\n                                           + \",\" + jointAnglesString + \"}\";\n\n                    spImpl->mUdpClient.send(data);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #else\n            UNUSED(adamPosePtr);\n            UNUSED(adamPoseRows);\n            UNUSED(adamTranslationPtr);\n            UNUSED(adamFaceCoeffsExpPtr);\n            UNUSED(faceCoeffRows);\n        #endif\n    }\n}\n"
  },
  {
    "path": "src/openpose/filestream/videoSaver.cpp",
    "content": "#include <openpose/filestream/videoSaver.hpp>\n#include <opencv2/highgui/highgui.hpp> // cv::VideoWriter\n#include <openpose/filestream/imageSaver.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/string.hpp>\n\nnamespace op\n{\n    const auto RANDOM_TEXT = \"_r8904530ijyiopf9034jiop4g90j0yh795640h38j\";\n\n    struct VideoSaver::ImplVideoSaver\n    {\n        const std::string mVideoSaverPath;\n        const int mCvFourcc;\n        const double mFps;\n        const std::string mAddAudioFromThisVideo;\n        const bool mUseFfmpeg;\n        Point<int> mCvSize;\n        bool mVideoStarted;\n        unsigned long long mImageSaverCounter;\n        cv::VideoWriter mVideoWriter;\n        std::unique_ptr<ImageSaver> upImageSaver;\n        std::string mTempImageFolder;\n\n        ImplVideoSaver(const std::string& videoSaverPath, const int cvFourcc, const double fps,\n                       const std::string& addAudioFromThisVideo) :\n            mVideoSaverPath{videoSaverPath},\n            mCvFourcc{cvFourcc},\n            mFps{fps},\n            mAddAudioFromThisVideo{addAudioFromThisVideo},\n            mUseFfmpeg{toLower(getFileExtension(videoSaverPath)) == \"mp4\"},\n            mVideoStarted{false},\n            mImageSaverCounter{0ull}\n        {\n            try\n            {\n                if (mUseFfmpeg)\n                    mTempImageFolder = getFullFilePathNoExtension(mVideoSaverPath) + RANDOM_TEXT;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    };\n\n    cv::VideoWriter openVideo(const std::string& videoSaverPath, const int cvFourcc, const double fps,\n                              const Point<int>& cvSize)\n    {\n        try\n        {\n            // Open video\n            const cv::VideoWriter videoWriter{\n                videoSaverPath, cvFourcc, fps, cv::Size{cvSize.x, cvSize.y}};\n            // Check it was successfully opened\n            if (!videoWriter.isOpened())\n            {\n                const std::string errorMessage{\n                    \"Video to write frames could not be opened as `\" + videoSaverPath + \"`. Please, check that:\"\n                    \"\\n\\t1. The path ends in `.avi`.\\n\\t2. The parent folder exists.\\n\\t3. OpenCV is properly\"\n                    \" compiled with the FFmpeg codecs in order to save video.\"\n                    \"\\n\\t4. You are not saving in a protected folder. If you desire to save a video in a\"\n                    \" protected folder, use sudo (Ubuntu) or execute the binary file as administrator (Windows).\"};\n                error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Return video\n            return videoWriter;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return cv::VideoWriter{};\n        }\n    }\n\n    VideoSaver::VideoSaver(const std::string& videoSaverPath, const int cvFourcc, const double fps,\n                           const std::string& addAudioFromThisVideo) :\n        upImpl{new ImplVideoSaver{videoSaverPath, cvFourcc, fps, addAudioFromThisVideo}}\n    {\n        try\n        {\n            // Sanity checks\n            if (fps <= 0.)\n                error(\"Desired fps (frame rate) to save the video is <= 0.\", __LINE__, __FUNCTION__, __FILE__);\n            #ifdef _WIN32\n                if (upImpl->mUseFfmpeg)\n                    error(\"MP4 recording requires an Ubuntu or Mac machine.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n            if (upImpl->mUseFfmpeg && system(\"ffmpeg -version\") != 0)\n                error(\"In order to save the video in MP4 format, FFmpeg must be installed on your system.\"\n                      \" Please, use an `avi` output format (e.g., `--write_video output.avi`) or install FFmpeg\"\n                      \" by running `sudo apt-get install ffmpeg` (Ubuntu) or an analogous command.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (!upImpl->mAddAudioFromThisVideo.empty() && !upImpl->mUseFfmpeg)\n                error(\"In order to save the video with audio, it must be in MP4 format. So either 1) do not set\"\n                      \" `--write_video_audio` or 2) make sure `--write_video` finishes in `.mp4`.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    VideoSaver::~VideoSaver()\n    {\n        try\n        {\n            // Images --> Video\n            if (upImpl->mUseFfmpeg)\n            {\n                opLog(\"JPG images temporarily generated in \" + upImpl->mTempImageFolder + \".\", op::Priority::High);\n                // FFmpeg command: Save video from images (override if video with same name exists)\n                // Framerate works with both `-r` and `-framerate` for an image folder. Source:\n                //     https://stackoverflow.com/questions/51143100/framerate-vs-r-vs-filter-fps\n                // Very important: Either FPS flag must go before `-i`!!! Otherwise, it would either not work (`-r`)\n                // or do a weird resample (`-framerate`)\n                const std::string imageToVideoCommand = \"ffmpeg -y -framerate \" + std::to_string(upImpl->mFps)\n                    + \" -i '\" + upImpl->mTempImageFolder + \"/%12d_rendered.jpg'\"\n                    + \" -c:v libx264 -pix_fmt yuv420p '\"\n                    + upImpl->mVideoSaverPath + \"'\";\n                opLog(\"Creating MP4 video out of JPG images by running:\\n\" + imageToVideoCommand + \"\\n\",\n                    op::Priority::High);\n                auto codeAnswerVideo = system(imageToVideoCommand.c_str());\n                // Remove temporary images\n                if (codeAnswerVideo == 0)\n                {\n                    codeAnswerVideo = system((\"rm -rf '\" + upImpl->mTempImageFolder + \"'\").c_str());\n                    opLog(\"Video saved and temporary image folder removed.\", op::Priority::High);\n                }\n                // Sanity check\n                if (codeAnswerVideo != 0)\n                    opLog(\"\\nVideo \" + upImpl->mVideoSaverPath + \" could not be saved (exit code: \"\n                        + std::to_string(codeAnswerVideo) + \"). Make sure you can manually run the following command\"\n                        \" (with no errors) from the terminal:\\n\" + imageToVideoCommand, op::Priority::High);\n                // Video (no sound) --> Video (with sound)\n                if (!upImpl->mAddAudioFromThisVideo.empty())\n                {\n                    const auto tempOutput = upImpl->mVideoSaverPath + RANDOM_TEXT + \".mp4\";\n                    const auto audioCommand = \"ffmpeg -y -i '\" + upImpl->mVideoSaverPath\n                        + \"' -i '\" + upImpl->mAddAudioFromThisVideo + \"' -codec copy -shortest '\" + tempOutput + \"'\";\n                    opLog(\"Adding audio to video by running:\\n\" + audioCommand, op::Priority::High);\n                    auto codeAnswerAudio = system(audioCommand.c_str());\n                    // Move temp output to real output\n                    if (codeAnswerAudio == 0)\n                        codeAnswerAudio = system((\"mv '\" + tempOutput + \"' '\" + upImpl->mVideoSaverPath + \"'\").c_str());\n                    // Sanity check\n                    if (codeAnswerAudio != 0)\n                        opLog(\"\\nVideo \" + upImpl->mVideoSaverPath + \" could not be saved with audio (exit code: \"\n                            + std::to_string(codeAnswerAudio) + \"). Make sure you can manually run the following command\"\n                            \" (with no errors) from the terminal:\\n\" + audioCommand, op::Priority::High);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool VideoSaver::isOpened()\n    {\n        try\n        {\n            // FFmpeg video\n            if (upImpl->mUseFfmpeg)\n                return (upImpl->upImageSaver != nullptr);\n            // OpenCV video\n            else\n                return upImpl->mVideoWriter.isOpened();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void VideoSaver::write(const Matrix& matToSave)\n    {\n        try\n        {\n            write(std::vector<Matrix>{matToSave});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void VideoSaver::write(const std::vector<Matrix>& matsToSave)\n    {\n        try\n        {\n            OP_OP2CVVECTORMAT(cvMats, matsToSave);\n            // Sanity check\n            if (cvMats.empty())\n                error(\"The image(s) to be saved cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            for (const auto& cvMat : cvMats)\n                if (cvMat.empty())\n                    error(\"The image(s) to be saved cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            // Open video (1st frame)\n            // Done here and not in the constructor to handle cases where the resolution is not known (e.g.,\n            // reading images or multiple cameras)\n            if (!upImpl->mVideoStarted)\n            {\n                upImpl->mVideoStarted = true;\n                const auto cvSize = cvMats.at(0).size();\n                upImpl->mCvSize = Point<int>{(int)cvMats.size()*cvSize.width, cvSize.height};\n                // FFmpeg video\n                if (upImpl->mUseFfmpeg)\n                {\n                    opLog(\"Temporarily saving video frames as JPG images in: \" + upImpl->mTempImageFolder,\n                        op::Priority::High);\n                    upImpl->upImageSaver.reset(new ImageSaver{upImpl->mTempImageFolder, \"jpg\"});\n                }\n                // OpenCV video\n                else\n                    upImpl->mVideoWriter = openVideo(\n                        upImpl->mVideoSaverPath, upImpl->mCvFourcc, upImpl->mFps, upImpl->mCvSize);\n            }\n            // Sanity check\n            if (!isOpened())\n                error(\"Video to write frames is not opened.\", __LINE__, __FUNCTION__, __FILE__);\n            // Concat images\n            cv::Mat cvOutputData;\n            if (cvMats.size() > 1)\n                cv::hconcat(cvMats.data(), cvMats.size(), cvOutputData);\n            else\n                cvOutputData = cvMats.at(0);\n            // Sanity check\n            if (upImpl->mCvSize.x != cvOutputData.cols || upImpl->mCvSize.y != cvOutputData.rows)\n                error(\"You selected to write video (`--write_video`), but the frames to be saved have different\"\n                      \" resolution. You can only save frames with the same resolution.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Save concatenated image\n            // FFmpeg video\n            if (upImpl->mUseFfmpeg)\n            {\n                const auto opMat = OP_CV2OPMAT(cvOutputData);\n                upImpl->upImageSaver->saveImages(opMat, toFixedLengthString(upImpl->mImageSaverCounter, 12u));\n                upImpl->mImageSaverCounter++;\n            }\n            // OpenCV video\n            else\n                upImpl->mVideoWriter.write(cvOutputData);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gpu/CMakeLists.txt",
    "content": "set(SOURCES_OP_GPU\n    cuda.cpp\n    cuda.cu\n    gpu.cpp\n    opencl.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_GPU_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_GPU})\nset(SOURCES_OP_GPU_WITH_CP ${SOURCES_OP_GPU_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_GPU_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_gpu ${SOURCES_OP_GPU})\n  else ()\n    add_library(openpose_gpu ${SOURCES_OP_GPU})\n  endif ()\n\n  target_link_libraries(openpose_gpu openpose_core)\n\n  install(TARGETS openpose_gpu\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/gpu/cuda.cpp",
    "content": "#include <openpose/gpu/cuda.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime.h>\n    #include <openpose/utilities/fastMath.hpp>\n#endif\n\nnamespace op\n{\n    #ifdef USE_CUDA\n        const dim3 THREADS_PER_BLOCK_TINY  {32, 32, 1};\n        const dim3 THREADS_PER_BLOCK_SMALL {64, 64, 1};\n        const dim3 THREADS_PER_BLOCK_MEDIUM{128, 128, 1};\n        const dim3 THREADS_PER_BLOCK_BIG   {256, 256, 1};\n        const dim3 THREADS_PER_BLOCK_HUGE  {256, 256, 1};\n    #endif\n\n    void cudaCheck(const int line, const std::string& function, const std::string& file)\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                const auto errorCode = cudaPeekAtLastError();\n                if(errorCode != cudaSuccess)\n                    error(\"Cuda check failed (\" + std::to_string(errorCode) + \" vs. \" + std::to_string(cudaSuccess) + \"): \"\n                          + cudaGetErrorString(errorCode), line, function, file);\n            #else\n                UNUSED(line);\n                UNUSED(function);\n                UNUSED(file);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    int getCudaGpuNumber()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                int gpuNumber;\n                cudaGetDeviceCount(&gpuNumber);\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                return gpuNumber;\n            #else\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    void getNumberCudaThreadsAndBlocks(dim3& numberCudaThreads, dim3& numberCudaBlocks, const Point<unsigned int>& frameSize)\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                // numberCudaThreads\n                // Image <= 480p    --> THREADS_PER_BLOCK_TINY\n                // Image <= 720p    --> THREADS_PER_BLOCK_SMALL\n                // Image <= 1080p   --> THREADS_PER_BLOCK_MEDIUM\n                // Image <= 4k      --> THREADS_PER_BLOCK_BIG\n                // Image >  4K      --> THREADS_PER_BLOCK_HUGE\n                const auto maxValue = fastMax(frameSize.x, frameSize.y);\n                // > 4K\n                if (maxValue > 3840)\n                    numberCudaThreads = THREADS_PER_BLOCK_HUGE;\n                // 4K\n                else if (maxValue > 1980)\n                    numberCudaThreads = THREADS_PER_BLOCK_BIG;\n                // FullHD\n                else if (maxValue > 1280)\n                    numberCudaThreads = THREADS_PER_BLOCK_MEDIUM;\n                // HD\n                else if (maxValue > 640)\n                    numberCudaThreads = THREADS_PER_BLOCK_SMALL;\n                // VGA\n                else\n                    numberCudaThreads = THREADS_PER_BLOCK_TINY;\n                // numberCudaBlocks\n                numberCudaBlocks = dim3{getNumberCudaBlocks(frameSize.x, numberCudaThreads.x),\n                                        getNumberCudaBlocks(frameSize.y, numberCudaThreads.y),\n                                        numberCudaThreads.z};\n            #else\n                UNUSED(numberCudaThreads);\n                UNUSED(numberCudaBlocks);\n                UNUSED(frameSize);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gpu/cuda.cu",
    "content": "#include <openpose/gpu/cuda.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime.h>\n    #include <openpose_private/gpu/cuda.hu>\n#endif\n\nnamespace op\n{\n    template <typename T>\n    __global__ void reorderAndNormalizeKernel(\n        T* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto c = (blockIdx.z * blockDim.z) + threadIdx.z;\n        if (x < width && y < height)\n        {\n            const auto originFramePtrOffsetY = y * width;\n            const auto channelOffset = c * width * height;\n            const auto targetIndex = channelOffset + y * width + x;\n            const auto srcIndex = (originFramePtrOffsetY + x) * channels + c;\n            targetPtr[targetIndex] =  T(srcPtr[srcIndex]) * T(1/256.f) - T(0.5f);\n        }\n    }\n\n    template <typename T>\n    __global__ void uCharImageCastKernel(\n        unsigned char* targetPtr, const T* const srcPtr, const int volume)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        if (x < volume)\n            targetPtr[x] =  (unsigned char)(fastTruncateCuda(srcPtr[x], T(0), T(255)));\n    }\n\n    template <typename T>\n    void reorderAndNormalize(\n        T* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels)\n    {\n        try\n        {\n            const dim3 threadsPerBlock{32, 1, 1};\n            const dim3 numBlocks{\n                getNumberCudaBlocks(width, threadsPerBlock.x),\n                getNumberCudaBlocks(height, threadsPerBlock.y),\n                getNumberCudaBlocks(channels, threadsPerBlock.z)};\n            reorderAndNormalizeKernel<<<numBlocks, threadsPerBlock>>>(targetPtr, srcPtr, width, height, channels);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void uCharImageCast(unsigned char* targetPtr, const T* const srcPtr, const int volume)\n    {\n        try\n        {\n            const dim3 threadsPerBlock{32, 1, 1};\n            const dim3 numBlocks{\n                getNumberCudaBlocks(volume, threadsPerBlock.x)};\n            uCharImageCastKernel<<<numBlocks, threadsPerBlock>>>(targetPtr, srcPtr, volume);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void reorderAndNormalize(\n        float* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels);\n    template void reorderAndNormalize(\n        double* targetPtr, const unsigned char* const srcPtr, const int width, const int height, const int channels);\n\n    template void uCharImageCast(\n        unsigned char* targetPtr, const float* const srcPtr, const int volume);\n    template void uCharImageCast(\n        unsigned char* targetPtr, const double* const srcPtr, const int volume);\n}\n"
  },
  {
    "path": "src/openpose/gpu/gpu.cpp",
    "content": "#include <openpose/gpu/gpu.hpp>\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n#endif\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n#endif\n\nnamespace op\n{\n    int getGpuNumber()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                return getCudaGpuNumber();\n            #elif defined USE_OPENCL\n                return OpenCL::getTotalGPU();\n            #else\n                error(\"OpenPose must be compiled with the `USE_CUDA` or `USE_OPENCL` macro definition in order to use\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    GpuMode getGpuMode()\n    {\n        try\n        {\n            #ifdef USE_CUDA\n                return GpuMode::Cuda;\n            #elif defined USE_OPENCL\n                return GpuMode::OpenCL;\n            #else\n                return GpuMode::NoGpu;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return GpuMode::NoGpu;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gpu/opencl.cpp",
    "content": "#include <openpose_private/gpu/opencl.hcl> // Must be before below includes\n#include <map>\n#include <mutex>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/cl2.hpp>\n    #include <viennacl/backend/opencl.hpp>\n    #include <caffe/caffe.hpp>\n#endif\n\nnamespace op\n{\n    #ifdef USE_OPENCL\n        void replaceAll(std::string &s, const std::string &search, const std::string &replace)\n        {\n            for (size_t pos = 0; ; pos += replace.length())\n            {\n                // Locate the substring to replace\n                pos = s.find( search, pos );\n                if ( pos == std::string::npos ) break;\n                // Replace by erasing and inserting\n                s.erase( pos, search.length() );\n                s.insert( pos, replace );\n            }\n        }\n\n        template <typename T> inline std::string getType()\n        {\n            std::string type = \"\";\n            if ((std::is_same<T, float>::value))\n                type = \"float\";\n            else if ((std::is_same<T, double>::value))\n                type = \"double\";\n            else\n                throw std::runtime_error(\"Error: Invalid CL type\");\n            return type;\n        }\n\n        template <typename T>\n        bool buildProgramFromSource(cl::Program& program, cl::Context& context, std::string src, bool isFile = false)\n        {\n            #ifdef USE_OPENCL\n                try\n                {\n                    std::string type = getType<T>();\n                    if (isFile)\n                    {\n                        std::ifstream programFile((char*) src.c_str());\n                        std::string programString(std::istreambuf_iterator<char>(programFile),\n                                                          (std::istreambuf_iterator<char>()));\n                        src = programString;\n                    }\n                    //src = std::regex_replace(src, std::regex(\"Type\"), std::string(type));\n                    replaceAll(src, \"Type\", type);\n                    program = cl::Program(context, src, true);\n                }\n                #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n                catch (cl::BuildError e)\n                {\n                    auto buildInfo = e.getBuildLog();\n                    for (auto &pair : buildInfo)\n                        std::cerr << \"Device: \" << pair.first.getInfo<CL_DEVICE_NAME>() << std::endl <<\n                                     pair.second << std::endl;\n                        error(\"OpenCL error: OpenPose crashed due to the previously printed errors.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                }\n                #endif\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n                return true;\n            #else\n                UNUSED(program);\n                UNUSED(src);\n                UNUSED(isFile);\n                error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n                return false;\n            #endif\n        }\n    #endif\n\n    std::shared_ptr<OpenCL> OpenCL::getInstance(const int deviceId, const int deviceType, bool getFromVienna)\n    {\n        static std::mutex managerMutex;\n        static std::map<int, std::shared_ptr<OpenCL>> clManagers;\n        if (clManagers.count(deviceId))\n            return clManagers[deviceId];\n        else\n        {\n            std::unique_lock<std::mutex> lock{managerMutex};\n            clManagers[deviceId] = std::shared_ptr<OpenCL>(new OpenCL(deviceId, deviceType, getFromVienna));\n            lock.unlock();\n            return clManagers[deviceId];\n        }\n    }\n\n    struct OpenCL::ImplCLManager\n    {\n    public:\n        #ifdef USE_OPENCL\n            std::map<std::string, cl::Program> mClPrograms;\n            std::map<std::string, cl::Kernel> mClKernels;\n            int mId;\n            cl::Device mDevice;\n            cl::CommandQueue mQueue;\n            cl::Context mContext;\n        #endif\n\n        ImplCLManager()\n        {\n        }\n    };\n\n    OpenCL::OpenCL(const int deviceId, const int deviceType, bool getFromVienna)\n        : upImpl{new ImplCLManager{}}\n    {\n        #ifdef USE_OPENCL\n            upImpl->mId = deviceId;\n            if (getFromVienna)\n            {\n                upImpl->mContext = cl::Context(caffe::Caffe::GetOpenCLContext(deviceId, 0), true);\n                upImpl->mQueue = cl::CommandQueue(caffe::Caffe::GetOpenCLQueue(deviceId, 0), true);\n                upImpl->mDevice = upImpl->mContext.getInfo<CL_CONTEXT_DEVICES>()[0];\n                //context = cl::Context(viennacl::ocl::get_context(deviceId).handle().get(), true);\n                //queue = cl::CommandQueue(viennacl::ocl::get_context(deviceId).get_queue().handle().get(), true);\n            }\n            else\n            {\n                std::vector<cl::Platform> platforms;\n                std::vector<cl::Device> devices;\n                std::string deviceName;\n                //cl_uint type;\n                try\n                {\n                    cl::Platform::get(&platforms);\n                    switch (deviceType)\n                    {\n                        case CL_DEVICE_TYPE_GPU:\n                        {\n                            auto type = platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);\n                            if ( type == CL_SUCCESS)\n                            {\n                                // Get only relevant device\n                                cl::Context allContext(devices);\n                                std::vector<cl::Device> gpuDevices;\n                                gpuDevices = allContext.getInfo<CL_CONTEXT_DEVICES>();\n                                bool deviceFound = false;\n                                for (size_t i=0; i<gpuDevices.size(); i++)\n                                {\n                                    if (i == (unsigned int)deviceId)\n                                    {\n                                        upImpl->mDevice = gpuDevices[i];\n                                        upImpl->mContext = cl::Context(upImpl->mDevice);\n                                        upImpl->mQueue = cl::CommandQueue(upImpl->mContext, upImpl->mDevice,\n                                                                          CL_QUEUE_PROFILING_ENABLE);\n                                        deviceFound = true;\n                                        opLog(\"Made new GPU Instance: \" + std::to_string(deviceId));\n                                        break;\n                                    }\n                                }\n                                if (!deviceFound)\n                                    throw std::runtime_error(\"Error: Invalid GPU ID\");\n                            }\n                            else if (type == CL_INVALID_DEVICE_TYPE || type == CL_DEVICE_NOT_FOUND)\n                                throw std::runtime_error(\"Error: GPU Invalid Device or Device not found\");\n                            break;\n                        }\n\n                        case CL_DEVICE_TYPE_CPU:\n                        {\n                            cl::Platform::get(&platforms);\n                            auto type = platforms[0].getDevices(CL_DEVICE_TYPE_CPU, &devices);\n                            if ( type == CL_SUCCESS)\n                            {\n                                // Get only relevant device\n                                std::vector<cl::Device> devices;\n                                cl::Context allContext(devices);\n                                std::vector<cl::Device> cpuDevices;\n                                cpuDevices = allContext.getInfo<CL_CONTEXT_DEVICES>();\n                                bool deviceFound = false;\n                                for (size_t i=0; i<cpuDevices.size(); i++){\n                                    if (i == (unsigned int)deviceId){\n                                        upImpl->mDevice = cpuDevices[i];\n                                        upImpl->mContext = cl::Context(upImpl->mDevice);\n                                        upImpl->mQueue = cl::CommandQueue(upImpl->mContext, upImpl->mDevice,\n                                                                          CL_QUEUE_PROFILING_ENABLE);\n                                        deviceFound = true;\n                                        opLog(\"Made new CPU Instance: \" + std::to_string(deviceId));\n                                        break;\n                                    }\n                                }\n                                if (!deviceFound)\n                                    throw std::runtime_error(\"Error: Invalid CPU ID\");\n                            }\n                            else if (type == CL_INVALID_DEVICE_TYPE || type == CL_DEVICE_NOT_FOUND)\n                                throw std::runtime_error(\"Error: CPU Invalid Device or Device not found\");\n                            break;\n                        }\n\n                        case CL_DEVICE_TYPE_ACCELERATOR:\n                        {\n                            cl::Platform::get(&platforms);\n                            auto type = platforms[0].getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices);\n                            if ( type == CL_SUCCESS)\n                            {\n                                // Get only relevant device\n                                std::vector<cl::Device> devices;\n                                cl::Context allContext(devices);\n                                std::vector<cl::Device> accDevices;\n                                accDevices = allContext.getInfo<CL_CONTEXT_DEVICES>();\n                                bool deviceFound = false;\n                                for (size_t i=0; i<accDevices.size(); i++)\n                                {\n                                    if (i == (unsigned int)deviceId)\n                                    {\n                                        upImpl->mDevice = accDevices[i];\n                                        upImpl->mContext = cl::Context(upImpl->mDevice);\n                                        upImpl->mQueue = cl::CommandQueue(upImpl->mContext, upImpl->mDevice,\n                                                                          CL_QUEUE_PROFILING_ENABLE);\n                                        deviceFound = true;\n                                        opLog(\"Made new ACC Instance: \" + std::to_string(deviceId));\n                                        break;\n                                    }\n                                }\n                                if (!deviceFound)\n                                    throw std::runtime_error(\"Error: Invalid ACC ID\");\n                            }\n                            else if (type == CL_INVALID_DEVICE_TYPE || type == CL_DEVICE_NOT_FOUND)\n                                throw std::runtime_error(\"Error: ACC Invalid Device or Device not found\");\n                            break;\n                        }\n\n                        default:\n                        {\n                            throw std::runtime_error(\"Error: No such CL Device Type\");\n                        }\n                    }\n                }\n                #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n                catch (cl::Error e)\n                {\n                    opLog(\"Error: \" + std::string(e.what()));\n                }\n                #endif\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        #else\n            UNUSED(deviceId);\n            UNUSED(deviceType);\n            UNUSED(getFromVienna);\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        #endif\n    }\n\n    OpenCL::~OpenCL()\n    {\n    }\n\n    cl::CommandQueue& OpenCL::getQueue()\n    {\n        #ifdef USE_OPENCL\n            return upImpl->mQueue;\n        #else\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            throw std::runtime_error(\"\");\n        #endif\n    }\n\n    cl::Device& OpenCL::getDevice()\n    {\n        #ifdef USE_OPENCL\n            return upImpl->mDevice;\n        #else\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            throw std::runtime_error(\"\");\n        #endif\n    }\n\n    cl::Context& OpenCL::getContext()\n    {\n        #ifdef USE_OPENCL\n            return upImpl->mContext;\n        #else\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            throw std::runtime_error(\"\");\n        #endif\n    }\n\n    template <typename T>\n    bool OpenCL::buildKernelIntoManager(const std::string& kernelName, const std::string& src, bool isFile)\n    {\n        #ifdef USE_OPENCL\n            // Set type\n            std::string type = getType<T>();\n            std::string key = kernelName + \"_\" + type;\n\n            // Program not built\n            if (!(upImpl->mClPrograms.find(key) != upImpl->mClPrograms.end()))\n            {\n                cl::Program program;\n                buildProgramFromSource<T>(program, upImpl->mContext, src, isFile);\n                upImpl->mClPrograms[key] = program;\n            }\n\n            cl::Program& program = upImpl->mClPrograms[key];\n\n            // Kernel not built\n            if (!(upImpl->mClKernels.find(key) != upImpl->mClKernels.end()))\n            {\n                upImpl->mClKernels[key] = cl::Kernel(program, kernelName.c_str());\n                opLog(\"Kernel: \" + kernelName + \" Type: \" + type + + \" GPU: \" + std::to_string(upImpl->mId) +\n                    \" built successfully\");\n                return true;\n            }\n            else\n            {\n                opLog(\"Kernel \" + kernelName + \" already built\");\n                return false;\n            }\n        #else\n            UNUSED(kernelName);\n            UNUSED(src);\n            UNUSED(isFile);\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        #endif\n    }\n\n    template <typename T>\n    cl::Kernel& OpenCL::getKernelFromManager(const std::string& kernelName, const std::string& src, bool isFile)\n    {\n        #ifdef USE_OPENCL\n        // Set type\n        std::string type = getType<T>();\n        std::string key = kernelName + \"_\" + type;\n\n        if (!(upImpl->mClKernels.find(key) != upImpl->mClKernels.end()))\n        {\n            if (!src.size())\n                throw std::runtime_error(\"Error: Kernel \" + kernelName + \" Type: \" + type + \" not found in Manager\");\n            else\n            {\n                buildKernelIntoManager<T>(kernelName, src, isFile);\n            }\n        }\n        return upImpl->mClKernels[key];\n        #else\n        UNUSED(kernelName);\n        UNUSED(src);\n        UNUSED(isFile);\n        error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n              \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        throw std::runtime_error(\"\");\n        #endif\n    }\n\n    std::string OpenCL::clErrorToString(int err)\n    {\n        #ifdef USE_OPENCL\n            switch (err)\n            {\n            case CL_SUCCESS: return \"Success\";\n            case CL_DEVICE_NOT_FOUND: return \"Device Not Found\";\n            case CL_DEVICE_NOT_AVAILABLE: return \"Device Not Available\";\n            case CL_COMPILER_NOT_AVAILABLE: return \"Compiler Not Available\";\n            case CL_MEM_OBJECT_ALLOCATION_FAILURE: return \"Memory Object Allocation Failure\";\n            case CL_OUT_OF_RESOURCES: return \"Out of Resources\";\n            case CL_OUT_OF_HOST_MEMORY: return \"Out of Host Memory\";\n            case CL_PROFILING_INFO_NOT_AVAILABLE: return \"Profiling Information Not Available\";\n            case CL_MEM_COPY_OVERLAP: return \"Memory Copy Overlap\";\n            case CL_IMAGE_FORMAT_MISMATCH: return \"Image Format Mismatch\";\n            case CL_IMAGE_FORMAT_NOT_SUPPORTED: return \"Image Format Not Supported\";\n            case CL_BUILD_PROGRAM_FAILURE: return \"Build Program Failure\";\n            case CL_MAP_FAILURE: return \"Map Failure\";\n            case CL_INVALID_VALUE: return \"Invalid Value\";\n            case CL_INVALID_DEVICE_TYPE: return \"Invalid Device Type\";\n            case CL_INVALID_PLATFORM: return \"Invalid Platform\";\n            case CL_INVALID_DEVICE: return \"Invalid Device\";\n            case CL_INVALID_CONTEXT: return \"Invalid Context\";\n            case CL_INVALID_QUEUE_PROPERTIES: return \"Invalid Queue Properties\";\n            case CL_INVALID_COMMAND_QUEUE: return \"Invalid Command Queue\";\n            case CL_INVALID_HOST_PTR: return \"Invalid Host Pointer\";\n            case CL_INVALID_MEM_OBJECT: return \"Invalid Memory Object\";\n            case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return \"Invalid Image Format Descriptor\";\n            case CL_INVALID_IMAGE_SIZE: return \"Invalid Image Size\";\n            case CL_INVALID_SAMPLER: return \"Invalid Sampler\";\n            case CL_INVALID_BINARY: return \"Invalid Binary\";\n            case CL_INVALID_BUILD_OPTIONS: return \"Invalid Build Options\";\n            case CL_INVALID_PROGRAM: return \"Invalid Program\";\n            case CL_INVALID_PROGRAM_EXECUTABLE: return \"Invalid Program Executable\";\n            case CL_INVALID_KERNEL_NAME: return \"Invalid Kernel Name\";\n            case CL_INVALID_KERNEL_DEFINITION: return \"Invalid Kernel Definition\";\n            case CL_INVALID_KERNEL: return \"Invalid Kernel\";\n            case CL_INVALID_ARG_INDEX: return \"Invalid Argument Index\";\n            case CL_INVALID_ARG_VALUE: return \"Invalid Argument Value\";\n            case CL_INVALID_ARG_SIZE: return \"Invalid Argument Size\";\n            case CL_INVALID_KERNEL_ARGS: return \"Invalid Kernel Arguments\";\n            case CL_INVALID_WORK_DIMENSION: return \"Invalid Work Dimension\";\n            case CL_INVALID_WORK_GROUP_SIZE: return \"Invalid Work Group Size\";\n            case CL_INVALID_WORK_ITEM_SIZE: return \"Invalid Work Item Size\";\n            case CL_INVALID_GLOBAL_OFFSET: return \"Invalid Global Offset\";\n            case CL_INVALID_EVENT_WAIT_LIST: return \"Invalid Event Wait List\";\n            case CL_INVALID_EVENT: return \"Invalid Event\";\n            case CL_INVALID_OPERATION: return \"Invalid Operation\";\n            case CL_INVALID_GL_OBJECT: return \"Invalid GL Object\";\n            case CL_INVALID_BUFFER_SIZE: return \"Invalid Buffer Size\";\n            case CL_INVALID_MIP_LEVEL: return \"Invalid MIP Level\";\n            case CL_INVALID_GLOBAL_WORK_SIZE: return \"Invalid Global Work Size\";\n            #ifdef CL_VERSION_1_2\n            case CL_COMPILE_PROGRAM_FAILURE: return \"Compile Program Failure\";\n            case CL_LINKER_NOT_AVAILABLE: return \"Linker Not Available\";\n            case CL_LINK_PROGRAM_FAILURE: return \"Link Program Failure\";\n            case CL_DEVICE_PARTITION_FAILED: return \"Device Partition Failed\";\n            case CL_KERNEL_ARG_INFO_NOT_AVAILABLE: return \"Kernel Argument Info Not Available\";\n            case CL_INVALID_PROPERTY: return \"Invalid Property\";\n            case CL_INVALID_IMAGE_DESCRIPTOR: return \"Invalid Image Descriptor\";\n            case CL_INVALID_COMPILER_OPTIONS: return \"Invalid Compiler Options\";\n            case CL_INVALID_LINKER_OPTIONS: return \"Invalid Linker Options\";\n            case CL_INVALID_DEVICE_PARTITION_COUNT: return \"Invalid Device Partition Count\";\n            #endif // CL_VERSION_1_2\n            #ifdef CL_VERSION_2_0\n            case CL_INVALID_PIPE_SIZE: return \"Invalid Pipe Size\";\n            case CL_INVALID_DEVICE_QUEUE: return \"Invalid Device Queue\";\n            #endif\n            default: {\n                std::stringstream s;\n                s << \"Unknown OpenCL Error (\" << err << \")\";\n                return s.str();\n            }\n            }\n        #else\n            UNUSED(err);\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        #endif\n    }\n\n    int OpenCL::getTotalGPU()\n    {\n        #ifdef USE_OPENCL\n            std::vector<cl::Platform> platforms;\n            std::vector<cl::Device> devices;\n            cl_uint type;\n            try\n            {\n                cl::Platform::get(&platforms);\n                if (!platforms.size())\n                    return -1;\n\n                // Special Case for Apple which has CPU OpenCL Device too\n                int cpu_device_count = 0;\n                #ifdef __APPLE__\n                    type = platforms[0].getDevices(CL_DEVICE_TYPE_CPU, &devices);\n                    if (type == CL_SUCCESS)\n                        cpu_device_count = devices.size();\n                #endif\n\n                type = platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);\n                if (type == CL_SUCCESS)\n                    return devices.size() + cpu_device_count;\n                else\n                {\n                    error(\"No GPU Devices were found. OpenPose only supports GPU OpenCL\", __LINE__, __FUNCTION__, __FILE__);\n                    return -1;\n                }\n            }\n            #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n            catch (cl::Error& e)\n            {\n                opLog(\"Error: \" + std::string(e.what()));\n            }\n            #endif\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #else\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        #endif\n        return -1;\n    }\n\n    template <typename T> void OpenCL::getBufferRegion(cl_buffer_region& region, const int origin, const int size)\n    {\n        #ifdef USE_OPENCL\n            region.origin = sizeof(T) * origin;\n            region.size = sizeof(T) * size;\n        #else\n            UNUSED(origin);\n            UNUSED(size);\n            UNUSED(region);\n            error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                  \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        #endif\n    }\n\n    int OpenCL::getAlignment()\n    {\n        #ifdef USE_OPENCL\n        cl::Device& device = this->getDevice();\n        cl_uint mem_align;\n        clGetDeviceInfo(device.get(), CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(mem_align), &mem_align, nullptr);\n        return mem_align;\n        #else\n        error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n              \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n        return 0;\n        #endif\n    }\n\n    template void OpenCL::getBufferRegion<float>(cl_buffer_region& region, const int origin, const int size);\n    template void OpenCL::getBufferRegion<double>(cl_buffer_region& region, const int origin, const int size);\n    template cl::Kernel&  OpenCL::getKernelFromManager<float>(const std::string& kernelName, const std::string& src, bool isFile);\n    template cl::Kernel& OpenCL::getKernelFromManager<double>(const std::string& kernelName, const std::string& src, bool isFile);\n    template bool OpenCL::buildKernelIntoManager<float>(const std::string& kernelName, const std::string& src, bool isFile);\n    template bool OpenCL::buildKernelIntoManager<double>(const std::string& kernelName, const std::string& src, bool isFile);\n}\n"
  },
  {
    "path": "src/openpose/gui/CMakeLists.txt",
    "content": "set(SOURCES_OP_GUI\n    defineTemplates.cpp\n    frameDisplayer.cpp\n    gui.cpp\n    guiAdam.cpp\n    gui3D.cpp\n    guiInfoAdder.cpp\n)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nset(SOURCES_OP_GUI_WITH_CP \"\" PARENT_SCOPE)\nprepend(SOURCES_OP_GUI_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_GUI})\nset(SOURCES_OP_GUI_WITH_CP ${SOURCES_OP_GUI_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OP_FILESTREAM_WITH_CP ${SOURCES_OP_FILESTREAM_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_GUI_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  add_library(openpose_gui ${SOURCES_OP_GUI})\n  target_link_libraries(openpose_gui openpose_pose ${OpenCV_LIBS})\n\n  install(TARGETS openpose_gui\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/gui/defineTemplates.cpp",
    "content": "#include <openpose/gui/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WGui);\n#ifdef USE_3D_ADAM_MODEL\n    DEFINE_TEMPLATE_DATUM(WGuiAdam);\n#endif\n    DEFINE_TEMPLATE_DATUM(WGui3D);\n    DEFINE_TEMPLATE_DATUM(WGuiInfoAdder);\n}\n"
  },
  {
    "path": "src/openpose/gui/frameDisplayer.cpp",
    "content": "#include <openpose/gui/frameDisplayer.hpp>\n #include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    FrameDisplayer::FrameDisplayer(const std::string& windowedName, const Point<int>& initialWindowedSize,\n                                   const bool fullScreen) :\n        mWindowName{windowedName},\n        mWindowedSize{initialWindowedSize},\n        mFullScreenMode{(fullScreen ? FullScreenMode::FullScreen : FullScreenMode::Windowed)}\n    {\n        try\n        {\n            // If initial window size = 0 --> initialize to 640x480\n            if (mWindowedSize.x <= 0 || mWindowedSize.y <= 0)\n                mWindowedSize = Point<int>{640, 480};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FrameDisplayer::~FrameDisplayer()\n    {\n    }\n\n    void FrameDisplayer::initializationOnThread()\n    {\n        try\n        {\n            setFullScreenMode(mFullScreenMode);\n\n            const cv::Mat cvBlackFrame(mWindowedSize.y, mWindowedSize.x, CV_32FC3, {0,0,0});\n            const Matrix blackFrame = OP_CV2OPCONSTMAT(cvBlackFrame);\n            FrameDisplayer::displayFrame(blackFrame);\n            // This one will show most probably a white image (I guess the program does not have time to render\n            // in 1 msec)\n            cv::waitKey(1);\n            // // This one will show the desired black image\n            // cv::waitKey(1000);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FrameDisplayer::setFullScreenMode(const FullScreenMode fullScreenMode)\n    {\n        try\n        {\n            mFullScreenMode = fullScreenMode;\n\n            // Setting output resolution\n            auto flags = CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO;\n            #ifdef USE_OPENCV_WITH_OPENGL\n                flags |= CV_WINDOW_OPENGL;\n            #endif\n            cv::namedWindow(mWindowName, flags);\n            if (mFullScreenMode == FullScreenMode::FullScreen)\n                cv::setWindowProperty(mWindowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);\n            else if (mFullScreenMode == FullScreenMode::Windowed)\n            {\n                cv::resizeWindow(mWindowName, mWindowedSize.x, mWindowedSize.y);\n                cv::setWindowProperty(mWindowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_NORMAL);\n            }\n            else\n                error(\"Unknown FullScreenMode\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FrameDisplayer::switchFullScreenMode()\n    {\n        try\n        {\n            if (mFullScreenMode == FullScreenMode::FullScreen)\n                setFullScreenMode(FullScreenMode::Windowed);\n            else if (mFullScreenMode == FullScreenMode::Windowed)\n                setFullScreenMode(FullScreenMode::FullScreen);\n            else\n                error(\"Unknown FullScreenMode\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FrameDisplayer::displayFrame(const Matrix& frame, const int waitKeyValue)\n    {\n        try\n        {\n            // Sanity check\n            if (frame.empty())\n                error(\"Empty frame introduced.\", __LINE__, __FUNCTION__, __FILE__);\n            const cv::Mat cvFrame = OP_OP2CVCONSTMAT(frame);\n            // If frame > window size --> Resize window\n            if (mWindowedSize.x < cvFrame.cols || mWindowedSize.y < cvFrame.rows)\n            {\n                mWindowedSize.x = std::max(mWindowedSize.x, cvFrame.cols);\n                mWindowedSize.y = std::max(mWindowedSize.y, cvFrame.rows);\n                cv::resizeWindow(mWindowName, mWindowedSize.x, mWindowedSize.y);\n                // This one will show most probably a white image (I guess the program does not have time to render\n                // in 1 msec)\n                cv::waitKey(1);\n            }\n            cv::imshow(mWindowName, cvFrame);\n            if (waitKeyValue != -1)\n                cv::waitKey(waitKeyValue);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void FrameDisplayer::displayFrame(const std::vector<Matrix>& frames, const int waitKeyValue)\n    {\n        try\n        {\n            // No frames\n            if (frames.empty())\n                displayFrame(Matrix(), waitKeyValue);\n            // 1 frame\n            else if (frames.size() == 1u)\n                displayFrame(frames[0], waitKeyValue);\n            // >= 2 frames\n            else\n            {\n                // Prepare final cvMat\n                // Concat (0)\n                Matrix opMat = frames[0].clone();\n                cv::Mat cvMat = OP_OP2CVMAT(opMat);\n                // Concat (1,size()-1)\n                for (auto i = 1u; i < frames.size(); i++)\n                {\n                    const cv::Mat framesI = OP_OP2CVCONSTMAT(frames[i]);\n                    cv::hconcat(cvMat, framesI, cvMat);\n                }\n                opMat = OP_CV2OPMAT(cvMat);\n                // Display it\n                displayFrame(opMat, waitKeyValue);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gui/gui.cpp",
    "content": "#include <openpose/gui/gui.hpp>\n#include <opencv2/highgui/highgui.hpp> // cv::waitKey\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/utilities/check.hpp>\n\nnamespace op\n{\n    inline void showGuiHelp()\n    {\n        try\n        {\n            const auto helpCvMat = loadImage(\"./doc/GUI_help/GUI_help.png\");\n\n            if (!helpCvMat.empty())\n            {\n                const auto fullScreen = false;\n                FrameDisplayer frameDisplayer{OPEN_POSE_NAME_AND_VERSION + \" - GUI Help\",\n                                              Point<int>{helpCvMat.cols(), helpCvMat.rows()}, fullScreen};\n                frameDisplayer.displayFrame(helpCvMat, 33);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void handleWaitKey(bool& guiPaused, FrameDisplayer& frameDisplayer,\n                       std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets,\n                       std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets,\n                       std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets,\n                       std::vector<std::shared_ptr<Renderer>>& renderers,\n                       std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n                       std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr,\n                       DisplayMode& displayMode, DisplayMode& displayModeOriginal)\n    {\n        try\n        {\n            const int key = cv::waitKey(1);\n            if (key != -1)\n            {\n                // Some OpenCV versions has a problem and key must be casted to char\n                const auto castedKey = (char)std::tolower((char)key);\n                // ------------------------- General Commands ------------------------- //\n                // Exit program\n                if (castedKey==27)\n                {\n                    if (isRunningSharedPtr != nullptr)\n                    {\n                        *isRunningSharedPtr = false;\n                        guiPaused = false;\n                    }\n                }\n                // Help\n                else if (castedKey=='h')\n                    showGuiHelp();\n                // Switch full screen - normal screen\n                else if (castedKey=='f')\n                    frameDisplayer.switchFullScreenMode();\n                // ------------------------- Producer-Related ------------------------- //\n                // Pause\n                else if (castedKey==' ')\n                    guiPaused = !guiPaused;\n                // Fake pause\n                else if (castedKey=='m')\n                {\n                    if (videoSeekSharedPtr != nullptr)\n                        videoSeekSharedPtr->first = !videoSeekSharedPtr->first;\n                }\n                // Seeking in video\n                else if (castedKey=='l' || castedKey=='k')\n                {\n                    if (videoSeekSharedPtr != nullptr)\n                    {\n                        // Normal case, +-30 frames\n                        if (!videoSeekSharedPtr->first)\n                            videoSeekSharedPtr->second += 30 * (castedKey=='k' ? -2 : 1);\n                        // Frame by frame (if forced paused)\n                        else\n                            videoSeekSharedPtr->second += (castedKey=='k' ? -1 : 1);\n                    }\n                }\n                // Enable/disable blending\n                else if (castedKey=='b')\n                {\n                    for (auto& renderer : renderers)\n                        renderer->setBlendOriginalFrame(!renderer->getBlendOriginalFrame());\n                }\n                // ------------------------- OpenPose-Related ------------------------- //\n                // Modifying thresholds\n                else if (castedKey=='-' || castedKey=='=')\n                    for (auto& poseExtractorNet : poseExtractorNets)\n                        poseExtractorNet->increase(PoseProperty::NMSThreshold, 0.005f * (castedKey=='-' ? -1 : 1));\n                else if (castedKey=='_' || castedKey=='+')\n                    for (auto& poseExtractorNet : poseExtractorNets)\n                        poseExtractorNet->increase(PoseProperty::ConnectMinSubsetScore,\n                                                0.005f * (castedKey=='_' ? -1 : 1));\n                else if (castedKey=='[' || castedKey==']')\n                    for (auto& poseExtractorNet : poseExtractorNets)\n                        poseExtractorNet->increase(PoseProperty::ConnectInterThreshold,\n                                                0.005f * (castedKey=='[' ? -1 : 1));\n                else if (castedKey=='{' || castedKey=='}')\n                    for (auto& poseExtractorNet : poseExtractorNets)\n                        poseExtractorNet->increase(PoseProperty::ConnectInterMinAboveThreshold,\n                                                (castedKey=='{' ? -0.1f : 0.1f));\n                else if (castedKey==';' || castedKey=='\\'')\n                    for (auto& poseExtractorNet : poseExtractorNets)\n                        poseExtractorNet->increase(PoseProperty::ConnectMinSubsetCnt, (castedKey==';' ? -1 : 1));\n                // ------------------------- Face/hands-Related ------------------------- //\n                // Enable/disable face\n                else if (castedKey=='z')\n                {\n                    for (auto& faceExtractorNet : faceExtractorNets)\n                        faceExtractorNet->setEnabled(!faceExtractorNet->getEnabled());\n                    // Warning if not enabled\n                    if (faceExtractorNets.empty())\n                        opLog(\"OpenPose must be run with face keypoint estimation enabled (`--face` flag).\",\n                            Priority::High);\n                }\n                // Enable/disable hands\n                else if (castedKey=='x')\n                {\n                    for (auto& handExtractorNet : handExtractorNets)\n                        handExtractorNet->setEnabled(!handExtractorNet->getEnabled());\n                    // Warning if not enabled\n                    if (handExtractorNets.empty())\n                        opLog(\"OpenPose must be run with face keypoint estimation enabled (`--hand` flag).\",\n                            Priority::High);\n                }\n                // Enable/disable extra rendering (3D/Adam), while keeping 2D rendering\n                else if (castedKey=='c')\n                {\n                    displayMode = (displayMode == displayModeOriginal\n                                   ? DisplayMode::Display2D : displayModeOriginal);\n                }\n                // ------------------------- Miscellaneous ------------------------- //\n                // Show googly eyes\n                else if (castedKey=='g')\n                    for (auto& renderer : renderers)\n                        renderer->setShowGooglyEyes(!renderer->getShowGooglyEyes());\n                // ------------------------- OpenPose-Related ------------------------- //\n                else if (castedKey==',' || castedKey=='.')\n                {\n                    const auto increment = (castedKey=='.' ? 1 : -1);\n                    for (auto& renderer : renderers)\n                        renderer->increaseElementToRender(increment);\n                }\n                else\n                {\n                    // Skeleton / Background / Add keypoints / Add PAFs\n                    const std::string key2part = \"1234\";\n                    const auto keyPressed = key2part.find(castedKey);\n                    if (keyPressed != std::string::npos)\n                    {\n                        ElementToRender elementToRender;\n                        if (castedKey=='1')\n                            elementToRender = ElementToRender::Skeleton;\n                        else if (castedKey=='2')\n                            elementToRender = ElementToRender::Background;\n                        else if (castedKey=='3')\n                            elementToRender = ElementToRender::AddKeypoints;\n                        else if (castedKey=='4')\n                            elementToRender = ElementToRender::AddPAFs;\n                        else\n                        {\n                            error(\"Unknown ElementToRender value.\", __LINE__, __FUNCTION__, __FILE__);\n                            elementToRender = ElementToRender::Skeleton;\n                        }\n                        for (auto& renderer : renderers)\n                            renderer->setElementToRender(elementToRender);\n                    }\n\n                    // Heatmap visualization\n                    else\n                    {\n                        // Other rendering options\n                        // const std::string key2partHeatmaps = \"0123456789qwertyuiopasd\";\n                        const std::string key2partHeatmaps = \"567890\";\n                        const auto newElementToRender = key2partHeatmaps.find(castedKey);\n                        if (newElementToRender != std::string::npos)\n                            for (auto& renderer : renderers)\n                                renderer->setElementToRender(int(newElementToRender+key2part.size()));\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void handleUserInput(FrameDisplayer& frameDisplayer,\n                         std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets,\n                         std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets,\n                         std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets,\n                         std::vector<std::shared_ptr<Renderer>>& renderers,\n                         std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n                         std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr,\n                         DisplayMode& displayMode, DisplayMode& displayModeOriginal)\n    {\n        try\n        {\n            // The handleUserInput must be always performed, even if no tDatum is detected\n            bool guiPaused = false;\n            handleWaitKey(guiPaused, frameDisplayer, poseExtractorNets, faceExtractorNets, handExtractorNets,\n                          renderers, isRunningSharedPtr, videoSeekSharedPtr, displayMode, displayModeOriginal);\n            while (guiPaused)\n            {\n                std::this_thread::sleep_for(std::chrono::milliseconds{1});\n                handleWaitKey(guiPaused, frameDisplayer, poseExtractorNets, faceExtractorNets, handExtractorNets,\n                              renderers, isRunningSharedPtr, videoSeekSharedPtr, displayMode, displayModeOriginal);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Gui::Gui(const Point<int>& outputSize, const bool fullScreen,\n             const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n             const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr,\n             const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets,\n             const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets,\n             const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets,\n             const std::vector<std::shared_ptr<Renderer>>& renderers,\n             const DisplayMode displayMode) :\n        spIsRunning{isRunningSharedPtr},\n        mDisplayMode{displayMode},\n        mDisplayModeOriginal{displayMode},\n        mFrameDisplayer{OPEN_POSE_NAME_AND_VERSION, outputSize, fullScreen},\n        mPoseExtractorNets{poseExtractorNets},\n        mFaceExtractorNets{faceExtractorNets},\n        mHandExtractorNets{handExtractorNets},\n        mRenderers{renderers},\n        spVideoSeek{videoSeekSharedPtr}\n    {\n    }\n\n    Gui::~Gui()\n    {\n    }\n\n    void Gui::initializationOnThread()\n    {\n        mFrameDisplayer.initializationOnThread();\n    }\n\n    void Gui::setImage(const Matrix& cvMatOutput)\n    {\n        try\n        {\n            setImage(std::vector<Matrix>{cvMatOutput});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Gui::setImage(const std::vector<Matrix>& cvMatOutputs)\n    {\n        try\n        {\n            // Check tDatum integrity\n            bool returnedIsValidFrame = ((spIsRunning == nullptr || *spIsRunning) && !cvMatOutputs.empty());\n            for (const auto& cvMatOutput : cvMatOutputs)\n            {\n                if (cvMatOutput.empty())\n                {\n                    returnedIsValidFrame = false;\n                    break;\n                }\n            }\n\n            // Display\n            if (returnedIsValidFrame)\n                mFrameDisplayer.displayFrame(cvMatOutputs, -1);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Gui::update()\n    {\n        try\n        {\n            // Handle user input\n            handleUserInput(mFrameDisplayer, mPoseExtractorNets, mFaceExtractorNets, mHandExtractorNets,\n                            mRenderers, spIsRunning, spVideoSeek, mDisplayMode, mDisplayModeOriginal);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gui/gui3D.cpp",
    "content": "﻿#include <openpose/gui/gui3D.hpp>\n#include <atomic>\n#include <mutex>\n#include <stdio.h>\n#ifdef USE_3D_RENDERER\n    #include <GL/glut.h>\n    #include <GL/freeglut_ext.h> // glutLeaveMainLoop\n    #include <GL/freeglut_std.h>\n#endif\n#include <opencv2/opencv.hpp>\n#include <openpose/face/faceParameters.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    #ifdef USE_3D_RENDERER\n        const bool LOG_VERBOSE_3D_RENDERER = false;\n        const auto WINDOW_WIDTH = 1280;\n        const auto WINDOW_HEIGHT = 720;\n        std::atomic<bool> sConstructorSet{false};\n\n        struct Keypoints3D\n        {\n            Array<float> poseKeypoints;\n            Array<float> faceKeypoints;\n            Array<float> leftHandKeypoints;\n            Array<float> rightHandKeypoints;\n            bool validKeypoints;\n            std::mutex mutex;\n        };\n\n        enum class CameraMode {\n            CAM_DEFAULT,\n            CAM_ROTATE,\n            CAM_PAN,\n            CAM_PAN_Z\n        };\n\n        Keypoints3D gKeypoints3D;\n        PoseModel sPoseModel = PoseModel::BODY_25;\n        int sLastKeyPressed = -1;\n\n        CameraMode gCameraMode = CameraMode::CAM_DEFAULT;\n\n        const std::vector<GLfloat> LIGHT_DIFFUSE{ 1.f, 1.f, 1.f, 1.f };  // Diffuse light\n        const std::vector<GLfloat> LIGHT_POSITION{ 1.f, 1.f, 1.f, 0.f };  // Infinite light location\n        const std::vector<GLfloat> COLOR_DIFFUSE{ 0.5f, 0.5f, 0.5f, 1.f };\n\n        const auto RAD_TO_DEG = 0.0174532925199433;\n\n        //View Change by Mouse\n        bool gBButton1Down = false;\n        auto gXClick = 0.f;\n        auto gYClick = 0.f;\n        auto gGViewDistance = -250.f; // -82.3994f; //-45;\n        auto gMouseXRotateDeg = 180.f; // -63.2f; //0;\n        auto gMouseYRotateDeg = -5.f; // 7.f; //60;\n        auto gMouseXPan = -70.f; // 0;\n        auto gMouseYPan = -30.f; // 0;\n        auto gMouseZPan = 0.f;\n        auto gScaleForMouseMotion = 0.1f;\n\n        void drawConeByTwoPts(const cv::Point3f& pt1, const cv::Point3f& pt2, const float ptSize)\n        {\n            const GLdouble x1 = pt1.x;\n            const GLdouble y1 = pt1.y;\n            const GLdouble z1 = pt1.z;\n            const GLdouble x2 = pt2.x;\n            const GLdouble y2 = pt2.y;\n            const GLdouble z2 = pt2.z;\n\n            const double x = x2 - x1;\n            const double y = y2 - y1;\n            const double z = z2 - z1;\n\n            glPushMatrix();\n\n            glTranslated(x1, y1, z1);\n\n            if ((x != 0.) || (y != 0.))\n            {\n                glRotated(std::atan2(y, x) / RAD_TO_DEG, 0., 0., 1.);\n                glRotated(std::atan2(std::sqrt(x*x + y*y), z) / RAD_TO_DEG, 0., 1., 0.);\n            }\n            else if (z<0)\n                glRotated(180, 1., 0., 0.);\n\n            const auto height = std::sqrt((pt1.x - pt2.x)*(pt1.x - pt2.x) + (pt1.y - pt2.y)*(pt1.y - pt2.y)\n                                          + (pt1.z - pt2.z)*(pt1.z - pt2.z));\n            glutSolidCone(ptSize, height, 5, 5);\n\n            glPopMatrix();\n        }\n\n        void renderHumanBody(const Array<float>& keypoints, const std::vector<unsigned int>& pairs,\n                             const std::vector<float> colors, const float ratio)\n        {\n            const auto person = 0;\n            const auto numberPeople = keypoints.getSize(0);\n            const auto numberBodyParts = keypoints.getSize(1);\n            const auto numberColors = colors.size();\n            const auto xOffset = -3000.f; // 640.f;\n            const auto yOffset = 1000.f; // 360.f;\n            const auto zOffset = 1000.f; // 360.f;\n            const auto xScale = 43.f;\n            const auto yScale = 24.f;\n            const auto zScale = 24.f;\n\n            if (numberPeople > person)\n            //for(int person=0;person<numberPeople;++person)\n            {\n                // Circle for each keypoint\n                for (auto part = 0; part < numberBodyParts; part++)\n                {\n                    // Set color\n                    const auto colorIndex = part * 3;\n                    const std::vector<float> keypointColor{\n                        colors[colorIndex % numberColors] / 255.f,\n                        colors[(colorIndex + 1) % numberColors] / 255.f,\n                        colors[(colorIndex + 2) % numberColors] / 255.f,\n                        1.f\n                    };\n                    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, COLOR_DIFFUSE.data());\n                    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, keypointColor.data());\n                    // Draw circle\n                    const auto baseIndex = 4 * part + person*numberBodyParts;\n                    if (keypoints[baseIndex + 3] > 0)\n                    {\n                        cv::Point3f keypoint{\n                            -(keypoints[baseIndex] - xOffset) / xScale,\n                            -(keypoints[baseIndex + 1] - yOffset) / yScale,\n                            (keypoints[baseIndex + 2] - zOffset) / zScale\n                        };\n                        // Create and add new sphere\n                        glPushMatrix();\n                        glTranslatef(keypoint.x, keypoint.y, keypoint.z);\n                        // Draw sphere\n                        glutSolidSphere(0.5 * ratio, 20, 20);\n                        glPopMatrix();\n                    }\n                }\n\n                // Lines connecting each keypoint pair\n                for (auto pair = 0u; pair < pairs.size(); pair += 2)\n                {\n                    // Set color\n                    const auto colorIndex = pairs[pair+1] * 3;\n                    const std::vector<float> keypointColor{\n                        colors[colorIndex % numberColors] / 255.f,\n                        colors[(colorIndex + 1) % numberColors] / 255.f,\n                        colors[(colorIndex + 2) % numberColors] / 255.f,\n                        1.f\n                    };\n                    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, COLOR_DIFFUSE.data());\n                    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, keypointColor.data());\n                    // Draw line\n                    const auto baseIndexPairA = 4 * pairs[pair] + person*numberBodyParts;\n                    const auto baseIndexPairB = 4 * pairs[pair + 1] + person*numberBodyParts;\n                    if (keypoints[baseIndexPairA + 3] > 0 && keypoints[baseIndexPairB + 3] > 0)\n                    {\n                        cv::Point3f pairKeypointA{\n                            -(keypoints[baseIndexPairA] - xOffset) / xScale,\n                            -(keypoints[baseIndexPairA + 1] - yOffset) / yScale,\n                            (keypoints[baseIndexPairA + 2] - zOffset) / zScale\n                        };\n                        cv::Point3f pairKeypointB{\n                            -(keypoints[baseIndexPairB] - xOffset) / xScale,\n                            -(keypoints[baseIndexPairB + 1] - yOffset) / yScale,\n                            (keypoints[baseIndexPairB + 2] - zOffset) / zScale\n                        };\n                        drawConeByTwoPts(pairKeypointA, pairKeypointB, 0.5f * ratio);\n                    }\n                }\n            }\n        }\n\n        void initGraphics()\n        {\n            // Enable a single OpenGL light\n            glLightfv(GL_LIGHT0, GL_AMBIENT, LIGHT_DIFFUSE.data());\n            glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT_DIFFUSE.data());\n            glLightfv(GL_LIGHT0, GL_POSITION, LIGHT_POSITION.data());\n            glEnable(GL_LIGHT0);\n            glEnable(GL_LIGHTING);\n\n            // Use depth buffering for hidden surface elimination\n            glEnable(GL_DEPTH_TEST);\n\n            // Setup the view of the cube\n            glMatrixMode(GL_PROJECTION);\n            gluPerspective( /* field of view in degree */ 40.0,\n                /* aspect ratio */ 1.0,\n                /* Z near */ 1.0, /* Z far */ 1000.0);\n            glMatrixMode(GL_MODELVIEW);\n            gluLookAt(\n                0.0, 0.0, 5.0,  // eye is at (0,0,5)\n                0.0, 0.0, 0.0,  // center is at (0,0,0)\n                0.0, 1.0, 0.  // up is in positive Y direction\n            );\n\n            // Adjust cube position to be aesthetic angle\n            glTranslatef(0.0, 0.0, -1.0);\n            glRotatef(60, 1.0, 0.0, 0.0);\n            glRotatef(-20, 0.0, 0.0, 1.0);\n\n            glColorMaterial(GL_FRONT, GL_DIFFUSE);\n            glEnable(GL_COLOR_MATERIAL);\n        }\n\n        // this is the actual idle function\n        void idleFunction()\n        {\n            glutPostRedisplay();\n            glutSwapBuffers();\n        }\n\n        void renderFloor()\n        {\n            glDisable(GL_LIGHTING);\n\n            const cv::Point3f gGloorCenter{ 0,0,0 };   //ankle\n            const cv::Point3f Noise{ 0,1,0 };\n\n            cv::Point3f upright = Noise - gGloorCenter;\n            upright = 1.0 / sqrt(upright.x *upright.x + upright.y *upright.y + upright.z *upright.z)*upright;\n            const cv::Point3f gGloorAxis2 = cv::Point3f{ 1,0,0 }.cross(upright);\n            const cv::Point3f gGloorAxis1 = gGloorAxis2.cross(upright);\n\n            const auto gridNum = 10;\n            const auto width = 50.;//sqrt(Distance(gGloorPts.front(),gGloorCenter)*2 /gridNum) * 1.2;\n            const cv::Point3f origin = gGloorCenter - gGloorAxis1*(width*gridNum / 2)\n                                     - gGloorAxis2*(width*gridNum / 2);\n            const cv::Point3f axis1 = gGloorAxis1 * width;\n            const cv::Point3f axis2 = gGloorAxis2 * width;\n            for (auto y = 0; y <= gridNum; ++y)\n            {\n                for (auto x = 0; x <= gridNum; ++x)\n                {\n                    if ((x + y) % 2 == 0)\n                        glColor4f(0.2f, 0.2f, 0.2f, 1.f); //black\n                    else\n                        glColor4f(0.5f, 0.5f, 0.5f, 1.f); //grey\n\n                    const cv::Point3f p1 = origin + axis1*x + axis2*y;\n                    const cv::Point3f p2 = p1 + axis1;\n                    const cv::Point3f p3 = p1 + axis2;\n                    const cv::Point3f p4 = p1 + axis1 + axis2;\n\n                    glBegin(GL_QUADS);\n\n                    glVertex3f(p1.x, p1.y, p1.z);\n                    glVertex3f(p2.x, p2.y, p2.z);\n                    glVertex3f(p4.x, p4.y, p4.z);\n                    glVertex3f(p3.x, p3.y, p3.z);\n                    glEnd();\n                }\n            }\n            glEnable(GL_LIGHTING);\n        }\n\n        void renderMain(void)\n        {\n            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n            glLoadIdentity();\n            //gluLookAt(0,0,0, 0, 0, 1, 0, -1, 0);\n            gluLookAt(\n                0.0, 0.0, 5.0,  // eye is at (0,0,5)\n                0.0, 0.0, 0.0,  // center is at (0,0,0)\n                0.0, 1.0, 0.  // up is in positive Y direction\n            );\n\n            glTranslatef(0, 0, gGViewDistance);\n            glRotatef(-gMouseYRotateDeg, 1.f, 0.f, 0.f);\n            glRotatef(-gMouseXRotateDeg, 0.f, 1.f, 0.f);\n\n            glTranslatef(-gMouseXPan, gMouseYPan, -gMouseZPan);\n\n            // renderFloor(); // Disabled, how to know where the floor is?\n            std::unique_lock<std::mutex> lock{gKeypoints3D.mutex};\n            if (gKeypoints3D.validKeypoints)\n            {\n                renderHumanBody(gKeypoints3D.poseKeypoints, getPoseBodyPartPairsRender(sPoseModel),\n                                getPoseColors(sPoseModel), 1.f);\n                renderHumanBody(gKeypoints3D.faceKeypoints, FACE_PAIRS_RENDER, FACE_COLORS_RENDER, 0.5f);\n                renderHumanBody(gKeypoints3D.leftHandKeypoints, HAND_PAIRS_RENDER, HAND_COLORS_RENDER, 0.5f);\n                renderHumanBody(gKeypoints3D.rightHandKeypoints, HAND_PAIRS_RENDER, HAND_COLORS_RENDER, 0.5f);\n            }\n            lock.unlock();\n\n            glutSwapBuffers();\n        }\n\n        void mouseButton(const int button, const int state, const int x, const int y)\n        {\n\n            if (button == 3 || button == 4) //mouse wheel\n            {\n                if (button == 3)  //zoom in\n                    gGViewDistance += 10 * gScaleForMouseMotion;\n                else  //zoom out\n                    gGViewDistance -= 10 * gScaleForMouseMotion;\n                if (LOG_VERBOSE_3D_RENDERER)\n                    opLog(\"gGViewDistance: \" + std::to_string(gGViewDistance));\n            }\n            else\n            {\n                if (button == GLUT_LEFT_BUTTON)\n                {\n                    gBButton1Down = (state == GLUT_DOWN) ? 1 : 0;\n                    gXClick = (float)x;\n                    gYClick = (float)y;\n\n                    if (glutGetModifiers() == GLUT_ACTIVE_SHIFT)\n                        gCameraMode = CameraMode::CAM_PAN;\n                    else\n                        gCameraMode = CameraMode::CAM_ROTATE;\n                }\n                if (LOG_VERBOSE_3D_RENDERER)\n                    opLog(\"Clicked: [\" + std::to_string(gXClick) + \",\" + std::to_string(gYClick) + \"]\");\n            }\n            glutPostRedisplay();\n        }\n\n        void mouseMotion(const int x, const int y)\n        {\n\n            // If button1 pressed, zoom in/out if mouse is moved up/down.\n            if (gBButton1Down)\n            {\n                if (gCameraMode == CameraMode::CAM_ROTATE)\n                {\n                    gMouseXRotateDeg += (x - gXClick)*0.2f;\n                    gMouseYRotateDeg -= (y - gYClick)*0.2f;\n                }\n                else if (gCameraMode == CameraMode::CAM_PAN)\n                {\n                    gMouseXPan -= (x - gXClick) / 2 * gScaleForMouseMotion;\n                    gMouseYPan -= (y - gYClick) / 2 * gScaleForMouseMotion;\n                }\n                else if (gCameraMode == CameraMode::CAM_PAN_Z)\n                {\n                    auto dist = std::sqrt(pow((x - gXClick), 2.0f) + pow((y - gYClick), 2.0f));\n                    if (y < gYClick)\n                        dist *= -1;\n                    gMouseZPan -= dist / 5 * gScaleForMouseMotion;\n                }\n\n                gXClick = (float)x;\n                gYClick = (float)y;\n\n                glutPostRedisplay();\n                if (LOG_VERBOSE_3D_RENDERER)\n                {\n                    opLog(\"gMouseXRotateDeg = \" + std::to_string(gMouseXRotateDeg));\n                    opLog(\"gMouseYRotateDeg = \" + std::to_string(gMouseYRotateDeg));\n                    opLog(\"gMouseXPan = \" + std::to_string(gMouseXPan));\n                    opLog(\"gMouseYPan = \" + std::to_string(gMouseYPan));\n                    opLog(\"gMouseZPan = \" + std::to_string(gMouseZPan));\n                }\n            }\n        }\n\n        void keyPressed(const unsigned char key, const int x, const int y)\n        {\n            try\n            {\n                UNUSED(x);\n                UNUSED(y);\n                const std::lock_guard<std::mutex> lock{gKeypoints3D.mutex};\n                sLastKeyPressed = key;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void initializeVisualization()\n        {\n            try\n            {\n                char *my_argv[] = { NULL };\n                int my_argc = 0;\n                glutInit(&my_argc, my_argv);\n                // Setup the size, position, and display mode for new windows\n                glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);\n                glutInitWindowPosition(200, 0);\n                // glutSetOption(GLUT_MULTISAMPLE,8);\n                // Ideally adding also GLUT_BORDERLESS | GLUT_CAPTIONLESS should fix the problem of disabling the `x`\n                // button, but it does not work (tested in Ubuntu)\n                // https://stackoverflow.com/questions/3799803/is-it-possible-to-make-a-window-withouth-a-top-in-glut\n                glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);\n                // Create and set up a window\n                glutCreateWindow(std::string{OPEN_POSE_NAME_AND_VERSION + \" - 3-D Display\"}.c_str());\n                initGraphics();\n                glutDisplayFunc(renderMain);\n                glutMouseFunc(mouseButton);\n                glutMotionFunc(mouseMotion);\n                // Only required if glutMainLoop() called\n                // glutIdleFunc(idleFunction);\n                // Full screen would fix the problem of disabling `x` button\n                // glutFullScreen();\n                // Key presses\n                glutKeyboardFunc(keyPressed);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #else\n        const std::string USE_3D_RENDERER_ERROR{\"OpenPose CMake must be compiled with the `USE_3D_RENDERER` flag in\"\n            \" order to use the 3-D visualization renderer. Alternatively, set 2-D rendering with `--display 2`.\"};\n    #endif\n\n    Gui3D::Gui3D(const Point<int>& outputSize, const bool fullScreen,\n                 const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n                 const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr,\n                 const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets,\n                 const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets,\n                 const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets,\n                 const std::vector<std::shared_ptr<Renderer>>& renderers, const PoseModel poseModel,\n                 const DisplayMode displayMode, const bool copyGlToCvMat) :\n        Gui{outputSize, fullScreen, isRunningSharedPtr, videoSeekSharedPtr, poseExtractorNets, faceExtractorNets,\n            handExtractorNets, renderers, displayMode},\n        mCopyGlToCvMat{copyGlToCvMat}\n    {\n        try\n        {\n            #ifdef USE_3D_RENDERER\n                // Update sPoseModel\n                sPoseModel = poseModel;\n                if (!sConstructorSet)\n                    sConstructorSet = true;\n                else\n                    error(\"The Gui3D class can only be initialized once.\", __LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(poseModel);\n                if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display3D)\n                    error(USE_3D_RENDERER_ERROR, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Gui3D::~Gui3D()\n    {\n        #ifdef USE_3D_RENDERER\n            try\n            {\n                glutLeaveMainLoop();\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #endif\n    }\n\n    void Gui3D::initializationOnThread()\n    {\n        try\n        {\n            // Init parent class\n            Gui::initializationOnThread();\n            #ifdef USE_3D_RENDERER\n                // OpenGL - Initialization\n                initializeVisualization();\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Gui3D::setKeypoints(const Array<float>& poseKeypoints3D, const Array<float>& faceKeypoints3D,\n                             const Array<float>& leftHandKeypoints3D, const Array<float>& rightHandKeypoints3D)\n    {\n        try\n        {\n            // 3-D rendering\n            #ifdef USE_3D_RENDERER\n                if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display3D)\n                {\n                    if (!poseKeypoints3D.empty() || !faceKeypoints3D.empty()\n                        || !leftHandKeypoints3D.empty() || !rightHandKeypoints3D.empty())\n                    {\n                        // OpenGL Rendering\n                        // Copy new keypoints\n                        std::unique_lock<std::mutex> lock{gKeypoints3D.mutex};\n                        gKeypoints3D.poseKeypoints = poseKeypoints3D;\n                        gKeypoints3D.faceKeypoints = faceKeypoints3D;\n                        gKeypoints3D.leftHandKeypoints = leftHandKeypoints3D;\n                        gKeypoints3D.rightHandKeypoints = rightHandKeypoints3D;\n                        gKeypoints3D.validKeypoints = true;\n                        // From m to mm\n                        scaleKeypoints(gKeypoints3D.poseKeypoints, 1e3f);\n                        scaleKeypoints(gKeypoints3D.faceKeypoints, 1e3f);\n                        scaleKeypoints(gKeypoints3D.leftHandKeypoints, 1e3f);\n                        scaleKeypoints(gKeypoints3D.rightHandKeypoints, 1e3f);\n                        // Unlock mutex\n                        lock.unlock();\n                    }\n                }\n            #else\n                UNUSED(poseKeypoints3D);\n                UNUSED(faceKeypoints3D);\n                UNUSED(leftHandKeypoints3D);\n                UNUSED(rightHandKeypoints3D);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Gui3D::update()\n    {\n        try\n        {\n            // 2-D rendering\n            // Display all 2-D views\n            if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display2D)\n                Gui::update();\n            // 3-D rendering\n            #ifdef USE_3D_RENDERER\n                if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display3D)\n                {\n                    // OpenGL Rendering\n                    std::unique_lock<std::mutex> lock{gKeypoints3D.mutex};\n                    // Esc pressed -> Close program\n                    if (sLastKeyPressed == 27)\n                        if (spIsRunning != nullptr)\n                            *spIsRunning = false;\n                    lock.unlock();\n                    // OpenCL - Run main loop event\n                    // It is run outside loop, or it would get visually stuck if loop to slow\n                    idleFunction();\n                    glutMainLoopEvent();\n                    // This alternative can only be called once, and it will block the thread until program exit\n                    // glutMainLoop();\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix Gui3D::readCvMat()\n    {\n        try\n        {\n            // 3-D rendering\n            cv::Mat cvImage;\n            #ifdef USE_3D_RENDERER\n                if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display3D)\n                {\n                    // Save/display 3D display in OpenCV window\n                    if (mCopyGlToCvMat)\n                    {\n                        cvImage = cv::Mat(WINDOW_HEIGHT, WINDOW_WIDTH, CV_8UC3);\n                        #ifdef _WIN32\n                            glReadPixels(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, GL_BGR_EXT, GL_UNSIGNED_BYTE, cvImage.data);\n                        #else\n                            glReadPixels(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, GL_BGR, GL_UNSIGNED_BYTE, cvImage.data);\n                        #endif\n                        cv::flip(cvImage, cvImage, 0);\n                    }\n                }\n            #endif\n            Matrix image = OP_CV2OPMAT(cvImage);\n            return image;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/gui/guiAdam.cpp",
    "content": "#ifdef USE_3D_ADAM_MODEL\n#include <openpose/gui/guiAdam.hpp>\n#ifdef USE_3D_ADAM_MODEL\n    #include <adam/KinematicModel.h>\n    #include <adam/Renderer.h>\n    #include <adam/utils.h>\n    #include <adam/VisualizedData.h>\n    #define SMPL_VIS_SCALING 100.0f\n#endif\n#include <openpose/3d/jointAngleEstimation.hpp>\n#include <openpose/filestream/videoSaver.hpp>\n\nnamespace op\n{\n    #ifdef USE_3D_ADAM_MODEL\n        const int NUMBER_BODY_KEYPOINTS = 20;\n        const int NUMBER_HAND_KEYPOINTS = 21;\n        const int NUMBER_FACE_KEYPOINTS = 70;\n        // targetJoints: Only for Body, LHand, RHand. No Face, no Foot\n        const int NUMBER_KEYPOINTS = 3*(NUMBER_BODY_KEYPOINTS + 2*NUMBER_HAND_KEYPOINTS);\n\n        void updateKeypoint(double* targetJoint, const float* const poseKeypoint3D)\n        {\n            try\n            {\n                // Keypoint found\n                if (poseKeypoint3D[2] > 0.5) // For 3-D keypoint, it's either 0 or 1.\n                {\n                    targetJoint[0] = poseKeypoint3D[0];\n                    targetJoint[1] = poseKeypoint3D[1];\n                    targetJoint[2] = poseKeypoint3D[2];\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    struct GuiAdam::ImplGuiAdam\n    {\n        #ifdef USE_3D_ADAM_MODEL\n            // Visualization\n            std::unique_ptr<adam::Renderer> spRender;\n            std::array<double, NUMBER_KEYPOINTS> mResultBody;\n            std::unique_ptr<GLubyte[]> upReadBuffer;\n\n            // Video AVI writing\n            const std::string mWriteAdamRenderAsVideo;\n            std::shared_ptr<VideoSaver> spVideoSaver;\n\n            // Shared parameters\n            const std::shared_ptr<const TotalModel> spTotalModel;\n\n            ImplGuiAdam(const std::shared_ptr<const TotalModel>& totalModel,\n                        const std::string& adamRenderedVideoPath = \"\") :\n                mWriteAdamRenderAsVideo{adamRenderedVideoPath},\n                spTotalModel{totalModel}\n            {\n                try\n                {\n                    // Sanity check\n                    if (spTotalModel == nullptr)\n                        error(\"Given totalModel is a nullptr.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        #endif\n    };\n\n    GuiAdam::GuiAdam(const Point<int>& outputSize, const bool fullScreen,\n                     const std::shared_ptr<std::atomic<bool>>& isRunningSharedPtr,\n                     const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr,\n                     const std::vector<std::shared_ptr<PoseExtractorNet>>& poseExtractorNets,\n                     const std::vector<std::shared_ptr<FaceExtractorNet>>& faceExtractorNets,\n                     const std::vector<std::shared_ptr<HandExtractorNet>>& handExtractorNets,\n                     const std::vector<std::shared_ptr<Renderer>>& renderers,\n                     const DisplayMode displayMode, const std::shared_ptr<const TotalModel>& totalModel,\n                     const std::string& adamRenderedVideoPath) :\n        Gui{outputSize, fullScreen, isRunningSharedPtr, videoSeekSharedPtr, poseExtractorNets, faceExtractorNets,\n            handExtractorNets, renderers, displayMode},\n        spImpl{std::make_shared<ImplGuiAdam>(totalModel, adamRenderedVideoPath)}\n    {\n        try\n        {\n            #ifndef USE_3D_ADAM_MODEL\n                UNUSED(outputSize);\n                UNUSED(fullScreen);\n                UNUSED(isRunningSharedPtr);\n                UNUSED(videoSeekSharedPtr);\n                UNUSED(poseExtractorNets);\n                UNUSED(renderers);\n                UNUSED(displayMode);\n                UNUSED(totalModel);\n                // UNUSED(adamRenderedVideoPath);\n                error(\"OpenPose CMake must be compiled with the `USE_3D_ADAM_MODEL` flag in order to use the\"\n                      \" Adam visualization renderer. Alternatively, set 2-D/3-D rendering with `--display 2`\"\n                      \" or `--display 3`.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    GuiAdam::~GuiAdam()\n    {\n    }\n\n    void GuiAdam::initializationOnThread()\n    {\n        try\n        {\n            // Init parent class\n            if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display2D)\n                Gui::initializationOnThread();\n            #ifdef USE_3D_ADAM_MODEL\n                if (mDisplayMode == DisplayMode::DisplayAll\n                    || mDisplayMode == DisplayMode::DisplayAdam)\n                {\n                    int argc = 0;\n                    // char* argv[0];\n                    spImpl->spRender.reset(new adam::Renderer{&argc, nullptr});\n                    // spImpl->spRender->options.yrot=-45;\n                    spImpl->spRender->options.yrot=45;\n                    spImpl->spRender->options.xrot=25;\n                    spImpl->spRender->options.meshSolid = true;\n                    // spImpl->spRender->options.meshSolid = false;\n                    spImpl->upReadBuffer.reset(new GLubyte[spImpl->spRender->options.width\n                                                           * spImpl->spRender->options.height * 3]);\n                }\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void GuiAdam::generateMesh(const Array<float>& poseKeypoints3D, const Array<float>& faceKeypoints3D,\n                               const std::array<Array<float>, 2>& handKeypoints3D,\n                               const double* const adamPosePtr, const double* const adamTranslationPtr,\n                               const double* const vtVecPtr, const int vtVecRows,\n                               const double* const j0VecPtr, const int j0VecRows,\n                               const double* const adamFaceCoeffsExpPtr)\n    {\n        try\n        {\n            // Adam rendering\n            #ifdef USE_3D_ADAM_MODEL\n                if (mDisplayMode == DisplayMode::DisplayAll\n                    || mDisplayMode == DisplayMode::DisplayAdam)\n                {\n                    const Eigen::Map<const Eigen::Vector3d> adamTranslation(adamTranslationPtr);\n                    const Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, 1>> vtVec(\n                        vtVecPtr, vtVecRows);\n                    const Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, 1>> j0Vec(\n                        j0VecPtr, j0VecRows);\n                    CMeshModelInstance cMeshModelInstance;\n                    VisualizedData visualizedData;\n                    // auto& visualizedData = spImpl->mVisualizedData;\n                    // GenerateMesh_Fast modifies cMeshModelInstance & spImpl->mResultBody\n                    GenerateMesh_Fast(cMeshModelInstance, spImpl->mResultBody.data(), *spImpl->spTotalModel, vtVec,\n                                    j0Vec, adamPosePtr, adamFaceCoeffsExpPtr, adamTranslation);\n                    CopyMesh(cMeshModelInstance, visualizedData);\n\n                    // Fill data\n                    // Body and hands\n                    std::array<double, NUMBER_KEYPOINTS> targetJoints;\n                    targetJoints.fill(0.);\n                    // If keypoints detected\n                    if (!poseKeypoints3D.empty())\n                    {\n                        // Update body\n                        for (auto part = 0 ; part < 19; part++)\n                            updateKeypoint(&targetJoints[mapOPToAdam(part)*(poseKeypoints3D.getSize(2)-1)],\n                                           &poseKeypoints3D[{0, part, 0}]);\n                        // Update left/right hand\n                        // NUMBER_BODY_KEYPOINTS = #parts_OP + 1 (top_head)\n                        const auto bodyOffset = NUMBER_BODY_KEYPOINTS*(poseKeypoints3D.getSize(2)-1);\n                        const auto handOffset = handKeypoints3D[0].getSize(1)*(handKeypoints3D[0].getSize(2)-1);\n                        for (auto hand = 0u ; hand < handKeypoints3D.size(); hand++)\n                            if (!handKeypoints3D.at(hand).empty())\n                                for (auto part = 0 ; part < handKeypoints3D[hand].getSize(1); part++)\n                                    updateKeypoint(&targetJoints[bodyOffset + hand*handOffset\n                                                    + part*(handKeypoints3D[hand].getSize(2)-1)],\n                                                   &handKeypoints3D[hand][{0, part, 0}]);\n\n                        // Meters --> cm\n                        for (auto i = 0 ; i < NUMBER_KEYPOINTS ; i++)\n                            targetJoints[i] *= 1e2;\n                    }\n                    visualizedData.targetJoint = targetJoints.data();\n                    // visualizedData.targetJoint = nullptr;\n                    // Update face\n                    if (!faceKeypoints3D.empty())\n                    {\n                        visualizedData.faceKeypoints.resize(faceKeypoints3D.getSize(1), 3);\n                        for (auto part = 0 ; part < faceKeypoints3D.getSize(1); part++)\n                        {\n                            if (faceKeypoints3D[{0, part, faceKeypoints3D.getSize(2)-1}] > 0.5)\n                                for (auto xyz = 0 ; xyz < faceKeypoints3D.getSize(2)-1 ; xyz++)\n                                    visualizedData.faceKeypoints(part, xyz) = faceKeypoints3D[{0, part, xyz}];\n                            else\n                            {\n                                visualizedData.faceKeypoints(part, 0) = 0;\n                                visualizedData.faceKeypoints(part, 1) = 0;\n                                visualizedData.faceKeypoints(part, 2) = 0;\n                            }\n                        }\n                        visualizedData.faceKeypoints *= 100;\n                    }\n                    else\n                        visualizedData.faceKeypoints.setZero();\n                    visualizedData.resultJoint = spImpl->mResultBody.data();\n\n                    // visualizedData: 2 for full body, 3 for left hand, 4 for right hand, 5 for face\n                    visualizedData.vis_type = 2;\n                    // If full body --> nRange > whole body object\n                    if (visualizedData.vis_type <= 2)\n                        spImpl->spRender->options.nRange = 150;\n                    // Otherwise (hand/face) --> ~zoom in\n                    else\n                        spImpl->spRender->options.nRange = 40;\n                    visualizedData.read_buffer = spImpl->upReadBuffer.get();\n\n                    // Send display to screen\n                    spImpl->spRender->RenderHand(visualizedData);\n                    spImpl->spRender->RenderAndRead(); // read the image into read_buffer\n                    // spImpl->spRender->Display();\n\n                    // Save/display Adam display in OpenCV window\n                    if (!spImpl->mWriteAdamRenderAsVideo.empty())\n                    {\n                        // img is y-flipped, and in RGB order\n                        cv::Mat img(spImpl->spRender->options.height, spImpl->spRender->options.width,\n                                    CV_8UC3, spImpl->upReadBuffer.get());\n                        cv::flip(img, img, 0);\n                        cv::cvtColor(img, img, cv::COLOR_RGB2BGR);\n                        if (spImpl->spVideoSaver == nullptr)\n                        {\n                            const auto originalVideoFps = 30;\n                            spImpl->spVideoSaver = std::make_shared<VideoSaver>(\n                                spImpl->mWriteAdamRenderAsVideo, CV_FOURCC('M','J','P','G'),\n                                originalVideoFps, \"\"\n                            );\n                        }\n                        spImpl->spVideoSaver->write(img);\n                        // cv::imshow( \"Display window\", img );\n                        // cv::waitKey(16);\n                    }\n                }\n            #else\n                UNUSED(poseKeypoints3D);\n                UNUSED(faceKeypoints3D);\n                UNUSED(handKeypoints3D);\n                UNUSED(adamPose);\n                UNUSED(adamTranslation);\n                UNUSED(vtVec);\n                UNUSED(j0Vec);\n                UNUSED(adamFaceCoeffsExpPtr);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void GuiAdam::update()\n    {\n        try\n        {\n            // 2-D rendering\n            if (mDisplayMode == DisplayMode::DisplayAll || mDisplayMode == DisplayMode::Display2D)\n                Gui::update();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "src/openpose/gui/guiInfoAdder.cpp",
    "content": "#include <openpose/gui/guiInfoAdder.hpp>\n#include <cstdio> // std::snprintf\n#include <limits> // std::numeric_limits\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/utilities/openCvPrivate.hpp>\n\nnamespace op\n{\n    // Used colors\n    const cv::Scalar WHITE_SCALAR{255, 255, 255};\n\n    void updateFps(unsigned long long& lastId, double& fps, unsigned int& fpsCounter,\n                   std::queue<std::chrono::high_resolution_clock::time_point>& fpsQueue,\n                   const unsigned long long id, const int numberGpus)\n    {\n        try\n        {\n            // If only 1 GPU -> update fps every frame.\n            // If > 1 GPU:\n                // We updated fps every (3*numberGpus) frames. This is due to the variability introduced by\n                // using > 1 GPU at the same time.\n                // However, we update every frame during the first few frames to have an initial estimator.\n            // In any of the previous cases, the fps value is estimated during the last several frames.\n            // In this way, a sudden fps drop will be quickly visually identified.\n            if (lastId != id)\n            {\n                lastId = id;\n                fpsQueue.emplace(std::chrono::high_resolution_clock::now());\n                bool updatePrintedFps = true;\n                if (fpsQueue.size() > 5)\n                {\n                    const auto factor = (numberGpus > 1 ? 25u : 15u);\n                    updatePrintedFps = (fpsCounter % factor == 0);\n                    // updatePrintedFps = (numberGpus == 1 ? true : fpsCounter % (3*numberGpus) == 0);\n                    fpsCounter++;\n                    if (fpsQueue.size() > factor)\n                        fpsQueue.pop();\n                }\n                if (updatePrintedFps)\n                {\n                    const auto timeSec = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(\n                        fpsQueue.back()-fpsQueue.front()\n                    ).count() * 1e-9;\n                    fps = (fpsQueue.size()-1) / (timeSec != 0. ? timeSec : 1.);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void addPeopleIds(\n        cv::Mat& cvOutputData, const Array<long long>& poseIds, const Array<float>& poseKeypoints,\n        const int borderMargin)\n    {\n        try\n        {\n            if (!poseIds.empty())\n            {\n                const auto poseKeypointsArea = poseKeypoints.getSize(1)*poseKeypoints.getSize(2);\n                const auto isVisible = 0.05f;\n                for (auto i = 0u ; i < poseIds.getVolume() ; i++)\n                {\n                    if (poseIds[i] > -1)\n                    {\n                        const auto indexMain = i * poseKeypointsArea;\n                        const auto indexSecondary = i * poseKeypointsArea + poseKeypoints.getSize(2);\n                        if (poseKeypoints[indexMain+2] > isVisible || poseKeypoints[indexSecondary+2] > isVisible)\n                        {\n                            const auto xA = positiveIntRound(poseKeypoints[indexMain]);\n                            const auto yA = positiveIntRound(poseKeypoints[indexMain+1]);\n                            const auto xB = positiveIntRound(poseKeypoints[indexSecondary]);\n                            const auto yB = positiveIntRound(poseKeypoints[indexSecondary+1]);\n                            int x;\n                            int y;\n                            if (poseKeypoints[indexMain+2] > isVisible && poseKeypoints[indexSecondary+2] > isVisible)\n                            {\n                                const auto keypointRatio = positiveIntRound(\n                                    0.15f * std::sqrt((xA-xB)*(xA-xB) + (yA-yB)*(yA-yB)));\n                                x = xA + 3*keypointRatio;\n                                y = yA - 3*keypointRatio;\n                            }\n                            else if (poseKeypoints[indexMain+2] > isVisible)\n                            {\n                                x = xA + positiveIntRound(0.25f*borderMargin);\n                                y = yA - positiveIntRound(0.25f*borderMargin);\n                            }\n                            else //if (poseKeypoints[indexSecondary+2] > isVisible)\n                            {\n                                x = xB + positiveIntRound(0.25f*borderMargin);\n                                y = yB - positiveIntRound(0.5f*borderMargin);\n                            }\n                            putTextOnCvMat(cvOutputData, std::to_string(poseIds[i]), {x, y}, WHITE_SCALAR, false, cvOutputData.cols);\n                        }\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    GuiInfoAdder::GuiInfoAdder(const int numberGpus, const bool guiEnabled) :\n        mNumberGpus{numberGpus},\n        mGuiEnabled{guiEnabled},\n        mFpsCounter{0u},\n        mLastElementRenderedCounter{std::numeric_limits<int>::max()},\n        mLastId{std::numeric_limits<unsigned long long>::max()}\n    {\n    }\n\n    GuiInfoAdder::~GuiInfoAdder()\n    {\n    }\n\n    void GuiInfoAdder::addInfo(Matrix& outputData, const int numberPeople, const unsigned long long id,\n                               const std::string& elementRenderedName, const unsigned long long frameNumber,\n                               const Array<long long>& poseIds, const Array<float>& poseKeypoints)\n    {\n        try\n        {\n            cv::Mat cvOutputData = OP_OP2CVMAT(outputData);\n            // Sanity check\n            if (cvOutputData.empty())\n                error(\"Wrong input element (empty outputData).\", __LINE__, __FUNCTION__, __FILE__);\n            // Size\n            const auto borderMargin = positiveIntRound(fastMax(cvOutputData.cols, cvOutputData.rows) * 0.025);\n            // Update fps\n            updateFps(mLastId, mFps, mFpsCounter, mFpsQueue, id, mNumberGpus);\n            // Fps or s/gpu\n            char charArrayAux[15];\n            std::snprintf(charArrayAux, 15, \"%4.1f fps\", mFps);\n            // Recording inverse: sec/gpu\n            // std::snprintf(charArrayAux, 15, \"%4.2f s/gpu\", (mFps != 0. ? mNumberGpus/mFps : 0.));\n            putTextOnCvMat(\n                cvOutputData, charArrayAux, {positiveIntRound(cvOutputData.cols - borderMargin), borderMargin},\n                WHITE_SCALAR, true, cvOutputData.cols);\n            // Part to show\n            // Allowing some buffer when changing the part to show (if >= 2 GPUs)\n            // I.e. one GPU might return a previous part after the other GPU returns the new desired part, it looks\n            // like a mini-bug on screen\n            // Difference between Titan X (~110 ms) & 1050 Ti (~290ms)\n            if (mNumberGpus == 1 || (elementRenderedName != mLastElementRenderedName\n                                     && mLastElementRenderedCounter > 4))\n            {\n                mLastElementRenderedName = elementRenderedName;\n                mLastElementRenderedCounter = 0;\n            }\n            mLastElementRenderedCounter = fastMin(mLastElementRenderedCounter, std::numeric_limits<int>::max() - 5);\n            mLastElementRenderedCounter++;\n            // Add each person ID\n            addPeopleIds(cvOutputData, poseIds, poseKeypoints, borderMargin);\n            // OpenPose name as well as help or part to show\n            putTextOnCvMat(cvOutputData, \"OpenPose - \" +\n                           (!mLastElementRenderedName.empty() ?\n                                mLastElementRenderedName : (mGuiEnabled ? \"'h' for help\" : \"\")),\n                           {borderMargin, borderMargin}, WHITE_SCALAR, false, cvOutputData.cols);\n            // Frame number\n            putTextOnCvMat(cvOutputData, \"Frame: \" + std::to_string(frameNumber),\n                           {borderMargin, (int)(cvOutputData.rows - borderMargin)}, WHITE_SCALAR, false, cvOutputData.cols);\n            // Number people\n            putTextOnCvMat(cvOutputData, \"People: \" + std::to_string(numberPeople),\n                           {(int)(cvOutputData.cols - borderMargin), (int)(cvOutputData.rows - borderMargin)},\n                           WHITE_SCALAR, true, cvOutputData.cols);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/CMakeLists.txt",
    "content": "set(SOURCES_OP_HAND\n    defineTemplates.cpp\n    handDetector.cpp\n    handDetectorFromTxt.cpp\n    handExtractorCaffe.cpp\n    handExtractorNet.cpp\n    handCpuRenderer.cpp\n    handGpuRenderer.cpp\n    handRenderer.cpp\n    renderHand.cpp\n    renderHand.cu)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_HAND_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_HAND})\nset(SOURCES_OP_HAND_WITH_CP ${SOURCES_OP_HAND_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_HAND_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_hand ${SOURCES_OP_HAND})\n  else ()\n    add_library(openpose_hand ${SOURCES_OP_HAND})\n  endif ()\n\n  target_link_libraries(openpose_hand openpose_core)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_hand openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_hand\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/hand/defineTemplates.cpp",
    "content": "#include <openpose/hand/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WHandDetector);\n    DEFINE_TEMPLATE_DATUM(WHandDetectorFromTxt);\n    DEFINE_TEMPLATE_DATUM(WHandDetectorTracking);\n    DEFINE_TEMPLATE_DATUM(WHandDetectorUpdate);\n    DEFINE_TEMPLATE_DATUM(WHandExtractorNet);\n    DEFINE_TEMPLATE_DATUM(WHandRenderer);\n}\n"
  },
  {
    "path": "src/openpose/hand/handCpuRenderer.cpp",
    "content": "#include <openpose/hand/handCpuRenderer.hpp>\n#include <openpose/hand/renderHand.hpp>\n\nnamespace op\n{\n    HandCpuRenderer::HandCpuRenderer(const float renderThreshold, const float alphaKeypoint,\n                                     const float alphaHeatMap) :\n        Renderer{renderThreshold, alphaKeypoint, alphaHeatMap}\n    {\n    }\n\n    HandCpuRenderer::~HandCpuRenderer()\n    {\n    }\n\n    void HandCpuRenderer::renderHandInherited(Array<float>& outputData,\n                                              const std::array<Array<float>, 2>& handKeypoints)\n    {\n        try\n        {\n            // CPU rendering\n            renderHandKeypointsCpu(\n                outputData,\n                handKeypoints,\n                mRenderThreshold\n            );\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handDetector.cpp",
    "content": "#include <openpose/hand/handDetector.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    inline Rectangle<float> getHandFromPoseIndexes(const Array<float>& poseKeypoints, const unsigned int person, const unsigned int wrist,\n                                                   const unsigned int elbow, const unsigned int shoulder, const float threshold)\n    {\n        try\n        {\n            Rectangle<float> handRectangle;\n            // Parameters\n            const auto* posePtr = &poseKeypoints.at(person*poseKeypoints.getSize(1)*poseKeypoints.getSize(2));\n            const auto wristScoreAbove = (posePtr[wrist*3+2] > threshold);\n            const auto elbowScoreAbove = (posePtr[elbow*3+2] > threshold);\n            const auto shoulderScoreAbove = (posePtr[shoulder*3+2] > threshold);\n            const auto ratioWristElbow = 0.33f;\n            // Hand\n            if (wristScoreAbove && elbowScoreAbove && shoulderScoreAbove)\n            {\n                // pos_hand = pos_wrist + ratio * (pos_wrist - pos_elbox) = (1 + ratio) * pos_wrist - ratio * pos_elbox\n                handRectangle.x = posePtr[wrist*3] + ratioWristElbow * (posePtr[wrist*3] - posePtr[elbow*3]);\n                handRectangle.y = posePtr[wrist*3+1] + ratioWristElbow * (posePtr[wrist*3+1] - posePtr[elbow*3+1]);\n                const auto distanceWristElbow = getDistance(poseKeypoints, person, wrist, elbow);\n                const auto distanceElbowShoulder = getDistance(poseKeypoints, person, elbow, shoulder);\n                handRectangle.width = 1.5f * fastMax(distanceWristElbow, 0.9f * distanceElbowShoulder);\n            }\n            // height = width\n            handRectangle.height = handRectangle.width;\n            // x-y refers to the center --> offset to topLeft point\n            handRectangle.x -= handRectangle.width / 2.f;\n            handRectangle.y -= handRectangle.height / 2.f;\n            // Return result\n            return handRectangle;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<float>{};\n        }\n    }\n\n    inline std::array<Rectangle<float>, 2> getHandFromPoseIndexes(const Array<float>& poseKeypoints, const unsigned int person,\n                                                                  const unsigned int lWrist, const unsigned int lElbow, const unsigned int lShoulder,\n                                                                  const unsigned int rWrist, const unsigned int rElbow, const unsigned int rShoulder,\n                                                                  const float threshold)\n    {\n        try\n        {\n            return {getHandFromPoseIndexes(poseKeypoints, person, lWrist, lElbow, lShoulder, threshold),\n                    getHandFromPoseIndexes(poseKeypoints, person, rWrist, rElbow, rShoulder, threshold)};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::array<Rectangle<float>, 2>(); // Parentheses instead of braces to avoid error in GCC 4.8\n        }\n    }\n\n    float getAreaRatio(const Rectangle<float>& rectangleA, const Rectangle<float>& rectangleB)\n    {\n        try\n        {\n            // https://stackoverflow.com/a/22613463\n            const auto sA = rectangleA.area();\n            const auto sB = rectangleB.area();\n            const auto bottomRightA = rectangleA.bottomRight();\n            const auto bottomRightB = rectangleB.bottomRight();\n            const auto sI = fastMax(0.f, 1.f + fastMin(bottomRightA.x, bottomRightB.x) - fastMax(rectangleA.x, rectangleB.x))\n                          * fastMax(0.f, 1.f + fastMin(bottomRightA.y, bottomRightB.y) - fastMax(rectangleA.y, rectangleB.y));\n            // // Option a - areaRatio = 1.f only if both Rectangle has same size and location\n            // const auto sU = sA + sB - sI;\n            // return sI / (float)sU;\n            // Option b - areaRatio = 1.f if at least one Rectangle is contained in the other\n            const auto sU = fastMin(sA, sB);\n            return fastMin(1.f, sI / (float)sU);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    void trackHand(Rectangle<float>& currentRectangle, const std::vector<Rectangle<float>>& previousHands)\n    {\n        try\n        {\n            if (currentRectangle.area() > 0 && previousHands.size() > 0)\n            {\n                // Find closest previous rectangle\n                auto maxIndex = -1;\n                auto maxValue = 0.f;\n                for (auto previous = 0u ; previous < previousHands.size() ; previous++)\n                {\n                    const auto areaRatio = getAreaRatio(currentRectangle, previousHands[previous]);\n                    if (maxValue < areaRatio)\n                    {\n                        maxValue = areaRatio;\n                        maxIndex = previous;\n                    }\n                }\n                // Update current rectangle with closest previous rectangle\n                if (maxIndex > -1)\n                {\n                    const auto& prevRectangle = previousHands[maxIndex];\n                    const auto ratio = 2.f;\n                    const auto newWidth = fastMax((currentRectangle.width * ratio + prevRectangle.width) * 0.5f,\n                                                  (currentRectangle.height * ratio + prevRectangle.height) * 0.5f);\n                    currentRectangle.x = 0.5f * (currentRectangle.x + prevRectangle.x + 0.5f * (currentRectangle.width + prevRectangle.width) - newWidth);\n                    currentRectangle.y = 0.5f * (currentRectangle.y + prevRectangle.y + 0.5f * (currentRectangle.height + prevRectangle.height) - newWidth);\n                    currentRectangle.width = newWidth;\n                    currentRectangle.height = newWidth;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    HandDetector::HandDetector(const PoseModel poseModel) :\n        // Parentheses instead of braces to avoid error in GCC 4.8\n        mPoseIndexes(getPoseKeypoints(poseModel, {\"LWrist\", \"LElbow\", \"LShoulder\", \"RWrist\", \"RElbow\", \"RShoulder\"})),\n        mCurrentId{0}\n    {\n    }\n\n    HandDetector::~HandDetector()\n    {\n    }\n\n    std::vector<std::array<Rectangle<float>, 2>> HandDetector::detectHands(const Array<float>& poseKeypoints) const\n    {\n        try\n        {\n            const auto numberPeople = poseKeypoints.getSize(0);\n            std::vector<std::array<Rectangle<float>, 2>> handRectangles(numberPeople);\n            const auto threshold = 0.03f;\n            // If no poseKeypoints detected -> no way to detect hand location\n            // Otherwise, get hand position(s)\n            if (!poseKeypoints.empty())\n            {\n                for (auto person = 0 ; person < numberPeople ; person++)\n                {\n                    handRectangles.at(person) = getHandFromPoseIndexes(\n                        poseKeypoints, person, mPoseIndexes[(int)PosePart::LWrist], mPoseIndexes[(int)PosePart::LElbow],\n                        mPoseIndexes[(int)PosePart::LShoulder], mPoseIndexes[(int)PosePart::RWrist],\n                        mPoseIndexes[(int)PosePart::RElbow], mPoseIndexes[(int)PosePart::RShoulder], threshold\n                    );\n                }\n            }\n            return handRectangles;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<std::array<Rectangle<float>, 2>>{};\n        }\n    }\n\n    std::vector<std::array<Rectangle<float>, 2>> HandDetector::trackHands(const Array<float>& poseKeypoints)\n    {\n        try\n        {\n            std::lock_guard<std::mutex> lock{mMutex};\n            // Baseline detectHands\n            auto handRectangles = detectHands(poseKeypoints);\n            // If previous hands saved\n            for (auto& handRectangle : handRectangles)\n            {\n                trackHand(handRectangle[0], mHandLeftPrevious);\n                trackHand(handRectangle[1], mHandRightPrevious);\n            }\n            // Return result\n            return handRectangles;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<std::array<Rectangle<float>, 2>>{};\n        }\n    }\n\n    void HandDetector::updateTracker(const std::array<Array<float>, 2>& handKeypoints, const unsigned long long id)\n    {\n        try\n        {\n            std::lock_guard<std::mutex> lock{mMutex};\n            if (mCurrentId < id)\n            {\n                mCurrentId = id;\n                // Parameters\n                const auto numberPeople = handKeypoints.at(0).getSize(0);\n                const auto thresholdRectangle = 0.25f;\n                // Update pose keypoints and hand rectangles\n                mPoseTrack.resize(numberPeople);\n                mHandLeftPrevious.clear();\n                mHandRightPrevious.clear();\n                for (auto person = 0u ; person < mPoseTrack.size() ; person++)\n                {\n                    const auto scoreThreshold = 0.66667f;\n                    // Left hand\n                    if (getAverageScore(handKeypoints[0], person) > scoreThreshold)\n                    {\n                        const auto handLeftRectangle = getKeypointsRectangle(handKeypoints[0], person, thresholdRectangle);\n                        if (handLeftRectangle.area() > 0)\n                            mHandLeftPrevious.emplace_back(handLeftRectangle);\n                    }\n                    // Right hand\n                    if (getAverageScore(handKeypoints[1], person) > scoreThreshold)\n                    {\n                        const auto handRightRectangle = getKeypointsRectangle(handKeypoints[1], person, thresholdRectangle);\n                        if (handRightRectangle.area() > 0)\n                            mHandRightPrevious.emplace_back(handRightRectangle);\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::array<unsigned int, (int)HandDetector::PosePart::Size> HandDetector::getPoseKeypoints(\n        const PoseModel poseModel, const std::array<std::string, (int)HandDetector::PosePart::Size>& poseStrings\n    ) const\n    {\n        std::array<unsigned int, (int)PosePart::Size> poseKeypoints;\n        for (auto i = 0u ; i < poseKeypoints.size() ; i++)\n            poseKeypoints.at(i) = poseBodyPartMapStringToKey(poseModel, poseStrings.at(i));\n        return poseKeypoints;\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handDetectorFromTxt.cpp",
    "content": "#include <openpose/hand/handDetectorFromTxt.hpp>\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n\nnamespace op\n{\n    std::vector<std::string> getTxtPathsOnDirectory(const std::string& txtDirectoryPath)\n    {\n        try\n        {\n            // Get files on directory with JSON extension\n            const auto txtPaths = getFilesOnDirectory(txtDirectoryPath, \".txt\");\n            // Check #files > 0\n            if (txtPaths.empty())\n                error(\"No txt files were found on \" + txtDirectoryPath, __LINE__, __FUNCTION__, __FILE__);\n            // Return file names\n            return txtPaths;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    HandDetectorFromTxt::HandDetectorFromTxt(const std::string& txtDirectoryPath) :\n        mTxtDirectoryPath{txtDirectoryPath},\n        mFilePaths{getTxtPathsOnDirectory(txtDirectoryPath)},\n        mFrameNameCounter{0}\n    {\n    }\n\n    HandDetectorFromTxt::~HandDetectorFromTxt()\n    {\n    }\n\n    std::vector<std::array<Rectangle<float>, 2>> HandDetectorFromTxt::detectHands()\n    {\n        try\n        {\n            return loadHandDetectorTxt(mFilePaths.at(mFrameNameCounter++));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<std::array<Rectangle<float>, 2>>{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handExtractorCaffe.cpp",
    "content": "#include <openpose/hand/handExtractorCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/net/maximumCaffe.hpp>\n#include <openpose/net/netCaffe.hpp>\n#include <openpose/net/resizeAndMergeCaffe.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    struct HandExtractorCaffe::ImplHandExtractorCaffe\n    {\n        #ifdef USE_CAFFE\n            bool mNetInitialized;\n            const int mGpuId;\n            std::shared_ptr<NetCaffe> spNetCaffe;\n            std::shared_ptr<ResizeAndMergeCaffe<float>> spResizeAndMergeCaffe;\n            std::shared_ptr<MaximumCaffe<float>> spMaximumCaffe;\n            // Init with thread\n            std::shared_ptr<ArrayCpuGpu<float>> spCaffeNetOutputBlob;\n            std::shared_ptr<ArrayCpuGpu<float>> spHeatMapsBlob;\n            std::shared_ptr<ArrayCpuGpu<float>> spPeaksBlob;\n\n            ImplHandExtractorCaffe(const std::string& modelFolder, const int gpuId,\n                                   const bool enableGoogleLogging) :\n                mNetInitialized{false},\n                mGpuId{gpuId},\n                spNetCaffe{std::make_shared<NetCaffe>(modelFolder + HAND_PROTOTXT, modelFolder + HAND_TRAINED_MODEL,\n                                                      gpuId, enableGoogleLogging)},\n                spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},\n                spMaximumCaffe{std::make_shared<MaximumCaffe<float>>()}\n            {\n            }\n        #endif\n    };\n\n    #ifdef USE_CAFFE\n        void cropFrame(Array<float>& handImageCrop, cv::Mat& affineMatrix, const cv::Mat& cvInputData,\n                       const Rectangle<float>& handRectangle, const int netInputSide,\n                       const Point<int>& netOutputSize, const bool mirrorImage)\n        {\n            try\n            {\n                // Resize image to hands positions\n                const auto scaleLeftHand = handRectangle.width / (float)netInputSide;\n                affineMatrix = cv::Mat::eye(2,3,CV_64F);\n                if (mirrorImage)\n                    affineMatrix.at<double>(0,0) = -scaleLeftHand;\n                else\n                    affineMatrix.at<double>(0,0) = scaleLeftHand;\n                affineMatrix.at<double>(1,1) = scaleLeftHand;\n                if (mirrorImage)\n                    affineMatrix.at<double>(0,2) = handRectangle.x + handRectangle.width;\n                else\n                    affineMatrix.at<double>(0,2) = handRectangle.x;\n                affineMatrix.at<double>(1,2) = handRectangle.y;\n                cv::Mat handImage;\n                cv::warpAffine(cvInputData, handImage, affineMatrix, cv::Size{netOutputSize.x, netOutputSize.y},\n                               CV_INTER_LINEAR | CV_WARP_INVERSE_MAP, cv::BORDER_CONSTANT, cv::Scalar{0,0,0});\n                               // CV_INTER_CUBIC | CV_WARP_INVERSE_MAP, cv::BORDER_CONSTANT, cv::Scalar{0,0,0});\n                // cv::Mat -> float*\n                uCharCvMatToFloatPtr(handImageCrop.getPtr(), OP_CV2OPMAT(handImage), true);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void connectKeypoints(Array<float>& handCurrent, const int person,\n                              const cv::Mat& affineMatrix, const float* handPeaks)\n        {\n            try\n            {\n                // Estimate keypoint locations\n                for (auto part = 0 ; part < handCurrent.getSize(1) ; part++)\n                {\n                    const auto xyIndex = part * handCurrent.getSize(2);\n                    const auto x = handPeaks[xyIndex];\n                    const auto y = handPeaks[xyIndex + 1];\n                    const auto score = handPeaks[xyIndex + 2];\n                    const auto baseIndex = handCurrent.getSize(2) * (part + person * handCurrent.getSize(1));\n                    handCurrent[baseIndex] = (float)(affineMatrix.at<double>(0,0)*x + affineMatrix.at<double>(0,1)*y\n                                                     + affineMatrix.at<double>(0,2));\n                    handCurrent[baseIndex+1] = (float)(affineMatrix.at<double>(1,0)*x + affineMatrix.at<double>(1,1)*y\n                                                       + affineMatrix.at<double>(1,2));\n                    handCurrent[baseIndex+2] = score;\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        Rectangle<float> getHandRectangle(Array<float>& handCurrent, const int person, const float increaseRatio,\n                                          const float thresholdRectangle,\n                                          const Rectangle<float>& previousHandRectangle = Rectangle<float>{})\n        {\n            try\n            {\n                // Initial Rectangle\n                auto handRectangle = getKeypointsRectangle(handCurrent, person, thresholdRectangle);\n                // Get final width\n                auto finalWidth = fastMax(handRectangle.width, handRectangle.height) * increaseRatio;\n                if (previousHandRectangle.width > 0 && previousHandRectangle.height > 0)\n                    finalWidth = fastMax(handRectangle.width, 0.85f\n                                         * fastMax(previousHandRectangle.width, previousHandRectangle.height));\n                // Update Rectangle\n                handRectangle.recenter(finalWidth, finalWidth);\n                return handRectangle;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return Rectangle<float>{};\n            }\n        }\n\n        void updateHandHeatMapsForPerson(Array<float>& heatMaps, const int person, const ScaleMode heatMapScaleMode,\n                                         const float* heatMapsGpuPtr)\n        {\n            try\n            {\n                // Copy memory\n                const auto channelOffset = heatMaps.getVolume(2, 3);\n                const auto volumeBodyParts = HAND_NUMBER_PARTS * channelOffset;\n                auto totalOffset = 0u;\n                auto* heatMapsPtr = &heatMaps.getPtr()[person*volumeBodyParts];\n                // Copy hand parts\n                #ifdef USE_CUDA\n                    cudaMemcpy(heatMapsPtr, heatMapsGpuPtr, volumeBodyParts * sizeof(float), cudaMemcpyDeviceToHost);\n                #else\n                    //std::memcpy(heatMapsPtr, heatMapsGpuPtr, volumeBodyParts * sizeof(float));\n                    std::copy(heatMapsGpuPtr, heatMapsGpuPtr + volumeBodyParts, heatMapsPtr);\n                #endif\n                // Change from [0,1] to [-1,1]\n                if (heatMapScaleMode == ScaleMode::PlusMinusOne\n                    || heatMapScaleMode == ScaleMode::PlusMinusOneFixedAspect)\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]) * 2.f - 1.f;\n                // [0, 255]\n                else if (heatMapScaleMode == ScaleMode::UnsignedChar)\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = (float)positiveIntRound(fastTruncate(heatMapsPtr[i]) * 255.f);\n                // Avoid values outside original range\n                else\n                    for (auto i = 0u ; i < volumeBodyParts ; i++)\n                        heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]);\n                totalOffset += (unsigned int)volumeBodyParts;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        inline void reshapeHandExtractorCaffe(std::shared_ptr<ResizeAndMergeCaffe<float>>& resizeAndMergeCaffe,\n                                              std::shared_ptr<MaximumCaffe<float>>& maximumCaffe,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& caffeNetOutputBlob,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& heatMapsBlob,\n                                              std::shared_ptr<ArrayCpuGpu<float>>& peaksBlob,\n                                              const int gpuID)\n        {\n            try\n            {\n                // HeatMaps extractor blob and layer\n                const bool mergeFirstDimension = true;\n                resizeAndMergeCaffe->Reshape(\n                    std::vector<ArrayCpuGpu<float>*>{caffeNetOutputBlob.get()},\n                    std::vector<ArrayCpuGpu<float>*>{heatMapsBlob.get()},\n                    HAND_CCN_DECREASE_FACTOR, 1.f, mergeFirstDimension, gpuID);\n                // Pose extractor blob and layer\n                maximumCaffe->Reshape({heatMapsBlob.get()}, {peaksBlob.get()});\n                // Cuda check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void detectHandKeypoints(\n            Array<float>& handCurrent, std::shared_ptr<NetCaffe>& netCaffe, std::shared_ptr<ResizeAndMergeCaffe<float>>& resizeAndMergeCaffe,\n            std::shared_ptr<MaximumCaffe<float>>& maximumCaffe, std::shared_ptr<ArrayCpuGpu<float>>& caffeNetOutputBlob,\n            std::shared_ptr<ArrayCpuGpu<float>>& heatMapsBlob, std::shared_ptr<ArrayCpuGpu<float>>& peaksBlob, bool& netInitialized,\n            Array<float>& handImageCrop, const int person, const cv::Mat& affineMatrix, const int gpuId)\n        {\n            try\n            {\n                #ifdef USE_CAFFE\n                    // 1. Deep net\n                    netCaffe->forwardPass(handImageCrop);\n\n                    // Reshape blobs\n                    if (!netInitialized)\n                    {\n                        netInitialized = true;\n                        reshapeHandExtractorCaffe(\n                            resizeAndMergeCaffe, maximumCaffe, caffeNetOutputBlob, heatMapsBlob, peaksBlob, gpuId);\n                    }\n\n                    // 2. Resize heat maps + merge different scales\n                    resizeAndMergeCaffe->Forward({caffeNetOutputBlob.get()}, {heatMapsBlob.get()});\n\n                    // 3. Get peaks by Non-Maximum Suppression\n                    maximumCaffe->Forward({heatMapsBlob.get()}, {peaksBlob.get()});\n\n                    // Estimate keypoint locations\n                    connectKeypoints(\n                        handCurrent, person, affineMatrix, peaksBlob->mutable_cpu_data());\n\n                    // 5. CUDA sanity check\n                    #ifdef USE_CUDA\n                        cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    #endif\n                #else\n                    UNUSED(handCurrent);\n                    UNUSED(person);\n                    UNUSED(affineMatrix);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    HandExtractorCaffe::HandExtractorCaffe(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                           const std::string& modelFolder, const int gpuId,\n                                           const int numberScales,\n                                           const float rangeScales, const std::vector<HeatMapType>& heatMapTypes,\n                                           const ScaleMode heatMapScaleMode,\n                                           const bool enableGoogleLogging) :\n        HandExtractorNet{netInputSize, netOutputSize, numberScales, rangeScales, heatMapTypes, heatMapScaleMode}\n        #ifdef USE_CAFFE\n        , upImpl{new ImplHandExtractorCaffe{modelFolder, gpuId, enableGoogleLogging}}\n        #endif\n    {\n        try\n        {\n            #if !defined USE_CAFFE\n                UNUSED(netInputSize);\n                UNUSED(netOutputSize);\n                UNUSED(modelFolder);\n                UNUSED(gpuId);\n                UNUSED(numberScales);\n                UNUSED(rangeScales);\n                UNUSED(heatMapTypes);\n                UNUSED(heatMapScaleMode);\n                UNUSED(enableGoogleLogging);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    HandExtractorCaffe::~HandExtractorCaffe()\n    {\n    }\n\n    void HandExtractorCaffe::netInitializationOnThread()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Logging\n                opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                // Initialize Caffe net\n                upImpl->spNetCaffe->initializationOnThread();\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Initialize blobs\n                upImpl->spCaffeNetOutputBlob = upImpl->spNetCaffe->getOutputBlobArray();\n                upImpl->spHeatMapsBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                upImpl->spPeaksBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Logging\n                opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void HandExtractorCaffe::forwardPass(\n        const std::vector<std::array<Rectangle<float>, 2>> handRectangles, const Matrix& inputData)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (mEnabled && !handRectangles.empty())\n                {\n                    const cv::Mat cvInputData = OP_OP2CVCONSTMAT(inputData);\n\n                    // Sanity check\n                    if (cvInputData.empty())\n                        error(\"Empty cvInputData.\", __LINE__, __FUNCTION__, __FILE__);\n\n                    // Fix parameters\n                    const auto netInputSide = fastMin(mNetOutputSize.x, mNetOutputSize.y);\n\n                    // Set hand size\n                    const auto numberPeople = (int)handRectangles.size();\n                    mHandKeypoints[0].reset({numberPeople, (int)HAND_NUMBER_PARTS, 3}, 0.f);\n                    mHandKeypoints[1].reset(mHandKeypoints[0].getSize(), 0.f);\n\n                    // HeatMaps: define size\n                    if (!mHeatMapTypes.empty())\n                    {\n                        mHeatMaps[0].reset({numberPeople, (int)HAND_NUMBER_PARTS, mNetOutputSize.y, mNetOutputSize.x});\n                        mHeatMaps[1].reset({numberPeople, (int)HAND_NUMBER_PARTS, mNetOutputSize.y, mNetOutputSize.x});\n                    }\n\n                    // // Debugging\n                    // cv::Mat cvInputDataCopied = cvInputData.clone();\n                    // Extract hand keypoints for each person\n                    for (auto hand = 0 ; hand < 2 ; hand++)\n                    {\n                        // Parameters\n                        auto& handCurrent = mHandKeypoints[hand];\n                        const bool mirrorImage = (hand == 0);\n                        for (auto person = 0 ; person < numberPeople ; person++)\n                        {\n                            const auto& handRectangle = handRectangles.at(person).at(hand);\n                            // Sanity check\n                            if (handRectangle.width != handRectangle.height)\n                                error(\"Hand rectangle for hand keypoint estimation must be squared, i.e.,\"\n                                      \" width = height (\" + std::to_string(handRectangle.width) + \" vs. \"\n                                      + std::to_string(handRectangle.height) + \").\", __LINE__, __FUNCTION__, __FILE__);\n                            // Only consider faces with a minimum pixel area\n                            const auto minHandSize = fastMin(handRectangle.width, handRectangle.height);\n                            // // Debugging -> red rectangle\n                            // if (handRectangle.width > 0)\n                            //     cv::rectangle(\n                            //         cvInputDataCopied,\n                            //         cv::Point{positiveIntRound(handRectangle.x),\n                            //                   positiveIntRound(handRectangle.y)},\n                            //         cv::Point{positiveIntRound(handRectangle.x + handRectangle.width),\n                            //                   positiveIntRound(handRectangle.y + handRectangle.height)},\n                            //         cv::Scalar{(hand * 255.f),0.f,255.f}, 2);\n                            // Get parts\n                            if (minHandSize > 1 && handRectangle.area() > 10)\n                            {\n                                // Single-scale detection\n                                if (mMultiScaleNumberAndRange.first == 1)\n                                {\n                                    // // Debugging -> green rectangle overwriting red one\n                                    // if (handRectangle.width > 0)\n                                    //     cv::rectangle(\n                                    //         cvInputDataCopied,\n                                    //         cv::Point{positiveIntRound(handRectangle.x),\n                                    //                   positiveIntRound(handRectangle.y)},\n                                    //         cv::Point{positiveIntRound(handRectangle.x + handRectangle.width),\n                                    //                   positiveIntRound(handRectangle.y + handRectangle.height)},\n                                    //         cv::Scalar{(hand * 255.f),255.f,0.f}, 2);\n                                    // Parameters\n                                    cv::Mat affineMatrix;\n                                    // Resize image to hands positions + cv::Mat -> float*\n                                    cropFrame(mHandImageCrop, affineMatrix, cvInputData, handRectangle, netInputSide,\n                                              mNetOutputSize, mirrorImage);\n                                    // Deep net + Estimate keypoint locations\n                                    detectHandKeypoints(\n                                        handCurrent, upImpl->spNetCaffe, upImpl->spResizeAndMergeCaffe,\n                                        upImpl->spMaximumCaffe, upImpl->spCaffeNetOutputBlob,\n                                        upImpl->spHeatMapsBlob, upImpl->spPeaksBlob, upImpl->mNetInitialized,\n                                        mHandImageCrop, person, affineMatrix, upImpl->mGpuId);\n                                }\n                                // Multi-scale detection\n                                else\n                                {\n                                    const auto handPtrArea = handCurrent.getSize(1) * handCurrent.getSize(2);\n                                    auto* handCurrentPtr = handCurrent.getPtr() + person * handPtrArea;\n                                    const auto numberScales = mMultiScaleNumberAndRange.first;\n                                    const auto initScale = 1.f - mMultiScaleNumberAndRange.second / 2.f;\n                                    for (auto i = 0 ; i < numberScales ; i++)\n                                    {\n                                        // Get current scale\n                                        const auto scale = initScale\n                                                         + mMultiScaleNumberAndRange.second * i / (numberScales-1.f);\n                                        // Process hand\n                                        Array<float> handEstimated(\n                                            {1, handCurrent.getSize(1), handCurrent.getSize(2)}, 0.f);\n                                        const auto handRectangleScale = recenter(\n                                            handRectangle,\n                                            (float)(positiveIntRound(handRectangle.width * scale) / 2 * 2),\n                                            (float)(positiveIntRound(handRectangle.height * scale) / 2 * 2)\n                                        );\n                                        // // Debugging -> blue rectangle\n                                        // cv::rectangle(cvInputDataCopied,\n                                        //               cv::Point{positiveIntRound(handRectangleScale.x),\n                                        //                         positiveIntRound(handRectangleScale.y)},\n                                        //               cv::Point{positiveIntRound(handRectangleScale.x\n                                        //                                  + handRectangleScale.width),\n                                        //                         positiveIntRound(handRectangleScale.y\n                                        //                                  + handRectangleScale.height)},\n                                        //               cv::Scalar{255,0,0}, 2);\n                                        // Parameters\n                                        cv::Mat affineMatrix;\n                                        // Resize image to hands positions + cv::Mat -> float*\n                                        cropFrame(mHandImageCrop, affineMatrix, cvInputData, handRectangleScale,\n                                                  netInputSide, mNetOutputSize, mirrorImage);\n                                        // Deep net + Estimate keypoint locations\n                                        detectHandKeypoints(\n                                            handEstimated, upImpl->spNetCaffe, upImpl->spResizeAndMergeCaffe,\n                                            upImpl->spMaximumCaffe, upImpl->spCaffeNetOutputBlob,\n                                            upImpl->spHeatMapsBlob, upImpl->spPeaksBlob, upImpl->mNetInitialized,\n                                            mHandImageCrop, 0, affineMatrix, upImpl->mGpuId);\n                                        if (i == 0\n                                            || getAverageScore(handEstimated,0) > getAverageScore(handCurrent,person))\n                                            std::copy(handEstimated.getConstPtr(),\n                                                      handEstimated.getConstPtr() + handPtrArea, handCurrentPtr);\n                                    }\n                                }\n                                // HeatMaps: storing\n                                if (!mHeatMapTypes.empty()){\n                                    #ifdef USE_CUDA\n                                        updateHandHeatMapsForPerson(mHeatMaps[hand], person, mHeatMapScaleMode,\n                                                                    upImpl->spHeatMapsBlob->gpu_data());\n                                    #else\n                                        updateHandHeatMapsForPerson(mHeatMaps[hand], person, mHeatMapScaleMode,\n                                                                    upImpl->spHeatMapsBlob->cpu_data());\n                                    #endif\n                                }\n                            }\n                        }\n                    }\n                    // // Debugging\n                    // cv::imshow(\"cvInputDataCopied\", cvInputDataCopied);\n                }\n                else\n                {\n                    mHandKeypoints[0].reset();\n                    mHandKeypoints[1].reset();\n                }\n            #else\n                UNUSED(handRectangles);\n                UNUSED(cvInputData);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handExtractorNet.cpp",
    "content": "#include <openpose/hand/handExtractorNet.hpp>\n#include <openpose/utilities/check.hpp>\n\nnamespace op\n{\n    HandExtractorNet::HandExtractorNet(const Point<int>& netInputSize, const Point<int>& netOutputSize,\n                                       const int numberScales, const float rangeScales,\n                                       const std::vector<HeatMapType>& heatMapTypes,\n                                       const ScaleMode heatMapScaleMode) :\n        mMultiScaleNumberAndRange{std::make_pair(numberScales, rangeScales)},\n        mNetOutputSize{netOutputSize},\n        mHandImageCrop{{1, 3, mNetOutputSize.y, mNetOutputSize.x}},\n        mHeatMapScaleMode{heatMapScaleMode},\n        mHeatMapTypes{heatMapTypes},\n        mEnabled{true}\n    {\n        try\n        {\n            // Error check\n            if (mHeatMapScaleMode != ScaleMode::ZeroToOne\n                && mHeatMapScaleMode != ScaleMode::ZeroToOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOne\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::UnsignedChar)\n                error(\"The ScaleMode heatMapScaleMode must be ZeroToOne, ZeroToOneFixedAspect, PlusMinusOne,\"\n                    \" PlusMinusOneFixedAspect or UnsignedChar.\", __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netOutputSize.x, netInputSize.x, \"Net input and output size must be equal.\",\n                __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netOutputSize.y, netInputSize.y, \"Net input and output size must be equal.\",\n                __LINE__, __FUNCTION__, __FILE__);\n            checkEqual(\n                netInputSize.x, netInputSize.y, \"Net input size must be squared.\", __LINE__, __FUNCTION__, __FILE__);\n            // Warnings\n            if (!mHeatMapTypes.empty())\n                opLog(\"Note that only the keypoint heatmaps are available with hand heatmaps (no background nor PAFs).\",\n                    Priority::High);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    HandExtractorNet::~HandExtractorNet()\n    {\n    }\n\n    void HandExtractorNet::initializationOnThread()\n    {\n        try\n        {\n            // Get thread id\n            mThreadId = {std::this_thread::get_id()};\n            // Deep net initialization\n            netInitializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::array<Array<float>, 2> HandExtractorNet::getHeatMaps() const\n    {\n        try\n        {\n            checkThread();\n            return mHeatMaps;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::array<Array<float>, 2>(); // Parentheses instead of braces to avoid error in GCC 4.8\n        }\n    }\n\n    std::array<Array<float>, 2> HandExtractorNet::getHandKeypoints() const\n    {\n        try\n        {\n            checkThread();\n            return mHandKeypoints;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::array<Array<float>, 2>(); // Parentheses instead of braces to avoid error in GCC 4.8\n        }\n    }\n\n    bool HandExtractorNet::getEnabled() const\n    {\n        try\n        {\n            return mEnabled;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void HandExtractorNet::setEnabled(const bool enabled)\n    {\n        try\n        {\n            mEnabled = enabled;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void HandExtractorNet::checkThread() const\n    {\n        try\n        {\n            if (mThreadId != std::this_thread::get_id())\n                error(\"The CPU/GPU pointer data cannot be accessed from a different thread.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handGpuRenderer.cpp",
    "content": "#include <openpose/hand/handGpuRenderer.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime_api.h>\n#endif\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/hand/renderHand.hpp>\n\nnamespace op\n{\n    HandGpuRenderer::HandGpuRenderer(const float renderThreshold, const float alphaKeypoint,\n                                     const float alphaHeatMap) :\n        GpuRenderer{renderThreshold, alphaKeypoint, alphaHeatMap},\n        pGpuHand{nullptr},\n        pMaxPtr{nullptr},\n        pMinPtr{nullptr},\n        pScalePtr{nullptr}\n    {\n    }\n\n    HandGpuRenderer::~HandGpuRenderer()\n    {\n        try\n        {\n            // Free CUDA pointers - Note that if pointers are 0 (i.e., nullptr), no operation is performed.\n            #ifdef USE_CUDA\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                if (pGpuHand != nullptr)\n                {\n                    cudaFree(pGpuHand);\n                    pGpuHand = nullptr;\n                }\n                if (pMaxPtr != nullptr)\n                {\n                    cudaFree(pMaxPtr);\n                    pMaxPtr = nullptr;\n                }\n                if (pMinPtr != nullptr)\n                {\n                    cudaFree(pMinPtr);\n                    pMinPtr = nullptr;\n                }\n                if (pScalePtr != nullptr)\n                {\n                    cudaFree(pScalePtr);\n                    pScalePtr = nullptr;\n                }\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void HandGpuRenderer::initializationOnThread()\n    {\n        try\n        {\n            opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // GPU memory allocation for rendering\n            #ifdef USE_CUDA\n                cudaMalloc((void**)(&pGpuHand), HAND_MAX_HANDS * HAND_NUMBER_PARTS * 3 * sizeof(float));\n                cudaMalloc((void**)&pMaxPtr, sizeof(float) * 2 * HAND_MAX_HANDS);\n                cudaMalloc((void**)&pMinPtr, sizeof(float) * 2 * HAND_MAX_HANDS);\n                cudaMalloc((void**)&pScalePtr, sizeof(float) * HAND_MAX_HANDS);\n            #endif\n            opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void HandGpuRenderer::renderHandInherited(\n        Array<float>& outputData, const std::array<Array<float>, 2>& handKeypoints)\n    {\n        try\n        {\n            // GPU rendering\n            #ifdef USE_CUDA\n                // I prefer std::round(T&) over positiveIntRound(T) for std::atomic\n                const auto elementRendered = spElementToRender->load();\n                const auto numberPeople = handKeypoints[0].getSize(0);\n                const Point<unsigned int> frameSize{(unsigned int)outputData.getSize(1), (unsigned int)outputData.getSize(0)};\n                // GPU rendering\n                if (numberPeople > 0 && elementRendered == 0)\n                {\n                    // Draw handKeypoints\n                    cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr(), outputData.getVolume());\n                    const auto handArea = handKeypoints[0].getSize(1)*handKeypoints[0].getSize(2);\n                    const auto handVolume = numberPeople * handArea;\n                    cudaMemcpy(pGpuHand, handKeypoints[0].getConstPtr(), handVolume * sizeof(float),\n                               cudaMemcpyHostToDevice);\n                    cudaMemcpy(pGpuHand + handVolume, handKeypoints[1].getConstPtr(),\n                               handVolume * sizeof(float), cudaMemcpyHostToDevice);\n                    renderHandKeypointsGpu(\n                        *spGpuMemory, pMaxPtr, pMinPtr, pScalePtr, frameSize, pGpuHand, 2 * numberPeople,\n                        mRenderThreshold, getAlphaKeypoint());\n                    // CUDA check\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n                // GPU memory to CPU if last renderer\n                gpuToCpuMemoryIfLastRenderer(outputData.getPtr(), outputData.getVolume());\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(outputData);\n                UNUSED(handKeypoints);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/handRenderer.cpp",
    "content": "#include <openpose/hand/handRenderer.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    void HandRenderer::renderHand(Array<float>& outputData,\n                                  const std::array<Array<float>, 2>& handKeypoints,\n                                  const float scaleInputToOutput)\n    {\n        try\n        {\n            // Sanity checks\n            if (outputData.empty())\n                error(\"Empty Array<float> outputData.\", __LINE__, __FUNCTION__, __FILE__);\n            if (handKeypoints[0].getSize(0) != handKeypoints[1].getSize(0))\n                error(\"Wrong hand format: handKeypoints.getSize(0) != handKeypoints.getSize(1).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Rescale keypoints to output size\n            auto leftHandKeypointsRescaled = handKeypoints[0].clone();\n            scaleKeypoints(leftHandKeypointsRescaled, scaleInputToOutput);\n            auto rightHandKeypointsRescaled = handKeypoints[1].clone();\n            scaleKeypoints(rightHandKeypointsRescaled, scaleInputToOutput);\n            // CPU/GPU rendering\n            renderHandInherited(\n                outputData,\n                std::array<Array<float>, 2>{leftHandKeypointsRescaled, rightHandKeypointsRescaled}\n            );\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/renderHand.cpp",
    "content": "#include <openpose/hand/renderHand.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    void renderHandKeypointsCpu(Array<float>& frameArray, const std::array<Array<float>, 2>& handKeypoints,\n                                const float renderThreshold)\n    {\n        try\n        {\n            // Parameters\n            const auto thicknessCircleRatio = 1.f/50.f;\n            const auto thicknessLineRatioWRTCircle = 0.75f;\n            const auto& pairs = HAND_PAIRS_RENDER;\n            const auto& scales = HAND_SCALES_RENDER;\n            // Render keypoints\n            if (!frameArray.empty())\n                renderKeypointsCpu(frameArray, handKeypoints[0], pairs, HAND_COLORS_RENDER, thicknessCircleRatio,\n                                   thicknessLineRatioWRTCircle, scales, renderThreshold);\n            if (!frameArray.empty())\n                renderKeypointsCpu(frameArray, handKeypoints[1], pairs, HAND_COLORS_RENDER, thicknessCircleRatio,\n                                   thicknessLineRatioWRTCircle, scales, renderThreshold);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/hand/renderHand.cu",
    "content": "#include <openpose/hand/renderHand.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/hand/handParameters.hpp>\n#include <openpose_private/gpu/cuda.hu>\n#include <openpose_private/utilities/render.hu>\n\nnamespace op\n{\n    __constant__ const unsigned int PART_PAIRS_GPU[] = {HAND_PAIRS_RENDER_GPU};\n    __constant__ const float SCALES[] = {HAND_SCALES_RENDER_GPU};\n    __constant__ const float COLORS[] = {HAND_COLORS_RENDER_GPU};\n\n    __global__ void getBoundingBoxPerPersonHand(\n        float* maxPtr, float* minPtr, float* scalePtr,const int targetWidth, const int targetHeight,\n        const float* const keypointsPtr, const int numberPeople, const int numberParts, const float threshold)\n    {\n        getBoundingBoxPerPerson(\n            maxPtr, minPtr, scalePtr, targetWidth, targetHeight, keypointsPtr, numberPeople, numberParts, threshold);\n    }\n\n    __global__ void renderHandsParts(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const int targetWidth, const int targetHeight,\n        const float* const handsPtr, const int numberHands, const float threshold, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float sharedMins[2*HAND_MAX_HANDS];\n        __shared__ float sharedMaxs[2*HAND_MAX_HANDS];\n        __shared__ float sharedScaleF[HAND_MAX_HANDS];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(SCALES) / sizeof(SCALES[0]);\n        const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 80.f;\n\n        // Render key points\n        renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, maxPtr, minPtr, scalePtr, globalIdx, x, y, targetWidth,\n            targetHeight, handsPtr, PART_PAIRS_GPU, numberHands, HAND_NUMBER_PARTS, numberPartPairs, COLORS,\n            numberColors, radius, lineWidth, SCALES, numberScales, threshold, alphaColorToAdd);\n    }\n\n    void renderHandKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const Point<unsigned int>& frameSize,\n        const float* const handsPtr, const int numberHands, const float renderThreshold, const float alphaColorToAdd)\n    {\n        try\n        {\n            if (numberHands > 0)\n            {\n                // Get bounding boxes\n                const dim3 threadsPerBlockBoundBox = {1, 1, 1};\n                const dim3 numBlocksBox{getNumberCudaBlocks(POSE_MAX_PEOPLE, threadsPerBlockBoundBox.x)};\n                getBoundingBoxPerPersonHand<<<threadsPerBlockBoundBox, numBlocksBox>>>(\n                    maxPtr, minPtr, scalePtr, frameSize.x, frameSize.y, handsPtr, numberHands,\n                    HAND_NUMBER_PARTS, renderThreshold);\n                // Draw hands\n                dim3 threadsPerBlock;\n                dim3 numBlocks;\n                getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n                renderHandsParts<<<threadsPerBlock, numBlocks>>>(\n                    framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, handsPtr, numberHands,\n                    renderThreshold, alphaColorToAdd);\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/net/CMakeLists.txt",
    "content": "set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP;cl)\nset(SOURCES_OP_NET\n    bodyPartConnectorBase.cpp\n    bodyPartConnectorBase.cu\n    bodyPartConnectorBaseCL.cpp\n    bodyPartConnectorCaffe.cpp\n    maximumBase.cpp\n    maximumBase.cu\n    maximumCaffe.cpp\n    netCaffe.cpp\n    netOpenCv.cpp\n    nmsBase.cpp\n    nmsBase.cu\n    nmsBaseCL.cpp\n    nmsCaffe.cpp\n    resizeAndMergeBase.cpp\n    resizeAndMergeBase.cu\n    resizeAndMergeBaseCL.cpp\n    resizeAndMergeCaffe.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_NET_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_NET})\nset(SOURCES_OP_NET_WITH_CP ${SOURCES_OP_NET_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_NET_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_net ${SOURCES_OP_NET})\n  else ()\n    add_library(openpose_net ${SOURCES_OP_NET})\n  endif ()\n\n  add_library(caffe SHARED IMPORTED)\n  set_property(TARGET caffe PROPERTY IMPORTED_LOCATION ${Caffe_LIBS})\n  target_link_libraries(openpose_net caffe ${MKL_LIBS} openpose_core)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_net openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_net\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/net/bodyPartConnectorBase.cpp",
    "content": "#include <openpose/net/bodyPartConnectorBase.hpp>\n#include <algorithm> // std::sort\n#include <cmath> // std::sqrt\n#include <set>\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n#include <openpose/pose/poseParameters.hpp>\n\nnamespace op\n{\n    template <typename T>\n    inline T getScoreAB(\n        const int i, const int j, const T* const candidateAPtr, const T* const candidateBPtr, const T* const mapX,\n        const T* const mapY, const Point<int>& heatMapSize, const T interThreshold, const T interMinAboveThreshold,\n        const T defaultNmsThreshold)\n    {\n        try\n        {\n            const auto vectorAToBX = candidateBPtr[3*j] - candidateAPtr[3*i];\n            const auto vectorAToBY = candidateBPtr[3*j+1] - candidateAPtr[3*i+1];\n            const auto vectorAToBMax = fastMax(std::abs(vectorAToBX), std::abs(vectorAToBY));\n            const auto numberPointsInLine = fastMax(\n                5, fastMin(25, positiveIntRound(std::sqrt(5*vectorAToBMax))));\n            const auto vectorNorm = T(std::sqrt( vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY ));\n            // If the peaksPtr are coincident. Don't connect them.\n            if (vectorNorm > 1e-6)\n            {\n                const auto sX = candidateAPtr[3*i];\n                const auto sY = candidateAPtr[3*i+1];\n                const auto vectorAToBNormX = vectorAToBX/vectorNorm;\n                const auto vectorAToBNormY = vectorAToBY/vectorNorm;\n\n                auto sum = T(0);\n                auto count = 0u;\n                const auto vectorAToBXInLine = vectorAToBX/numberPointsInLine;\n                const auto vectorAToBYInLine = vectorAToBY/numberPointsInLine;\n                for (auto lm = 0; lm < numberPointsInLine; lm++)\n                {\n                    const auto mX = fastMax(\n                        0, fastMin(heatMapSize.x-1, positiveIntRound(sX + lm*vectorAToBXInLine)));\n                    const auto mY = fastMax(\n                        0, fastMin(heatMapSize.y-1, positiveIntRound(sY + lm*vectorAToBYInLine)));\n                    const auto idx = mY * heatMapSize.x + mX;\n                    const auto score = (vectorAToBNormX*mapX[idx] + vectorAToBNormY*mapY[idx]);\n                    if (score > interThreshold)\n                    {\n                        sum += score;\n                        count++;\n                    }\n                }\n                // Return PAF score\n                if (count/T(numberPointsInLine) > interMinAboveThreshold)\n                    return sum/count;\n                else\n                {\n                    // Ideally, if distanceAB = 0, PAF is 0 between A and B, provoking a false negative\n                    // To fix it, we consider PAF-connected keypoints very close to have a minimum PAF score, such that:\n                    //     1. It will consider very close keypoints (where the PAF is 0)\n                    //     2. But it will not automatically connect them (case PAF score = 1), or real PAF might got\n                    //        missing\n                    const auto l2Dist = std::sqrt(vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY);\n                    const auto threshold = std::sqrt(heatMapSize.x*heatMapSize.y)/150;\n                    if (l2Dist < threshold)\n                        return T(defaultNmsThreshold+1e-6); // Without 1e-6 will not work because I use strict greater\n                }\n            }\n            return T(0);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(0);\n        }\n    }\n\n    template <typename T>\n    void getKeypointCounter(\n        int& personCounter, const std::vector<std::pair<std::vector<int>, T>>& peopleVector,\n        const unsigned int part, const int partFirst, const int partLast, const int minimum)\n    {\n        try\n        {\n            // Count keypoints\n            auto keypointCounter = 0;\n            for (auto i = partFirst ; i < partLast ; i++)\n                keypointCounter += (peopleVector[part].first.at(i) > 0);\n            // If enough keypoints --> subtract them and keep them at least as big as minimum\n            if (keypointCounter > minimum)\n                personCounter += minimum-keypointCounter; // personCounter = non-considered keypoints + minimum\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void getRoiDiameterAndBounds(\n        Rectangle<T>& roi, int& partFirstNon0, int& partLastNon0,\n        const std::vector<int>& personVector, const T* const peaksPtr,\n        const int partInit, const int partEnd, const T margin)\n    {\n        try\n        {\n            // Find ROI, partFirstNon0, and partLastNon0\n            roi = Rectangle<T>{std::numeric_limits<T>::max(),std::numeric_limits<T>::max(),T(0),T(0)};\n            partFirstNon0 = -1;\n            partLastNon0 = -1;\n            for (auto part = partInit ; part < partEnd ; part++)\n            {\n                const auto x = peaksPtr[personVector[part]-2];\n                const auto y = peaksPtr[personVector[part]-1];\n                const auto score = peaksPtr[personVector[part]];\n                if (personVector[part] > 0 && score > 0)\n                {\n                    // ROI\n                    if (roi.x > x)\n                        roi.x = x;\n                    if (roi.y > y)\n                        roi.y = y;\n                    if (roi.width < x)\n                        roi.width = x;\n                    if (roi.height < y)\n                        roi.height = y;\n                    // First keypoint?\n                    if (partFirstNon0 < 0)\n                        partFirstNon0 = part;\n                    // Last keypoint?\n                    partLastNon0 = part;\n                }\n            }\n            if (partLastNon0 > -1)\n            {\n                // Add margin\n                const auto marginX = T(roi.width * margin);\n                const auto marginY = T(roi.height * margin);\n                roi.x -= marginX;\n                roi.y -= marginY;\n                roi.width += 2*marginX;\n                roi.height += 2*marginY;\n                // partFirstNon0+1 for loops\n                partLastNon0++;\n                // From [p1, p2] to [p1, width, height]\n                // +1 to account for 1-line keypoints\n                roi.width += 1 - roi.x;\n                roi.height += 1 - roi.y;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    std::vector<std::pair<std::vector<int>, T>> createPeopleVector(\n        const T* const heatMapPtr, const T* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize,\n        const int maxPeaks, const T interThreshold, const T interMinAboveThreshold,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs, const T defaultNmsThreshold, const Array<T>& pairScores)\n    {\n        try\n        {\n            if (poseModel != PoseModel::BODY_25 && poseModel != PoseModel::COCO_18\n                && poseModel != PoseModel::MPI_15 && poseModel != PoseModel::MPI_15_4)\n                error(\"Model not implemented for CPU body connector.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // std::vector<std::pair<std::vector<int>, double>> refers to:\n            //     - std::vector<int>: [body parts locations, #body parts found]\n            //     - double: person subset score\n            std::vector<std::pair<std::vector<int>, T>> peopleVector;\n            const auto& mapIdx = getPoseMapIndex(poseModel);\n            const auto numberBodyPartsAndBkg = numberBodyParts + (addBkgChannel(poseModel) ? 1 : 0);\n            const auto vectorSize = numberBodyParts+1;\n            const auto peaksOffset = 3*(maxPeaks+1);\n            const auto heatMapOffset = heatMapSize.area();\n            // Iterate over it PAF connection, e.g., neck-nose, neck-Lshoulder, etc.\n            for (auto pairIndex = 0u; pairIndex < numberBodyPartPairs; pairIndex++)\n            {\n                const auto bodyPartA = bodyPartPairs[2*pairIndex];\n                const auto bodyPartB = bodyPartPairs[2*pairIndex+1];\n                const auto* candidateAPtr = peaksPtr + bodyPartA*peaksOffset;\n                const auto* candidateBPtr = peaksPtr + bodyPartB*peaksOffset;\n                const auto numberPeaksA = positiveIntRound(candidateAPtr[0]);\n                const auto numberPeaksB = positiveIntRound(candidateBPtr[0]);\n\n                // E.g., neck-nose connection. If one of them is empty (e.g., no noses detected)\n                // Add the non-empty elements into the peopleVector\n                if (numberPeaksA == 0 || numberPeaksB == 0)\n                {\n                    // E.g., neck-nose connection. If no necks, add all noses\n                    // Change w.r.t. other\n                    if (numberPeaksA == 0) // numberPeaksB == 0 or not\n                    {\n                        // Non-MPI\n                        if (numberBodyParts != 15)\n                        {\n                            for (auto i = 1; i <= numberPeaksB; i++)\n                            {\n                                bool found = false;\n                                for (const auto& personVector : peopleVector)\n                                {\n                                    const auto off = (int)bodyPartB*peaksOffset + i*3 + 2;\n                                    if (personVector.first[bodyPartB] == off)\n                                    {\n                                        found = true;\n                                        break;\n                                    }\n                                }\n                                // Add new personVector with this element\n                                if (!found)\n                                {\n                                    std::vector<int> rowVector(vectorSize, 0);\n                                    // Store the index\n                                    rowVector[ bodyPartB ] = bodyPartB*peaksOffset + i*3 + 2;\n                                    // Last number in each row is the parts number of that person\n                                    rowVector.back() = 1;\n                                    const auto personScore = candidateBPtr[i*3+2];\n                                    // Second last number in each row is the total score\n                                    peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                                }\n                            }\n                        }\n                        // MPI\n                        else\n                        {\n                            for (auto i = 1; i <= numberPeaksB; i++)\n                            {\n                                std::vector<int> rowVector(vectorSize, 0);\n                                // Store the index\n                                rowVector[ bodyPartB ] = bodyPartB*peaksOffset + i*3 + 2;\n                                // Last number in each row is the parts number of that person\n                                rowVector.back() = 1;\n                                // Second last number in each row is the total score\n                                const auto personScore = candidateBPtr[i*3+2];\n                                peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                            }\n                        }\n                    }\n                    // E.g., neck-nose connection. If no noses, add all necks\n                    else // if (numberPeaksA != 0 && numberPeaksB == 0)\n                    {\n                        // Non-MPI\n                        if (numberBodyParts != 15)\n                        {\n                            for (auto i = 1; i <= numberPeaksA; i++)\n                            {\n                                bool found = false;\n                                const auto indexA = bodyPartA;\n                                for (const auto& personVector : peopleVector)\n                                {\n                                    const auto off = (int)bodyPartA*peaksOffset + i*3 + 2;\n                                    if (personVector.first[indexA] == off)\n                                    {\n                                        found = true;\n                                        break;\n                                    }\n                                }\n                                if (!found)\n                                {\n                                    std::vector<int> rowVector(vectorSize, 0);\n                                    // Store the index\n                                    rowVector[ bodyPartA ] = bodyPartA*peaksOffset + i*3 + 2;\n                                    // Last number in each row is the parts number of that person\n                                    rowVector.back() = 1;\n                                    // Second last number in each row is the total score\n                                    const auto personScore = candidateAPtr[i*3+2];\n                                    peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                                }\n                            }\n                        }\n                        // MPI\n                        else\n                        {\n                            for (auto i = 1; i <= numberPeaksA; i++)\n                            {\n                                std::vector<int> rowVector(vectorSize, 0);\n                                // Store the index\n                                rowVector[ bodyPartA ] = bodyPartA*peaksOffset + i*3 + 2;\n                                // Last number in each row is the parts number of that person\n                                rowVector.back() = 1;\n                                // Second last number in each row is the total score\n                                const auto personScore = candidateAPtr[i*3+2];\n                                peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                            }\n                        }\n                    }\n                }\n                // E.g., neck-nose connection. If necks and noses, look for maximums\n                else // if (numberPeaksA != 0 && numberPeaksB != 0)\n                {\n                    // (score, indexA, indexB). Inverted order for easy std::sort\n                    std::vector<std::tuple<double, int, int>> allABConnections;\n                    // Note: Problem of this function, if no right PAF between A and B, both elements are\n                    // discarded. However, they should be added independently, not discarded\n                    if (heatMapPtr != nullptr)\n                    {\n                        const auto* mapX = heatMapPtr\n                                         + (numberBodyPartsAndBkg + mapIdx[2*pairIndex]) * heatMapOffset;\n                        const auto* mapY = heatMapPtr\n                                         + (numberBodyPartsAndBkg + mapIdx[2*pairIndex+1]) * heatMapOffset;\n                        // E.g., neck-nose connection. For each neck\n                        for (auto i = 1; i <= numberPeaksA; i++)\n                        {\n                            // E.g., neck-nose connection. For each nose\n                            for (auto j = 1; j <= numberPeaksB; j++)\n                            {\n                                // Initial PAF\n                                auto scoreAB = getScoreAB(\n                                    i, j, candidateAPtr, candidateBPtr, mapX, mapY, heatMapSize, interThreshold,\n                                    interMinAboveThreshold, defaultNmsThreshold);\n\n                                // E.g., neck-nose connection. If possible PAF between neck i, nose j --> add\n                                // parts score + connection score\n                                if (scoreAB > 1e-6)\n                                    allABConnections.emplace_back(std::make_tuple(scoreAB, i, j));\n                            }\n                        }\n                    }\n                    else if (!pairScores.empty())\n                    {\n                        const auto firstIndex = (int)pairIndex*pairScores.getSize(1)*pairScores.getSize(2);\n                        // E.g., neck-nose connection. For each neck\n                        for (auto i = 0; i < numberPeaksA; i++)\n                        {\n                            const auto iIndex = firstIndex + i*pairScores.getSize(2);\n                            // E.g., neck-nose connection. For each nose\n                            for (auto j = 0; j < numberPeaksB; j++)\n                            {\n                                const auto scoreAB = pairScores[iIndex + j];\n\n                                // E.g., neck-nose connection. If possible PAF between neck i, nose j --> add\n                                // parts score + connection score\n                                if (scoreAB > 1e-6)\n                                    // +1 because peaksPtr starts with counter\n                                    allABConnections.emplace_back(std::make_tuple(scoreAB, i+1, j+1));\n                            }\n                        }\n                    }\n                    else\n                        error(\"Error. Should not reach here.\", __LINE__, __FUNCTION__, __FILE__);\n\n                    // select the top minAB connection, assuming that each part occur only once\n                    // sort rows in descending order based on parts + connection score\n                    if (!allABConnections.empty())\n                        std::sort(allABConnections.begin(), allABConnections.end(),\n                                  std::greater<std::tuple<double, int, int>>());\n\n                    std::vector<std::tuple<int, int, double>> abConnections; // (x, y, score)\n                    {\n                        const auto minAB = fastMin(numberPeaksA, numberPeaksB);\n                        std::vector<int> occurA(numberPeaksA, 0);\n                        std::vector<int> occurB(numberPeaksB, 0);\n                        auto counter = 0;\n                        for (const auto& aBConnection : allABConnections)\n                        {\n                            const auto score = std::get<0>(aBConnection);\n                            const auto indexA = std::get<1>(aBConnection);\n                            const auto indexB = std::get<2>(aBConnection);\n                            if (!occurA[indexA-1] && !occurB[indexB-1])\n                            {\n                                abConnections.emplace_back(std::make_tuple(\n                                    bodyPartA*peaksOffset+indexA*3+2, bodyPartB*peaksOffset+indexB*3+2, score));\n                                counter++;\n                                if (counter==minAB)\n                                    break;\n                                occurA[indexA-1] = 1;\n                                occurB[indexB-1] = 1;\n                            }\n                        }\n                    }\n\n                    // Cluster all the body part candidates into peopleVector based on the part connection\n                    if (!abConnections.empty())\n                    {\n                        // initialize first body part connection 15&16\n                        if (pairIndex==0)\n                        {\n                            for (const auto& abConnection : abConnections)\n                            {\n                                std::vector<int> rowVector(numberBodyParts+3, 0);\n                                const auto indexA = std::get<0>(abConnection);\n                                const auto indexB = std::get<1>(abConnection);\n                                const auto score = std::get<2>(abConnection);\n                                rowVector[bodyPartPairs[0]] = indexA;\n                                rowVector[bodyPartPairs[1]] = indexB;\n                                rowVector.back() = 2;\n                                // add the score of parts and the connection\n                                const auto personScore = T(peaksPtr[indexA] + peaksPtr[indexB] + score);\n                                peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                            }\n                        }\n                        // Add ears connections (in case person is looking to opposite direction to camera)\n                        // Note: This has some issues:\n                        //     - It does not prevent repeating the same keypoint in different people\n                        //     - Assuming I have nose,eye,ear as 1 person subset, and whole arm as another one, it\n                        //       will not merge them both\n                        else if (\n                            (numberBodyParts == 18 && (pairIndex==17 || pairIndex==18))\n                            || ((numberBodyParts == 19 || (numberBodyParts == 25)\n                                 || numberBodyParts == 59 || numberBodyParts == 65)\n                                && (pairIndex==18 || pairIndex==19))\n                            )\n                        {\n                            for (const auto& abConnection : abConnections)\n                            {\n                                const auto indexA = std::get<0>(abConnection);\n                                const auto indexB = std::get<1>(abConnection);\n                                for (auto& personVector : peopleVector)\n                                {\n                                    auto& personVectorA = personVector.first[bodyPartA];\n                                    auto& personVectorB = personVector.first[bodyPartB];\n                                    if (personVectorA == indexA && personVectorB == 0)\n                                    {\n                                        personVectorB = indexB;\n                                        // // This seems to harm acc 0.1% for BODY_25\n                                        // personVector.first.back()++;\n                                    }\n                                    else if (personVectorB == indexB && personVectorA == 0)\n                                    {\n                                        personVectorA = indexA;\n                                        // // This seems to harm acc 0.1% for BODY_25\n                                        // personVector.first.back()++;\n                                    }\n                                }\n                            }\n                        }\n                        else\n                        {\n                            // A is already in the peopleVector, find its connection B\n                            for (const auto& abConnection : abConnections)\n                            {\n                                const auto indexA = std::get<0>(abConnection);\n                                const auto indexB = std::get<1>(abConnection);\n                                const auto score = T(std::get<2>(abConnection));\n                                bool found = false;\n                                for (auto& personVector : peopleVector)\n                                {\n                                    // Found partA in a peopleVector, add partB to same one.\n                                    if (personVector.first[bodyPartA] == indexA)\n                                    {\n                                        personVector.first[bodyPartB] = indexB;\n                                        personVector.first.back()++;\n                                        personVector.second += peaksPtr[indexB] + score;\n                                        found = true;\n                                        break;\n                                    }\n                                }\n                                // Not found partA in peopleVector, add new peopleVector element\n                                if (!found)\n                                {\n                                    std::vector<int> rowVector(vectorSize, 0);\n                                    rowVector[bodyPartA] = indexA;\n                                    rowVector[bodyPartB] = indexB;\n                                    rowVector.back() = 2;\n                                    const auto personScore = T(peaksPtr[indexA] + peaksPtr[indexB] + score);\n                                    peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            return peopleVector;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    template <typename T>\n    std::vector<std::tuple<T, T, int, int, int>> pafPtrIntoVector(\n        const Array<T>& pairScores, const T* const peaksPtr, const int maxPeaks,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyPartPairs)\n    {\n        try\n        {\n            // Result is a std::vector<std::tuple<double, double, int, int, int>> with:\n            // (totalScore, PAFscore, pairIndex, indexA, indexB)\n            // totalScore is first to simplify later sorting\n            std::vector<std::tuple<T, T, int, int, int>> pairConnections;\n\n            // Get all PAF pairs in a single std::vector\n            const auto peaksOffset = 3*(maxPeaks+1);\n            for (auto pairIndex = 0u; pairIndex < numberBodyPartPairs; pairIndex++)\n            {\n                const auto bodyPartA = bodyPartPairs[2*pairIndex];\n                const auto bodyPartB = bodyPartPairs[2*pairIndex+1];\n                const auto* candidateAPtr = peaksPtr + bodyPartA*peaksOffset;\n                const auto* candidateBPtr = peaksPtr + bodyPartB*peaksOffset;\n                const auto numberPeaksA = positiveIntRound(candidateAPtr[0]);\n                const auto numberPeaksB = positiveIntRound(candidateBPtr[0]);\n                const auto firstIndex = (int)pairIndex*pairScores.getSize(1)*pairScores.getSize(2);\n                // E.g., neck-nose connection. For each neck\n                for (auto indexA = 0; indexA < numberPeaksA; indexA++)\n                {\n                    const auto iIndex = firstIndex + indexA*pairScores.getSize(2);\n                    // E.g., neck-nose connection. For each nose\n                    for (auto indexB = 0; indexB < numberPeaksB; indexB++)\n                    {\n                        const auto scoreAB = pairScores[iIndex + indexB];\n\n                        // E.g., neck-nose connection. If possible PAF between neck indexA, nose indexB --> add\n                        // parts score + connection score\n                        if (scoreAB > 1e-6)\n                        {\n                            // totalScore - Only used for sorting\n                            // // Original totalScore\n                            // const auto totalScore = scoreAB;\n                            // Improved totalScore\n                            // Improved to avoid too much weight in the PAF between 2 elements, adding some weight\n                            // on their confidence (avoid connecting high PAFs on very low-confident keypoints)\n                            const auto indexScoreA = bodyPartA*peaksOffset + (indexA+1)*3 + 2;\n                            const auto indexScoreB = bodyPartB*peaksOffset + (indexB+1)*3 + 2;\n                            const auto totalScore = scoreAB\n                                                  + T(0.1)*peaksPtr[indexScoreA]\n                                                  + T(0.1)*peaksPtr[indexScoreB];\n                            // +1 because peaksPtr starts with counter\n                            pairConnections.emplace_back(\n                                std::make_tuple(totalScore, scoreAB, pairIndex, indexA+1, indexB+1));\n                        }\n                    }\n                }\n            }\n\n            // Sort rows in descending order based on its first element (`totalScore`)\n            if (!pairConnections.empty())\n                std::sort(pairConnections.begin(), pairConnections.end(),\n                          std::greater<std::tuple<double, double, int, int, int>>());\n\n            // Return result\n            return pairConnections;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    template <typename T>\n    std::vector<std::pair<std::vector<int>, T>> pafVectorIntoPeopleVector(\n        const std::vector<std::tuple<T, T, int, int, int>>& pairConnections, const T* const peaksPtr,\n        const int maxPeaks, const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyParts)\n    {\n        try\n        {\n            // std::vector<std::pair<std::vector<int>, double>> refers to:\n            //     - std::vector<int>: [body parts locations, #body parts found]\n            //     - double: person subset score\n            std::vector<std::pair<std::vector<int>, T>> peopleVector;\n            const auto vectorSize = numberBodyParts+1;\n            const auto peaksOffset = (maxPeaks+1);\n            // Save which body parts have been already assigned\n            std::vector<int> personAssigned(numberBodyParts*maxPeaks, -1);\n            std::set<int, std::greater<int>> indexesToRemoveSortedSet;\n            // Iterate over each PAF pair connection detected\n            // E.g., neck1-nose2, neck5-Lshoulder0, etc.\n            for (const auto& pairConnection : pairConnections)\n            {\n                // Read pairConnection\n                // // Total score - only required for previous sort\n                // const auto totalScore = std::get<0>(pairConnection);\n                const auto pafScore = std::get<1>(pairConnection);\n                const auto pairIndex = std::get<2>(pairConnection);\n                const auto indexA = std::get<3>(pairConnection);\n                const auto indexB = std::get<4>(pairConnection);\n                // Derived data\n                const auto bodyPartA = bodyPartPairs[2*pairIndex];\n                const auto bodyPartB = bodyPartPairs[2*pairIndex+1];\n\n                const auto indexScoreA = (bodyPartA*peaksOffset + indexA)*3 + 2;\n                const auto indexScoreB = (bodyPartB*peaksOffset + indexB)*3 + 2;\n                // -1 because indexA and indexB are 1-based\n                auto& aAssigned = personAssigned[bodyPartA*maxPeaks+indexA-1];\n                auto& bAssigned = personAssigned[bodyPartB*maxPeaks+indexB-1];\n                // Debugging\n                #ifdef DEBUG\n                    if (indexA-1 > peaksOffset || indexA <= 0)\n                        error(\"Something is wrong: \" + std::to_string(indexA)\n                              + \" vs. \" + std::to_string(peaksOffset) + \". Contact us.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    if (indexB-1 > peaksOffset || indexB <= 0)\n                        error(\"Something is wrong: \" + std::to_string(indexB)\n                              + \" vs. \" + std::to_string(peaksOffset) + \". Contact us.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                #endif\n\n                // Different cases:\n                //     1. A & B not assigned yet: Create new person\n                //     2. A assigned but not B: Add B to person with A (if no another B there)\n                //     3. B assigned but not A: Add A to person with B (if no another A there)\n                //     4. A & B already assigned to same person (circular/redundant PAF): Update person score\n                //     5. A & B already assigned to different people: Merge people if keypoint intersection is null\n                // 1. A & B not assigned yet: Create new person\n                if (aAssigned < 0 && bAssigned < 0)\n                {\n                    // Keypoint indexes\n                    std::vector<int> rowVector(vectorSize, 0);\n                    rowVector[bodyPartA] = indexScoreA;\n                    rowVector[bodyPartB] = indexScoreB;\n                    // Number keypoints\n                    rowVector.back() = 2;\n                    // Score\n                    const auto personScore = T(peaksPtr[indexScoreA] + peaksPtr[indexScoreB] + pafScore);\n                    // Set associated personAssigned as assigned\n                    aAssigned = (int)peopleVector.size();\n                    bAssigned = aAssigned;\n                    // Create new personVector\n                    peopleVector.emplace_back(std::make_pair(rowVector, personScore));\n                }\n                // 2. A assigned but not B: Add B to person with A (if no another B there)\n                // or\n                // 3. B assigned but not A: Add A to person with B (if no another A there)\n                else if ((aAssigned >= 0 && bAssigned < 0)\n                    || (aAssigned < 0 && bAssigned >= 0))\n                {\n                    // Assign person1 to one where xAssigned >= 0\n                    const auto assigned1 = (aAssigned >= 0 ? aAssigned : bAssigned);\n                    auto& assigned2 = (aAssigned >= 0 ? bAssigned : aAssigned);\n                    const auto bodyPart2 = (aAssigned >= 0 ? bodyPartB : bodyPartA);\n                    const auto indexScore2 = (aAssigned >= 0 ? indexScoreB : indexScoreA);\n                    // Person index\n                    auto& personVector = peopleVector[assigned1];\n                    // Debugging\n                    #ifdef DEBUG\n                        const auto bodyPart1 = (aAssigned >= 0 ? bodyPartA : bodyPartB);\n                        const auto indexScore1 = (aAssigned >= 0 ? indexScoreA : indexScoreB);\n                        const auto index1 = (aAssigned >= 0 ? indexA : indexB);\n                        if ((unsigned int)personVector.first.at(bodyPart1) != indexScore1)\n                            error(\"Something is wrong: \"\n                                  + std::to_string((personVector.first[bodyPart1]-2)/3-bodyPart1*peaksOffset)\n                                  + \" vs. \" + std::to_string((indexScore1-2)/3-bodyPart1*peaksOffset) + \" vs. \"\n                                  + std::to_string(index1) + \". Contact us.\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                    #endif\n                    // If person with 1 does not have a 2 yet\n                    if (personVector.first[bodyPart2] == 0)\n                    {\n                        // Update keypoint indexes\n                        personVector.first[bodyPart2] = indexScore2;\n                        // Update number keypoints\n                        personVector.first.back()++;\n                        // Update score\n                        personVector.second += peaksPtr[indexScore2] + pafScore;\n                        // Set associated personAssigned as assigned\n                        assigned2 = assigned1;\n                    }\n                    // Otherwise, ignore this B because the previous one came from a higher PAF-confident score\n                }\n                // 4. A & B already assigned to same person (circular/redundant PAF): Update person score\n                else if (aAssigned >=0 && bAssigned >=0 && aAssigned == bAssigned)\n                    peopleVector[aAssigned].second += pafScore;\n                // 5. A & B already assigned to different people: Merge people if keypoint intersection is null\n                // I.e., that the keypoints in person A and B do not overlap\n                else if (aAssigned >=0 && bAssigned >=0 && aAssigned != bAssigned)\n                {\n                    // Assign person1 to the one with lowest index for 2 reasons:\n                    //     1. Speed up: Removing an element from std::vector is cheaper for latest elements\n                    //     2. Avoid harder index update: Updated elements in person1ssigned would depend on\n                    //        whether person1 > person2 or not: element = aAssigned - (person2 > person1 ? 1 : 0)\n                    const auto assigned1 = (aAssigned < bAssigned ? aAssigned : bAssigned);\n                    const auto assigned2 = (aAssigned < bAssigned ? bAssigned : aAssigned);\n                    auto& person1 = peopleVector[assigned1].first;\n                    const auto& person2 = peopleVector[assigned2].first;\n                    // Check if complementary\n                    // Defining found keypoint indexes in personA as kA, and analogously kB\n                    // Complementary if and only if kA intersection kB = empty. I.e., no common keypoints\n                    bool complementary = true;\n                    for (auto part = 0u ; part < numberBodyParts ; part++)\n                    {\n                        if (person1[part] > 0 && person2[part] > 0)\n                        {\n                            complementary = false;\n                            break;\n                        }\n                    }\n                    // If complementary, merge both people into 1\n                    if (complementary)\n                    {\n                        // Update keypoint indexes\n                        for (auto part = 0u ; part < numberBodyParts ; part++)\n                            if (person1[part] == 0)\n                                person1[part] = person2[part];\n                        // Update number keypoints\n                        person1.back() += person2.back();\n                        // Update score\n                        peopleVector[assigned1].second += peopleVector[assigned2].second + pafScore;\n                        // Erase the non-merged person\n                        // peopleVector.erase(peopleVector.begin()+assigned2); // x2 slower when removing on-the-fly\n                        indexesToRemoveSortedSet.emplace(assigned2); // Add into set so we can remove them all at once\n                        // Update associated personAssigned (person indexes have changed)\n                        for (auto& element : personAssigned)\n                        {\n                            if (element == assigned2)\n                                element = assigned1;\n                            // No need because I will only remove them at the very end\n                            // else if (element > assigned2)\n                            //     element--;\n                        }\n                    }\n                }\n            }\n            // Remove unused people\n            for (const auto& index : indexesToRemoveSortedSet)\n                peopleVector.erase(peopleVector.begin()+index);\n            // Return result\n            return peopleVector;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    template <typename T>\n    void removePeopleBelowThresholdsAndFillFaces(\n        std::vector<int>& validSubsetIndexes, int& numberPeople,\n        std::vector<std::pair<std::vector<int>, T>>& peopleVector, const unsigned int numberBodyParts,\n        const int minSubsetCnt, const T minSubsetScore, const bool maximizePositives, const T* const peaksPtr)\n        // const int minSubsetCnt, const T minSubsetScore, const int maxPeaks, const bool maximizePositives)\n    {\n        try\n        {\n            // Delete people below the following thresholds:\n                // a) minSubsetCnt: removed if less than minSubsetCnt body parts\n                // b) minSubsetScore: removed if global score smaller than this\n                // c) maxPeaks (POSE_MAX_PEOPLE): keep first maxPeaks people above thresholds -> Not required\n            numberPeople = 0;\n            validSubsetIndexes.clear();\n            // validSubsetIndexes.reserve(fastMin((size_t)maxPeaks, peopleVector.size())); // maxPeaks is not required\n            validSubsetIndexes.reserve(peopleVector.size());\n            // Face valid sets\n            std::vector<int> faceValidSubsetIndexes;\n            faceValidSubsetIndexes.reserve(peopleVector.size());\n            // Face invalid sets\n            std::vector<int> faceInvalidSubsetIndexes;\n            if (numberBodyParts >= 135)\n                faceInvalidSubsetIndexes.reserve(peopleVector.size());\n            // For each person candidate\n            for (auto person = 0u ; person < peopleVector.size() ; person++)\n            {\n                auto personCounter = peopleVector[person].first.back();\n                // Analog for hand/face keypoints\n                if (numberBodyParts >= 135)\n                {\n                    // No consider face keypoints for personCounter\n                    const auto currentCounter = personCounter;\n                    getKeypointCounter(personCounter, peopleVector, person, 65, 135, 1);\n                    const auto newCounter = personCounter;\n                    if (personCounter == 1)\n                    {\n                        faceInvalidSubsetIndexes.emplace_back(person);\n                        continue;\n                    }\n                    // If body is still valid and facial points were removed, then add to valid faces\n                    else if (currentCounter != newCounter)\n                        faceValidSubsetIndexes.emplace_back(person);\n                    // No consider right hand keypoints for personCounter\n                    getKeypointCounter(personCounter, peopleVector, person, 45, 65, 1);\n                    // No consider left hand keypoints for personCounter\n                    getKeypointCounter(personCounter, peopleVector, person, 25, 45, 1);\n                }\n                // Foot keypoints do not affect personCounter (too many false positives,\n                // same foot usually appears as both left and right keypoints)\n                // Pros: Removed tons of false positives\n                // Cons: Standalone leg will never be recorded\n                // Solution: No consider foot keypoints for that\n                if (!maximizePositives && (numberBodyParts == 25 || numberBodyParts > 70))\n                {\n                    const auto currentCounter = personCounter;\n                    getKeypointCounter(personCounter, peopleVector, person, 19, 25, 0);\n                    const auto newCounter = personCounter;\n                    // Problem: Same leg/foot keypoints are considered for both left and right keypoints.\n                    // Solution: Remove legs that are duplicated and that do not have upper torso\n                    // Result: Slight increase in COCO mAP and decrease in mAR + reducing a lot false positives!\n                    if (newCounter != currentCounter && newCounter <= 4)\n                        continue;\n                }\n                // Add only valid people\n                const auto personScore = peopleVector[person].second;\n                if (personCounter >= minSubsetCnt && (personScore/personCounter) >= minSubsetScore)\n                {\n                    numberPeople++;\n                    validSubsetIndexes.emplace_back(person);\n                    // // This is not required, it is OK if there are more people. No more GPU memory used.\n                    // if (numberPeople == maxPeaks)\n                    //     break;\n                }\n                // Sanity check\n                else if ((personCounter < 1 && numberBodyParts != 25 && numberBodyParts < 70) || personCounter < 0)\n                    error(\"Bad personCounter (\" + std::to_string(personCounter) + \"). Bug in this\"\n                          \" function if this happens.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Random standalone facial keypoints --> Merge into a more complete face\n            if (numberPeople > 0)\n            {\n                // Check invalid faces\n                for (const auto& personInvalid : faceInvalidSubsetIndexes)\n                {\n                    // Get ROI of current face\n                    Rectangle<T> roiInvalid;\n                    int partFirstNon0Invalid = -1;\n                    int partLastNon0Invalid = -1;\n                    getRoiDiameterAndBounds(\n                        roiInvalid, partFirstNon0Invalid, partLastNon0Invalid,\n                        peopleVector[personInvalid].first, peaksPtr, 65, 135, T(0.2));\n                    // Check all valid faces to find best candidate\n                    float keypointsRoiBest = 0.f;\n                    auto keypointsRoiBestIndex = -1;\n                    for (auto personId = 0u ; personId < faceValidSubsetIndexes.size() ; personId++)\n                    {\n                        const auto& personValid = faceValidSubsetIndexes[personId];\n                        // Get ROI of current face\n                        Rectangle<T> roiValid;\n                        int partFirstNon0Valid = -1;\n                        int partLastNon0Valid = -1;\n                        getRoiDiameterAndBounds(\n                            roiValid, partFirstNon0Valid, partLastNon0Valid, peopleVector[personValid].first,\n                            peaksPtr, 65, 135, T(0.1));\n                        // Get ROI between both faces\n                        const auto keypointsRoi = getKeypointsRoi(roiValid, roiInvalid);\n                        // Update best so far\n                        if (keypointsRoiBest < keypointsRoi)\n                        {\n                            keypointsRoiBest = keypointsRoi;\n                            keypointsRoiBestIndex = personId;\n                        }\n                    }\n                    // If invalid and best valid candidate overlap enough --> Merge them\n                    if (keypointsRoiBest > 0.3f || (keypointsRoiBest > 0.01f && faceValidSubsetIndexes.size() < 3))\n                    {\n                        const auto& personValid = faceValidSubsetIndexes[keypointsRoiBestIndex];\n                        // If it is from that face --> Combine invalid face keypoints into valid face\n                        for (auto part = partFirstNon0Invalid ; part < partLastNon0Invalid ; part++)\n                        {\n                            auto& personVectorValid = peopleVector[personValid].first;\n                            const auto scoreValid = peaksPtr[personVectorValid[part]];\n                            const auto& personVectorInvalid = peopleVector[personInvalid].first;\n                            const auto scoreInvalid = peaksPtr[personVectorInvalid[part]];\n                            // If the new one has a keypoint...\n                            if (personVectorInvalid[part] != 0)\n                            {\n                                // ... and the original face does not have it, then add it to it\n                                if (personVectorValid[part] == 0)\n                                {\n                                    if (personVectorInvalid[part] != 0)\n                                    {\n                                        personVectorValid[part] = personVectorInvalid[part];\n                                        peopleVector[personValid].second += scoreInvalid;\n                                    }\n                                }\n                                // ... and its score is higher than the original one, then replace it\n                                else if (scoreValid < scoreInvalid)\n                                {\n                                    personVectorValid[part] = personVectorInvalid[part];\n                                    peopleVector[personValid].second += scoreInvalid - scoreValid;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            // If no people found --> Repeat with maximizePositives = true\n            // Result: Increased COCO mAP because we catch more foot-only images\n            if (numberPeople == 0 && !maximizePositives)\n            {\n                removePeopleBelowThresholdsAndFillFaces(\n                    validSubsetIndexes, numberPeople, peopleVector, numberBodyParts, minSubsetCnt, minSubsetScore,\n                    true, peaksPtr);\n                // // Debugging\n                // if (numberPeople > 0)\n                //     opLog(\"Found \" + std::to_string(numberPeople) + \" people in second iteration\");\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void peopleVectorToPeopleArray(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T scaleFactor,\n        const std::vector<std::pair<std::vector<int>, T>>& peopleVector, const std::vector<int>& validSubsetIndexes,\n        const T* const peaksPtr, const int numberPeople, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs)\n    {\n        try\n        {\n            // Allocate memory (initialized to 0)\n            if (numberPeople > 0)\n            {\n                // Initialized to 0 for non-found keypoints in people\n                poseKeypoints.reset({numberPeople, (int)numberBodyParts, 3}, 0.f);\n                poseScores.reset(numberPeople);\n            }\n            // No people --> Empty Arrays\n            else\n            {\n                poseKeypoints.reset();\n                poseScores.reset();\n            }\n            // Fill people keypoints\n            const auto oneOverNumberBodyPartsAndPAFs = 1/T(numberBodyParts + numberBodyPartPairs);\n            // For each person\n            for (auto person = 0u ; person < validSubsetIndexes.size() ; person++)\n            {\n                const auto& personPair = peopleVector[validSubsetIndexes[person]];\n                const auto& personVector = personPair.first;\n                // For each body part\n                for (auto bodyPart = 0u; bodyPart < numberBodyParts; bodyPart++)\n                {\n                    const auto baseOffset = (person*numberBodyParts + bodyPart) * 3;\n                    const auto bodyPartIndex = personVector[bodyPart];\n                    if (bodyPartIndex > 0)\n                    {\n                        poseKeypoints[baseOffset] = peaksPtr[bodyPartIndex-2] * scaleFactor;\n                        poseKeypoints[baseOffset + 1] = peaksPtr[bodyPartIndex-1] * scaleFactor;\n                        poseKeypoints[baseOffset + 2] = peaksPtr[bodyPartIndex];\n                    }\n                }\n                poseScores[person] = personPair.second * oneOverNumberBodyPartsAndPAFs;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n//     template <typename T>\n//     void connectDistanceStar(Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapPtr,\n//                              const T* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize,\n//                              const int maxPeaks, const T scaleFactor, const unsigned int numberBodyParts,\n//                              const unsigned int bodyPartPairsSize)\n//     {\n//         try\n//         {\n//             // poseKeypoints from neck-part distances\n//             if (poseModel == PoseModel::BODY_25D)\n//             {\n//                 const auto scaleDownFactor = 8;\n//                 Array<T> poseKeypoints2 = poseKeypoints.clone();\n//                 const auto rootIndex = 1;\n//                 const auto rootNumberIndex = rootIndex*(maxPeaks+1)*3;\n//                 const auto numberPeople = positiveIntRound(peaksPtr[rootNumberIndex]);\n//                 poseKeypoints.reset({numberPeople, (int)numberBodyParts, 3}, 0);\n//                 poseScores.reset(numberPeople, 0);\n//                 // // 48 channels\n//                 // const std::vector<float> AVERAGE{\n//                 //     0.f, -2.76364f, -1.3345f, 0.f,   -1.95322f, 3.95679f, -1.20664f, 4.76543f,\n//                 //     1.3345f, 0.f, 1.92318f, 3.96891f,   1.17999f, 4.7901f, 0.f, 7.72201f,\n//                 //     -0.795236f, 7.74017f, -0.723963f,   11.209f, -0.651316f, 15.6972f,\n//                 //     0.764623f, 7.74869f, 0.70755f,   11.2307f, 0.612832f, 15.7281f,\n//                 //     -0.123134f, -3.43515f,   0.111775f, -3.42761f,\n//                 //     -0.387066f, -3.16603f,   0.384038f, -3.15951f,\n//                 //     0.344764f, 12.9666f, 0.624157f,   12.9057f, 0.195454f, 12.565f,\n//                 //     -1.06074f, 12.9951f, -1.2427f,   12.9309f, -0.800837f, 12.5845f};\n//                 // const std::vector<float> SIGMA{\n//                 //     3.39629f, 3.15605f, 3.16913f, 1.8234f,   5.82252f, 5.05674f, 7.09876f, 6.64574f,\n//                 //     3.16913f, 1.8234f, 5.79415f, 5.01424f,   7.03866f, 6.62427f, 5.52593f, 6.75962f,\n//                 //     5.91224f, 6.87241f, 8.66473f,   10.1792f, 11.5871f, 13.6565f,\n//                 //     5.86653f, 6.89568f, 8.68067f,   10.2127f, 11.5954f, 13.6722f,\n//                 //     3.3335f, 3.49128f,   3.34476f, 3.50079f,\n//                 //     2.93982f, 3.11151f,   2.95006f, 3.11004f,\n//                 //     9.69408f, 7.58921f, 9.71193f,   7.44185f, 9.19343f, 7.11157f,\n//                 //     9.16848f, 7.86122f, 9.07613f,   7.83682f, 8.91951f, 7.33715f};\n//                 // 50 channels\n//                 const std::vector<float> AVERAGE{\n//                     0.f, -6.55251f,\n//                     0.f, -4.15062f, -1.48818f, -4.15506f,   -2.22408f, -0.312264f, -1.42204f, 0.588495f,\n//                     1.51044f, -4.14629f, 2.2113f, -0.312283f,   1.41081f, 0.612377f, -0.f, 3.41112f,\n//                     -0.932306f, 3.45504f, -0.899812f,   6.79837f, -0.794223f, 11.4972f,\n//                     0.919047f, 3.46442, 0.902314f,   6.81245f, 0.79518f, 11.5132f,\n//                     -0.243982f, -7.07925f,   0.28065f, -7.07398f,\n//                     -0.792812f, -7.09374f,   0.810145f, -7.06958f,\n//                     0.582387f, 7.46846f, 0.889349f,   7.40577f, 0.465088f, 7.03969f,\n//                     -0.96686f, 7.46148f, -1.20773f,   7.38834f, -0.762135f, 6.99575f};\n//                 const std::vector<float> SIGMA{\n//                     7.26789f, 9.70751f,\n//                     6.29588f, 8.93472f, 6.97401f, 9.13746f,   7.49632f, 9.44757f, 8.06695f, 9.97319f,\n//                     6.99726f, 9.14608f, 7.50529f, 9.43568f,   8.05888f, 9.98207f, 6.38929f, 9.29314f,\n//                     6.71801f, 9.39271f, 8.00608f,   10.6141f, 10.3416f, 12.7812f,\n//                     6.69875f, 9.41407f, 8.01876f,   10.637f, 10.3475f, 12.7849f,\n//                     7.30923f, 9.7324f,   7.27886f, 9.73406f,\n//                     7.35978f, 9.7289f,   7.28914f, 9.67711f,\n//                     7.93153f, 8.10845f, 7.95577f,   8.01729f, 7.56865f, 7.87314f,\n//                     7.4655f, 8.25336f, 7.43958f,   8.26333f, 7.33667f, 7.97446f};\n//                 // To get ideal distance\n//                 const auto numberBodyPartsAndBkgAndPAFChannels = numberBodyParts + 1 + bodyPartPairsSize;\n//                 const auto heatMapOffset = heatMapSize.area();\n//                 // For each person\n//                 for (auto p = 0 ; p < numberPeople ; p++)\n//                 {\n//                     // For root (neck) position\n//                     // bpOrig == rootIndex\n//                     const auto rootXYSIndex = rootNumberIndex+3*(1+p);\n//                     // Set (x,y,score)\n//                     const auto rootX = scaleFactor*peaksPtr[rootXYSIndex];\n//                     const auto rootY = scaleFactor*peaksPtr[rootXYSIndex+1];\n//                     poseKeypoints[{p,rootIndex,0}] = rootX;\n//                     poseKeypoints[{p,rootIndex,1}] = rootY;\n//                     poseKeypoints[{p,rootIndex,2}] = peaksPtr[rootXYSIndex+2];\n//                     // For each body part\n//                     for (auto bpOrig = 0 ; bpOrig < (int)numberBodyParts ; bpOrig++)\n//                     {\n//                         if (bpOrig != rootIndex)\n//                         {\n//                             // // 48 channels\n//                             // const auto bpChannel = (bpOrig < rootIndex ? bpOrig : bpOrig-1);\n//                             // 50 channels\n//                             const auto bpChannel = bpOrig;\n//                             // Get ideal distance\n//                             const auto offsetIndex = numberBodyPartsAndBkgAndPAFChannels + 2*bpChannel;\n//                             const auto* mapX = heatMapPtr + offsetIndex * heatMapOffset;\n//                             const auto* mapY = heatMapPtr + (offsetIndex+1) * heatMapOffset;\n//                             const auto increaseRatio = scaleFactor*scaleDownFactor;\n//                             // Set (x,y) coordinates from the distance\n//                             const auto indexChannel = 2*bpChannel;\n//                             // // Not refined method\n//                             // const auto index = positiveIntRound(rootY/scaleFactor)*heatMapSize.x\n//                                                 + positiveIntRound(rootX/scaleFactor);\n//                             // const Point<T> neckPartDist{\n//                             //     increaseRatio*(mapX[index]*SIGMA[indexChannel]+AVERAGE[indexChannel]),\n//                             //     increaseRatio*(mapY[index]*SIGMA[indexChannel+1]+AVERAGE[indexChannel+1])};\n//                             // poseKeypoints[{p,bpOrig,0}] = rootX + neckPartDist.x;\n//                             // poseKeypoints[{p,bpOrig,1}] = rootY + neckPartDist.y;\n//                             // Refined method\n//                             const auto constant = 5;\n//                             Point<T> neckPartDistRefined{0, 0};\n//                             auto counterRefinements = 0;\n//                             // We must keep it inside the image size\n//                             for (auto y = fastMax(0, positiveIntRound(rootY/scaleFactor) - constant);\n//                                  y < fastMin(heatMapSize.y, positiveIntRound(rootY/scaleFactor) + constant+1) ; y++)\n//                             {\n//                                 for (auto x = fastMax(0, positiveIntRound(rootX/scaleFactor) - constant);\n//                                      x < fastMin(heatMapSize.x, positiveIntRound(rootX/scaleFactor) + constant+1) ; x++)\n//                                 {\n//                                     const auto index = y*heatMapSize.x + x;\n//                                     neckPartDistRefined.x += mapX[index];\n//                                     neckPartDistRefined.y += mapY[index];\n//                                     counterRefinements++;\n//                                 }\n//                             }\n//                             neckPartDistRefined = Point<T>{\n//                                 neckPartDistRefined.x*SIGMA[indexChannel]+counterRefinements*AVERAGE[indexChannel],\n//                                 neckPartDistRefined.y*SIGMA[indexChannel+1]+counterRefinements*AVERAGE[indexChannel+1],\n//                             };\n//                             neckPartDistRefined *= increaseRatio/counterRefinements;\n//                             const auto partX = rootX + neckPartDistRefined.x;\n//                             const auto partY = rootY + neckPartDistRefined.y;\n//                             poseKeypoints[{p,bpOrig,0}] = partX;\n//                             poseKeypoints[{p,bpOrig,1}] = partY;\n//                             // Set (temporary) body part score\n//                             poseKeypoints[{p,bpOrig,2}] = T(0.0501);\n//                             // Associate estimated keypoint with closest one\n//                             const auto xCleaned = fastMax(\n//                                 0, fastMin(heatMapSize.x-1, positiveIntRound(partX/scaleFactor)));\n//                             const auto yCleaned = fastMax(\n//                                 0, fastMin(heatMapSize.y-1, positiveIntRound(partY/scaleFactor)));\n//                             const auto partConfidence = heatMapPtr[\n//                                 bpOrig * heatMapOffset + yCleaned*heatMapSize.x + xCleaned];\n//                             // If partConfidence is big enough, it means we are close to a keypoint\n//                             if (partConfidence > T(0.05))\n//                             {\n//                                 const auto candidateNumberIndex = bpOrig*(maxPeaks+1)*3;\n//                                 const auto numberCandidates = positiveIntRound(peaksPtr[candidateNumberIndex]);\n//                                 int closestIndex = -1;\n//                                 T closetValue = std::numeric_limits<T>::max();\n//                                 for (auto i = 0 ; i < numberCandidates ; i++)\n//                                 {\n//                                     const auto candidateXYSIndex = candidateNumberIndex+3*(1+i);\n//                                     const auto diffX = partX-scaleFactor*peaksPtr[candidateXYSIndex];\n//                                     const auto diffY = partY-scaleFactor*peaksPtr[candidateXYSIndex+1];\n//                                     const auto dist = (diffX*diffX + diffY*diffY);\n//                                     if (closetValue > dist)\n//                                     {\n//                                         closetValue = dist;\n//                                         closestIndex = candidateXYSIndex;\n//                                     }\n//                                 }\n//                                 if (closestIndex != -1)\n//                                 {\n//                                     poseKeypoints[{p,bpOrig,0}] = scaleFactor*peaksPtr[closestIndex];\n//                                     poseKeypoints[{p,bpOrig,1}] = scaleFactor*peaksPtr[closestIndex+1];\n//                                     // Set body part score\n//                                     poseKeypoints[{p,bpOrig,2}] = peaksPtr[closestIndex+2];\n//                                 }\n//                             }\n//                             // Set poseScore\n//                             poseScores[p] += poseKeypoints[{p,bpOrig,2}];\n//                         }\n//                     }\n//                 }\n//             }\n//         }\n//         catch (const std::exception& e)\n//         {\n//             error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n//         }\n//     }\n\n//     const std::vector<float> AVERAGE{\n//         0.f, -6.55251f,\n//         0.f, -4.15062f, -1.48818, -4.15506f,   -2.22408f, -0.312264f, -1.42204f, 0.588495f,\n//         1.51044f, -4.14629f, 2.2113f, -0.312283f,   1.41081f, 0.612377f, -0.f, 3.41112f,\n//         -0.932306f, 3.45504f, -0.899812f,   6.79837f, -0.794223f, 11.4972f,\n//         0.919047f, 3.46442f, 0.902314f,   6.81245f, 0.79518f, 11.5132f,\n//         -0.243982f, -7.07925f,   0.28065f, -7.07398f,\n//         -0.792812f, -7.09374f,   0.810145f, -7.06958f,\n//         0.582387f, 7.46846f, 0.889349f,   7.40577f, 0.465088f, 7.03969f,\n//         -0.96686f, 7.46148f, -1.20773f,   7.38834f, -0.762135f, 6.99575f};\n//     const std::vector<float> SIGMA{\n//         7.26789f, 9.70751f,\n//         6.29588f, 8.93472f, 6.97401f, 9.13746f,   7.49632f, 9.44757f, 8.06695f, 9.97319f,\n//         6.99726f, 9.14608f, 7.50529f, 9.43568f,   8.05888f, 9.98207f, 6.38929f, 9.29314f,\n//         6.71801f, 9.39271f, 8.00608f,   10.6141f, 10.3416f, 12.7812f,\n//         6.69875f, 9.41407f, 8.01876f,   10.637f, 10.3475f, 12.7849f,\n//         7.30923f, 9.7324f,   7.27886f, 9.73406f,\n//         7.35978f, 9.7289f,   7.28914f, 9.67711f,\n//         7.93153f, 8.10845f, 7.95577f,   8.01729f, 7.56865f, 7.87314f,\n//         7.4655f, 8.25336f, 7.43958f,   8.26333f, 7.33667f, 7.97446f};\n//     template <typename T>\n//     std::array<T,3> regressPart(const Array<T>& person, const int rootIndex, const int targetIndex,\n//                                 const int scaleDownFactor, const T* const heatMapPtr, const T* const peaksPtr,\n//                                 const Point<int>& heatMapSize, const int maxPeaks, const T scaleFactor,\n//                                 const unsigned int numberBodyPartsAndBkgAndPAFChannels)\n//     {\n//         try\n//         {\n//             std::array<T,3> result{0,0,0};\n//             // poseKeypoints from neck-part distances\n//             if (targetIndex != rootIndex && person[{rootIndex,2}] > T(0.05))\n//             {\n//                 // Set (x,y)\n//                 const auto rootX = person[{rootIndex,0}];\n//                 const auto rootY = person[{rootIndex,1}];\n//                 // Get ideal distance\n//                 const auto indexChannel = 2*targetIndex;\n//                 const auto offsetIndex = numberBodyPartsAndBkgAndPAFChannels + indexChannel;\n//                 const auto heatMapOffset = heatMapSize.area();\n//                 const auto* mapX = heatMapPtr + offsetIndex * heatMapOffset;\n//                 const auto* mapY = heatMapPtr + (offsetIndex+1) * heatMapOffset;\n//                 const auto increaseRatio = scaleFactor*scaleDownFactor;\n//                 // // Not refined method\n//                 // const auto index = positiveIntRound(rootY/scaleFactor)*heatMapSize.x\n//                                     + positiveIntRound(rootX/scaleFactor);\n//                 // const Point<T> neckPartDist{\n//                 //     increaseRatio*(mapX[index]*SIGMA[indexChannel]+AVERAGE[indexChannel]),\n//                 //     increaseRatio*(mapY[index]*SIGMA[indexChannel+1]+AVERAGE[indexChannel+1])};\n//                 // poseKeypoints[{p,targetIndex,0}] = rootX + neckPartDist.x;\n//                 // poseKeypoints[{p,targetIndex,1}] = rootY + neckPartDist.y;\n//                 // Refined method\n//                 const auto constant = 5;\n//                 Point<T> neckPartDistRefined{0, 0};\n//                 auto counterRefinements = 0;\n//                 // We must keep it inside the image size\n//                 for (auto y = fastMax(0, positiveIntRound(rootY/scaleFactor) - constant);\n//                      y < fastMin(heatMapSize.y, positiveIntRound(rootY/scaleFactor) + constant+1) ; y++)\n//                 {\n//                     for (auto x = fastMax(0, positiveIntRound(rootX/scaleFactor) - constant);\n//                          x < fastMin(heatMapSize.x, positiveIntRound(rootX/scaleFactor) + constant+1) ; x++)\n//                     {\n//                         const auto index = y*heatMapSize.x + x;\n//                         neckPartDistRefined.x += mapX[index];\n//                         neckPartDistRefined.y += mapY[index];\n//                         counterRefinements++;\n//                     }\n//                 }\n//                 neckPartDistRefined = Point<T>{\n//                     neckPartDistRefined.x*SIGMA[indexChannel]+counterRefinements*AVERAGE[indexChannel],\n//                     neckPartDistRefined.y*SIGMA[indexChannel+1]+counterRefinements*AVERAGE[indexChannel+1],\n//                 };\n//                 neckPartDistRefined *= increaseRatio/counterRefinements;\n//                 const auto partX = rootX + neckPartDistRefined.x;\n//                 const auto partY = rootY + neckPartDistRefined.y;\n//                 result[0] = partX;\n//                 result[1] = partY;\n//                 // Set (temporary) body part score\n//                 result[2] = T(0.0501);\n//                 // Associate estimated keypoint with closest one\n//                 const auto xCleaned = fastMax(0, fastMin(heatMapSize.x-1, positiveIntRound(partX/scaleFactor)));\n//                 const auto yCleaned = fastMax(0, fastMin(heatMapSize.y-1, positiveIntRound(partY/scaleFactor)));\n//                 const auto partConfidence = heatMapPtr[\n//                     targetIndex * heatMapOffset + yCleaned*heatMapSize.x + xCleaned];\n//                 // If partConfidence is big enough, it means we are close to a keypoint\n//                 if (partConfidence > T(0.05))\n//                 {\n//                     const auto candidateNumberIndex = targetIndex*(maxPeaks+1)*3;\n//                     const auto numberCandidates = positiveIntRound(peaksPtr[candidateNumberIndex]);\n//                     int closestIndex = -1;\n//                     T closetValue = std::numeric_limits<T>::max();\n//                     for (auto i = 0 ; i < numberCandidates ; i++)\n//                     {\n//                         const auto candidateXYSIndex = candidateNumberIndex+3*(1+i);\n//                         const auto diffX = partX-scaleFactor*peaksPtr[candidateXYSIndex];\n//                         const auto diffY = partY-scaleFactor*peaksPtr[candidateXYSIndex+1];\n//                         const auto dist = (diffX*diffX + diffY*diffY);\n//                         if (closetValue > dist)\n//                         {\n//                             closetValue = dist;\n//                             closestIndex = candidateXYSIndex;\n//                         }\n//                     }\n//                     if (closestIndex != -1)\n//                     {\n//                         result[0] = scaleFactor*peaksPtr[closestIndex];\n//                         result[1] = scaleFactor*peaksPtr[closestIndex+1];\n//                         // Set body part score\n//                         result[2] = peaksPtr[closestIndex+2];\n//                     }\n//                 }\n//             }\n//             return result;\n//         }\n//         catch (const std::exception& e)\n//         {\n//             error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n//             return std::array<T,3>{};\n//         }\n//     }\n\n//     template <typename T>\n//     void connectDistanceMultiStar(Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapPtr,\n//                                   const T* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize,\n//                                   const int maxPeaks, const T scaleFactor, const unsigned int numberBodyParts,\n//                                   const unsigned int bodyPartPairsSize)\n//     {\n//         try\n//         {\n//             // poseKeypoints from neck-part distances\n//             if (poseModel == PoseModel::BODY_25D)\n//             {\n//                 // Add all the root elements (necks)\n//                 const std::vector<int> keypointsSize = {(int)numberBodyParts, 3};\n//                 // Initial #people = number root elements\n//                 const auto rootIndex = 1;\n//                 std::vector<Array<T>> poseKeypointsTemp;\n//                 // Iterate for each body part\n//                 const std::array<int, 25> MAPPING{\n//                     1, 8, 0, 2,5,9,12, 3,6,10,13, 15,16, 4,7,11,14, 17,18, 19,22,20,23,21,24};\n//                 const auto numberBodyPartsAndBkgAndPAFChannels = numberBodyParts + 1 + bodyPartPairsSize;\n//                 const auto scaleDownFactor = 8;\n//                 for (auto index = 0u ; index < numberBodyParts ; index++)\n//                 {\n//                     const auto targetIndex = MAPPING[index];\n//                     // Get all candidate keypoints\n//                     const auto partNumberIndex = targetIndex*(maxPeaks+1)*3;\n//                     const auto numberPartParts = positiveIntRound(peaksPtr[partNumberIndex]);\n//                     std::vector<std::array<T, 3>> currentPartCandidates(numberPartParts);\n//                     for (auto i = 0u ; i < currentPartCandidates.size() ; i++)\n//                     {\n//                         const auto baseIndex = partNumberIndex+3*(i+1);\n//                         currentPartCandidates[i][0] = scaleFactor*peaksPtr[baseIndex];\n//                         currentPartCandidates[i][1] = scaleFactor*peaksPtr[baseIndex+1];\n//                         currentPartCandidates[i][2] = peaksPtr[baseIndex+2];\n//                     }\n//                     // Detect new body part for existing people\n//                     // For each temporary person --> Add new targetIndex part\n//                     for (auto& person : poseKeypointsTemp)\n//                     {\n//                         // Estimate new body part w.r.t. each already-detected body part\n//                         for (auto rootMapIndex = 0u ; rootMapIndex < index ; rootMapIndex++)\n//                         {\n//                             const auto rootIndex = MAPPING[rootMapIndex];\n//                             if (person[{rootIndex,2}] > T(0.0501))\n//                             {\n//                                 const auto result = regressPart(\n//                                     person, rootIndex, targetIndex, scaleDownFactor, heatMapPtr, peaksPtr,\n//                                     heatMapSize, maxPeaks, scaleFactor, numberBodyPartsAndBkgAndPAFChannels);\n//                                 if (person[{targetIndex,2}] < result[2])\n//                                 {\n//                                     person[{targetIndex,0}] = result[0];\n//                                     person[{targetIndex,1}] = result[1];\n//                                     person[{targetIndex,2}] = result[2];\n//                                 }\n//                             }\n//                         }\n//                     }\n//                     // Add leftovers body parts as new people\n// if (targetIndex == rootIndex)\n// {\n//                     const auto currentSize = poseKeypointsTemp.size();\n//                     poseKeypointsTemp.resize(currentSize+currentPartCandidates.size());\n//                     for (auto p = 0u ; p < currentPartCandidates.size() ; p++)\n//                     {\n//                         poseKeypointsTemp[currentSize+p] = Array<T>(keypointsSize, 0.f);\n//                         const auto baseIndex = 3*targetIndex;\n//                         poseKeypointsTemp[currentSize+p][baseIndex  ] = currentPartCandidates[p][0];\n//                         poseKeypointsTemp[currentSize+p][baseIndex+1] = currentPartCandidates[p][1];\n//                         poseKeypointsTemp[currentSize+p][baseIndex+2] = currentPartCandidates[p][2];\n//                     }\n\n// }\n//                 }\n//                 // poseKeypoints: Reformat poseKeypointsTemp as poseKeypoints\n//                 poseKeypoints.reset({(int)poseKeypointsTemp.size(), (int)numberBodyParts, 3}, 0);\n//                 poseScores.reset(poseKeypoints.getSize(0), 0.f);\n//                 const auto keypointArea = poseKeypoints.getSize(1)*poseKeypoints.getSize(2);\n//                 for (auto p = 0 ; p < poseKeypoints.getSize(0) ; p++)\n//                 {\n//                     const auto pIndex = p*keypointArea;\n//                     for (auto part = 0 ; part < poseKeypoints.getSize(1) ; part++)\n//                     {\n//                         const auto baseIndexTemp = 3*part;\n//                         const auto baseIndex = pIndex+baseIndexTemp;\n//                         poseKeypoints[baseIndex  ] = poseKeypointsTemp[p][baseIndexTemp];\n//                         poseKeypoints[baseIndex+1] = poseKeypointsTemp[p][baseIndexTemp+1];\n//                         poseKeypoints[baseIndex+2] = poseKeypointsTemp[p][baseIndexTemp+2];\n//                         // Set poseScore\n//                         poseScores[p] += poseKeypoints[baseIndex+2];\n//                     }\n//                 }\n//             }\n//         }\n//         catch (const std::exception& e)\n//         {\n//             error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n//         }\n//     }\n\n    template <typename T>\n    void connectBodyPartsCpu(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor, const bool maximizePositives)\n    {\n        try\n        {\n            // Parts Connection\n            const auto& bodyPartPairs = getPosePartPairs(poseModel);\n            const auto numberBodyParts = getPoseNumberBodyParts(poseModel);\n            const auto numberBodyPartPairs = (unsigned int)(bodyPartPairs.size() / 2);\n            if (numberBodyParts == 0)\n                error(\"Invalid value of numberBodyParts, it must be positive, not \" + std::to_string(numberBodyParts),\n                      __LINE__, __FUNCTION__, __FILE__);\n            // std::vector<std::pair<std::vector<int>, double>> refers to:\n            //     - std::vector<int>: [body parts locations, #body parts found]\n            //     - double: person subset score\n\n            auto peopleVector = createPeopleVector(\n                heatMapPtr, peaksPtr, poseModel, heatMapSize, maxPeaks, interThreshold, interMinAboveThreshold,\n                bodyPartPairs, numberBodyParts, numberBodyPartPairs, defaultNmsThreshold);\n            // Delete people below the following thresholds:\n                // a) minSubsetCnt: removed if less than minSubsetCnt body parts\n                // b) minSubsetScore: removed if global score smaller than this\n                // c) maxPeaks (POSE_MAX_PEOPLE): keep first maxPeaks people above thresholds\n            int numberPeople;\n            std::vector<int> validSubsetIndexes;\n            // validSubsetIndexes.reserve(fastMin((size_t)maxPeaks, peopleVector.size()));\n            validSubsetIndexes.reserve(peopleVector.size());\n            removePeopleBelowThresholdsAndFillFaces(\n                validSubsetIndexes, numberPeople, peopleVector, numberBodyParts, minSubsetCnt, minSubsetScore,\n                maximizePositives, peaksPtr);\n            // Fill and return poseKeypoints\n            peopleVectorToPeopleArray(\n                poseKeypoints, poseScores, scaleFactor, peopleVector, validSubsetIndexes, peaksPtr, numberPeople,\n                numberBodyParts, numberBodyPartPairs);\n            // Experimental code\n            if (poseModel == PoseModel::BODY_25D)\n                error(\"BODY_25D is an experimental branch which is not usable.\", __LINE__, __FUNCTION__, __FILE__);\n//                 connectDistanceMultiStar(poseKeypoints, poseScores, heatMapPtr, peaksPtr, poseModel, heatMapSize,\n//                                          maxPeaks, scaleFactor, numberBodyParts, bodyPartPairs.size());\n//                 connectDistanceStar(poseKeypoints, poseScores, heatMapPtr, peaksPtr, poseModel, heatMapSize,\n//                                     maxPeaks, scaleFactor, numberBodyParts, bodyPartPairs.size());\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template OP_API void connectBodyPartsCpu(\n        Array<float>& poseKeypoints, Array<float>& poseScores, const float* const heatMapPtr,\n        const float* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const float interMinAboveThreshold, const float interThreshold, const int minSubsetCnt,\n        const float minSubsetScore, const float defaultNmsThreshold, const float scaleFactor,\n        const bool maximizePositives);\n    template OP_API void connectBodyPartsCpu(\n        Array<double>& poseKeypoints, Array<double>& poseScores, const double* const heatMapPtr,\n        const double* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const double interMinAboveThreshold, const double interThreshold, const int minSubsetCnt,\n        const double minSubsetScore, const double defaultNmsThreshold, const double scaleFactor,\n        const bool maximizePositives);\n\n    template OP_API std::vector<std::pair<std::vector<int>, float>> createPeopleVector(\n        const float* const heatMapPtr, const float* const peaksPtr, const PoseModel poseModel,\n        const Point<int>& heatMapSize, const int maxPeaks, const float interThreshold,\n        const float interMinAboveThreshold, const std::vector<unsigned int>& bodyPartPairs,\n        const unsigned int numberBodyParts, const unsigned int numberBodyPartPairs,\n        const float defaultNmsThreshold, const Array<float>& precomputedPAFs);\n    template OP_API std::vector<std::pair<std::vector<int>, double>> createPeopleVector(\n        const double* const heatMapPtr, const double* const peaksPtr, const PoseModel poseModel,\n        const Point<int>& heatMapSize, const int maxPeaks, const double interThreshold,\n        const double interMinAboveThreshold, const std::vector<unsigned int>& bodyPartPairs,\n        const unsigned int numberBodyParts, const unsigned int numberBodyPartPairs,\n        const double defaultNmsThreshold, const Array<double>& precomputedPAFs);\n\n    template OP_API void removePeopleBelowThresholdsAndFillFaces(\n        std::vector<int>& validSubsetIndexes, int& numberPeople,\n        std::vector<std::pair<std::vector<int>, float>>& peopleVector,\n        const unsigned int numberBodyParts, const int minSubsetCnt, const float minSubsetScore,\n        const bool maximizePositives, const float* const peaksPtr);\n    template OP_API void removePeopleBelowThresholdsAndFillFaces(\n        std::vector<int>& validSubsetIndexes, int& numberPeople,\n        std::vector<std::pair<std::vector<int>, double>>& peopleVector,\n        const unsigned int numberBodyParts, const int minSubsetCnt, const double minSubsetScore,\n        const bool maximizePositives, const double* const peaksPtr);\n\n    template OP_API void peopleVectorToPeopleArray(\n        Array<float>& poseKeypoints, Array<float>& poseScores, const float scaleFactor,\n        const std::vector<std::pair<std::vector<int>, float>>& peopleVector,\n        const std::vector<int>& validSubsetIndexes, const float* const peaksPtr,\n        const int numberPeople, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs);\n    template OP_API void peopleVectorToPeopleArray(\n        Array<double>& poseKeypoints, Array<double>& poseScores, const double scaleFactor,\n        const std::vector<std::pair<std::vector<int>, double>>& peopleVector,\n        const std::vector<int>& validSubsetIndexes, const double* const peaksPtr,\n        const int numberPeople, const unsigned int numberBodyParts,\n        const unsigned int numberBodyPartPairs);\n\n    template OP_API std::vector<std::tuple<float, float, int, int, int>> pafPtrIntoVector(\n        const Array<float>& pairScores, const float* const peaksPtr, const int maxPeaks,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyPartPairs);\n    template OP_API std::vector<std::tuple<double, double, int, int, int>> pafPtrIntoVector(\n        const Array<double>& pairScores, const double* const peaksPtr, const int maxPeaks,\n        const std::vector<unsigned int>& bodyPartPairs, const unsigned int numberBodyPartPairs);\n\n    template OP_API std::vector<std::pair<std::vector<int>, float>> pafVectorIntoPeopleVector(\n        const std::vector<std::tuple<float, float, int, int, int>>& pairConnections,\n        const float* const peaksPtr, const int maxPeaks, const std::vector<unsigned int>& bodyPartPairs,\n        const unsigned int numberBodyParts);\n    template OP_API std::vector<std::pair<std::vector<int>, double>> pafVectorIntoPeopleVector(\n        const std::vector<std::tuple<double, double, int, int, int>>& pairConnections,\n        const double* const peaksPtr, const int maxPeaks, const std::vector<unsigned int>& bodyPartPairs,\n        const unsigned int numberBodyParts);\n}\n"
  },
  {
    "path": "src/openpose/net/bodyPartConnectorBase.cu",
    "content": "#include <openpose/net/bodyPartConnectorBase.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    template<typename T>\n    inline __device__ int intRoundGPU(const T a)\n    {\n        return int(a+T(0.5));\n    }\n\n    template <typename T>\n    inline __device__  T process(\n        const T* bodyPartA, const T* bodyPartB, const T* mapX, const T* mapY, const int heatmapWidth,\n        const int heatmapHeight, const T interThreshold, const T interMinAboveThreshold, const T defaultNmsThreshold)\n    {\n        const auto vectorAToBX = bodyPartB[0] - bodyPartA[0];\n        const auto vectorAToBY = bodyPartB[1] - bodyPartA[1];\n        const auto vectorAToBMax = max(abs(vectorAToBX), abs(vectorAToBY));\n        const auto numberPointsInLine = max(5, min(25, intRoundGPU(sqrt(5*vectorAToBMax))));\n        const auto vectorNorm = T(sqrt(vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY));\n\n        // If the peaksPtr are coincident. Don't connect them.\n        if (vectorNorm > 1e-6)\n        {\n            const auto sX = bodyPartA[0];\n            const auto sY = bodyPartA[1];\n            const auto vectorAToBNormX = vectorAToBX/vectorNorm;\n            const auto vectorAToBNormY = vectorAToBY/vectorNorm;\n\n            auto sum = T(0.);\n            auto count = 0;\n            const auto vectorAToBXInLine = vectorAToBX/numberPointsInLine;\n            const auto vectorAToBYInLine = vectorAToBY/numberPointsInLine;\n            for (auto lm = 0; lm < numberPointsInLine; lm++)\n            {\n                const auto mX = min(heatmapWidth-1, intRoundGPU(sX + lm*vectorAToBXInLine));\n                const auto mY = min(heatmapHeight-1, intRoundGPU(sY + lm*vectorAToBYInLine));\n                const auto idx = mY * heatmapWidth + mX;\n                const auto score = (vectorAToBNormX*mapX[idx] + vectorAToBNormY*mapY[idx]);\n                if (score > interThreshold)\n                {\n                    sum += score;\n                    count++;\n                }\n            }\n            // Return PAF score\n            if (count/T(numberPointsInLine) > interMinAboveThreshold)\n                return sum/count;\n            else\n            {\n                // Ideally, if distanceAB = 0, PAF is 0 between A and B, provoking a false negative\n                // To fix it, we consider PAF-connected keypoints very close to have a minimum PAF score, such that:\n                //     1. It will consider very close keypoints (where the PAF is 0)\n                //     2. But it will not automatically connect them (case PAF score = 1), or real PAF might got\n                //        missing\n                const auto l2Dist = sqrtf(vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY);\n                const auto threshold = sqrtf(heatmapWidth*heatmapHeight)/150; // 3.3 for 368x656, 6.6 for 2x resolution\n                if (l2Dist < threshold)\n                    return T(defaultNmsThreshold+1e-6); // Without 1e-6 will not work because I use strict greater\n            }\n        }\n        return -1;\n    }\n\n    // template <typename T>\n    // __global__ void pafScoreKernelOld(\n    //     T* pairScoresPtr, const T* const heatMapPtr, const T* const peaksPtr, const unsigned int* const bodyPartPairsPtr,\n    //     const unsigned int* const mapIdxPtr, const unsigned int maxPeaks, const int numberBodyPartPairs,\n    //     const int heatmapWidth, const int heatmapHeight, const T interThreshold, const T interMinAboveThreshold,\n    //     const T defaultNmsThreshold)\n    // {\n    //     const auto pairIndex = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto peakA = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     const auto peakB = (blockIdx.z * blockDim.z) + threadIdx.z;\n\n    //     if (pairIndex < numberBodyPartPairs && peakA < maxPeaks && peakB < maxPeaks)\n    //     {\n    //         const auto baseIndex = 2*pairIndex;\n    //         const auto partA = bodyPartPairsPtr[baseIndex];\n    //         const auto partB = bodyPartPairsPtr[baseIndex + 1];\n\n    //         const T numberPeaksA = peaksPtr[3*partA*(maxPeaks+1)];\n    //         const T numberPeaksB = peaksPtr[3*partB*(maxPeaks+1)];\n\n    //         const auto outputIndex = (pairIndex*maxPeaks+peakA)*maxPeaks + peakB;\n    //         if (peakA < numberPeaksA && peakB < numberPeaksB)\n    //         {\n    //             const auto mapIdxX = mapIdxPtr[baseIndex];\n    //             const auto mapIdxY = mapIdxPtr[baseIndex + 1];\n\n    //             const T* const bodyPartA = peaksPtr + (3*(partA*(maxPeaks+1) + peakA+1));\n    //             const T* const bodyPartB = peaksPtr + (3*(partB*(maxPeaks+1) + peakB+1));\n    //             const T* const mapX = heatMapPtr + mapIdxX*heatmapWidth*heatmapHeight;\n    //             const T* const mapY = heatMapPtr + mapIdxY*heatmapWidth*heatmapHeight;\n    //             pairScoresPtr[outputIndex] = process(\n    //                 bodyPartA, bodyPartB, mapX, mapY, heatmapWidth, heatmapHeight, interThreshold,\n    //                 interMinAboveThreshold, defaultNmsThreshold);\n    //         }\n    //         else\n    //             pairScoresPtr[outputIndex] = -1;\n    //     }\n    // }\n\n    template <typename T>\n    __global__ void pafScoreKernel(\n        T* pairScoresPtr, const T* const heatMapPtr, const T* const peaksPtr, const unsigned int* const bodyPartPairsPtr,\n        const unsigned int* const mapIdxPtr, const unsigned int maxPeaks, const int numberBodyPartPairs,\n        const int heatmapWidth, const int heatmapHeight, const T interThreshold, const T interMinAboveThreshold,\n        const T defaultNmsThreshold)\n    {\n        const auto peakB = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto peakA = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto pairIndex = (blockIdx.z * blockDim.z) + threadIdx.z;\n\n        if (peakA < maxPeaks && peakB < maxPeaks)\n        // if (pairIndex < numberBodyPartPairs && peakA < maxPeaks && peakB < maxPeaks)\n        {\n            const auto baseIndex = 2*pairIndex;\n            const auto partA = bodyPartPairsPtr[baseIndex];\n            const auto partB = bodyPartPairsPtr[baseIndex + 1];\n\n            const T numberPeaksA = peaksPtr[3*partA*(maxPeaks+1)];\n            const T numberPeaksB = peaksPtr[3*partB*(maxPeaks+1)];\n\n            const auto outputIndex = (pairIndex*maxPeaks+peakA)*maxPeaks + peakB;\n            if (peakA < numberPeaksA && peakB < numberPeaksB)\n            {\n                const auto mapIdxX = mapIdxPtr[baseIndex];\n                const auto mapIdxY = mapIdxPtr[baseIndex + 1];\n\n                const T* const bodyPartA = peaksPtr + (3*(partA*(maxPeaks+1) + peakA+1));\n                const T* const bodyPartB = peaksPtr + (3*(partB*(maxPeaks+1) + peakB+1));\n                const T* const mapX = heatMapPtr + mapIdxX*heatmapWidth*heatmapHeight;\n                const T* const mapY = heatMapPtr + mapIdxY*heatmapWidth*heatmapHeight;\n                pairScoresPtr[outputIndex] = process(\n                    bodyPartA, bodyPartB, mapX, mapY, heatmapWidth, heatmapHeight, interThreshold,\n                    interMinAboveThreshold, defaultNmsThreshold);\n            }\n            else\n                pairScoresPtr[outputIndex] = -1;\n        }\n    }\n\n    template <typename T>\n    void connectBodyPartsGpu(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor, const bool maximizePositives, Array<T> pairScoresCpu, T* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const T* const peaksGpuPtr)\n    {\n        try\n        {\n            // Parts Connection\n            const auto& bodyPartPairs = getPosePartPairs(poseModel);\n            const auto numberBodyParts = getPoseNumberBodyParts(poseModel);\n            const auto numberBodyPartPairs = (unsigned int)(bodyPartPairs.size() / 2);\n            const auto totalComputations = pairScoresCpu.getVolume();\n\n            if (numberBodyParts == 0)\n                error(\"Invalid value of numberBodyParts, it must be positive, not \" + std::to_string(numberBodyParts),\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (bodyPartPairsGpuPtr == nullptr || mapIdxGpuPtr == nullptr)\n                error(\"The pointers bodyPartPairsGpuPtr and mapIdxGpuPtr cannot be nullptr.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n\n            // const auto REPS = 1000;\n            // double timeNormalize0 = 0.;\n            // double timeNormalize1 = 0.;\n            // double timeNormalize2 = 0.;\n\n            // // Old - Non-efficient code\n            // OP_CUDA_PROFILE_INIT(REPS);\n            // // Run Kernel - pairScoresGpu\n            // const dim3 THREADS_PER_BLOCK{4, 16, 16};\n            // const dim3 numBlocks{\n            //     getNumberCudaBlocks(numberBodyPartPairs, THREADS_PER_BLOCK.x),\n            //     getNumberCudaBlocks(maxPeaks, THREADS_PER_BLOCK.y),\n            //     getNumberCudaBlocks(maxPeaks, THREADS_PER_BLOCK.z)};\n            // pafScoreKernelOld<<<numBlocks, THREADS_PER_BLOCK>>>(\n            //     pairScoresGpuPtr, heatMapGpuPtr, peaksGpuPtr, bodyPartPairsGpuPtr, mapIdxGpuPtr,\n            //     maxPeaks, (int)numberBodyPartPairs, heatMapSize.x, heatMapSize.y, interThreshold,\n            //     interMinAboveThreshold, defaultNmsThreshold);\n            // // pairScoresCpu <-- pairScoresGpu\n            // cudaMemcpy(pairScoresCpu.getPtr(), pairScoresGpuPtr, totalComputations * sizeof(T),\n            //            cudaMemcpyDeviceToHost);\n            // OP_PROFILE_END(timeNormalize1, 1e3, REPS);\n\n            // Efficient code\n            // OP_CUDA_PROFILE_INIT(REPS);\n            // Run Kernel - pairScoresGpu\n            const dim3 THREADS_PER_BLOCK{128, 1, 1};\n            const dim3 numBlocks{\n                getNumberCudaBlocks(maxPeaks, THREADS_PER_BLOCK.x),\n                getNumberCudaBlocks(maxPeaks, THREADS_PER_BLOCK.y),\n                getNumberCudaBlocks(numberBodyPartPairs, THREADS_PER_BLOCK.z)};\n            pafScoreKernel<<<numBlocks, THREADS_PER_BLOCK>>>(\n                pairScoresGpuPtr, heatMapGpuPtr, peaksGpuPtr, bodyPartPairsGpuPtr, mapIdxGpuPtr,\n                maxPeaks, (int)numberBodyPartPairs, heatMapSize.x, heatMapSize.y, interThreshold,\n                interMinAboveThreshold, defaultNmsThreshold);\n            // pairScoresCpu <-- pairScoresGpu\n            cudaMemcpy(pairScoresCpu.getPtr(), pairScoresGpuPtr, totalComputations * sizeof(T),\n                       cudaMemcpyDeviceToHost);\n            // OP_PROFILE_END(timeNormalize2, 1e3, REPS);\n\n            // Get pair connections and their scores\n            const auto pairConnections = pafPtrIntoVector(\n                pairScoresCpu, peaksPtr, maxPeaks, bodyPartPairs, numberBodyPartPairs);\n            auto peopleVector = pafVectorIntoPeopleVector(\n                pairConnections, peaksPtr, maxPeaks, bodyPartPairs, numberBodyParts);\n            // // Old code: Get pair connections and their scores\n            // // std::vector<std::pair<std::vector<int>, double>> refers to:\n            // //     - std::vector<int>: [body parts locations, #body parts found]\n            // //     - double: person subset score\n            // const T* const tNullptr = nullptr;\n            // const auto peopleVector = createPeopleVector(\n            //     tNullptr, peaksPtr, poseModel, heatMapSize, maxPeaks, interThreshold, interMinAboveThreshold,\n            //     bodyPartPairs, numberBodyParts, numberBodyPartPairs, defaultNmsThreshold, pairScoresCpu);\n            // Delete people below the following thresholds:\n                // a) minSubsetCnt: removed if less than minSubsetCnt body parts\n                // b) minSubsetScore: removed if global score smaller than this\n                // c) maxPeaks (POSE_MAX_PEOPLE): keep first maxPeaks people above thresholds\n            int numberPeople;\n            std::vector<int> validSubsetIndexes;\n            // validSubsetIndexes.reserve(fastMin((size_t)maxPeaks, peopleVector.size()));\n            validSubsetIndexes.reserve(peopleVector.size());\n            removePeopleBelowThresholdsAndFillFaces(\n                validSubsetIndexes, numberPeople, peopleVector, numberBodyParts, minSubsetCnt, minSubsetScore,\n                maximizePositives, peaksPtr);\n            // Fill and return poseKeypoints\n            peopleVectorToPeopleArray(\n                poseKeypoints, poseScores, scaleFactor, peopleVector, validSubsetIndexes, peaksPtr, numberPeople,\n                numberBodyParts, numberBodyPartPairs);\n\n            // // Profiling verbose\n            // opLog(\"  BPC(ori)=\" + std::to_string(timeNormalize1) + \"ms\");\n            // opLog(\"  BPC(new)=\" + std::to_string(timeNormalize2) + \"ms\");\n\n            // Sanity check\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void connectBodyPartsGpu(\n        Array<float>& poseKeypoints, Array<float>& poseScores, const float* const heatMapGpuPtr,\n        const float* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const float interMinAboveThreshold, const float interThreshold, const int minSubsetCnt,\n        const float minSubsetScore, const float scaleFactor, const float defaultNmsThreshold,\n        const bool maximizePositives, Array<float> pairScoresCpu, float* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const float* const peaksGpuPtr);\n    template void connectBodyPartsGpu(\n        Array<double>& poseKeypoints, Array<double>& poseScores, const double* const heatMapGpuPtr,\n        const double* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const double interMinAboveThreshold, const double interThreshold, const int minSubsetCnt,\n        const double minSubsetScore, const double scaleFactor, const double defaultNmsThreshold,\n        const bool maximizePositives, Array<double> pairScoresCpu, double* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const double* const peaksGpuPtr);\n}\n"
  },
  {
    "path": "src/openpose/net/bodyPartConnectorBaseCL.cpp",
    "content": "#include <openpose/net/bodyPartConnectorBase.hpp>\n#include <iostream>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    #ifdef USE_OPENCL\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, cl::Buffer, cl::Buffer, cl::Buffer, unsigned int, int, int,\n            int, float, float, float> PAFScoreKernelFunctor;\n        const std::string pafScoreKernel = MULTI_LINE_STRING(\n\n            int intRoundGPU(const Type a)\n            {\n                return (int)(a+0.5);\n            }\n\n            Type process(\n                __global const Type* bodyPartA, __global const Type* bodyPartB, __global const Type* mapX,\n                __global const Type* mapY, const int heatmapWidth, const int heatmapHeight, const Type interThreshold,\n                const Type interMinAboveThreshold, const Type defaultNmsThreshold)\n            {\n                const Type vectorAToBX = bodyPartB[0] - bodyPartA[0];\n                const Type vectorAToBY = bodyPartB[1] - bodyPartA[1];\n                const Type vectorAToBMax = max(fabs(vectorAToBX), fabs(vectorAToBY));\n                const int numberPointsInLine = max(5, min(25, intRoundGPU(sqrt(5*vectorAToBMax))));\n                const Type vectorNorm = (Type)(sqrt(vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY));\n                Type rval = -1;\n\n                if (vectorNorm > 1e-6)\n                {\n                    const Type sX = bodyPartA[0];\n                    const Type sY = bodyPartA[1];\n                    const Type vectorAToBNormX = vectorAToBX/vectorNorm;\n                    const Type vectorAToBNormY = vectorAToBY/vectorNorm;\n\n                    Type sum = (Type)(0.);\n                    int count = 0;\n                    const Type vectorAToBXInLine = vectorAToBX/numberPointsInLine;\n                    const Type vectorAToBYInLine = vectorAToBY/numberPointsInLine;\n                    for (int lm = 0; lm < numberPointsInLine; lm++)\n                    {\n                        const int mX = min(heatmapWidth-1, intRoundGPU(sX + lm*vectorAToBXInLine));\n                        const int mY = min(heatmapHeight-1, intRoundGPU(sY + lm*vectorAToBYInLine));\n                        const int idx = mY * heatmapWidth + mX;\n                        const Type score = (vectorAToBNormX*mapX[idx] + vectorAToBNormY*mapY[idx]);\n                        if (score > interThreshold)\n                        {\n                            sum += score;\n                            count++;\n                        }\n                    }\n\n                    // Return PAF score\n                    if (count/(Type)(numberPointsInLine) > interMinAboveThreshold)\n                        return (Type)(sum)/(Type)(count);\n                    else\n                    {\n                        // Ideally, if distanceAB = 0, PAF is 0 between A and B, provoking a false negative\n                        // To fix it, we consider PAF-connected keypoints very close to have a minimum PAF score, such that:\n                        //     1. It will consider very close keypoints (where the PAF is 0)\n                        //     2. But it will not automatically connect them (case PAF score = 1), or real PAF might got\n                        //        missing\n                        const Type l2Dist = sqrt((Type)(vectorAToBX*vectorAToBX + vectorAToBY*vectorAToBY));\n                        const Type threshold = sqrt((Type)(heatmapWidth*heatmapHeight))/150; // 3.3 for 368x656, 6.6 for 2x resolution\n                        if (l2Dist < threshold)\n                            return (Type)(defaultNmsThreshold+1e-6); // Without 1e-6 will not work because I use strict greater\n                    }\n                }\n                return -1;\n            }\n\n            __kernel void pafScoreKernel(\n                __global Type* pairScoresPtr, __global const Type* const heatMapPtr, __global const Type* const peaksPtr,\n                __global const unsigned int* const bodyPartPairsPtr, __global const unsigned int* const mapIdxPtr,\n                const unsigned int maxPeaks, const int numberBodyPartPairs, const int heatmapWidth,\n                const int heatmapHeight, const Type interThreshold, const Type interMinAboveThreshold,\n                const Type defaultNmsThreshold)\n            {\n                int pairIndex = get_global_id(0);\n                int peakA = get_global_id(1);\n                int peakB = get_global_id(2);\n\n                if (pairIndex < numberBodyPartPairs && peakA < maxPeaks && peakB < maxPeaks)\n                {\n                    int baseIndex = 2*pairIndex;\n                    int partA = bodyPartPairsPtr[baseIndex];\n                    int partB = bodyPartPairsPtr[baseIndex + 1];\n\n                    const Type numberPeaksA = peaksPtr[3*partA*(maxPeaks+1)];\n                    const Type numberPeaksB = peaksPtr[3*partB*(maxPeaks+1)];\n\n                    const int outputIndex = (pairIndex*maxPeaks+peakA)*maxPeaks + peakB;\n                    if (peakA < numberPeaksA && peakB < numberPeaksB)\n                    {\n                        const int mapIdxX = mapIdxPtr[baseIndex];\n                        const int mapIdxY = mapIdxPtr[baseIndex + 1];\n\n                        __global const Type* bodyPartA = peaksPtr + (3*(partA*(maxPeaks+1) + peakA+1));\n                        __global const Type* bodyPartB = peaksPtr + (3*(partB*(maxPeaks+1) + peakB+1));\n                        __global const Type* mapX = heatMapPtr + mapIdxX*heatmapWidth*heatmapHeight;\n                        __global const Type* mapY = heatMapPtr + mapIdxY*heatmapWidth*heatmapHeight;\n\n                        pairScoresPtr[outputIndex] = process(\n                            bodyPartA, bodyPartB, mapX, mapY, heatmapWidth, heatmapHeight, interThreshold,\n                            interMinAboveThreshold, defaultNmsThreshold);\n                    }\n                    else\n                        pairScoresPtr[outputIndex] = -1;\n                }\n\n            }\n        );\n    #endif\n\n    template <typename T>\n    void connectBodyPartsOcl(\n        Array<T>& poseKeypoints, Array<T>& poseScores, const T* const heatMapGpuPtr, const T* const peaksPtr,\n        const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks, const T interMinAboveThreshold,\n        const T interThreshold, const int minSubsetCnt, const T minSubsetScore, const T defaultNmsThreshold,\n        const T scaleFactor, const bool maximizePositives, Array<T> pairScoresCpu, T* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const T* const peaksGpuPtr, const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_OPENCL\n                // Parts Connection\n                const auto& bodyPartPairs = getPosePartPairs(poseModel);\n                const auto numberBodyParts = getPoseNumberBodyParts(poseModel);\n                const auto numberBodyPartPairs = (unsigned int)(bodyPartPairs.size() / 2);\n                const auto totalComputations = pairScoresCpu.getVolume();\n\n                if (numberBodyParts == 0)\n                    error(\"Invalid value of numberBodyParts, it must be positive, not \" + std::to_string(numberBodyParts),\n                          __LINE__, __FUNCTION__, __FILE__);\n                if (bodyPartPairsGpuPtr == nullptr || mapIdxGpuPtr == nullptr)\n                    error(\"The pointers bodyPartPairsGpuPtr and mapIdxGpuPtr cannot be nullptr.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                auto pafScoreKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <PAFScoreKernelFunctor, T>(\n                         \"pafScoreKernel\", op::pafScoreKernel);\n\n                cl::Buffer pairScoresGpuPtrBuffer = cl::Buffer((cl_mem)(pairScoresGpuPtr), true);\n                cl::Buffer heatMapGpuPtrBuffer = cl::Buffer((cl_mem)(heatMapGpuPtr), true);\n                cl::Buffer peaksGpuPtrBuffer = cl::Buffer((cl_mem)(peaksGpuPtr), true);\n                cl::Buffer bodyPartPairsGpuPtrBuffer = cl::Buffer((cl_mem)(bodyPartPairsGpuPtr), true);\n                cl::Buffer mapIdxGpuPtrBuffer = cl::Buffer((cl_mem)(mapIdxGpuPtr), true);\n\n                // PAF Kernel Runtime\n                pafScoreKernel(\n                    cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(numberBodyPartPairs,maxPeaks,maxPeaks)),\n                    pairScoresGpuPtrBuffer, heatMapGpuPtrBuffer, peaksGpuPtrBuffer, bodyPartPairsGpuPtrBuffer, mapIdxGpuPtrBuffer,\n                    maxPeaks, (int)numberBodyPartPairs, heatMapSize.x, heatMapSize.y, interThreshold,\n                    interMinAboveThreshold, defaultNmsThreshold);\n                OpenCL::getInstance(gpuID)->getQueue().enqueueReadBuffer(\n                    pairScoresGpuPtrBuffer, CL_TRUE, 0, totalComputations * sizeof(T), pairScoresCpu.getPtr());\n\n                // New code\n                // Get pair connections and their scores\n                const auto pairConnections = pafPtrIntoVector(\n                    pairScoresCpu, peaksPtr, maxPeaks, bodyPartPairs, numberBodyPartPairs);\n                auto peopleVector = pafVectorIntoPeopleVector(\n                    pairConnections, peaksPtr, maxPeaks, bodyPartPairs, numberBodyParts);\n                // // Old code\n                // // Get pair connections and their scores\n                // // std::vector<std::pair<std::vector<int>, double>> refers to:\n                // //     - std::vector<int>: [body parts locations, #body parts found]\n                // //     - double: person subset score\n                // const T* const tNullptr = nullptr;\n                // const auto peopleVector = createPeopleVector(\n                //     tNullptr, peaksPtr, poseModel, heatMapSize, maxPeaks, interThreshold, interMinAboveThreshold,\n                //     bodyPartPairs, numberBodyParts, numberBodyPartPairs, pairScoresCpu);\n                // Delete people below the following thresholds:\n                    // a) minSubsetCnt: removed if less than minSubsetCnt body parts\n                    // b) minSubsetScore: removed if global score smaller than this\n                    // c) maxPeaks (POSE_MAX_PEOPLE): keep first maxPeaks people above thresholds\n                int numberPeople;\n                std::vector<int> validSubsetIndexes;\n                validSubsetIndexes.reserve(fastMin((size_t)maxPeaks, peopleVector.size()));\n                removePeopleBelowThresholdsAndFillFaces(\n                    validSubsetIndexes, numberPeople, peopleVector, numberBodyParts, minSubsetCnt, minSubsetScore,\n                    maximizePositives, peaksPtr);\n                // Fill and return poseKeypoints\n                peopleVectorToPeopleArray(\n                    poseKeypoints, poseScores, scaleFactor, peopleVector, validSubsetIndexes, peaksPtr, numberPeople,\n                    numberBodyParts, numberBodyPartPairs);\n            #else\n                UNUSED(poseKeypoints);\n                UNUSED(poseScores);\n                UNUSED(heatMapGpuPtr);\n                UNUSED(peaksPtr);\n                UNUSED(poseModel);\n                UNUSED(heatMapSize);\n                UNUSED(maxPeaks);\n                UNUSED(interMinAboveThreshold);\n                UNUSED(interThreshold);\n                UNUSED(minSubsetCnt);\n                UNUSED(minSubsetScore);\n                UNUSED(defaultNmsThreshold);\n                UNUSED(scaleFactor);\n                UNUSED(maximizePositives);\n                UNUSED(pairScoresCpu);\n                UNUSED(pairScoresGpuPtr);\n                UNUSED(bodyPartPairsGpuPtr);\n                UNUSED(mapIdxGpuPtr);\n                UNUSED(peaksGpuPtr);\n                UNUSED(gpuID);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void connectBodyPartsOcl(\n        Array<float>& poseKeypoints, Array<float>& poseScores, const float* const heatMapGpuPtr,\n        const float* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const float interMinAboveThreshold, const float interThreshold, const int minSubsetCnt,\n        const float defaultNmsThreshold, const float minSubsetScore, const float scaleFactor,\n        const bool maximizePositives, Array<float> pairScoresCpu, float* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const float* const peaksGpuPtr, const int gpuID);\n    template void connectBodyPartsOcl(\n        Array<double>& poseKeypoints, Array<double>& poseScores, const double* const heatMapGpuPtr,\n        const double* const peaksPtr, const PoseModel poseModel, const Point<int>& heatMapSize, const int maxPeaks,\n        const double interMinAboveThreshold, const double interThreshold, const int minSubsetCnt,\n        const double defaultNmsThreshold, const double minSubsetScore, const double scaleFactor,\n        const bool maximizePositives, Array<double> pairScoresCpu, double* pairScoresGpuPtr,\n        const unsigned int* const bodyPartPairsGpuPtr, const unsigned int* const mapIdxGpuPtr,\n        const double* const peaksGpuPtr, const int gpuID);\n}\n"
  },
  {
    "path": "src/openpose/net/bodyPartConnectorCaffe.cpp",
    "content": "#include <openpose/net/bodyPartConnectorCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n    #include <openpose_private/gpu/cuda.hu>\n#endif\n#include <openpose/net/bodyPartConnectorBase.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    template <typename T>\n    BodyPartConnectorCaffe<T>::BodyPartConnectorCaffe() :\n        mPoseModel{PoseModel::Size},\n        mMaximizePositives{false},\n        pBodyPartPairsGpuPtr{nullptr},\n        pMapIdxGpuPtr{nullptr},\n        pFinalOutputGpuPtr{nullptr}\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    BodyPartConnectorCaffe<T>::~BodyPartConnectorCaffe()\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_CUDA\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                if (pBodyPartPairsGpuPtr != nullptr)\n                {\n                    cudaFree(pBodyPartPairsGpuPtr);\n                    pBodyPartPairsGpuPtr = nullptr;\n                }\n                if (pMapIdxGpuPtr != nullptr)\n                {\n                    cudaFree(pMapIdxGpuPtr);\n                    pMapIdxGpuPtr = nullptr;\n                }\n                if (pFinalOutputGpuPtr != nullptr)\n                {\n                    cudaFree(pFinalOutputGpuPtr);\n                    pFinalOutputGpuPtr = nullptr;\n                }\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                auto heatMapsBlob = bottom.at(0);\n                auto peaksBlob = bottom.at(1);\n                // Top shape\n                const auto maxPeaks = peaksBlob->shape(2) - 1;\n                const auto numberBodyParts = peaksBlob->shape(1);\n                // Array sizes\n                mTopSize = std::array<int, 4>{1, maxPeaks, numberBodyParts, 3};\n                mHeatMapsSize = std::array<int, 4>{\n                    heatMapsBlob->shape(0), heatMapsBlob->shape(1), heatMapsBlob->shape(2), heatMapsBlob->shape(3)};\n                mPeaksSize = std::array<int, 4>{\n                    peaksBlob->shape(0), peaksBlob->shape(1), peaksBlob->shape(2), peaksBlob->shape(3)};\n                // GPU ID\n                mGpuID = gpuID;\n            #else\n                UNUSED(bottom);\n                UNUSED(gpuID);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setPoseModel(const PoseModel poseModel)\n    {\n        try\n        {\n            mPoseModel = {poseModel};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setMaximizePositives(const bool maximizePositives)\n    {\n        try\n        {\n            mMaximizePositives = {maximizePositives};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setDefaultNmsThreshold(const T defaultNmsThreshold)\n    {\n        try\n        {\n            mDefaultNmsThreshold = {defaultNmsThreshold};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setInterMinAboveThreshold(const T interMinAboveThreshold)\n    {\n        try\n        {\n            mInterMinAboveThreshold = {interMinAboveThreshold};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setInterThreshold(const T interThreshold)\n    {\n        try\n        {\n            mInterThreshold = {interThreshold};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setMinSubsetCnt(const int minSubsetCnt)\n    {\n        try\n        {\n            mMinSubsetCnt = {minSubsetCnt};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setMinSubsetScore(const T minSubsetScore)\n    {\n        try\n        {\n            mMinSubsetScore = {minSubsetScore};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::setScaleNetToOutput(const T scaleNetToOutput)\n    {\n        try\n        {\n            mScaleNetToOutput = {scaleNetToOutput};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints,\n                                            Array<T>& poseScores)\n    {\n        try\n        {\n            // CUDA\n            #ifdef USE_CUDA\n                Forward_gpu(bottom, poseKeypoints, poseScores);\n            // OpenCL\n            #elif defined USE_OPENCL\n                Forward_ocl(bottom, poseKeypoints, poseScores);\n            // CPU\n            #else\n                Forward_cpu(bottom, poseKeypoints, poseScores);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Forward_cpu(\n        const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints, Array<T>& poseScores)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                const auto heatMapsBlob = bottom.at(0);\n                const auto* const heatMapsPtr = heatMapsBlob->cpu_data();                 // ~8.5 ms COCO, ~35ms BODY_135\n                const auto* const peaksPtr = bottom.at(1)->cpu_data();                    // ~0.02ms\n                const auto maxPeaks = mTopSize[1];\n                connectBodyPartsCpu(\n                    poseKeypoints, poseScores, heatMapsPtr, peaksPtr, mPoseModel,\n                    Point<int>{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks, mInterMinAboveThreshold,\n                    mInterThreshold, mMinSubsetCnt, mMinSubsetScore, mDefaultNmsThreshold, mScaleNetToOutput,\n                    mMaximizePositives);\n            #else\n                UNUSED(bottom);\n                UNUSED(poseKeypoints);\n                UNUSED(poseScores);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Forward_ocl(\n        const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints, Array<T>& poseScores)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_OPENCL\n                // Global data\n                const auto heatMapsBlob = bottom.at(0);\n                const auto* const heatMapsGpuPtr = heatMapsBlob->gpu_data();\n                const auto* const peaksPtr = bottom.at(1)->cpu_data();\n                const auto maxPeaks = mTopSize[1];\n                const auto* const peaksGpuPtr = bottom.at(1)->gpu_data();\n\n                // Initialize fixed pointers (1-time task) - It must be done in the same thread than Forward_gpu\n                if (pBodyPartPairsGpuPtr == nullptr || pMapIdxGpuPtr == nullptr)\n                {\n                    // Data\n                    const auto& bodyPartPairs = getPosePartPairs(mPoseModel);\n                    const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel);\n                    const auto& mapIdxOffset = getPoseMapIndex(mPoseModel);\n                    // Update mapIdx\n                    const auto offset = (mPoseModel != PoseModel::BODY_25B ? 1 : 0);\n                    auto mapIdx = mapIdxOffset;\n                    for (auto& i : mapIdx)\n                        i += (numberBodyParts+offset);\n                    // Re-allocate memory\n                    pBodyPartPairsGpuPtr = (unsigned int*)clCreateBuffer(\n                        OpenCL::getInstance(mGpuID)->getContext().operator()(), CL_MEM_READ_WRITE,\n                        bodyPartPairs.size() * sizeof(unsigned int), NULL, NULL);\n                    clEnqueueWriteBuffer(\n                        OpenCL::getInstance(mGpuID)->getQueue().operator()(), (cl_mem)pBodyPartPairsGpuPtr, CL_TRUE,\n                        0, bodyPartPairs.size() * sizeof(unsigned int), &bodyPartPairs[0], NULL, NULL, NULL);\n                    pMapIdxGpuPtr = (unsigned int*)clCreateBuffer(\n                        OpenCL::getInstance(mGpuID)->getContext().operator()(), CL_MEM_READ_WRITE,\n                        mapIdx.size() * sizeof(unsigned int), NULL, NULL);\n                    clEnqueueWriteBuffer(\n                        OpenCL::getInstance(mGpuID)->getQueue().operator()(), (cl_mem)pMapIdxGpuPtr, CL_TRUE,\n                        0, mapIdx.size() * sizeof(unsigned int), &mapIdx[0], NULL, NULL, NULL);\n                }\n                // Initialize auxiliary pointers (1-time task)\n                if (mFinalOutputCpu.empty()) // if (pFinalOutputGpuPtr == nullptr)\n                {\n                    // Data\n                    const auto& bodyPartPairs = getPosePartPairs(mPoseModel);\n                    const auto numberBodyPartPairs = bodyPartPairs.size() / 2;\n                    // Allocate memory\n                    mFinalOutputCpu.reset({(int)numberBodyPartPairs, maxPeaks, maxPeaks});\n                    const auto totalComputations = mFinalOutputCpu.getVolume();\n                    if (pFinalOutputGpuPtr == nullptr)\n                        pFinalOutputGpuPtr = (T*)clCreateBuffer(\n                            OpenCL::getInstance(mGpuID)->getContext().operator()(), CL_MEM_READ_WRITE,\n                            totalComputations * sizeof(T), NULL, NULL);\n                }\n\n                // Run body part connector\n                connectBodyPartsOcl(\n                    poseKeypoints, poseScores, heatMapsGpuPtr, peaksPtr, mPoseModel,\n                    Point<int>{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks, mInterMinAboveThreshold,\n                    mInterThreshold, mMinSubsetCnt, mMinSubsetScore, mDefaultNmsThreshold, mScaleNetToOutput,\n                    mMaximizePositives, mFinalOutputCpu, pFinalOutputGpuPtr, pBodyPartPairsGpuPtr, pMapIdxGpuPtr,\n                    peaksGpuPtr, mGpuID);\n            #else\n                UNUSED(bottom);\n                UNUSED(poseKeypoints);\n                UNUSED(poseScores);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Forward_gpu(\n        const std::vector<ArrayCpuGpu<T>*>& bottom, Array<T>& poseKeypoints, Array<T>& poseScores)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_CUDA\n                // Global data\n                const auto heatMapsBlob = bottom.at(0);\n                const auto* const heatMapsGpuPtr = heatMapsBlob->gpu_data();\n                const auto* const peaksPtr = bottom.at(1)->cpu_data();\n                const auto maxPeaks = mTopSize[1];\n                const auto* const peaksGpuPtr = bottom.at(1)->gpu_data();\n\n                // Initialize fixed pointers (1-time task) - It must be done in the same thread than Forward_gpu\n                if (pBodyPartPairsGpuPtr == nullptr || pMapIdxGpuPtr == nullptr)\n                {\n                    // Free previous memory\n                    cudaFree(pBodyPartPairsGpuPtr);\n                    cudaFree(pMapIdxGpuPtr);\n                    // Data\n                    const auto& bodyPartPairs = getPosePartPairs(mPoseModel);\n                    const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel);\n                    const auto& mapIdxOffset = getPoseMapIndex(mPoseModel);\n                    // Update mapIdx\n                    const auto offset = (addBkgChannel(mPoseModel) ? 1 : 0);\n                    auto mapIdx = mapIdxOffset;\n                    for (auto& i : mapIdx)\n                        i += (numberBodyParts+offset);\n                    // Re-allocate memory\n                    cudaMalloc((void **)&pBodyPartPairsGpuPtr, bodyPartPairs.size() * sizeof(unsigned int));\n                    cudaMemcpy(pBodyPartPairsGpuPtr, &bodyPartPairs[0], bodyPartPairs.size() * sizeof(unsigned int),\n                               cudaMemcpyHostToDevice);\n                    cudaMalloc((void **)&pMapIdxGpuPtr, mapIdx.size() * sizeof(unsigned int));\n                    cudaMemcpy(pMapIdxGpuPtr, &mapIdx[0], mapIdx.size() * sizeof(unsigned int),\n                               cudaMemcpyHostToDevice);\n                    // Sanity check\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n                // Initialize auxiliary pointers (1-time task)\n                if (mFinalOutputCpu.empty()) // if (pFinalOutputGpuPtr == nullptr)\n                {\n                    // Data\n                    const auto& bodyPartPairs = getPosePartPairs(mPoseModel);\n                    const auto numberBodyPartPairs = bodyPartPairs.size() / 2;\n                    // Allocate memory\n                    mFinalOutputCpu.reset({(int)numberBodyPartPairs, maxPeaks, maxPeaks});\n                    const auto totalComputations = mFinalOutputCpu.getVolume();\n                    if (pFinalOutputGpuPtr == nullptr)\n                        cudaMalloc((void **)&pFinalOutputGpuPtr, totalComputations * sizeof(float));\n                    // Sanity check\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                }\n\n                // Run body part connector\n                connectBodyPartsGpu(\n                    poseKeypoints, poseScores, heatMapsGpuPtr, peaksPtr, mPoseModel,\n                    Point<int>{heatMapsBlob->shape(3), heatMapsBlob->shape(2)}, maxPeaks, mInterMinAboveThreshold,\n                    mInterThreshold, mMinSubsetCnt, mMinSubsetScore, mDefaultNmsThreshold, mScaleNetToOutput,\n                    mMaximizePositives, mFinalOutputCpu, pFinalOutputGpuPtr, pBodyPartPairsGpuPtr, pMapIdxGpuPtr,\n                    peaksGpuPtr);\n            #else\n                UNUSED(bottom);\n                UNUSED(poseKeypoints);\n                UNUSED(poseScores);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                                 const std::vector<bool>& propagate_down,\n                                                 const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void BodyPartConnectorCaffe<T>::Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                                 const std::vector<bool>& propagate_down,\n                                                 const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(BodyPartConnectorCaffe);\n}\n"
  },
  {
    "path": "src/openpose/net/maximumBase.cpp",
    "content": "#include <openpose/net/maximumBase.hpp>\n// #include <thrust/extrema.h>\n#include <opencv2/core/core.hpp> // cv::Mat\n\nnamespace op\n{\n    template <typename T>\n    void maximumCpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize,\n                    const std::array<int, 4>& sourceSize)\n    {\n        try\n        {\n            // // TODO: ideally done, try, debug & compare to *.cu\n            const auto height = sourceSize[2];\n            const auto width = sourceSize[3];\n            const auto imageOffset = height * width;\n            const auto num = targetSize[0];\n            const auto channels = targetSize[1];\n            const auto numberParts = targetSize[2];\n            const auto numberSubparts = targetSize[3];\n\n            // opLog(\"sourceSize[0]: \" + std::to_string(sourceSize[0])); // = 1\n            // opLog(\"sourceSize[1]: \" + std::to_string(sourceSize[1])); // = #body_parts+bck=22(hands) or 71(face)\n            // opLog(\"sourceSize[2]: \" + std::to_string(sourceSize[2])); // = 368 = height\n            // opLog(\"sourceSize[3]: \" + std::to_string(sourceSize[3])); // = 368 = width\n            // opLog(\"targetSize[0]: \" + std::to_string(targetSize[0])); // = 1\n            // opLog(\"targetSize[1]: \" + std::to_string(targetSize[1])); // = 1\n            // opLog(\"targetSize[2]: \" + std::to_string(targetSize[2])); // = 21(hands) or 70 (face)\n            // opLog(\"targetSize[3]: \" + std::to_string(targetSize[3])); // = 3 = [x, y, score]\n            // opLog(\" \");\n\n            for (auto n = 0; n < num; n++)\n            {\n                for (auto c = 0; c < channels; c++)\n                {\n                    // Parameters\n                    const auto offsetChannel = (n * channels + c);\n                    for (auto part = 0; part < numberParts; part++)\n                    {\n                        auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts;\n                        const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset;\n                        cv::Mat source(cv::Size(width, height), CV_32FC1, const_cast<T*>(sourcePtrOffsetted));\n                        double minVal, maxVal;\n                        cv::Point minLoc, maxLoc;\n                        cv::minMaxLoc(source, &minVal, &maxVal, &minLoc, &maxLoc);\n                        targetPtrOffsetted[0] = T(maxLoc.x);\n                        targetPtrOffsetted[1] = T(maxLoc.y);\n                        targetPtrOffsetted[2] = T(maxVal);\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template OP_API void maximumCpu(\n        float* targetPtr, const float* const sourcePtr, const std::array<int, 4>& targetSize,\n        const std::array<int, 4>& sourceSize);\n    template OP_API void maximumCpu(\n        double* targetPtr, const double* const sourcePtr, const std::array<int, 4>& targetSize,\n        const std::array<int, 4>& sourceSize);\n}\n"
  },
  {
    "path": "src/openpose/net/maximumBase.cu",
    "content": "#include <openpose/net/maximumBase.hpp>\n#include <thrust/device_ptr.h>\n#include <thrust/extrema.h>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/gpu/cuda.hpp>\n\nnamespace op\n{\n    template <typename T>\n    __global__ void fillTargetPtrPart(T* targetPtrOffsetted, const T* sourcePtrOffsetted, const int sourceIndex,\n                                      const int x, const int y)\n    {\n        targetPtrOffsetted[0] = x;\n        targetPtrOffsetted[1] = y;\n        targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];\n    }\n\n    // template <typename T>\n    // __global__ void fillTargetPtrChannel(T* targetPtrOffsetted, const T* sourcePtrOffsetted, const int width,\n    //                                      const int imageOffset)\n    // {\n    //     const auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted);\n    //     // Ideal option (not working for CUDA < 8)\n    //     // const auto sourceIndexIterator = thrust::max_element(\n    //     //     thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset);\n    //     // Workaround to make it work for CUDA 7.5\n    //     const auto sourceIndexIterator = thrust::max_element(sourceThrustPtr, sourceThrustPtr + imageOffset);\n    //     const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr);\n    //     targetPtrOffsetted[0] = sourceIndex % width;\n    //     targetPtrOffsetted[1] = sourceIndex / width;\n    //     targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];\n    // }\n\n    // template <typename T>\n    // __global__ void fillTargetPtr(T* targetPtr, const T* sourcePtr, const int width, const int imageOffset,\n    //                               const int numberSubparts, const int offsetChannel)\n    // {\n    //     // get pixel location (x,y)\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     const auto part = y*width + x;\n\n    //     // if (0 < x && x < (w-1) && 0 < y && y < (h-1))\n    //     {\n    //         auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts;\n    //         const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset;\n    //         auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted);\n    //         const auto sourceIndexIterator = thrust::max_element(thrust::device, sourceThrustPtr,\n    //                                                              sourceThrustPtr + imageOffset);\n    //         // Ideal option (not working for CUDA < 8)\n    //         // const auto sourceIndexIterator = thrust::max_element(\n    //         //     thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset);\n    //         // Workaround to make it work for CUDA 7.5\n    //         const auto sourceIndexIterator = thrust::max_element(sourceThrustPtr, sourceThrustPtr + imageOffset);\n    //         const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr);\n    //         targetPtrOffsetted[0] = sourceIndex % width;\n    //         targetPtrOffsetted[1] = sourceIndex / width;\n    //         targetPtrOffsetted[2] = sourcePtrOffsetted[sourceIndex];\n    //     }\n    // }\n\n    template <typename T>\n    void maximumGpu(T* targetPtr, const T* const sourcePtr, const std::array<int, 4>& targetSize,\n                    const std::array<int, 4>& sourceSize)\n    {\n        try\n        {\n            const auto height = sourceSize[2];\n            const auto width = sourceSize[3];\n            const auto imageOffset = height * width;\n            const auto num = targetSize[0];\n            const auto channels = targetSize[1];\n            const auto numberParts = targetSize[2];\n            const auto numberSubparts = targetSize[3];\n\n            // opLog(\"sourceSize[0]: \" + std::to_string(sourceSize[0]));  // = 1\n            // opLog(\"sourceSize[1]: \" + std::to_string(sourceSize[1]));  // = #BodyParts + bkg = 22 (hands) or 71 (face)\n            // opLog(\"sourceSize[2]: \" + std::to_string(sourceSize[2]));  // = 368 = height\n            // opLog(\"sourceSize[3]: \" + std::to_string(sourceSize[3]));  // = 368 = width\n            // opLog(\"targetSize[0]: \" + std::to_string(targetSize[0]));  // = 1\n            // opLog(\"targetSize[1]: \" + std::to_string(targetSize[1]));  // = 1\n            // opLog(\"targetSize[2]: \" + std::to_string(targetSize[2]));  // = 21(hands) or 70 (face)\n            // opLog(\"targetSize[3]: \" + std::to_string(targetSize[3]));  // = 3 = [x, y, score]\n            // opLog(\" \");\n            for (auto n = 0; n < num; n++)\n            {\n                for (auto c = 0; c < channels; c++)\n                {\n                    // // Parameters\n                    const auto offsetChannel = (n * channels + c);\n                    for (auto part = 0; part < numberParts; part++)\n                    {\n                        auto* targetPtrOffsetted = targetPtr + (offsetChannel + part) * numberSubparts;\n                        const auto* const sourcePtrOffsetted = sourcePtr + (offsetChannel + part) * imageOffset;\n                        // Option a - 6.3 fps\n                        const auto sourceThrustPtr = thrust::device_pointer_cast(sourcePtrOffsetted);\n                        // Ideal option (not working for CUDA < 8)\n                        // const auto sourceIndexIterator = thrust::max_element(\n                        //     thrust::device, sourceThrustPtr, sourceThrustPtr + imageOffset);\n                        // Workaround to make it work for CUDA 7.5\n                        const auto sourceIndexIterator = thrust::max_element(\n                            sourceThrustPtr, sourceThrustPtr + imageOffset);\n                        const auto sourceIndex = (int)(sourceIndexIterator - sourceThrustPtr);\n                        fillTargetPtrPart<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, sourceIndex,\n                                                    sourceIndex % width, sourceIndex / width);\n                        // // Option b - <1 fps\n                        // fillTargetPtrChannel<<<1, 1>>>(targetPtrOffsetted, sourcePtrOffsetted, width, imageOffset);\n                    }\n                    // Option c - 4.9 fps\n                    // fillTargetPtr<<<1, numberParts>>>(targetPtr, sourcePtr, width, imageOffset, numberSubparts,\n                    //                                   offsetChannel);\n                }\n            }\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void maximumGpu(\n        float* targetPtr, const float* const sourcePtr, const std::array<int, 4>& targetSize,\n        const std::array<int, 4>& sourceSize);\n    template void maximumGpu(\n        double* targetPtr, const double* const sourcePtr, const std::array<int, 4>& targetSize,\n        const std::array<int, 4>& sourceSize);\n}\n"
  },
  {
    "path": "src/openpose/net/maximumCaffe.cpp",
    "content": "#include <openpose/net/maximumCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/net/maximumBase.hpp>\n\nnamespace op\n{\n    template <typename T>\n    MaximumCaffe<T>::MaximumCaffe()\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    MaximumCaffe<T>::~MaximumCaffe()\n    {\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                     const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (top.size() != 1)\n                    error(\"top.size() != 1\", __LINE__, __FUNCTION__, __FILE__);\n                if (bottom.size() != 1)\n                    error(\"bottom.size() != 1\", __LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                  const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                auto bottomBlob = bottom.at(0);\n                auto topBlob = top.at(0);\n\n                // Bottom shape\n                std::vector<int> bottomShape = bottomBlob->shape();\n\n                // Top shape\n                std::vector<int> topShape{bottomShape};\n                topShape[1] = 1; // Unnecessary\n                topShape[2] = bottomShape[1]-1; // Number parts + bck - 1\n                topShape[3] = 3;  // X, Y, score\n                topBlob->Reshape(topShape);\n\n                // Array sizes\n                mTopSize = std::array<int, 4>{topBlob->shape(0), topBlob->shape(1), topBlob->shape(2),\n                                              topBlob->shape(3)};\n                mBottomSize = std::array<int, 4>{bottomBlob->shape(0), bottomBlob->shape(1), bottomBlob->shape(2),\n                                                 bottomBlob->shape(3)};\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Forward(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                  const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            // CUDA\n            #ifdef USE_CUDA\n                Forward_gpu(bottom, top);\n            // OpenCL or CPU\n            #else\n                // CPU Version is already very fast (4ms)\n                Forward_cpu(bottom, top);\n            #endif\n\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                      const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                maximumCpu(top.at(0)->mutable_cpu_data(), bottom.at(0)->cpu_data(), mTopSize, mBottomSize);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                      const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_CUDA\n                maximumGpu(top.at(0)->mutable_gpu_data(), bottom.at(0)->gpu_data(), mTopSize, mBottomSize);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                       const std::vector<bool>& propagate_down,\n                                       const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void MaximumCaffe<T>::Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                       const std::vector<bool>& propagate_down,\n                                       const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(MaximumCaffe);\n}\n"
  },
  {
    "path": "src/openpose/net/netCaffe.cpp",
    "content": "#include <openpose/net/netCaffe.hpp>\n#include <numeric> // std::accumulate\n#ifdef USE_CAFFE\n    #include <atomic>\n    #include <mutex>\n    #include <caffe/net.hpp>\n    #include <glog/logging.h> // google::InitGoogleLogging\n#endif\n#ifdef USE_CUDA\n    #include <openpose/gpu/cuda.hpp>\n#endif\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/standard.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    std::mutex sMutexNetCaffe;\n    std::atomic<bool> sGoogleLoggingInitialized{false};\n    #ifdef USE_OPENCL\n        std::atomic<bool> sOpenCLInitialized{false};\n    #endif\n\n    struct NetCaffe::ImplNetCaffe\n    {\n        #ifdef USE_CAFFE\n            // Init with constructor\n            const int mGpuId;\n            const std::string mCaffeProto;\n            const std::string mCaffeTrainedModel;\n            const std::string mLastBlobName;\n            std::vector<int> mNetInputSize4D;\n            // Init with thread\n            #ifdef NV_CAFFE\n                std::unique_ptr<caffe::Net> upCaffeNet;\n                boost::shared_ptr<caffe::TBlob<float>> spOutputBlob;\n            #else\n                std::unique_ptr<caffe::Net<float>> upCaffeNet;\n                boost::shared_ptr<caffe::Blob<float>> spOutputBlob;\n            #endif\n\n            ImplNetCaffe(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId,\n                         const bool enableGoogleLogging, const std::string& lastBlobName) :\n                mGpuId{gpuId},\n                mCaffeProto{caffeProto},\n                mCaffeTrainedModel{caffeTrainedModel},\n                mLastBlobName{lastBlobName}\n            {\n                try\n                {\n                    const std::string message{\".\\nPossible causes:\\n\"\n                        \"\\t1. Not downloading the OpenPose trained models.\\n\"\n                        \"\\t2. Not running OpenPose from the root directory (i.e., where the `model` folder is located, but do not move the `model` folder!). E.g.,\\n\"\n                        \"\\t\\tRight example for the Windows portable binary: `cd {OpenPose_root_path}; bin/openpose.exe`\\n\"\n                        \"\\t\\tWrong example for the Windows portable binary: `cd {OpenPose_root_path}/bin; openpose.exe`\\n\"\n                        \"\\t3. Using paths with spaces.\"};\n                    if (!existFile(mCaffeProto))\n                        error(\"Prototxt file not found: \" + mCaffeProto + message, __LINE__, __FUNCTION__, __FILE__);\n                    if (!existFile(mCaffeTrainedModel))\n                        error(\"Caffe trained model file not found: \" + mCaffeTrainedModel + message,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    // Double if condition in order to speed up the program if it is called several times\n                    if (enableGoogleLogging && !sGoogleLoggingInitialized)\n                    {\n                        std::lock_guard<std::mutex> lock{sMutexNetCaffe};\n                        if (enableGoogleLogging && !sGoogleLoggingInitialized)\n                        {\n                            google::InitGoogleLogging(\"OpenPose\");\n                            sGoogleLoggingInitialized = true;\n                        }\n                    }\n                    #ifdef USE_OPENCL\n                        // Initialize OpenCL\n                        if (!sOpenCLInitialized)\n                        {\n                            std::lock_guard<std::mutex> lock{sMutexNetCaffe};\n                            if (!sOpenCLInitialized)\n                            {\n                                caffe::Caffe::set_mode(caffe::Caffe::GPU);\n                                std::vector<int> devices;\n                                const int maxNumberGpu = OpenCL::getTotalGPU();\n                                for (auto i = 0; i < maxNumberGpu; i++)\n                                    devices.emplace_back(i);\n                                caffe::Caffe::SetDevices(devices);\n                                if (mGpuId >= maxNumberGpu)\n                                    error(\"Unexpected error. Please, notify us.\", __LINE__, __FUNCTION__, __FILE__);\n                                sOpenCLInitialized = true;\n                            }\n                        }\n                    #endif\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        #endif\n    };\n\n    #ifdef USE_CAFFE\n        #ifdef NV_CAFFE\n        inline void reshapeNetCaffe(caffe::Net* caffeNet, const std::vector<int>& dimensions)\n        #else\n        inline void reshapeNetCaffe(caffe::Net<float>* caffeNet, const std::vector<int>& dimensions)\n        #endif\n        {\n            try\n            {\n                caffeNet->blobs()[0]->Reshape(dimensions);\n                caffeNet->Reshape();\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    NetCaffe::NetCaffe(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId,\n                       const bool enableGoogleLogging, const std::string& lastBlobName)\n        #ifdef USE_CAFFE\n            : upImpl{new ImplNetCaffe{caffeProto, caffeTrainedModel, gpuId, enableGoogleLogging,\n                                      lastBlobName}}\n        #endif\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                UNUSED(caffeProto);\n                UNUSED(caffeTrainedModel);\n                UNUSED(gpuId);\n                UNUSED(enableGoogleLogging);\n                UNUSED(lastBlobName);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    NetCaffe::~NetCaffe()\n    {\n    }\n\n    void NetCaffe::initializationOnThread()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Initialize net\n                #ifdef USE_OPENCL\n                    caffe::Caffe::set_mode(caffe::Caffe::GPU);\n                    caffe::Caffe::SelectDevice(upImpl->mGpuId, true);\n                    upImpl->upCaffeNet.reset(new caffe::Net<float>{upImpl->mCaffeProto, caffe::TEST,\n                                             caffe::Caffe::GetDefaultDevice()});\n                    upImpl->upCaffeNet->CopyTrainedLayersFrom(upImpl->mCaffeTrainedModel);\n                    OpenCL::getInstance(upImpl->mGpuId, CL_DEVICE_TYPE_GPU, true);\n                #else\n                    #ifdef USE_CUDA\n                        caffe::Caffe::set_mode(caffe::Caffe::GPU);\n                        caffe::Caffe::SetDevice(upImpl->mGpuId);\n                        #ifdef NV_CAFFE\n                            upImpl->upCaffeNet.reset(new caffe::Net{upImpl->mCaffeProto, caffe::TEST});\n                        #else\n                            upImpl->upCaffeNet.reset(new caffe::Net<float>{upImpl->mCaffeProto, caffe::TEST});\n                        #endif\n                    #else\n                        caffe::Caffe::set_mode(caffe::Caffe::CPU);\n                        #ifdef _WIN32\n                            upImpl->upCaffeNet.reset(new caffe::Net<float>{upImpl->mCaffeProto, caffe::TEST,\n                                                                           caffe::Caffe::GetCPUDevice()});\n                        #else\n                            upImpl->upCaffeNet.reset(new caffe::Net<float>{upImpl->mCaffeProto, caffe::TEST});\n                        #endif\n                    #endif\n                    upImpl->upCaffeNet->CopyTrainedLayersFrom(upImpl->mCaffeTrainedModel);\n                    #ifdef USE_CUDA\n                        cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    #endif\n                #endif\n                // Set spOutputBlob\n                #ifdef NV_CAFFE\n                    upImpl->spOutputBlob = boost::static_pointer_cast<caffe::TBlob<float>>(\n                        upImpl->upCaffeNet->blob_by_name(upImpl->mLastBlobName));\n                #else\n                    upImpl->spOutputBlob = upImpl->upCaffeNet->blob_by_name(upImpl->mLastBlobName);\n                #endif\n                // Sanity check\n                if (upImpl->spOutputBlob == nullptr)\n                    error(\"The output blob is a nullptr. Did you use the same name than the prototxt? (Used: \"\n                          + upImpl->mLastBlobName + \").\", __LINE__, __FUNCTION__, __FILE__);\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void NetCaffe::forwardPass(const Array<float>& inputData) const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Sanity checks\n                if (inputData.empty())\n                    error(\"The Array inputData cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n                if (inputData.getNumberDimensions() != 4 || inputData.getSize(1) != 3)\n                    error(\"The Array inputData must have 4 dimensions: [batch size, 3 (RGB), height, width].\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // Reshape Caffe net if required\n                if (!vectorsAreEqual(upImpl->mNetInputSize4D, inputData.getSize()))\n                {\n                    upImpl->mNetInputSize4D = inputData.getSize();\n                    reshapeNetCaffe(upImpl->upCaffeNet.get(), inputData.getSize());\n                }\n                // Copy frame data to GPU memory\n                #ifdef USE_CUDA\n                    #ifdef NV_CAFFE\n                        auto* gpuImagePtr = upImpl->upCaffeNet->blobs().at(0)->mutable_gpu_data<float>();\n                    #else\n                        auto* gpuImagePtr = upImpl->upCaffeNet->blobs().at(0)->mutable_gpu_data();\n                    #endif\n                    cudaMemcpy(gpuImagePtr, inputData.getConstPtr(), inputData.getVolume() * sizeof(float),\n                               cudaMemcpyHostToDevice);\n                #elif defined USE_OPENCL\n                    auto* gpuImagePtr = upImpl->upCaffeNet->blobs().at(0)->mutable_gpu_data();\n                    cl::Buffer imageBuffer = cl::Buffer((cl_mem)gpuImagePtr, true);\n                    OpenCL::getInstance(upImpl->mGpuId)->getQueue().enqueueWriteBuffer(\n                        imageBuffer, true, 0, inputData.getVolume() * sizeof(float), inputData.getConstPtr());\n                #else\n                    auto* cpuImagePtr = upImpl->upCaffeNet->blobs().at(0)->mutable_cpu_data();\n                    std::copy(inputData.getConstPtr(), inputData.getConstPtr() + inputData.getVolume(), cpuImagePtr);\n                #endif\n                // Perform deep network forward pass\n                upImpl->upCaffeNet->ForwardFrom(0);\n                // Cuda checks\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            #else\n                UNUSED(inputData);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::shared_ptr<ArrayCpuGpu<float>> NetCaffe::getOutputBlobArray() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                return std::make_shared<ArrayCpuGpu<float>>(upImpl->spOutputBlob.get());\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/net/netOpenCv.cpp",
    "content": "// TODO: After completely adding the OpenCV DNN module, add this flag to CMake as alternative to USE_CAFFE\n// #define USE_OPEN_CV_DNN\n\n#include <openpose/net/netOpenCv.hpp>\n// Note: OpenCV only uses CPU or OpenCL (for Intel GPUs). Used CUDA for following blobs (Resize + NMS)\n#ifdef USE_CAFFE\n    #include <caffe/net.hpp>\n#endif\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp> // OPEN_CV_IS_4_OR_HIGHER\n#ifdef USE_OPEN_CV_DNN\n    #if defined(USE_CAFFE) && defined(USE_CUDA) && defined(OPEN_CV_IS_4_OR_HIGHER)\n        #include <opencv2/opencv.hpp>\n        #include <openpose/gpu/cuda.hpp>\n    #else\n        #error In order to enable OpenCV DNN module in OpenPose, the CMake flags of Caffe and CUDA must be \\\n               enabled, and OpenCV version must be at least 4.0.0.\n    #endif\n#endif\n#include <numeric> // std::accumulate\n#include <openpose/utilities/fileSystem.hpp>\n\nnamespace op\n{\n    struct NetOpenCv::ImplNetOpenCv\n    {\n        #ifdef USE_OPEN_CV_DNN\n            // Init with constructor\n            const int mGpuId;\n            const std::string mCaffeProto;\n            const std::string mCaffeTrainedModel;\n            // OpenCV DNN\n            cv::dnn::Net mNet;\n            cv::Mat mNetOutputBlob;\n            boost::shared_ptr<caffe::Blob<float>> spOutputBlob;\n\n            ImplNetOpenCv(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId) :\n                mGpuId{gpuId},\n                mCaffeProto{caffeProto},\n                mCaffeTrainedModel{caffeTrainedModel},\n                mNet{cv::dnn::readNetFromCaffe(caffeProto, caffeTrainedModel)},\n                spOutputBlob{new caffe::Blob<float>(1,1,1,1)}\n            {\n                    const std::string message{\".\\nPossible causes:\\n\"\n                        \"\\t1. Not downloading the OpenPose trained models.\\n\"\n                        \"\\t2. Not running OpenPose from the root directory (i.e., where the `model` folder is located, but do not move the `model` folder!). E.g.,\\n\"\n                        \"\\t\\tRight example for the Windows portable binary: `cd {OpenPose_root_path}; bin/openpose.exe`\\n\"\n                        \"\\t\\tWrong example for the Windows portable binary: `cd {OpenPose_root_path}/bin; openpose.exe`\\n\"\n                        \"\\t3. Using paths with spaces.\"};\n                if (!existFile(mCaffeProto))\n                    error(\"Prototxt file not found: \" + mCaffeProto + message, __LINE__, __FUNCTION__, __FILE__);\n                if (!existFile(mCaffeTrainedModel))\n                    error(\"Caffe trained model file not found: \" + mCaffeTrainedModel + message,\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                // Set GPU\n                mNet.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); // 1.7 sec at -1x160\n                // mNet.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL); // 1.2 sec at -1x160\n                // mNet.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL_FP16);\n                // mNet.setPreferableTarget(cv::dnn::DNN_TARGET_MYRIAD);\n                // mNet.setPreferableTarget(cv::dnn::DNN_TARGET_VULKAN);\n                // // Set backen\n                // mNet.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);\n                // mNet.setPreferableBackend(cv::dnn::DNN_BACKEND_HALIDE);\n                // mNet.setPreferableBackend(cv::dnn::DNN_BACKEND_INFERENCE_ENGINE);\n                // mNet.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);\n                // mNet.setPreferableBackend(cv::dnn::DNN_BACKEND_VKCOM);\n            }\n        #endif\n    };\n\n    #ifdef USE_OPEN_CV_DNN\n        inline void reshapeNetOpenCv(caffe::Net<float>* caffeNet, const std::vector<int>& dimensions)\n        {\n            try\n            {\n                caffeNet->blobs()[0]->Reshape(dimensions);\n                caffeNet->Reshape();\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    NetOpenCv::NetOpenCv(const std::string& caffeProto, const std::string& caffeTrainedModel, const int gpuId)\n        #ifdef USE_OPEN_CV_DNN\n            : upImpl{new ImplNetOpenCv{caffeProto, caffeTrainedModel, gpuId}}\n        #endif\n    {\n        try\n        {\n            #ifndef USE_OPEN_CV_DNN\n                UNUSED(caffeProto);\n                UNUSED(caffeTrainedModel);\n                UNUSED(gpuId);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    NetOpenCv::~NetOpenCv()\n    {\n    }\n\n    void NetOpenCv::initializationOnThread()\n    {\n    }\n\n    void NetOpenCv::forwardPass(const Array<float>& inputData) const\n    {\n        try\n        {\n            #ifdef USE_OPEN_CV_DNN\n                upImpl->mNet.setInput(inputData.getConstCvMat());\n                upImpl->mNetOutputBlob = upImpl->mNet.forward(); // 99% of the runtime here\n                std::vector<int> outputSize(upImpl->mNetOutputBlob.dims,0);\n                for (auto i = 0u ; i < outputSize.size() ; i++)\n                    outputSize[i] = upImpl->mNetOutputBlob.size[i];\n                upImpl->spOutputBlob->Reshape(outputSize);\n                auto* gpuImagePtr = upImpl->spOutputBlob->mutable_gpu_data();\n                cudaMemcpy(gpuImagePtr, (float*)upImpl->mNetOutputBlob.data,\n                           upImpl->spOutputBlob->count() * sizeof(float),\n                           cudaMemcpyHostToDevice);\n            #else\n                UNUSED(inputData);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::shared_ptr<ArrayCpuGpu<float>> NetOpenCv::getOutputBlobArray() const\n    {\n        try\n        {\n            #ifdef USE_OPEN_CV_DNN\n                return std::make_shared<ArrayCpuGpu<float>>(upImpl->spOutputBlob.get());\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/net/nmsBase.cpp",
    "content": "#include <openpose/net/nmsBase.hpp>\n#include <opencv2/opencv.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void nmsRegisterKernelCPU(int* kernelPtr, const T* const sourcePtr, const int w, const int h,\n                              const T& threshold, const int x, const int y)\n    {\n        // We have three scenarios for NMS, one for the border, 1 for the 1st inner border, and\n        // 1 for the rest. cv::resize adds artifacts around the 1st inner border, causing two\n        // maximas to occur side by side. Eg. [1 1 0.8 0.8 0.5 ..]. The CUDA kernel gives\n        // [0.8 1 0.8 0.8 0.5 ..] Hence for this special case in the 1st inner border, we look at the\n        // visible regions.\n\n        const auto index = y*w + x;\n        if (1 < x && x < (w-2) && 1 < y && y < (h-2))\n        {\n            const auto value = sourcePtr[index];\n            if (value > threshold)\n            {\n                const auto topLeft     = sourcePtr[(y-1)*w + x-1];\n                const auto top         = sourcePtr[(y-1)*w + x];\n                const auto topRight    = sourcePtr[(y-1)*w + x+1];\n                const auto left        = sourcePtr[    y*w + x-1];\n                const auto right       = sourcePtr[    y*w + x+1];\n                const auto bottomLeft  = sourcePtr[(y+1)*w + x-1];\n                const auto bottom      = sourcePtr[(y+1)*w + x];\n                const auto bottomRight = sourcePtr[(y+1)*w + x+1];\n\n                if (value > topLeft && value > top && value > topRight\n                    && value > left && value > right\n                        && value > bottomLeft && value > bottom && value > bottomRight)\n                    kernelPtr[index] = 1;\n                else\n                    kernelPtr[index] = 0;\n            }\n            else\n                kernelPtr[index] = 0;\n        }\n        else if (x == 1 || x == (w-2) || y == 1 || y == (h-2))\n        {\n            //kernelPtr[index] = 0;\n            const auto value = sourcePtr[index];\n            if (value > threshold)\n            {\n                const auto topLeft      = ((0 < x && 0 < y)         ? sourcePtr[(y-1)*w + x-1]  : threshold);\n                const auto top          = (0 < y                    ? sourcePtr[(y-1)*w + x]    : threshold);\n                const auto topRight     = ((0 < y && x < (w-1))     ? sourcePtr[(y-1)*w + x+1]  : threshold);\n                const auto left         = (0 < x                    ? sourcePtr[    y*w + x-1]  : threshold);\n                const auto right        = (x < (w-1)                ? sourcePtr[y*w + x+1]      : threshold);\n                const auto bottomLeft   = ((y < (h-1) && 0 < x)     ? sourcePtr[(y+1)*w + x-1]  : threshold);\n                const auto bottom       = (y < (h-1)                ? sourcePtr[(y+1)*w + x]    : threshold);\n                const auto bottomRight  = ((x < (w-1) && y < (h-1)) ? sourcePtr[(y+1)*w + x+1]  : threshold);\n\n                if (value >= topLeft && value >= top && value >= topRight\n                    && value >= left && value >= right\n                        && value >= bottomLeft && value >= bottom && value >= bottomRight)\n                    kernelPtr[index] = 1;\n                else\n                    kernelPtr[index] = 0;\n            }\n            else\n                kernelPtr[index] = 0;\n        }\n        else\n            kernelPtr[index] = 0;\n    }\n\n    template <typename T>\n    void nmsAccuratePeakPosition(T* output, const T* const sourcePtr, const int& peakLocX, const int& peakLocY,\n                                 const int& width, const int& height, const Point<T>& offset)\n    {\n        T xAcc = 0.f;\n        T yAcc = 0.f;\n        T scoreAcc = 0.f;\n        const auto dWidth = 3;\n        const auto dHeight = 3;\n        for (auto dy = -dHeight ; dy <= dHeight ; dy++)\n        {\n            const auto y = peakLocY + dy;\n            if (0 <= y && y < height) // Default height = 368\n            {\n                for (auto dx = -dWidth ; dx <= dWidth ; dx++)\n                {\n                    const auto x = peakLocX + dx;\n                    if (0 <= x && x < width) // Default width = 656\n                    {\n                        const auto score = sourcePtr[y * width + x];\n                        if (score > 0)\n                        {\n                            xAcc += x*score;\n                            yAcc += y*score;\n                            scoreAcc += score;\n                        }\n                    }\n                }\n            }\n        }\n\n        // Offset to keep Matlab format (empirically higher acc)\n        // Best results for 1 scale: x + 0, y + 0.5\n        // +0.5 to both to keep Matlab format\n        output[0] = xAcc / scoreAcc + offset.x;\n        output[1] = yAcc / scoreAcc + offset.y;\n        output[2] = sourcePtr[peakLocY*width + peakLocX];\n    }\n\n    template <typename T>\n    void nmsCpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold,\n                const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize,\n                const Point<T>& offset)\n    {\n        try\n        {\n            // Sanity checks\n            if (sourceSize.empty())\n                error(\"sourceSize cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            if (targetSize.empty())\n                error(\"targetSize cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            if (threshold < 0 || threshold > 1.0)\n                error(\"threshold value invalid.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Params\n            const auto channels = targetSize[1]; // 57\n            const auto sourceHeight = sourceSize[2]; // 368\n            const auto sourceWidth = sourceSize[3]; // 496\n            const auto targetPeaks = targetSize[2]; // 97\n            const auto targetPeakVec = targetSize[3]; // 3\n            const auto sourceChannelOffset = sourceWidth * sourceHeight;\n            const auto targetChannelOffset = targetPeaks * targetPeakVec;\n\n            // Per channel operation\n            for (auto c = 0 ; c < channels ; c++)\n            {\n                auto* currKernelPtr = &kernelPtr[c*sourceChannelOffset];\n                const T* currSourcePtr = &sourcePtr[c*sourceChannelOffset];\n\n                for (auto y = 0; y < sourceHeight; y++)\n                    for (auto x = 0; x < sourceWidth; x++)\n                        nmsRegisterKernelCPU(currKernelPtr, currSourcePtr, sourceWidth, sourceHeight, threshold, x, y);\n\n                auto currentPeakCount = 1;\n                auto* currTargetPtr = &targetPtr[c*targetChannelOffset];\n                for (auto y = 0; y < sourceHeight; y++)\n                {\n                    for (auto x = 0; x < sourceWidth; x++)\n                    {\n                        const auto index = y*sourceWidth + x;\n                        // Find high intensity points\n                        if (currentPeakCount < targetPeaks)\n                        {\n                            if (currKernelPtr[index] == 1)\n                            {\n                                // Accurate Peak Position\n                                nmsAccuratePeakPosition(&currTargetPtr[currentPeakCount*3], currSourcePtr, x, y,\n                                                        sourceWidth, sourceHeight, offset);\n                                currentPeakCount++;\n                            }\n                        }\n                    }\n                }\n                currTargetPtr[0] = T(currentPeakCount-1);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template OP_API void nmsCpu(\n        float* targetPtr, int* kernelPtr, const float* const sourcePtr, const float threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<float>& offset);\n    template OP_API void nmsCpu(\n        double* targetPtr, int* kernelPtr, const double* const sourcePtr, const double threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<double>& offset);\n}\n"
  },
  {
    "path": "src/openpose/net/nmsBase.cu",
    "content": "#include <openpose/net/nmsBase.hpp>\n#include <thrust/device_ptr.h>\n#include <thrust/scan.h>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose_private/gpu/cuda.hu>\n\nnamespace op\n{\n    const auto THREADS_PER_BLOCK_1D = 16u;\n    const auto THREADS_PER_BLOCK = 512u;\n\n    // template <typename T>\n    // __global__ void nmsRegisterKernelOld(\n    //     int* kernelPtr, const T* const sourcePtr, const int w, const int h, const T threshold)\n    // {\n    //     // get pixel location (x,y)\n    //     const auto x = blockIdx.x * blockDim.x + threadIdx.x;\n    //     const auto y = blockIdx.y * blockDim.y + threadIdx.y;\n    //     const auto index = y*w + x;\n\n    //     if (0 < x && x < (w-1) && 0 < y && y < (h-1))\n    //     {\n    //         const auto value = sourcePtr[index];\n    //         if (value > threshold)\n    //         {\n    //             const auto topLeft     = sourcePtr[(y-1)*w + x-1];\n    //             const auto top         = sourcePtr[(y-1)*w + x];\n    //             const auto topRight    = sourcePtr[(y-1)*w + x+1];\n    //             const auto left        = sourcePtr[    y*w + x-1];\n    //             const auto right       = sourcePtr[    y*w + x+1];\n    //             const auto bottomLeft  = sourcePtr[(y+1)*w + x-1];\n    //             const auto bottom      = sourcePtr[(y+1)*w + x];\n    //             const auto bottomRight = sourcePtr[(y+1)*w + x+1];\n\n    //             if (value > topLeft && value > top && value > topRight\n    //                 && value > left && value > right\n    //                 && value > bottomLeft && value > bottom && value > bottomRight)\n    //                 kernelPtr[index] = 1;\n    //             else\n    //                 kernelPtr[index] = 0;\n    //         }\n    //         else\n    //             kernelPtr[index] = 0;\n    //     }\n    //     else if (x == 0 || x == (w-1) || y == 0 || y == (h-1))\n    //         kernelPtr[index] = 0;\n    // }\n\n    // Note: Shared memory made this function slower, from 1.2 ms to about 2 ms.\n    template <typename T>\n    __global__ void nmsRegisterKernel(\n        int* kernelPtr, const T* const sourcePtr, const int w, const int h, const T threshold)\n    {\n        // get pixel location (x,y)\n        const auto x = blockIdx.x * blockDim.x + threadIdx.x;\n        const auto y = blockIdx.y * blockDim.y + threadIdx.y;\n        const auto channel = blockIdx.z * blockDim.z + threadIdx.z;\n        const auto channelOffset = channel * w*h;\n        const auto index = y*w + x;\n\n        auto* kernelPtrOffset = &kernelPtr[channelOffset];\n        const T* const sourcePtrOffset = &sourcePtr[channelOffset];\n\n        if (0 < x && x < (w-1) && 0 < y && y < (h-1))\n        {\n            const auto value = sourcePtrOffset[index];\n            if (value > threshold)\n            {\n                const auto topLeft     = sourcePtrOffset[(y-1)*w + x-1];\n                const auto top         = sourcePtrOffset[(y-1)*w + x];\n                const auto topRight    = sourcePtrOffset[(y-1)*w + x+1];\n                const auto left        = sourcePtrOffset[    y*w + x-1];\n                const auto right       = sourcePtrOffset[    y*w + x+1];\n                const auto bottomLeft  = sourcePtrOffset[(y+1)*w + x-1];\n                const auto bottom      = sourcePtrOffset[(y+1)*w + x];\n                const auto bottomRight = sourcePtrOffset[(y+1)*w + x+1];\n\n                if (value > topLeft && value > top && value > topRight\n                    && value > left && value > right\n                    && value > bottomLeft && value > bottom && value > bottomRight)\n                    kernelPtrOffset[index] = 1;\n                else\n                    kernelPtrOffset[index] = 0;\n            }\n            else\n                kernelPtrOffset[index] = 0;\n        }\n        else if (x == 0 || x == (w-1) || y == 0 || y == (h-1))\n            kernelPtrOffset[index] = 0;\n    }\n\n    // template <typename T>\n    // __global__ void writeResultKernelOld(\n    //     T* output, const int length, const int* const kernelPtr, const T* const sourcePtr, const int width,\n    //     const int height, const int maxPeaks, const T offsetX, const T offsetY)\n    // {\n    //     __shared__ int local[THREADS_PER_BLOCK+1]; // one more\n    //     const auto globalIdx = blockIdx.x * blockDim.x + threadIdx.x;\n\n    //     if (globalIdx < length)\n    //     {\n    //         local[threadIdx.x] = kernelPtr[globalIdx];\n    //         //last thread in the block but not globally last, load one more\n    //         if (threadIdx.x == THREADS_PER_BLOCK - 1 && globalIdx != length - 1)\n    //             local[threadIdx.x+1] = kernelPtr[globalIdx+1];\n\n    //         __syncthreads();\n    //         // See difference, except the globally last one\n    //         if (globalIdx != length - 1)\n    //         {\n    //             // A[globalIdx] == A[globalIdx + 1] means no peak\n    //             if (local[threadIdx.x] != local[threadIdx.x + 1])\n    //             {\n    //                 const auto peakIndex = kernelPtr[globalIdx]; //0-index\n    //                 const auto peakLocX = (int)(globalIdx % width);\n    //                 const auto peakLocY = (int)(globalIdx / width);\n\n    //                 // Accurate peak location: considered neighbors\n    //                 if (peakIndex < maxPeaks) // limitation\n    //                 {\n    //                     T xAcc = 0.f;\n    //                     T yAcc = 0.f;\n    //                     T scoreAcc = 0.f;\n    //                     const auto dWidth = 3;\n    //                     const auto dHeight = 3;\n    //                     for (auto dy = -dHeight ; dy <= dHeight ; dy++)\n    //                     {\n    //                         const auto y = peakLocY + dy;\n    //                         if (0 <= y && y < height) // Default height = 368\n    //                         {\n    //                             for (auto dx = -dWidth ; dx <= dWidth ; dx++)\n    //                             {\n    //                                 const auto x = peakLocX + dx;\n    //                                 if (0 <= x && x < width) // Default width = 656\n    //                                 {\n    //                                     const auto score = sourcePtr[y * width + x];\n    //                                     if (score > 0)\n    //                                     {\n    //                                         xAcc += x*score;\n    //                                         yAcc += y*score;\n    //                                         scoreAcc += score;\n    //                                     }\n    //                                 }\n    //                             }\n    //                         }\n    //                     }\n\n    //                     // Offset to keep Matlab format (empirically higher acc)\n    //                     // Best results for 1 scale: x + 0, y + 0.5\n    //                     // +0.5 to both to keep Matlab format\n    //                     const auto outputIndex = (peakIndex + 1) * 3;\n    //                     output[outputIndex] = xAcc / scoreAcc + offsetX;\n    //                     output[outputIndex + 1] = yAcc / scoreAcc + offsetY;\n    //                     output[outputIndex + 2] = sourcePtr[peakLocY*width + peakLocX];\n    //                 }\n    //             }\n    //         }\n    //         // If index 0 --> Assign number of peaks (truncated to the maximum possible number of peaks)\n    //         else\n    //             output[0] = (kernelPtr[globalIdx] < maxPeaks ? kernelPtr[globalIdx] : maxPeaks);\n    //     }\n    // }\n\n    template <typename T>\n    __global__ void writeResultKernel(\n        T* output, const int length, const int* const kernelPtr, const T* const sourcePtr, const int width,\n        const int height, const int maxPeaks, const T offsetX, const T offsetY, const int offsetTarget)\n    {\n        __shared__ int local[THREADS_PER_BLOCK+1]; // one more\n        __shared__ int kernel0; // Offset for kernel\n        const auto globalIdx = blockIdx.x * blockDim.x + threadIdx.x;\n        const auto channel = blockIdx.y * blockDim.y + threadIdx.y;\n        const auto channelOffsetSource = channel * width*height;\n        const auto channelOffset = channel * offsetTarget;\n\n        // We need to subtract the peak at pixel 0 of the current channel for all values\n        if (threadIdx.x == 0)\n            kernel0 = kernelPtr[channelOffsetSource];\n        __syncthreads();\n\n        if (globalIdx < length)\n        {\n            auto* outputOffset = &output[channelOffset];\n            const auto* const kernelPtrOffset = &kernelPtr[channelOffsetSource];\n            const auto* const sourcePtrOffset = &sourcePtr[channelOffsetSource];\n            local[threadIdx.x] = kernelPtrOffset[globalIdx] - kernel0;\n            //last thread in the block but not globally last, load one more\n            if (threadIdx.x == THREADS_PER_BLOCK - 1 && globalIdx != length - 1)\n                local[threadIdx.x+1] = kernelPtrOffset[globalIdx+1] - kernel0;\n            __syncthreads();\n\n            // See difference, except the globally last one\n            if (globalIdx != length - 1)\n            {\n                // A[globalIdx] == A[globalIdx + 1] means no peak\n                if (local[threadIdx.x] != local[threadIdx.x + 1])\n                {\n                    const auto peakIndex = local[threadIdx.x]; //0-index\n                    const auto peakLocX = (int)(globalIdx % width);\n                    const auto peakLocY = (int)(globalIdx / width);\n\n                    // Accurate peak location: considered neighbors\n                    if (peakIndex < maxPeaks) // limitation\n                    {\n                        T xAcc = 0.f;\n                        T yAcc = 0.f;\n                        T scoreAcc = 0.f;\n                        const auto dWidth = 3;\n                        const auto dHeight = 3;\n                        for (auto dy = -dHeight ; dy <= dHeight ; dy++)\n                        {\n                            const auto y = peakLocY + dy;\n                            if (0 <= y && y < height) // Default height = 368\n                            {\n                                for (auto dx = -dWidth ; dx <= dWidth ; dx++)\n                                {\n                                    const auto x = peakLocX + dx;\n                                    if (0 <= x && x < width) // Default width = 656\n                                    {\n                                        const auto score = sourcePtrOffset[y * width + x];\n                                        if (score > 0)\n                                        {\n                                            xAcc += x*score;\n                                            yAcc += y*score;\n                                            scoreAcc += score;\n                                        }\n                                    }\n                                }\n                            }\n                        }\n\n                        // Offset to keep Matlab format (empirically higher acc)\n                        // Best results for 1 scale: x + 0, y + 0.5\n                        // +0.5 to both to keep Matlab format\n                        const auto outputIndex = (peakIndex + 1) * 3;\n                        outputOffset[outputIndex] = xAcc / scoreAcc + offsetX;\n                        outputOffset[outputIndex + 1] = yAcc / scoreAcc + offsetY;\n                        outputOffset[outputIndex + 2] = sourcePtrOffset[peakLocY*width + peakLocX];\n                    }\n                }\n            }\n            // If index 0 --> Assign number of peaks (truncated to the maximum possible number of peaks)\n            else\n                outputOffset[0] = (local[threadIdx.x] < maxPeaks ? local[threadIdx.x] : maxPeaks);\n        }\n    }\n\n    template <typename T>\n    void nmsGpu(T* targetPtr, int* kernelPtr, const T* const sourcePtr, const T threshold,\n                const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<T>& offset)\n    {\n        try\n        {\n            const auto num = sourceSize[0];\n            const auto height = sourceSize[2];\n            const auto width = sourceSize[3];\n            const auto channels = targetSize[1];\n            const auto maxPeaks = targetSize[2]-1;\n            const auto imageOffset = height * width;\n            const auto offsetTarget = (maxPeaks+1)*targetSize[3];\n\n            const dim3 threadsPerBlock2D{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D};\n            const dim3 numBlocks2D{getNumberCudaBlocks(width, threadsPerBlock2D.x),\n                                   getNumberCudaBlocks(height, threadsPerBlock2D.y)};\n            const dim3 threadsPerBlock1D{THREADS_PER_BLOCK};\n            const dim3 numBlocks1D{getNumberCudaBlocks(imageOffset, threadsPerBlock1D.x)};\n            // const dim3 threadsPerBlockSort{128};\n            // const dim3 numBlocksSort{getNumberCudaBlocks(channels, threadsPerBlockSort.x)};\n            // opLog(\"num_b: \" + std::to_string(sourceSize[0]));       // = 1\n            // opLog(\"channel_b: \" + std::to_string(sourceSize[1]));   // = 57 = 18 body parts + bkg + 19x2 PAFs\n            // opLog(\"height_b: \" + std::to_string(sourceSize[2]));    // = 368 = height\n            // opLog(\"width_b: \" + std::to_string(sourceSize[3]));     // = 656 = width\n            // opLog(\"num_t: \" + std::to_string(targetSize[0]));       // = 1\n            // opLog(\"channel_t: \" + std::to_string(targetSize[1]));   // = 18 = numberParts\n            // opLog(\"height_t: \" + std::to_string(targetSize[2]));    // = 128 = maxPeople + 1\n            // opLog(\"width_t: \" + std::to_string(targetSize[3]));     // = 3 = [x, y, score]\n            // opLog(\"\");\n\n            // // Old code: Running 3 kernels per channel\n            // // const auto REPS = 1;\n            // const auto REPS = 1000;\n            // double timeNormalize1 = 0.;\n            // double timeNormalize2 = 0.;\n            // OP_CUDA_PROFILE_INIT(REPS);\n            // for (auto n = 0; n < num; n++)\n            // {\n            //     for (auto c = 0; c < channels; c++)\n            //     {\n            //         // opLog(\"channel: \" + std::to_string(c));\n            //         const auto offsetChannel = (n * channels + c);\n            //         auto* kernelPtrOffsetted = kernelPtr + offsetChannel * imageOffset;\n            //         const auto* const sourcePtrOffsetted = sourcePtr + offsetChannel * imageOffset;\n            //         auto* targetPtrOffsetted = targetPtr + offsetChannel * offsetTarget;\n            //         // This returns kernelPtrOffsetted, a binary array with 0s & 1s. 1s in the local maximum\n            //         // positions (size = size(sourcePtrOffsetted))\n            //         // Example result: [0,0,0,0,1,0,0,0,0,1,0,0,0,0]\n            //         nmsRegisterKernelOld<<<numBlocks2D, threadsPerBlock2D>>>(\n            //             kernelPtrOffsetted, sourcePtrOffsetted, width, height, threshold);\n            //         // This modifies kernelPtrOffsetted, now it indicates the local maximum indexes\n            //         // Format: 0,0,0,1,1,1,1,2,2,2,... First maximum at index 2, second at 6, etc...\n            //         // Example result: [0,0,0,0,0,1,1,1,1,1,2,2,2,2]\n            //         auto kernelThrustPtr = thrust::device_pointer_cast(kernelPtrOffsetted);\n            //         thrust::exclusive_scan(kernelThrustPtr, kernelThrustPtr + imageOffset, kernelThrustPtr);\n            //         // This returns targetPtrOffsetted, with the NMS applied over it\n            //         writeResultKernelOld<<<numBlocks1D, threadsPerBlock1D>>>(\n            //             targetPtrOffsetted, imageOffset, kernelPtrOffsetted, sourcePtrOffsetted, width, height,\n            //             maxPeaks, offset.x, offset.y);\n            //     }\n            // }\n            // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n            // OP_CUDA_PROFILE_INIT(REPS);\n\n            // Optimized code: Running 3 kernels in total\n            // This returns kernelPtr, a binary array with 0s & 1s. 1s in the local maximum\n            // positions (size = size(sourcePtrOffsetted))\n            // Example result: [0,0,0,0,1,0,0,0,0,1,0,0,0,0]\n            // time = 1.24 ms\n            const dim3 threadsPerBlockRegister{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n            const dim3 numBlocksRegister{getNumberCudaBlocks(width, threadsPerBlockRegister.x),\n                                         getNumberCudaBlocks(height, threadsPerBlockRegister.y),\n                                         getNumberCudaBlocks(num * channels, threadsPerBlockRegister.z)};\n            nmsRegisterKernel<<<numBlocksRegister, threadsPerBlockRegister>>>(\n                kernelPtr, sourcePtr, width, height, threshold);\n            // This modifies kernelPtrOffsetted, now it indicates the local maximum indexes\n            // Format: 0,0,0,1,1,1,1,2,2,2,... First maximum at index 2, second at 6, etc...\n            // Example result: [0,0,0,0,0,1,1,1,1,1,2,2,2,2]\n            // time = 2.71 ms\n            auto kernelThrustPtr = thrust::device_pointer_cast(kernelPtr);\n            thrust::exclusive_scan(kernelThrustPtr, kernelThrustPtr + num*channels*imageOffset, kernelThrustPtr);\n            // This returns targetPtrOffsetted, with the NMS applied over it\n            // time = 1.10 ms\n            const dim3 threadsPerBlockWrite{THREADS_PER_BLOCK, 1};\n            const dim3 numBlocksWrite{getNumberCudaBlocks(imageOffset, threadsPerBlockWrite.x),\n                                      getNumberCudaBlocks(num * channels, threadsPerBlockWrite.z)};\n            writeResultKernel<<<numBlocksWrite, threadsPerBlockWrite>>>(\n                targetPtr, imageOffset, kernelPtr, sourcePtr, width, height,\n                maxPeaks, offset.x, offset.y, offsetTarget);\n\n            // // Profiling code\n            // OP_CUDA_PROFILE_END(timeNormalize2, 1e3, REPS);\n            // opLog(\"  NMS1(or)=\" + std::to_string(timeNormalize1) + \"ms\");\n            // opLog(\"  NMS2(1k)=\" + std::to_string(timeNormalize2) + \"ms\");\n\n            // Sanity check\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void nmsGpu(\n        float* targetPtr, int* kernelPtr, const float* const sourcePtr, const float threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<float>& offset);\n    template void nmsGpu(\n        double* targetPtr, int* kernelPtr, const double* const sourcePtr, const double threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<double>& offset);\n}\n"
  },
  {
    "path": "src/openpose/net/nmsBaseCL.cpp",
    "content": "#include <openpose/net/nmsBase.hpp>\n#include <algorithm>\n#include <bitset>\n#include <numeric>\n#include <opencv2/opencv.hpp>\n#include <openpose/core/common.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    #ifdef USE_OPENCL\n        const std::string nmsOclCommonFunctions = MULTI_LINE_STRING(\n            void nmsAccuratePeakPosition(__global const Type* sourcePtr, Type* fx, Type* fy, Type* fscore,\n                                         const int peakLocX, const int peakLocY, const int width, const int height,\n                                         const Type offsetX, const Type offsetY)\n            {\n                Type xAcc = 0.f;\n                Type yAcc = 0.f;\n                Type scoreAcc = 0.f;\n                const int dWidth = 3;\n                const int dHeight = 3;\n                for (int dy = -dHeight ; dy <= dHeight ; dy++)\n                {\n                    const int y = peakLocY + dy;\n                    if (0 <= y && y < height) // Default height = 368\n                    {\n                        for (int dx = -dWidth ; dx <= dWidth ; dx++)\n                        {\n                            const int x = peakLocX + dx;\n                            if (0 <= x && x < width) // Default width = 656\n                            {\n                                const Type score = sourcePtr[y * width + x];\n                                if (score > 0)\n                                {\n                                    xAcc += (Type)x*score;\n                                    yAcc += (Type)y*score;\n                                    scoreAcc += score;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // Offset to keep Matlab format (empirically higher acc)\n                // Best results for 1 scale: x + 0, y + 0.5\n                // +0.5 to both to keep Matlab format\n                *fx = xAcc / scoreAcc + offsetX;\n                *fy = yAcc / scoreAcc + offsetY;\n                *fscore = sourcePtr[peakLocY*width + peakLocX];\n            }\n\n            union DS {\n              struct {\n                short x;\n                short y;\n                float score;\n              } ds;\n              double dbl;\n            };\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, int, int> PartialSumKernelFunctor;\n        const std::string partialSumKernel = MULTI_LINE_STRING(\n            __kernel void partialSumKernel(__global int* kernelFullPtr,\n                                               const int w, const int h)\n            {\n                int c = get_global_id(0);\n                __global int* kernelPtr = kernelFullPtr + (c*w*h);\n\n                int incr = 0;\n                for(int y=0; y<h; y++){\n                    for(int x=0; x<w; x++){\n                        int index = y*w + x;\n                        if(kernelPtr[index]) incr += 1;\n                        kernelPtr[index] = incr;\n                    }\n                }\n\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, int, int, float, int> NMSFullRegisterKernelFunctor;\n        const std::string nmsFullRegisterKernel = MULTI_LINE_STRING(\n            __kernel void nmsFullRegisterKernel(__global uchar* kernelFullPtr, __global const Type* sourceFullPtr,\n                                               const int w, const int h, const Type threshold, const int debug)\n            {\n                int c = get_global_id(0);\n                int x = get_global_id(1);\n                int y = get_global_id(2);\n\n                __global const Type* sourcePtr = sourceFullPtr + (c*w*h);\n                __global uchar* kernelPtr = kernelFullPtr + (c*w*h);\n                int index = y*w + x;\n\n                if (0 < x && x < (w-1) && 0 < y && y < (h-1))\n                {\n                    const Type value = sourcePtr[index];\n\n                    if (value > threshold)\n                    {\n\n                        const Type topLeft     = sourcePtr[(y-1)*w + x-1];\n                        const Type top         = sourcePtr[(y-1)*w + x];\n                        const Type topRight    = sourcePtr[(y-1)*w + x+1];\n                        const Type left        = sourcePtr[    y*w + x-1];\n                        const Type right       = sourcePtr[    y*w + x+1];\n                        const Type bottomLeft  = sourcePtr[(y+1)*w + x-1];\n                        const Type bottom      = sourcePtr[(y+1)*w + x];\n                        const Type bottomRight = sourcePtr[(y+1)*w + x+1];\n\n                        if (value > topLeft && value > top && value > topRight\n                            && value > left && value > right\n                            && value > bottomLeft && value > bottom && value > bottomRight)\n                        {\n                            kernelPtr[index] = 1;\n                        }\n                        else\n                            kernelPtr[index] = 0;\n                    }\n                    else\n                        kernelPtr[index] = 0;\n                }\n                else if (x == 0 || x == (w-1) || y == 0 || y == (h-1))\n                    kernelPtr[index] = 0;\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, int, int, float, int> NMSRegisterKernelFunctor;\n        const std::string nmsRegisterKernel = MULTI_LINE_STRING(\n            __kernel void nmsRegisterKernel(__global int* kernelPtr, __global const Type* sourcePtr,\n                                               const int w, const int h, const Type threshold, const int debug)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n                int index = y*w + x;\n\n                if (0 < x && x < (w-1) && 0 < y && y < (h-1))\n                {\n                    const Type value = sourcePtr[index];\n                    if (value > threshold)\n                    {\n                        const Type topLeft     = sourcePtr[(y-1)*w + x-1];\n                        const Type top         = sourcePtr[(y-1)*w + x];\n                        const Type topRight    = sourcePtr[(y-1)*w + x+1];\n                        const Type left        = sourcePtr[    y*w + x-1];\n                        const Type right       = sourcePtr[    y*w + x+1];\n                        const Type bottomLeft  = sourcePtr[(y+1)*w + x-1];\n                        const Type bottom      = sourcePtr[(y+1)*w + x];\n                        const Type bottomRight = sourcePtr[(y+1)*w + x+1];\n\n                        if (value > topLeft && value > top && value > topRight\n                            && value > left && value > right\n                            && value > bottomLeft && value > bottom && value > bottomRight)\n                        {\n                            kernelPtr[index] = 1;\n                        }\n                        else\n                            kernelPtr[index] = 0;\n                    }\n                    else\n                        kernelPtr[index] = 0;\n                }\n                else if (x == 0 || x == (w-1) || y == 0 || y == (h-1))\n                    kernelPtr[index] = 0;\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int, int, float, float> NMSWriteKernelFunctor;\n        const std::string nmsWriteKernel = MULTI_LINE_STRING(\n            __kernel void nmsWriteKernel(__global Type* targetPtr, __global int* kernelPtr, __global const Type* sourcePtr,\n                                         const int w, const int h, const int maxPeaks, const int debug,\n                                         const Type offsetX, const Type offsetY)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n                int index = y*w + x;\n\n                if (index != 0){\n                    int prev = kernelPtr[index-1];\n                    int curr = kernelPtr[index];\n                    if (curr < maxPeaks)\n                    {\n                        if (prev - curr)\n                        {\n                            Type fx = 0; Type fy = 0; Type fscore = 0;\n                            nmsAccuratePeakPosition(sourcePtr, &fx, &fy, &fscore, x, y, w, h, offsetX, offsetY);\n                            //if (debug) printf(\"C %d %d %d \\n\", x,y,kernelPtr[index]);\n                            __global Type* output = &targetPtr[curr*3];\n                            output[0] = fx; output[1] = fy; output[2] = fscore;\n                        }\n                        if (index + 1 == w*h)\n                        {\n                            __global Type* output = &targetPtr[0*3];\n                            output[0] = curr;\n                        }\n                    }\n                    else\n                    {\n                        if (index + 1 == w*h)\n                        {\n                            __global Type* output = &targetPtr[0*3];\n                            output[0] = maxPeaks;\n                        }\n                    }\n                }\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, cl::Buffer, int, int, int, int, float, float> NMSFullWriteKernelFunctor;\n        const std::string nmsFullWriteKernel = MULTI_LINE_STRING(\n            __kernel void nmsFullWriteKernel(__global Type* targetPtrFull, __global uchar* kernelPtrFull, __global const Type* sourcePtrFull,\n                                         const int w, const int h, const int maxPeaks, const int debug,\n                                         const Type offsetX, const Type offsetY)\n            {\n                int c = get_global_id(0);\n                int x = get_global_id(1);\n                int y = get_global_id(2);\n\n                __global Type* targetPtr = targetPtrFull + c*(maxPeaks+1)*3;\n                __global uchar* kernelPtr = kernelPtrFull + c*w*h;\n                __global const Type* sourcePtr = sourcePtrFull + c*w*h;\n\n                int index = y*w + x;\n\n                if (index != 0){\n                    uchar prev = kernelPtr[index-1];\n                    uchar curr = kernelPtr[index];\n                    if (curr < maxPeaks)\n                    {\n                        if (prev - curr)\n                        {\n                            Type fx = 0; Type fy = 0; Type fscore = 0;\n                            nmsAccuratePeakPosition(sourcePtr, &fx, &fy, &fscore, x, y, w, h, offsetX, offsetY);\n                            //printf(\"C %d %d %d \\n\", x,y,kernelPtr[index]);\n                            __global Type* output = &targetPtr[curr*3];\n                            output[0] = fx; output[1] = fy; output[2] = fscore;\n                        }\n                        if (index + 1 == w*h)\n                        {\n                            __global Type* output = &targetPtr[0*3];\n                            output[0] = curr;\n                        }\n                    }\n                    else\n                    {\n                        if (index + 1 == w*h)\n                        {\n                            __global Type* output = &targetPtr[0*3];\n                            output[0] = maxPeaks;\n                        }\n                    }\n                }\n            }\n        );\n    #endif\n\n    template <typename T>\n    void nmsOcl(T* targetPtr, uint8_t* kernelGpuPtr, uint8_t* kernelCpuPtr, const T* const sourcePtr, const T threshold,\n                const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<T>& offset,\n                const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_OPENCL\n                // Sanity checks\n                if (sourceSize.empty())\n                    error(\"sourceSize cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n                if (targetSize.empty())\n                    error(\"targetSize cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n                if (threshold < 0 || threshold > 1.0)\n                    error(\"threshold value invalid.\", __LINE__, __FUNCTION__, __FILE__);\n\n                //Forward_cpu(bottom, top);\n                const auto num = sourceSize[0];\n                const auto height = sourceSize[2];\n                const auto width = sourceSize[3];\n                const auto channels = targetSize[1];\n                const auto targetPeaks = targetSize[2]; // 97\n                const auto targetPeakVec = targetSize[3]; // 3\n                const auto imageOffset = height * width;\n                const auto targetChannelOffset = targetPeaks * targetPeakVec;\n\n                //std::cout << targetPeaks << std::endl;\n                //std::cout << targetPeakVec << std::endl;\n\n                // Get Kernel\n                cl::Buffer sourcePtrBuffer = cl::Buffer((cl_mem)(sourcePtr), true);\n                cl::Buffer kernelPtrBuffer = cl::Buffer((cl_mem)(kernelGpuPtr), true);\n                cl::Buffer targetPtrBuffer = cl::Buffer((cl_mem)(targetPtr), true);\n                auto nmsRegisterKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <NMSRegisterKernelFunctor, T>(\n                         \"nmsRegisterKernel\", op::nmsOclCommonFunctions + op::nmsRegisterKernel);\n                auto nmsFullRegisterKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <NMSFullRegisterKernelFunctor, T>(\n                         \"nmsFullRegisterKernel\", op::nmsOclCommonFunctions + op::nmsFullRegisterKernel);\n                auto nmsWriteKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <NMSWriteKernelFunctor, T>(\n                         \"nmsWriteKernel\", op::nmsOclCommonFunctions + op::nmsWriteKernel);\n                auto partialSumKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <PartialSumKernelFunctor, T>(\n                         \"partialSumKernel\", op::nmsOclCommonFunctions + op::partialSumKernel);\n                auto nmsFullWriteKernel = OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <NMSFullWriteKernelFunctor, T>(\n                         \"nmsFullWriteKernel\", op::nmsOclCommonFunctions + op::nmsFullWriteKernel);\n\n                // Temp DS\n                for (auto n = 0; n < num; n++)\n                {\n                    nmsFullRegisterKernel(cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange((int)channels, (int)width, (int)height)),\n                                      kernelPtrBuffer, sourcePtrBuffer, width, height, (float)threshold, false);\n                    OpenCL::getInstance(gpuID)->getQueue().enqueueReadBuffer(kernelPtrBuffer, CL_TRUE, 0,\n                                                                                 sizeof(uint8_t) * channels * imageOffset, &kernelCpuPtr[0]);\n                    for(int c=0; c<channels; c++){\n                        uint8_t* currPtr = kernelCpuPtr + c*imageOffset;\n                        std::partial_sum(currPtr,currPtr + imageOffset,currPtr);\n                    }\n                    OpenCL::getInstance(gpuID)->getQueue().enqueueWriteBuffer(kernelPtrBuffer, CL_TRUE, 0,\n                                                                                  sizeof(uint8_t) * channels * imageOffset, &kernelCpuPtr[0]);\n                    nmsFullWriteKernel(cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(channels, width, height)),\n                                      targetPtrBuffer, kernelPtrBuffer, sourcePtrBuffer, width, height, targetPeaks-1, false,\n                                      offset.x, offset.y);\n                }\n            #else\n                UNUSED(targetPtr);\n                UNUSED(kernelGpuPtr);\n                UNUSED(kernelCpuPtr);\n                UNUSED(sourcePtr);\n                UNUSED(threshold);\n                UNUSED(targetSize);\n                UNUSED(sourceSize);\n                UNUSED(offset);\n                UNUSED(gpuID);\n                error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n        catch (const cl::Error& e)\n        {\n            error(std::string(e.what()) + \" : \" + OpenCL::clErrorToString(e.err()) + \" ID: \" +\n                  std::to_string(gpuID), __LINE__, __FUNCTION__, __FILE__);\n        }\n        #endif\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void nmsOcl(\n        float* targetPtr, uint8_t* kernelGpuPtr, uint8_t* kernelCpuPtr, const float* const sourcePtr, const float threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<float>& offset,\n        const int gpuID);\n    template void nmsOcl(\n        double* targetPtr, uint8_t* kernelGpuPtr, uint8_t* kernelCpuPtr, const double* const sourcePtr, const double threshold,\n        const std::array<int, 4>& targetSize, const std::array<int, 4>& sourceSize, const Point<double>& offset,\n        const int gpuID);\n}\n\n//                    for (auto c = 0; c < channels; c++)\n//                    {\n//                        // opLog(\"channel: \" + std::to_string(c));\n//                        const auto offsetChannel = (n * channels + c);\n\n//                        // CL Data\n//                        cl_buffer_region kernelRegion, sourceRegion, targetRegion;\n//                        kernelRegion.origin = sizeof(int) * offsetChannel * imageOffset;\n//                        kernelRegion.size = sizeof(int) * imageOffset;\n//                        cl::Buffer kernelBuffer = kernelPtrBuffer.createSubBuffer(CL_MEM_READ_WRITE,\n//                                                                                  CL_BUFFER_CREATE_TYPE_REGION,\n//                                                                                  &kernelRegion);\n//                        OpenCL::getBufferRegion<T>(sourceRegion, offsetChannel * imageOffset, imageOffset);\n//                        OpenCL::getBufferRegion<T>(targetRegion, offsetChannel * targetChannelOffset, targetChannelOffset);\n//                        cl::Buffer sourceBuffer = sourcePtrBuffer.createSubBuffer(CL_MEM_READ_ONLY,\n//                                                                                  CL_BUFFER_CREATE_TYPE_REGION,\n//                                                                                  &sourceRegion);\n//                        cl::Buffer targetBuffer = targetPtrBuffer.createSubBuffer(CL_MEM_READ_WRITE,\n//                                                                                  CL_BUFFER_CREATE_TYPE_REGION,\n//                                                                                  &targetRegion);\n\n//                        // Run Kernel to get 1-0 map\n//                        bool debug = false;\n////                        nmsRegisterKernel(cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(width, height)),\n////                                          kernelBuffer, sourceBuffer, width, height, threshold, debug);\n//                        // This is a really bad approach. We need to write a custom accumulator to run on gpu\n//                        // Download it to CPU\n////                        OpenCL::getInstance(gpuID)->getQueue().enqueueReadBuffer(kernelBuffer, CL_TRUE, 0,\n////                                                                                     sizeof(int) *  width * height, &kernelCPU[0]);\n////                        // Compute partial sum in CPU\n////                        std::partial_sum(kernelCPU.begin(),kernelCPU.end(),kernelCPU.begin());\n////                        // Reupload to GPU\n////                        OpenCL::getInstance(gpuID)->getQueue().enqueueWriteBuffer(kernelBuffer, CL_TRUE, 0,\n////                                                                                      sizeof(int) *  width * height, &kernelCPU[0]);\n\n//                        // Write Kernel\n//                        nmsWriteKernel(cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(width, height)),\n//                                          targetBuffer, kernelBuffer, sourceBuffer, width, height, targetPeaks-1, false,\n//                                          offset.x, offset.y);\n//                    }\n"
  },
  {
    "path": "src/openpose/net/nmsCaffe.cpp",
    "content": "#include <openpose/net/nmsCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/net/nmsBase.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    template <typename T>\n    struct NmsCaffe<T>::ImplNmsCaffe\n    {\n        #ifdef USE_CAFFE\n            ArrayCpuGpu<int> mKernelBlob;\n            std::array<int, 4> mBottomSize;\n            std::array<int, 4> mTopSize;\n            // Special Kernel for OpenCL NMS\n            #if defined USE_CAFFE && defined USE_OPENCL\n                //std::shared_ptr<ArrayCpuGpu<uint8_t>> mKernelBlobT;\n                uint8_t* mKernelGpuPtr;\n                uint8_t* mKernelCpuPtr;\n            #endif\n        #endif\n\n        ImplNmsCaffe()\n        {\n            #if defined USE_CAFFE && defined USE_OPENCL\n                try\n                {\n                    mKernelGpuPtr = nullptr;\n                    mKernelCpuPtr = nullptr;\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            #endif\n        }\n\n        ~ImplNmsCaffe()\n        {\n            #if defined USE_CAFFE && defined USE_OPENCL\n                try\n                {\n                    if (mKernelGpuPtr != nullptr)\n                        clReleaseMemObject((cl_mem)mKernelGpuPtr);\n                    if (mKernelCpuPtr != nullptr)\n                        delete mKernelCpuPtr;\n                }\n                catch (const std::exception& e)\n                {\n                    errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            #endif\n        }\n    };\n\n    template <typename T>\n    NmsCaffe<T>::NmsCaffe() :\n        upImpl{new ImplNmsCaffe{}}\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    NmsCaffe<T>::~NmsCaffe()\n    {\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (top.size() != 1)\n                    error(\"top.size() != 1\", __LINE__, __FUNCTION__, __FILE__);\n                if (bottom.size() != 1)\n                    error(\"bottom.size() != 1\", __LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Reshape(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top,\n                              const int maxPeaks, const int outputChannels, const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                auto bottomBlob = bottom.at(0);\n                auto topBlob = top.at(0);\n\n                // Bottom shape\n                std::vector<int> bottomShape = bottomBlob->shape();\n\n                // Top shape\n                std::vector<int> topShape{bottomShape};\n                topShape[1] = (outputChannels > 0 ? outputChannels : bottomShape[1]);\n                topShape[2] = maxPeaks+1; // # maxPeaks + 1\n                topShape[3] = 3;  // X, Y, score\n                topBlob->Reshape(topShape);\n                upImpl->mKernelBlob.Reshape(bottomShape);\n\n                // Special Kernel for OpenCL NMS\n                #if defined USE_CAFFE && defined USE_OPENCL\n                    int bottomShapeVolume = bottomShape[0] * bottomShape[1] * bottomShape[2] * bottomShape[3];\n                    upImpl->mKernelGpuPtr = (uint8_t*)clCreateBuffer(\n                        OpenCL::getInstance(gpuID)->getContext().operator()(), CL_MEM_READ_WRITE,\n                        sizeof(uint8_t) * bottomShapeVolume, NULL, NULL);\n                    upImpl->mKernelCpuPtr = new uint8_t[bottomShapeVolume];\n                    // GPU ID\n                    mGpuID = gpuID;\n                #else\n                    UNUSED(gpuID);\n                #endif\n                // Array sizes\n                upImpl->mTopSize = std::array<int, 4>{topBlob->shape(0), topBlob->shape(1),\n                                                      topBlob->shape(2), topBlob->shape(3)};\n                upImpl->mBottomSize = std::array<int, 4>{bottomBlob->shape(0), bottomBlob->shape(1),\n                                                         bottomBlob->shape(2), bottomBlob->shape(3)};\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                UNUSED(maxPeaks);\n                UNUSED(outputChannels);\n                UNUSED(gpuID);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::setThreshold(const T threshold)\n    {\n        try\n        {\n            mThreshold = {threshold};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::setOffset(const Point<T>& offset)\n    {\n        try\n        {\n            mOffset = {offset};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Forward(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            // CUDA\n            #ifdef USE_CUDA\n                Forward_gpu(bottom, top);\n            // OpenCL\n            #elif defined USE_OPENCL\n                Forward_ocl(bottom, top);\n            // CPU\n            #else\n                Forward_cpu(bottom, top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                nmsCpu(top.at(0)->mutable_cpu_data(), upImpl->mKernelBlob.mutable_cpu_data(), bottom.at(0)->cpu_data(),\n                       mThreshold, upImpl->mTopSize, upImpl->mBottomSize, mOffset);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_CUDA\n                nmsGpu(top.at(0)->mutable_gpu_data(), upImpl->mKernelBlob.mutable_gpu_data(),\n                       bottom.at(0)->gpu_data(), mThreshold, upImpl->mTopSize, upImpl->mBottomSize, mOffset);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Forward_ocl(const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_OPENCL\n                nmsOcl(top.at(0)->mutable_gpu_data(), upImpl->mKernelGpuPtr, upImpl->mKernelCpuPtr,\n                       bottom.at(0)->gpu_data(), mThreshold, upImpl->mTopSize, upImpl->mBottomSize, mOffset,\n                       mGpuID);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_OPENCL` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                   const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void NmsCaffe<T>::Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top, const std::vector<bool>& propagate_down,\n                                   const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(NmsCaffe);\n}\n"
  },
  {
    "path": "src/openpose/net/resizeAndMergeBase.cpp",
    "content": "#include <openpose/net/resizeAndMergeBase.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    template <typename T>\n    void resizeAndMergeCpu(T* targetPtr, const std::vector<const T*>& sourcePtrs,\n                           const std::array<int, 4>& targetSize,\n                           const std::vector<std::array<int, 4>>& sourceSizes,\n                           const std::vector<T>& scaleInputToNetInputs)\n    {\n        try\n        {\n            // Scale used in CUDA/CL to know scale ratio between input and output\n            // CPU directly uses sourceWidth/Height and targetWidth/Height\n            UNUSED(scaleInputToNetInputs);\n\n            // Sanity check\n            if (sourceSizes.empty())\n                error(\"sourceSizes cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Params\n            const auto nums = (signed)sourceSizes.size();\n            const auto channels = targetSize[1]; // 57\n            const auto targetHeight = targetSize[2]; // 368\n            const auto targetWidth = targetSize[3]; // 496\n            const auto targetChannelOffset = targetWidth * targetHeight;\n\n            // No multi-scale merging or no merging required\n            if (sourceSizes.size() == 1)\n            {\n                // Params\n                const auto& sourceSize = sourceSizes[0];\n                const auto sourceHeight = sourceSize[2]; // 368/8 ..\n                const auto sourceWidth = sourceSize[3]; // 496/8 ..\n                const auto sourceChannelOffset = sourceHeight * sourceWidth;\n                if (sourceSize[0] != 1)\n                    error(\"It should never reache this point. Notify us otherwise.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                // Per channel resize\n                const T* sourcePtr = sourcePtrs[0];\n                for (auto c = 0 ; c < channels ; c++)\n                {\n                    cv::Mat source(cv::Size(sourceWidth, sourceHeight), CV_32FC1,\n                                   const_cast<T*>(&sourcePtr[c*sourceChannelOffset]));\n                    cv::Mat target(cv::Size(targetWidth, targetHeight), CV_32FC1,\n                                   (&targetPtr[c*targetChannelOffset]));\n                    cv::resize(source, target, {targetWidth, targetHeight}, 0, 0, CV_INTER_CUBIC);\n                }\n            }\n            // Multi-scale merging\n            else\n            {\n                // Construct temp targets. We reuse targetPtr to store first scale\n                std::vector<std::unique_ptr<T>> tempTargetPtrs;\n                for (auto n = 1; n < nums; n++){\n                    tempTargetPtrs.emplace_back(std::unique_ptr<T>(new T[targetChannelOffset * channels]()));\n                }\n\n                // Resize and sum\n                for (auto n = 0; n < nums; n++){\n\n                    // Params\n                    const auto& sourceSize = sourceSizes[n];\n                    const auto sourceHeight = sourceSize[2]; // 368/6 ..\n                    const auto sourceWidth = sourceSize[3]; // 496/8 ..\n                    const auto sourceChannelOffset = sourceHeight * sourceWidth;\n\n                    // Access pointers\n                    const T* sourcePtr = sourcePtrs[n];\n                    T* tempTargetPtr;\n                    if (n != 0)\n                        tempTargetPtr = tempTargetPtrs[n-1].get();\n                    else\n                        tempTargetPtr = targetPtr;\n\n                    T* firstTempTargetPtr = targetPtr;\n                    for (auto c = 0 ; c < channels ; c++)\n                    {\n                        // Resize\n                        cv::Mat source(cv::Size(sourceWidth, sourceHeight), CV_32FC1,\n                                       const_cast<T*>(&sourcePtr[c*sourceChannelOffset]));\n                        cv::Mat target(cv::Size(targetWidth, targetHeight), CV_32FC1,\n                                       (&tempTargetPtr[c*targetChannelOffset]));\n                        cv::resize(source, target, {targetWidth, targetHeight}, 0, 0, CV_INTER_CUBIC);\n\n                        // Add\n                        if (n != 0)\n                        {\n                            cv::Mat addTarget(cv::Size(targetWidth, targetHeight), CV_32FC1,\n                                              (&firstTempTargetPtr[c*targetChannelOffset]));\n                            cv::add(target, addTarget, addTarget);\n                        }\n                    }\n                }\n\n                // Average\n                for (auto c = 0 ; c < channels ; c++)\n                {\n                    cv::Mat target(cv::Size(targetWidth, targetHeight), CV_32FC1, (&targetPtr[c*targetChannelOffset]));\n                    target /= (float)nums;\n                }\n\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template OP_API void resizeAndMergeCpu(\n        float* targetPtr, const std::vector<const float*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<float>& scaleInputToNetInputs);\n    template OP_API void resizeAndMergeCpu(\n        double* targetPtr, const std::vector<const double*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<double>& scaleInputToNetInputs);\n}\n"
  },
  {
    "path": "src/openpose/net/resizeAndMergeBase.cu",
    "content": "#include <openpose/net/resizeAndMergeBase.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose_private/gpu/cuda.hu>\n\nnamespace op\n{\n    const auto THREADS_PER_BLOCK = 256u;\n    const auto THREADS_PER_BLOCK_1D = 16u;\n\n    template <typename T>\n    __global__ void fillKernel(\n        T* targetPtr, const T* const sourcePtr, const int N)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        if (x < N)\n            targetPtr[x] = sourcePtr[x];\n    }\n\n    // template <typename T>\n    // __global__ void resizeKernelOld(\n    //     T* targetPtr, const T* const sourcePtr, const int widthSource, const int heightSource, const int widthTarget,\n    //     const int heightTarget)\n    // {\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     if (x < widthTarget && y < heightTarget)\n    //     {\n    //         const T xSource = (x + T(0.5f)) * widthSource / T(widthTarget) - T(0.5f);\n    //         const T ySource = (y + T(0.5f)) * heightSource / T(heightTarget) - T(0.5f);\n    //         targetPtr[y*widthTarget+x] = bicubicInterpolate(\n    //             sourcePtr, xSource, ySource, widthSource, heightSource, widthSource);\n    //     }\n    // }\n\n    template <typename T>\n    __global__ void resizeKernel(\n        T* targetPtr, const T* const sourcePtr, const int widthSource, const int heightSource, const int widthTarget,\n        const int heightTarget)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n        if (x < widthTarget && y < heightTarget)\n        {\n            const auto sourceArea = widthSource * heightSource;\n            const auto targetArea = widthTarget * heightTarget;\n            const T xSource = (x + T(0.5f)) * widthSource / T(widthTarget) - T(0.5f);\n            const T ySource = (y + T(0.5f)) * heightSource / T(heightTarget) - T(0.5f);\n            const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n            targetPtr[channel * targetArea + y*widthTarget+x] = bicubicInterpolate(\n                sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n        }\n    }\n\n    template <typename T>\n    __global__ void resizeAndPadKernel(\n        T* targetPtr, const T* const sourcePtr, const int widthSource, const int heightSource, const int widthTarget,\n        const int heightTarget, const T rescaleFactor)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n        if (x < widthTarget && y < heightTarget)\n        {\n            const auto targetArea = widthTarget * heightTarget;\n            if (x < widthSource * rescaleFactor && y < heightSource * rescaleFactor)\n            {\n                const auto sourceArea = widthSource * heightSource;\n                const T xSource = (x + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const T ySource = (y + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n                targetPtr[channel * targetArea + y*widthTarget+x] = bicubicInterpolate(\n                    sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n            }\n            else\n                targetPtr[channel * targetArea + y*widthTarget+x] = 0;\n        }\n    }\n\n    template <typename T>\n    __global__ void resizeAndPadKernel(\n        T* targetPtr, const unsigned char* const sourcePtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const T rescaleFactor)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n        if (x < widthTarget && y < heightTarget)\n        {\n            const auto targetArea = widthTarget * heightTarget;\n            if (x < widthSource * rescaleFactor && y < heightSource * rescaleFactor)\n            {\n                const auto sourceArea = widthSource * heightSource;\n                const T xSource = (x + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const T ySource = (y + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const unsigned char* sourcePtrChannel = sourcePtr + channel * sourceArea;\n                targetPtr[channel * targetArea + y*widthTarget+x] = bicubicInterpolate(\n                    sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n            }\n            else\n                targetPtr[channel * targetArea + y*widthTarget+x] = 0;\n        }\n    }\n\n    template <typename T>\n    __global__ void resize8TimesKernel(\n        T* targetPtr, const T* const sourcePtr, const int widthSource, const int heightSource, const int widthTarget,\n        const int heightTarget, const unsigned int rescaleFactor)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n\n        if (x < widthTarget && y < heightTarget)\n        {\n            // Normal resize\n            // Note: The first blockIdx of each dimension behaves differently, so applying old version in those\n            if (blockIdx.x < 1 || blockIdx.y < 1)\n            // Actually it is only required for the first 4, but then I would have not loaded the shared memory\n            // if ((blockIdx.x < 1 || blockIdx.y < 1) && (threadIdx.x < 4 || threadIdx.y < 4))\n            {\n                const auto sourceArea = widthSource * heightSource;\n                const auto targetArea = widthTarget * heightTarget;\n                const T xSource = (x + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const T ySource = (y + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n                targetPtr[channel * targetArea + y*widthTarget+x] = bicubicInterpolate(\n                    sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n                return;\n            }\n\n            // Load shared memory\n            // If resize >= 5, then #threads per block >= # elements of shared memory\n            const auto sharedSize = 25; // (4+1)^2\n            __shared__ T sourcePtrShared[sharedSize];\n            const auto sharedLoadId = threadIdx.x + rescaleFactor*threadIdx.y;\n            if (sharedLoadId < sharedSize)\n            {\n                // Idea: Find minimum possible x and y\n                const auto minTargetX = blockIdx.x * rescaleFactor;\n                const auto minSourceXFloat = (minTargetX + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const auto minSourceXInt = int(floor(minSourceXFloat)) - 1;\n                const auto minTargetY = blockIdx.y * rescaleFactor;\n                const auto minSourceYFloat = (minTargetY + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n                const auto minSourceYInt = int(floor(minSourceYFloat)) - 1;\n                // Get current x and y\n                const auto xClean = fastTruncateCuda(minSourceXInt+int(sharedLoadId%5), 0, widthSource - 1);\n                const auto yClean = fastTruncateCuda(minSourceYInt+int(sharedLoadId/5), 0, heightSource - 1);\n                // Load into shared memory\n                const auto sourceIndex = (channel * heightSource + yClean) * widthSource + xClean;\n                sourcePtrShared[sharedLoadId] = sourcePtr[sourceIndex];\n            }\n            __syncthreads();\n\n            // Apply resize\n            const auto targetArea = widthTarget * heightTarget;\n            const T xSource = (x + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n            const T ySource = (y + T(0.5f)) / T(rescaleFactor) - T(0.5f);\n            targetPtr[channel * targetArea + y*widthTarget+x] = bicubicInterpolate8Times(\n                sourcePtrShared, xSource, ySource, widthSource, heightSource, threadIdx.x, threadIdx.y);\n        }\n    }\n\n    template <typename T>\n    __global__ void resizeAndAddAndAverageKernel(\n        T* targetPtr, const int counter, const T* const scaleWidths, const T* const scaleHeights,\n        const int* const widthSources, const int* const heightSources, const int widthTarget, const int heightTarget,\n        const T* const sourcePtr0, const T* const sourcePtr1, const T* const sourcePtr2, const T* const sourcePtr3,\n        const T* const sourcePtr4, const T* const sourcePtr5, const T* const sourcePtr6, const T* const sourcePtr7)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n        // For each pixel\n        if (x < widthTarget && y < heightTarget)\n        {\n            // Local variable for higher speed\n            T interpolated = T(0.f);\n            // For each input source pointer\n            for (auto i = 0 ; i < counter ; ++i)\n            {\n                const auto sourceArea = widthSources[i] * heightSources[i];\n                const T xSource = (x + T(0.5f)) / scaleWidths[i] - T(0.5f);\n                const T ySource = (y + T(0.5f)) / scaleHeights[i] - T(0.5f);\n                const T* const sourcePtr = (\n                    i == 0 ? sourcePtr0 : i == 1 ? sourcePtr1 : i == 2 ? sourcePtr2 : i == 3 ? sourcePtr3\n                        : i == 4 ? sourcePtr4 : i == 5 ? sourcePtr5 : i == 6 ? sourcePtr6 : sourcePtr7);\n                const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n                interpolated += bicubicInterpolate(\n                    sourcePtrChannel, xSource, ySource, widthSources[i], heightSources[i], widthSources[i]);\n            }\n            // Save into memory\n            const auto targetArea = widthTarget * heightTarget;\n            targetPtr[channel * targetArea + y*widthTarget+x] = interpolated / T(counter);\n        }\n    }\n\n    // template <typename T>\n    // __global__ void resizeAndAddKernel(\n    //     T* targetPtr, const T* const sourcePtr, const T scaleWidth, const T scaleHeight, const int widthSource,\n    //     const int heightSource, const int widthTarget, const int heightTarget)\n    // {\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n    //     if (x < widthTarget && y < heightTarget)\n    //     {\n    //         const auto sourceArea = widthSource * heightSource;\n    //         const auto targetArea = widthTarget * heightTarget;\n    //         const T xSource = (x + T(0.5f)) * widthSource / T(widthTarget) - T(0.5f);\n    //         const T ySource = (y + T(0.5f)) * heightSource / T(heightTarget) - T(0.5f);\n    //         const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n    //         targetPtr[channel * targetArea + y*widthTarget+x] += bicubicInterpolate(\n    //             sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n    //     }\n    // }\n\n    // template <typename T>\n    // __global__ void resizeAndAverageKernel(\n    //     T* targetPtr, const T* const sourcePtr, const T scaleWidth, const T scaleHeight, const int widthSource,\n    //     const int heightSource, const int widthTarget, const int heightTarget, const int counter)\n    // {\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     const auto channel = (blockIdx.z * blockDim.z) + threadIdx.z;\n    //     if (x < widthTarget && y < heightTarget)\n    //     {\n    //         const auto sourceArea = widthSource * heightSource;\n    //         const auto targetArea = widthTarget * heightTarget;\n    //         const T xSource = (x + T(0.5f)) / scaleWidth - T(0.5f);\n    //         const T ySource = (y + T(0.5f)) / scaleHeight - T(0.5f);\n    //         const T* const sourcePtrChannel = sourcePtr + channel * sourceArea;\n    //         const auto interpolated = bicubicInterpolate(\n    //             sourcePtrChannel, xSource, ySource, widthSource, heightSource, widthSource);\n    //         auto& targetPixel = targetPtr[channel * targetArea + y*widthTarget+x];\n    //         targetPixel = (targetPixel + interpolated) / T(counter);\n    //     }\n    // }\n\n    // template <typename T>\n    // __global__ void resizeAndAddKernelOld(\n    //     T* targetPtr, const T* const sourcePtr, const T scaleWidth, const T scaleHeight, const int widthSource,\n    //     const int heightSource, const int widthTarget, const int heightTarget)\n    // {\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     if (x < widthTarget && y < heightTarget)\n    //     {\n    //         const T xSource = (x + T(0.5f)) / scaleWidth - T(0.5f);\n    //         const T ySource = (y + T(0.5f)) / scaleHeight - T(0.5f);\n    //         targetPtr[y*widthTarget+x] += bicubicInterpolate(\n    //             sourcePtr, xSource, ySource, widthSource, heightSource, widthSource);\n    //     }\n    // }\n\n    // template <typename T>\n    // __global__ void resizeAndAverageKernelOld(\n    //     T* targetPtr, const T* const sourcePtr, const T scaleWidth, const T scaleHeight, const int widthSource,\n    //     const int heightSource, const int widthTarget, const int heightTarget, const int counter)\n    // {\n    //     const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n    //     const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n    //     if (x < widthTarget && y < heightTarget)\n    //     {\n    //         const T xSource = (x + T(0.5f)) / scaleWidth - T(0.5f);\n    //         const T ySource = (y + T(0.5f)) / scaleHeight - T(0.5f);\n    //         const auto interpolated = bicubicInterpolate(\n    //             sourcePtr, xSource, ySource, widthSource, heightSource, widthSource);\n    //         auto& targetPixel = targetPtr[y*widthTarget+x];\n    //         targetPixel = (targetPixel + interpolated) / T(counter);\n    //     }\n    // }\n\n    template <typename T>\n    void resizeAndMergeGpu(\n        T* targetPtr, const std::vector<const T*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<T>& scaleInputToNetInputs)\n    {\n        try\n        {\n            // Sanity checks\n            if (sourceSizes.empty())\n                error(\"sourceSizes cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n            if (sourcePtrs.size() != sourceSizes.size() || sourceSizes.size() != scaleInputToNetInputs.size())\n                error(\"Size(sourcePtrs) must match size(sourceSizes) and size(scaleInputToNetInputs). Currently: \"\n                      + std::to_string(sourcePtrs.size()) + \" vs. \" + std::to_string(sourceSizes.size()) + \" vs. \"\n                      + std::to_string(scaleInputToNetInputs.size()) + \".\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Parameters\n            const auto channels = targetSize[1];\n            const auto heightTarget = targetSize[2];\n            const auto widthTarget = targetSize[3];\n            // const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D};\n            // const dim3 numBlocks{\n            //     getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n            //     getNumberCudaBlocks(heightTarget, threadsPerBlock.y)};\n            const auto& sourceSize = sourceSizes[0];\n            const auto heightSource = sourceSize[2];\n            const auto widthSource = sourceSize[3];\n\n            // No multi-scale merging or no merging required\n            if (sourceSizes.size() == 1)\n            {\n                const auto num = sourceSize[0];\n                if (targetSize[0] > 1 || num == 1)\n                {\n                    // // Profiling code\n                    // const auto REPS = 100;\n                    // double timeNormalize1 = 0.;\n                    // double timeNormalize2 = 0.;\n                    // double timeNormalize3 = 0.;\n                    // // Non-optimized function\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    // const auto sourceChannelOffset = heightSource * widthSource;\n                    // const auto targetChannelOffset = widthTarget * heightTarget;\n                    // for (auto n = 0; n < num; n++)\n                    // {\n                    //     const auto offsetBase = n*channels;\n                    //     for (auto c = 0 ; c < channels ; c++)\n                    //     {\n                    //         const auto offset = offsetBase + c;\n                    //         resizeKernelOld<<<numBlocks, threadsPerBlock>>>(\n                    //             targetPtr + offset * targetChannelOffset,\n                    //             sourcePtrs.at(0) + offset * sourceChannelOffset,\n                    //             widthSource, heightSource, widthTarget, heightTarget);\n                    //     }\n                    // }\n                    // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n                    // // Optimized function for any resize size (suboptimal for 8x resize)\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    // const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n                    // const dim3 numBlocks{\n                    //     getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                    //     getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                    //     getNumberCudaBlocks(num * channels, threadsPerBlock.z)};\n                    // resizeKernel<<<numBlocks, threadsPerBlock>>>(\n                    //     targetPtr, sourcePtrs.at(0), widthSource, heightSource, widthTarget, heightTarget);\n                    // OP_CUDA_PROFILE_END(timeNormalize2, 1e3, REPS);\n\n                    // Optimized function for 8x resize\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    if (widthTarget / widthSource == 1 && heightTarget / heightSource == 1)\n                    {\n                        const auto N = widthTarget * heightTarget * num * channels;\n                        const dim3 threadsPerBlock{THREADS_PER_BLOCK};\n                        const dim3 numBlocks{getNumberCudaBlocks(N, threadsPerBlock.x)};\n                        fillKernel<<<numBlocks, threadsPerBlock>>>(\n                            targetPtr, sourcePtrs.at(0), N);\n                    }\n                    else\n                    {\n                        if (widthTarget / widthSource != 8 || heightTarget / heightSource != 8)\n                            error(\"Kernel only implemented for 8x resize. Notify us if this error appears.\",\n                                __LINE__, __FUNCTION__, __FILE__);\n                        const auto rescaleFactor = (unsigned int) std::ceil(heightTarget / (float)(heightSource));\n                        const dim3 threadsPerBlock{rescaleFactor, rescaleFactor, 1};\n                        const dim3 numBlocks{\n                            getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                            getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                            getNumberCudaBlocks(num * channels, threadsPerBlock.z)};\n                        resize8TimesKernel<<<numBlocks, threadsPerBlock>>>(\n                            targetPtr, sourcePtrs.at(0), widthSource, heightSource, widthTarget, heightTarget,\n                            rescaleFactor);\n                    }\n                    // OP_CUDA_PROFILE_END(timeNormalize3, 1e3, REPS);\n\n                    // // Profiling code\n                    // opLog(\"  Res(ori)=\" + std::to_string(timeNormalize1) + \"ms\");\n                    // opLog(\"  Res(new)=\" + std::to_string(timeNormalize2) + \"ms\");\n                    // opLog(\"  Res(new8x)=\" + std::to_string(timeNormalize3) + \"ms\");\n                }\n                // Old inefficient multi-scale merging\n                else\n                    error(\"It should never reache this point. Notify us otherwise.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Multi-scaling merging\n            else\n            {\n                const auto scaleToMainScaleWidth = widthTarget / T(widthSource);\n                const auto scaleToMainScaleHeight = heightTarget / T(heightSource);\n\n                // // Profiling code\n                // const auto REPS = 10;\n                // // const auto REPS = 100;\n                // double timeNormalize1 = 0.;\n                // double timeNormalize2 = 0.;\n                // double timeNormalize3 = 0.;\n                // // Non-optimized function\n                // OP_CUDA_PROFILE_INIT(REPS);\n                // const auto targetChannelOffset = widthTarget * heightTarget;\n                // cudaMemset(targetPtr, 0, channels*targetChannelOffset * sizeof(T));\n                // for (auto i = 0u ; i < sourceSizes.size(); ++i)\n                // {\n                //     const auto& currentSize = sourceSizes.at(i);\n                //     const auto currentHeight = currentSize[2];\n                //     const auto currentWidth = currentSize[3];\n                //     const auto sourceChannelOffset = currentHeight * currentWidth;\n                //     const auto scaleInputToNet = scaleInputToNetInputs[i] / scaleInputToNetInputs[0];\n                //     const auto scaleWidth = scaleToMainScaleWidth / scaleInputToNet;\n                //     const auto scaleHeight = scaleToMainScaleHeight / scaleInputToNet;\n                //     // All but last image --> add\n                //     if (i < sourceSizes.size() - 1)\n                //     {\n                //         for (auto c = 0 ; c < channels ; c++)\n                //         {\n                //             resizeAndAddKernelOld<<<numBlocks, threadsPerBlock>>>(\n                //                 targetPtr + c * targetChannelOffset, sourcePtrs[i] + c * sourceChannelOffset,\n                //                 scaleWidth, scaleHeight, currentWidth, currentHeight, widthTarget,\n                //                 heightTarget);\n                //         }\n                //     }\n                //     // Last image --> average all\n                //     else\n                //     {\n                //         for (auto c = 0 ; c < channels ; c++)\n                //         {\n                //             resizeAndAverageKernelOld<<<numBlocks, threadsPerBlock>>>(\n                //                 targetPtr + c * targetChannelOffset, sourcePtrs[i] + c * sourceChannelOffset,\n                //                 scaleWidth, scaleHeight, currentWidth, currentHeight, widthTarget,\n                //                 heightTarget, (int)sourceSizes.size());\n                //         }\n                //     }\n                // }\n                // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n                // // Optimized function for any resize size (suboptimal for 8x resize)\n                // OP_CUDA_PROFILE_INIT(REPS);\n                // const auto targetChannelOffset = widthTarget * heightTarget;\n                // cudaMemset(targetPtr, 0, channels*targetChannelOffset * sizeof(T));\n                // const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n                // const dim3 numBlocks{\n                //     getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                //     getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                //     getNumberCudaBlocks(channels, threadsPerBlock.z)};\n                // for (auto i = 0u ; i < sourceSizes.size(); ++i)\n                // {\n                //     const auto& currentSize = sourceSizes.at(i);\n                //     const auto currentHeight = currentSize[2];\n                //     const auto currentWidth = currentSize[3];\n                //     const auto scaleInputToNet = scaleInputToNetInputs[i] / scaleInputToNetInputs[0];\n                //     const auto scaleWidth = scaleToMainScaleWidth / scaleInputToNet;\n                //     const auto scaleHeight = scaleToMainScaleHeight / scaleInputToNet;\n                //     // All but last image --> add\n                //     if (i < sourceSizes.size() - 1)\n                //         resizeAndAddKernel<<<numBlocks, threadsPerBlock>>>(\n                //             targetPtr, sourcePtrs[i], scaleWidth, scaleHeight, currentWidth, currentHeight,\n                //             widthTarget, heightTarget);\n                //     // Last image --> average all\n                //     else\n                //         resizeAndAverageKernelOld<<<numBlocks, threadsPerBlock>>>(\n                //             targetPtr, sourcePtrs[i], scaleWidth, scaleHeight, currentWidth, currentHeight,\n                //             widthTarget, heightTarget, (int)sourceSizes.size());\n                // }\n                // OP_CUDA_PROFILE_END(timeNormalize2, 1e3, REPS);\n\n                // Super optimized function\n                // OP_CUDA_PROFILE_INIT(REPS);\n                if (sourcePtrs.size() > 8)\n                    error(\"More than 8 scales are not implemented (yet). Notify us to implement it.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n                const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n                const dim3 numBlocks{\n                    getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                    getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                    getNumberCudaBlocks(channels, threadsPerBlock.z)};\n                // Fill auxiliary params\n                std::vector<int> widthSourcesCpu(sourceSizes.size());\n                std::vector<int> heightSourcesCpu(sourceSizes.size());\n                std::vector<T> scaleWidthsCpu(sourceSizes.size());\n                std::vector<T> scaleHeightsCpu(sourceSizes.size());\n                for (auto i = 0u ; i < sourceSizes.size(); ++i)\n                {\n                    const auto& currentSize = sourceSizes.at(i);\n                    heightSourcesCpu[i] = currentSize[2];\n                    widthSourcesCpu[i] = currentSize[3];\n                    const auto scaleInputToNet = scaleInputToNetInputs[i] / scaleInputToNetInputs[0];\n                    scaleWidthsCpu[i] = scaleToMainScaleWidth / scaleInputToNet;\n                    scaleHeightsCpu[i] = scaleToMainScaleHeight / scaleInputToNet;\n                }\n                // GPU params\n                int* widthSources;\n                cudaMalloc((void**)&widthSources, sizeof(int) * sourceSizes.size());\n                cudaMemcpy(\n                    widthSources, widthSourcesCpu.data(), sizeof(int) * sourceSizes.size(),\n                    cudaMemcpyHostToDevice);\n                int* heightSources;\n                cudaMalloc((void**)&heightSources, sizeof(int) * sourceSizes.size());\n                cudaMemcpy(\n                    heightSources, heightSourcesCpu.data(), sizeof(int) * sourceSizes.size(),\n                    cudaMemcpyHostToDevice);\n                T* scaleWidths;\n                cudaMalloc((void**)&scaleWidths, sizeof(T) * sourceSizes.size());\n                cudaMemcpy(\n                    scaleWidths, scaleWidthsCpu.data(), sizeof(T) * sourceSizes.size(),\n                    cudaMemcpyHostToDevice);\n                T* scaleHeights;\n                cudaMalloc((void**)&scaleHeights, sizeof(T) * sourceSizes.size());\n                cudaMemcpy(\n                    scaleHeights, scaleHeightsCpu.data(), sizeof(T) * sourceSizes.size(),\n                    cudaMemcpyHostToDevice);\n                // Resize each channel, add all, and get average\n                resizeAndAddAndAverageKernel<<<numBlocks, threadsPerBlock>>>(\n                    targetPtr, (int)sourceSizes.size(), scaleWidths, scaleHeights, widthSources, heightSources,\n                    widthTarget, heightTarget, sourcePtrs[0], sourcePtrs[1], sourcePtrs[2], sourcePtrs[3],\n                    sourcePtrs[4], sourcePtrs[5], sourcePtrs[6], sourcePtrs[7]);\n                // Free memory\n                if (widthSources != nullptr)\n                    cudaFree(widthSources);\n                if (heightSources != nullptr)\n                    cudaFree(heightSources);\n                if (scaleWidths != nullptr)\n                    cudaFree(scaleWidths);\n                if (scaleHeights != nullptr)\n                    cudaFree(scaleHeights);\n                // OP_CUDA_PROFILE_END(timeNormalize3, 1e3, REPS);\n\n                // // Profiling code\n                // opLog(\"  Res(orig)=\" + std::to_string(timeNormalize1) + \"ms\");\n                // opLog(\"  Res(new4)=\" + std::to_string(timeNormalize2) + \"ms\");\n                // opLog(\"  Res(new1)=\" + std::to_string(timeNormalize3) + \"ms\");\n            }\n\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void resizeAndPadRbgGpu(\n        T* targetPtr, const T* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const T scaleFactor)\n    {\n        try\n        {\n            const auto channels = 3;\n            const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n            const dim3 numBlocks{\n                getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                getNumberCudaBlocks(channels, threadsPerBlock.z)};\n            resizeAndPadKernel<<<numBlocks, threadsPerBlock>>>(\n                targetPtr, srcPtr, widthSource, heightSource, widthTarget, heightTarget, scaleFactor);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void resizeAndPadRbgGpu(\n        T* targetPtr, const unsigned char* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const T scaleFactor)\n\n    {\n        try\n        {\n            const auto channels = 3;\n            const dim3 threadsPerBlock{THREADS_PER_BLOCK_1D, THREADS_PER_BLOCK_1D, 1};\n            const dim3 numBlocks{\n                getNumberCudaBlocks(widthTarget, threadsPerBlock.x),\n                getNumberCudaBlocks(heightTarget, threadsPerBlock.y),\n                getNumberCudaBlocks(channels, threadsPerBlock.z)};\n            resizeAndPadKernel<<<numBlocks, threadsPerBlock>>>(\n                targetPtr, srcPtr, widthSource, heightSource, widthTarget, heightTarget, scaleFactor);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void resizeAndMergeGpu(\n        float* targetPtr, const std::vector<const float*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<float>& scaleInputToNetInputs);\n    template void resizeAndMergeGpu(\n        double* targetPtr, const std::vector<const double*>& sourcePtrs, const std::array<int, 4>& targetSize,\n        const std::vector<std::array<int, 4>>& sourceSizes, const std::vector<double>& scaleInputToNetInputs);\n\n    template void resizeAndPadRbgGpu(\n        float* targetPtr, const float* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const float scaleFactor);\n    template void resizeAndPadRbgGpu(\n        double* targetPtr, const double* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const double scaleFactor);\n\n    template void resizeAndPadRbgGpu(\n        float* targetPtr, const unsigned char* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const float scaleFactor);\n    template void resizeAndPadRbgGpu(\n        double* targetPtr, const unsigned char* const srcPtr, const int widthSource, const int heightSource,\n        const int widthTarget, const int heightTarget, const double scaleFactor);\n}\n"
  },
  {
    "path": "src/openpose/net/resizeAndMergeBaseCL.cpp",
    "content": "#include <openpose/net/resizeAndMergeBase.hpp>\n#include <iostream>\n#include <openpose/core/common.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    #ifdef USE_OPENCL\n        const std::string resizeAndMergeOclCommonFunctions = MULTI_LINE_STRING(\n            // Max/min functions\n            int fastMax(int a, int b)\n            {\n                return (a > b ? a : b);\n            }\n\n            int fastMin(int a, int b)\n            {\n                return (a < b ? a : b);\n            }\n\n            int fastTruncate(int value, int min, int max)\n            {\n                return fastMin(max, fastMax(min, value));\n            }\n\n            void cubicSequentialData(int* xIntArray, int* yIntArray, Type* dx, Type* dy, const Type xSource,\n                                     const Type ySource, const int width, const int height)\n            {\n                xIntArray[1] = fastTruncate((int)(xSource + 1e-5), 0, width - 1);\n                xIntArray[0] = fastMax(0, xIntArray[1] - 1);\n                xIntArray[2] = fastMin(width - 1, xIntArray[1] + 1);\n                xIntArray[3] = fastMin(width - 1, xIntArray[2] + 1);\n                *dx = xSource - xIntArray[1];\n\n                yIntArray[1] = fastTruncate((int)(ySource + 1e-5), 0, height - 1);\n                yIntArray[0] = fastMax(0, yIntArray[1] - 1);\n                yIntArray[2] = fastMin(height - 1, yIntArray[1] + 1);\n                yIntArray[3] = fastMin(height - 1, yIntArray[2] + 1);\n                *dy = ySource - yIntArray[1];\n            }\n\n            Type cubicInterpolate(const Type v0, const Type v1, const Type v2, const Type v3, const Type dx)\n            {\n                // http://www.paulinternet.nl/?page=bicubic\n                // const auto a = (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3);\n                // const auto b = (v0 - 2.5f * v1 + 2.0 * v2 - 0.5 * v3);\n                // const auto c = (-0.5f * v0 + 0.5f * v2);\n                // out = ((a * dx + b) * dx + c) * dx + v1;\n                return (-0.5f * v0 + 1.5f * v1 - 1.5f * v2 + 0.5f * v3) * dx * dx * dx\n                        + (v0 - 2.5f * v1 + 2.f * v2 - 0.5f * v3) * dx * dx\n                        - 0.5f * (v0 - v2) * dx // + (-0.5f * v0 + 0.5f * v2) * dx\n                        + v1;\n                // return v1 + 0.5f * dx * (v2 - v0 + dx * (2.f * v0 - 5.f * v1 + 4.f * v2 - v3 + dx * (3.f * (v1 - v2) + v3 - v0)));\n            }\n\n            Type bicubicInterpolate(__global const Type* sourcePtr, const Type xSource, const Type ySource,\n                                    const int widthSource, const int heightSource, const int widthSourcePtr)\n            {\n                int xIntArray[4];\n                int yIntArray[4];\n                Type dx;\n                Type dy;\n                cubicSequentialData(xIntArray, yIntArray, &dx, &dy, xSource, ySource, widthSource, heightSource);\n\n                Type temp[4];\n                for (unsigned char i = 0; i < 4; i++)\n                {\n                    const int offset = yIntArray[i]*widthSourcePtr;\n                    temp[i] = cubicInterpolate(sourcePtr[offset + xIntArray[0]], sourcePtr[offset + xIntArray[1]],\n                                               sourcePtr[offset + xIntArray[2]], sourcePtr[offset + xIntArray[3]], dx);\n                }\n                return cubicInterpolate(temp[0], temp[1], temp[2], temp[3], dy);\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, int, int, int, int> ResizeAndMergeFullFunctor;\n        const std::string resizeAndMergeFullKernel = MULTI_LINE_STRING(\n            __kernel void resizeAndMergeFullKernel(__global Type* targetPtr, __global const Type* sourcePtr,\n                                               const int sourceWidth, const int sourceHeight,\n                                               const int targetWidth, const int targetHeight)\n            {\n                int c = get_global_id(0);\n                int y = get_global_id(1);\n                int x = get_global_id(2);\n\n                __global Type* targetPtrC = &targetPtr[c*targetWidth*targetHeight];\n                const __global Type* sourcePtrC = &sourcePtr[c*sourceWidth*sourceHeight];\n\n                if (x < targetWidth && y < targetHeight)\n                {\n                    const Type xSource = (x + 0.5f) * sourceWidth / (Type)targetWidth - 0.5f;\n                    const Type ySource = (y + 0.5f) * sourceHeight / (Type)targetHeight - 0.5f;\n                    targetPtrC[y*targetWidth+x] = bicubicInterpolate(sourcePtrC, xSource, ySource, sourceWidth,\n                            sourceHeight, sourceWidth);\n                }\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, int, int, int, int, int, int> ResizeAndMergeFunctor;\n        const std::string resizeAndMergeKernel = MULTI_LINE_STRING(\n            __kernel void resizeAndMergeKernel(__global Type* targetPtr, __global const Type* sourcePtr,\n                                               const int sourceWidth, const int sourceHeight,\n                                               const int targetWidth, const int targetHeight,\n                                               const int widthPadding, const int heightPadding)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n\n                if (x < targetWidth && y < targetHeight)\n                {\n                    const Type xSource = (x + 0.5f) * (sourceWidth-widthPadding) / (Type)targetWidth - 0.5f;\n                    const Type ySource = (y + 0.5f) * (sourceHeight-heightPadding) / (Type)targetHeight - 0.5f;\n                    targetPtr[y*targetWidth+x] = bicubicInterpolate(sourcePtr, xSource, ySource, sourceWidth,\n                            sourceHeight, sourceWidth);\n                }\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, float, float, int, int, int, int, int, int> ResizeAndAddFunctor;\n        const std::string resizeAndAddKernel = MULTI_LINE_STRING(\n            __kernel void resizeAndAddKernel(__global Type* targetPtr, __global const Type* sourcePtr,\n                                               const Type scaleWidth, const Type scaleHeight,\n                                               const int sourceWidth, const int sourceHeight,\n                                               const int targetWidth, const int targetHeight,\n                                               const int widthPadding, const int heightPadding)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n\n                if (x < targetWidth && y < targetHeight)\n                {\n                    const Type xSource = (x + 0.5f) / scaleWidth - 0.5f;\n                    const Type ySource = (y + 0.5f) / scaleHeight - 0.5f;\n                    targetPtr[y*targetWidth+x] += bicubicInterpolate(sourcePtr, xSource, ySource, sourceWidth,\n                            sourceHeight, sourceWidth);\n                }\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, float, float, int, int, int, int, int, int, int> ResizeAndAverageFunctor;\n        const std::string resizeAndAverageKernel = MULTI_LINE_STRING(\n            __kernel void resizeAndAverageKernel(__global Type* targetPtr, __global const Type* sourcePtr,\n                                               const Type scaleWidth, const Type scaleHeight,\n                                               const int sourceWidth, const int sourceHeight,\n                                               const int targetWidth, const int targetHeight,\n                                               const int widthPadding, const int heightPadding,\n                                               const int counter)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n\n                if (x < targetWidth && y < targetHeight)\n                {\n                    const Type xSource = (x + 0.5f) / scaleWidth - 0.5f;\n                    const Type ySource = (y + 0.5f) / scaleHeight - 0.5f;\n                    Type interpolated = bicubicInterpolate(sourcePtr, xSource, ySource, sourceWidth, sourceHeight, sourceWidth);\n                    __global Type* targetPixel = &targetPtr[y*targetWidth+x];\n                    *targetPixel = (*targetPixel + interpolated) / (Type)(counter);\n                }\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, int, int> ZeroBufferFunctor;\n        const std::string zeroBufferKernel = MULTI_LINE_STRING(\n            __kernel void zeroBufferKernel(__global Type* targetPtr, const int targetWidth, const int targetHeight)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n                int c = get_global_id(2);\n\n                __global Type* targetPtrC = &targetPtr[c*targetWidth*targetHeight];\n                targetPtrC[y*targetWidth+x] = 0;\n            }\n        );\n\n        typedef cl::KernelFunctor<cl::Buffer, cl::Buffer, int, int, int, int> CopyBufferFunctor;\n        const std::string copyBufferKernel = MULTI_LINE_STRING(\n            __kernel void copyBufferKernel(__global Type* targetPtr, __global const Type* sourcePtr,\n                                           const int sourceWidth, const int sourceHeight,\n                                           const int targetWidth, const int targetHeight)\n            {\n                int x = get_global_id(0);\n                int y = get_global_id(1);\n                int c = get_global_id(2);\n\n                __global Type* targetPtrC = &targetPtr[c*targetWidth*targetHeight];\n                __global const Type* sourcePtrC = &sourcePtr[c*sourceWidth*sourceHeight];\n\n                if(x < sourceWidth && y < sourceHeight)\n                    targetPtrC[y*targetWidth+x] = sourcePtrC[y*sourceWidth+x];\n                else\n                    targetPtrC[y*targetWidth+x] = 0;\n            }\n        );\n    #endif\n\n    int roundUps(int numToRound, int multiple)\n    {\n        if (multiple == 0)\n            return numToRound;\n\n        int remainder = numToRound % multiple;\n        if (remainder == 0)\n            return numToRound;\n\n        return numToRound + multiple - remainder;\n    }\n\n    template <typename T>\n    void resizeAndMergeOcl(T* targetPtr, const std::vector<const T*>& sourcePtrs,\n                           std::vector<T*>& sourceTempPtrs,\n                           const std::array<int, 4>& targetSize,\n                           const std::vector<std::array<int, 4>>& sourceSizes,\n                           const std::vector<T>& scaleInputToNetInputs,\n                           const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_OPENCL\n                // Sanity checks\n                if (sourceSizes.empty())\n                    error(\"sourceSizes cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n                if (sourcePtrs.size() != sourceSizes.size() || sourceSizes.size() != scaleInputToNetInputs.size())\n                    error(\"Size(sourcePtrs) must match size(sourceSizes) and size(scaleInputToNetInputs). Currently: \"\n                          + std::to_string(sourcePtrs.size()) + \" vs. \" + std::to_string(sourceSizes.size()) + \" vs. \"\n                          + std::to_string(scaleInputToNetInputs.size()) + \".\", __LINE__, __FUNCTION__, __FILE__);\n\n                // Get Kernels\n                cl::Buffer targetPtrBuffer = cl::Buffer((cl_mem)(targetPtr), true);\n                auto resizeAndMergeFullKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::ResizeAndMergeFullFunctor, T>(\n                            \"resizeAndMergeFullKernel\",\n                            op::resizeAndMergeOclCommonFunctions+op::resizeAndMergeFullKernel);\n                auto resizeAndMergeKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::ResizeAndMergeFunctor, T>(\n                            \"resizeAndMergeKernel\",op::resizeAndMergeOclCommonFunctions+op::resizeAndMergeKernel);\n                auto resizeAndAddKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::ResizeAndAddFunctor, T>(\n                            \"resizeAndAddKernel\",op::resizeAndMergeOclCommonFunctions+op::resizeAndAddKernel);\n                auto resizeAndAverageKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::ResizeAndAverageFunctor, T>(\n                            \"resizeAndAverageKernel\",op::resizeAndMergeOclCommonFunctions+op::resizeAndAverageKernel);\n                auto zeroBufferKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::ZeroBufferFunctor, T>(\n                            \"zeroBufferKernel\",op::zeroBufferKernel);\n                auto copyBufferKernel = op::OpenCL::getInstance(gpuID)->getKernelFunctorFromManager\n                        <op::CopyBufferFunctor, T>(\n                            \"copyBufferKernel\",op::copyBufferKernel);\n\n                // Parameters\n                const auto channels = targetSize[1];\n                const auto targetHeight = targetSize[2];\n                const auto targetWidth = targetSize[3];\n                const auto& sourceSize = sourceSizes[0];\n                const auto sourceHeight = sourceSize[2];\n                const auto sourceWidth = sourceSize[3];\n                //int gpuAlign = (op::OpenCL::getInstance(gpuID)->getAlignment() / 8) / sizeof(T);\n\n                // No multi-scale merging or no merging required\n                if (sourceSizes.size() == 1)\n                {\n                    const auto num = sourceSize[0];\n                    if (targetSize[0] > 1 || num == 1)\n                    {\n                        cl::Buffer sourcePtrBuffer = cl::Buffer((cl_mem)(sourcePtrs.at(0)), true);\n                        const auto sourceChannelOffset = sourceHeight * sourceWidth;\n                        const auto sourceWidthIdeal = roundUps(sourceWidth, 16);\n                        const auto sourceHeightIdeal = roundUps(sourceHeight, 16);\n                        const auto sourceChannelOffsetIdeal = sourceHeightIdeal * sourceWidthIdeal;\n                        const auto targetChannelOffset = targetWidth * targetHeight;\n                        for (auto n = 0; n < num; n++)\n                        {\n                            // Allocate memory on GPU once\n                            if(sourceTempPtrs[0] == nullptr){\n                                cl::Buffer* sourcePtrBufferIdealX = new cl::Buffer(\n                                    op::OpenCL::getInstance(gpuID)->getContext(), CL_MEM_READ_WRITE,\n                                    sizeof(float) * channels * sourceWidthIdeal * sourceHeightIdeal);\n                                sourceTempPtrs[0] = (T*)sourcePtrBufferIdealX->get();\n                            }\n                            cl::Buffer sourcePtrBufferIdeal = cl::Buffer((cl_mem)(sourceTempPtrs[0]), true);\n\n                            // Copy to Buffer\n                            copyBufferKernel(cl::EnqueueArgs(op::OpenCL::getInstance(gpuID)->getQueue(),\n                                                 cl::NDRange(sourceWidthIdeal, sourceHeightIdeal, channels)),\n                                                 sourcePtrBufferIdeal, sourcePtrBuffer,\n                                                 sourceWidth, sourceHeight, sourceWidthIdeal, sourceHeightIdeal);\n\n                            const auto offsetBase = n*channels;\n                            for (auto c = 0 ; c < channels ; c++)\n                            {\n                                const auto offset = offsetBase + c;\n                                cl_buffer_region targerRegion, sourceRegion;\n                                OpenCL::getBufferRegion<T>(\n                                    targerRegion, offset * targetChannelOffset, targetChannelOffset);\n                                cl::Buffer targetBuffer = targetPtrBuffer.createSubBuffer(\n                                    CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &targerRegion);\n                                op::OpenCL::getBufferRegion<T>(\n                                    sourceRegion, offset * sourceChannelOffsetIdeal, sourceChannelOffsetIdeal);\n                                cl::Buffer sourceBuffer = sourcePtrBufferIdeal.createSubBuffer(\n                                    CL_MEM_READ_ONLY, CL_BUFFER_CREATE_TYPE_REGION, &sourceRegion);\n                                resizeAndMergeKernel(cl::EnqueueArgs(op::OpenCL::getInstance(gpuID)->getQueue(),\n                                                     cl::NDRange(targetWidth, targetHeight)),\n                                                     targetBuffer, sourceBuffer,\n                                                     sourceWidthIdeal, sourceHeightIdeal, targetWidth, targetHeight,\n                                                     (sourceWidthIdeal-sourceWidth), (sourceHeightIdeal-sourceHeight));\n                            }\n                        }\n                    }\n                    // Old inefficient multi-scale merging\n                    else\n                        error(\"It should never reache this point. Notify us otherwise.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Multi-scaling merging\n                else\n                {\n                    const auto targetChannelOffset = targetWidth * targetHeight;\n                    //cudaMemset(targetPtr, 0.f, channels*targetChannelOffset * sizeof(T));\n                    zeroBufferKernel(cl::EnqueueArgs(OpenCL::getInstance(gpuID)->getQueue(),\n                                                     cl::NDRange(targetWidth, targetHeight, channels)),\n                                                     targetPtrBuffer, targetWidth, targetHeight);\n                    const auto scaleToMainScaleWidth = targetWidth / T(sourceWidth);\n                    const auto scaleToMainScaleHeight = targetHeight / T(sourceHeight);\n\n                    for (auto i = 0u ; i < sourceSizes.size(); i++)\n                    {\n                        const auto& currentSize = sourceSizes.at(i);\n                        const auto currentHeight = currentSize[2];\n                        const auto currentWidth = currentSize[3];\n                        const auto sourceChannelOffset = currentHeight * currentWidth;\n                        const auto scaleInputToNet = scaleInputToNetInputs[i] / scaleInputToNetInputs[0];\n                        const auto scaleWidth = scaleToMainScaleWidth / scaleInputToNet;\n                        const auto scaleHeight = scaleToMainScaleHeight / scaleInputToNet;\n                        cl::Buffer sourcePtrBuffer = cl::Buffer((cl_mem)(sourcePtrs.at(i)), true);\n\n                        const auto currentHeightIdeal = roundUps(currentHeight, 16);\n                        const auto currentWidthIdeal = roundUps(currentWidth, 16);\n                        const auto sourceChannelOffsetIdeal = currentHeightIdeal * currentWidthIdeal;\n\n                        // Allocate memory on GPU once\n                        if(sourceTempPtrs[i] == nullptr){\n                            cl::Buffer* sourcePtrBufferIdealX = new cl::Buffer(\n                                op::OpenCL::getInstance(gpuID)->getContext(), CL_MEM_READ_WRITE,\n                                sizeof(float) * channels * currentWidthIdeal * currentHeightIdeal);\n                            sourceTempPtrs[i] = (T*)sourcePtrBufferIdealX->get();\n                        }\n                        cl::Buffer sourcePtrBufferIdeal = cl::Buffer((cl_mem)(sourceTempPtrs[i]), true);\n\n                        // Copy to Buffer\n                        copyBufferKernel(cl::EnqueueArgs(op::OpenCL::getInstance(gpuID)->getQueue(),\n                                             cl::NDRange(currentWidthIdeal, currentHeightIdeal, channels)),\n                                             sourcePtrBufferIdeal, sourcePtrBuffer,\n                                             currentWidth, currentHeight, currentWidthIdeal, currentHeightIdeal);\n\n                        // All but last image --> add\n                        if (i < sourceSizes.size() - 1)\n                        {\n                            for (auto c = 0 ; c < channels ; c++)\n                            {\n                                cl_buffer_region targerRegion, sourceRegion;\n                                op::OpenCL::getBufferRegion<T>(\n                                    targerRegion, c * targetChannelOffset, targetChannelOffset);\n                                op::OpenCL::getBufferRegion<T>(\n                                    sourceRegion, c * sourceChannelOffsetIdeal, sourceChannelOffsetIdeal);\n                                cl::Buffer targetBuffer = targetPtrBuffer.createSubBuffer(\n                                    CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &targerRegion);\n                                cl::Buffer sourceBuffer = sourcePtrBufferIdeal.createSubBuffer(\n                                    CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &sourceRegion);\n                                resizeAndAddKernel(cl::EnqueueArgs(\n                                    OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(targetWidth, targetHeight)),\n                                    targetBuffer, sourceBuffer, scaleWidth, scaleHeight, currentWidthIdeal,\n                                    currentHeightIdeal, targetWidth, targetHeight, (currentWidthIdeal-currentWidth),\n                                    (currentHeightIdeal-currentHeight));\n                            }\n                        }\n                        // Last image --> average all\n                        else\n                        {\n                            for (auto c = 0 ; c < channels ; c++)\n                            {\n                                cl_buffer_region targerRegion, sourceRegion;\n                                op::OpenCL::getBufferRegion<T>(\n                                    targerRegion, c * targetChannelOffset, targetChannelOffset);\n                                op::OpenCL::getBufferRegion<T>(\n                                    sourceRegion, c * sourceChannelOffsetIdeal, sourceChannelOffsetIdeal);\n                                cl::Buffer targetBuffer = targetPtrBuffer.createSubBuffer(\n                                    CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &targerRegion);\n                                cl::Buffer sourceBuffer = sourcePtrBufferIdeal.createSubBuffer(\n                                    CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, &sourceRegion);\n                                resizeAndAverageKernel(cl::EnqueueArgs(\n                                    OpenCL::getInstance(gpuID)->getQueue(), cl::NDRange(targetWidth, targetHeight)),\n                                    targetBuffer, sourceBuffer, scaleWidth, scaleHeight, currentWidthIdeal,\n                                    currentHeightIdeal, targetWidth, targetHeight, (currentWidthIdeal-currentWidth),\n                                    (currentHeightIdeal-currentHeight), (int)sourceSizes.size());\n                            }\n                        }\n                    }\n                }\n            #else\n                UNUSED(targetPtr);\n                UNUSED(sourcePtrs);\n                UNUSED(targetSize);\n                UNUSED(sourceSizes);\n                UNUSED(scaleInputToNetInputs);\n                UNUSED(gpuID);\n                UNUSED(sourceTempPtrs);\n                error(\"OpenPose must be compiled with the `USE_OPENCL` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        #if defined(USE_OPENCL) && defined(CL_HPP_ENABLE_EXCEPTIONS)\n        catch (const cl::Error& e)\n        {\n            error(std::string(e.what()) + \" : \" + OpenCL::clErrorToString(e.err()) + \" ID: \" +\n                  std::to_string(gpuID), __LINE__, __FUNCTION__, __FILE__);\n        }\n        #endif\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template void resizeAndMergeOcl(\n        float* targetPtr, const std::vector<const float*>& sourcePtrs, std::vector<float*>& sourceTempPtrs,\n        const std::array<int, 4>& targetSize, const std::vector<std::array<int, 4>>& sourceSizes,\n        const std::vector<float>& scaleInputToNetInputs, const int gpuID);\n\n    template void resizeAndMergeOcl(\n        double* targetPtr, const std::vector<const double*>& sourcePtrs, std::vector<double*>& sourceTempPtrs,\n        const std::array<int, 4>& targetSize, const std::vector<std::array<int, 4>>& sourceSizes,\n        const std::vector<double>& scaleInputToNetInputs, const int gpuID);\n}\n"
  },
  {
    "path": "src/openpose/net/resizeAndMergeCaffe.cpp",
    "content": "#include <openpose/net/resizeAndMergeCaffe.hpp>\n#ifdef USE_CAFFE\n    #include <caffe/blob.hpp>\n#endif\n#include <openpose/net/resizeAndMergeBase.hpp>\n#ifdef USE_OPENCL\n    #include <openpose_private/gpu/opencl.hcl>\n    #include <openpose_private/gpu/cl2.hpp>\n#endif\n\nnamespace op\n{\n    template <typename T>\n    ResizeAndMergeCaffe<T>::ResizeAndMergeCaffe() :\n        mScaleRatios{T(1)}\n    {\n        try\n        {\n            #ifndef USE_CAFFE\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    ResizeAndMergeCaffe<T>::~ResizeAndMergeCaffe()\n    {\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::LayerSetUp(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                            const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (top.size() != 1)\n                    error(\"top.size() != 1.\", __LINE__, __FUNCTION__, __FILE__);\n                if (bottom.size() != 1)\n                    error(\"bottom.size() != 1.\", __LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Reshape(\n        const std::vector<ArrayCpuGpu<T>*>& bottom, const std::vector<ArrayCpuGpu<T>*>& top, const T netFactor,\n        const T scaleFactor, const bool mergeFirstDimension, const int gpuID)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Sanity checks\n                if (top.size() != 1)\n                    error(\"top.size() != 1.\", __LINE__, __FUNCTION__, __FILE__);\n                if (bottom.empty())\n                    error(\"bottom cannot be empty.\", __LINE__, __FUNCTION__, __FILE__);\n                // Data\n                auto* topBlob = top.at(0);\n                const auto* bottomBlob = bottom.at(0);\n                // Set top shape\n                auto topShape = bottomBlob->shape();\n                topShape[0] = (mergeFirstDimension ? 1 : bottomBlob->shape(0));\n                // -1 and later +1 to take into account that we are using 0-based index\n                // E.g., 100x100 image --> 200x200 --> 0-99 to 0-199 --> scale = 199/99 (not 2!)\n                // E.g., 101x101 image --> 201x201 --> scale = 2\n                // Test: pixel 0 --> 0, pixel 99 (ex 1) --> 199, pixel 100 (ex 2) --> 200\n                topShape[2] = (int)std::round((topShape[2]*netFactor - 1.f) * scaleFactor) + 1;\n                topShape[3] = (int)std::round((topShape[3]*netFactor - 1.f) * scaleFactor) + 1;\n                topBlob->Reshape(topShape);\n                // Array sizes\n                mTopSize = std::array<int, 4>{\n                    topBlob->shape(0), topBlob->shape(1), topBlob->shape(2), topBlob->shape(3)};\n                mBottomSizes.resize(bottom.size());\n                for (auto i = 0u ; i < mBottomSizes.size() ; i++)\n                    mBottomSizes[i] = std::array<int, 4>{\n                        bottom[i]->shape(0), bottom[i]->shape(1), bottom[i]->shape(2), bottom[i]->shape(3)};\n                #ifdef USE_OPENCL\n                    // GPU ID\n                    mGpuID = gpuID;\n                    mTempGPUData.resize(mBottomSizes.size(), nullptr);\n                #else\n                    UNUSED(gpuID);\n                #endif\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                UNUSED(netFactor);\n                UNUSED(scaleFactor);\n                UNUSED(mergeFirstDimension);\n                UNUSED(gpuID);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::setScaleRatios(const std::vector<T>& scaleRatios)\n    {\n        try\n        {\n            mScaleRatios = {scaleRatios};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Forward(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                         const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            // CUDA\n            #ifdef USE_CUDA\n                Forward_gpu(bottom, top);\n            // OpenCL\n            #elif defined USE_OPENCL\n                Forward_ocl(bottom, top);\n            // CPU\n            #else\n                Forward_cpu(bottom, top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Forward_cpu(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                             const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                std::vector<const T*> sourcePtrs(bottom.size());\n                for (auto i = 0u ; i < sourcePtrs.size() ; i++)\n                    sourcePtrs[i] = bottom[i]->cpu_data();\n                resizeAndMergeCpu(top.at(0)->mutable_cpu_data(), sourcePtrs, mTopSize, mBottomSizes,\n                                  mScaleRatios);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Forward_gpu(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                             const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_CUDA\n                std::vector<const T*> sourcePtrs(bottom.size());\n                for (auto i = 0u ; i < sourcePtrs.size() ; i++)\n                    sourcePtrs[i] = bottom[i]->gpu_data();\n                resizeAndMergeGpu(top.at(0)->mutable_gpu_data(), sourcePtrs, mTopSize, mBottomSizes,\n                                  mScaleRatios);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_CUDA` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Forward_ocl(const std::vector<ArrayCpuGpu<T>*>& bottom,\n                                             const std::vector<ArrayCpuGpu<T>*>& top)\n    {\n        try\n        {\n            #if defined USE_CAFFE && defined USE_OPENCL\n                std::vector<const T*> sourcePtrs(bottom.size());\n                for (auto i = 0u ; i < sourcePtrs.size() ; i++)\n                    sourcePtrs[i] = bottom[i]->gpu_data();\n                resizeAndMergeOcl(top.at(0)->mutable_gpu_data(), sourcePtrs, mTempGPUData, mTopSize, mBottomSizes,\n                                  mScaleRatios, mGpuID);\n            #else\n                UNUSED(bottom);\n                UNUSED(top);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` & `USE_OPENCL` macro definitions in order to run\"\n                      \" this functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Backward_cpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                              const std::vector<bool>& propagate_down,\n                                              const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    template <typename T>\n    void ResizeAndMergeCaffe<T>::Backward_gpu(const std::vector<ArrayCpuGpu<T>*>& top,\n                                              const std::vector<bool>& propagate_down,\n                                              const std::vector<ArrayCpuGpu<T>*>& bottom)\n    {\n        try\n        {\n            UNUSED(top);\n            UNUSED(propagate_down);\n            UNUSED(bottom);\n            #ifdef USE_CAFFE\n                NOT_IMPLEMENTED;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    COMPILE_TEMPLATE_FLOATING_TYPES_CLASS(ResizeAndMergeCaffe);\n}\n"
  },
  {
    "path": "src/openpose/pose/CMakeLists.txt",
    "content": "set(SOURCES_OP_POSE\n    defineTemplates.cpp\n    poseCpuRenderer.cpp\n    poseExtractor.cpp\n    poseExtractorCaffe.cpp\n    poseExtractorNet.cpp\n    poseGpuRenderer.cpp\n    poseParameters.cpp\n    poseParametersRender.cpp\n    poseRenderer.cpp\n    renderPose.cpp\n    renderPose.cu)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_POSE_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_POSE})\nset(SOURCES_OP_POSE_WITH_CP ${SOURCES_OP_POSE_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_POSE_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_pose ${SOURCES_OP_POSE})\n  else ()\n    add_library(openpose_pose ${SOURCES_OP_POSE})\n  endif ()\n\n  target_link_libraries(openpose_pose openpose_core)\n\n  if (BUILD_CAFFE)\n    add_dependencies(openpose_pose openpose)\n  endif (BUILD_CAFFE)\n\n  install(TARGETS openpose_pose\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/pose/defineTemplates.cpp",
    "content": "#include <openpose/pose/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WPoseExtractor);\n    DEFINE_TEMPLATE_DATUM(WPoseExtractorNet);\n    DEFINE_TEMPLATE_DATUM(WPoseRenderer);\n}\n"
  },
  {
    "path": "src/openpose/pose/poseCpuRenderer.cpp",
    "content": "#include <openpose/pose/poseCpuRenderer.hpp>\n#include <openpose/pose/renderPose.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    PoseCpuRenderer::PoseCpuRenderer(const PoseModel poseModel, const float renderThreshold,\n                                     const bool blendOriginalFrame, const float alphaKeypoint,\n                                     const float alphaHeatMap, const unsigned int elementToRender) :\n        Renderer{renderThreshold, alphaKeypoint, alphaHeatMap, blendOriginalFrame, elementToRender,\n                 getNumberElementsToRender(poseModel)}, // mNumberElementsToRender\n        PoseRenderer{poseModel}\n    {\n    }\n\n    PoseCpuRenderer::~PoseCpuRenderer()\n    {\n    }\n\n    std::pair<int, std::string> PoseCpuRenderer::renderPose(Array<float>& outputData,\n                                                            const Array<float>& poseKeypoints,\n                                                            const float scaleInputToOutput,\n                                                            const float scaleNetToOutput)\n    {\n        try\n        {\n            // Sanity check\n            if (outputData.empty())\n                error(\"Empty Array<float> outputData.\", __LINE__, __FUNCTION__, __FILE__);\n            // CPU rendering\n            const auto elementRendered = spElementToRender->load();\n            std::string elementRenderedName;\n            // Draw poseKeypoints\n            if (elementRendered == 0)\n            {\n                // Rescale keypoints to output size\n                auto poseKeypointsRescaled = poseKeypoints.clone();\n                scaleKeypoints(poseKeypointsRescaled, scaleInputToOutput);\n                // Render keypoints\n                renderPoseKeypointsCpu(outputData, poseKeypointsRescaled, mPoseModel, mRenderThreshold,\n                                       mBlendOriginalFrame);\n            }\n            // Draw heat maps / PAFs\n            else\n            {\n                UNUSED(scaleNetToOutput);\n                error(\"CPU rendering only available for drawing keypoints, no heat maps nor PAFs.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            }\n            // Return result\n            return std::make_pair(elementRendered, elementRenderedName);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(-1, \"\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseExtractor.cpp",
    "content": "#include <openpose/pose/poseExtractor.hpp>\n\nnamespace op\n{\n    const std::string errorMessage = \"Either person identification (`--identification`) must be enabled or\"\n                                     \" `--number_people_max 1` in order to run the person tracker (`--tracking`).\";\n\n    PoseExtractor::PoseExtractor(const std::shared_ptr<PoseExtractorNet>& poseExtractorNet,\n                                 const std::shared_ptr<KeepTopNPeople>& keepTopNPeople,\n                                 const std::shared_ptr<PersonIdExtractor>& personIdExtractor,\n                                 const std::shared_ptr<std::vector<std::shared_ptr<PersonTracker>>>& personTrackers,\n                                 const int numberPeopleMax, const int tracking) :\n        mNumberPeopleMax{numberPeopleMax},\n        mTracking{tracking},\n        spPoseExtractorNet{poseExtractorNet},\n        spKeepTopNPeople{keepTopNPeople},\n        spPersonIdExtractor{personIdExtractor},\n        spPersonTrackers{personTrackers}\n    {\n    }\n\n    PoseExtractor::~PoseExtractor()\n    {\n    }\n\n    void PoseExtractor::initializationOnThread()\n    {\n        try\n        {\n            spPoseExtractorNet->initializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractor::forwardPass(const std::vector<Array<float>>& inputNetData,\n                                    const Point<int>& inputDataSize,\n                                    const std::vector<double>& scaleInputToNetInputs,\n                                    const Array<float>& poseNetOutput,\n                                    const long long frameId)\n    {\n        try\n        {\n            if (mTracking < 1 || frameId % (mTracking+1) == 0)\n                spPoseExtractorNet->forwardPass(inputNetData, inputDataSize, scaleInputToNetInputs, poseNetOutput);\n            else\n                spPoseExtractorNet->clear();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Array<float> PoseExtractor::getHeatMapsCopy() const\n    {\n        try\n        {\n            return spPoseExtractorNet->getHeatMapsCopy();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    std::vector<std::vector<std::array<float, 3>>> PoseExtractor::getCandidatesCopy() const\n    {\n        try\n        {\n            return spPoseExtractorNet->getCandidatesCopy();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<std::vector<std::array<float,3>>>{};\n        }\n    }\n\n    Array<float> PoseExtractor::getPoseKeypoints() const\n    {\n        try\n        {\n            return spPoseExtractorNet->getPoseKeypoints();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    Array<float> PoseExtractor::getPoseScores() const\n    {\n        try\n        {\n            return spPoseExtractorNet->getPoseScores();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    float PoseExtractor::getScaleNetToOutput() const\n    {\n        try\n        {\n            return spPoseExtractorNet->getScaleNetToOutput();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void PoseExtractor::keepTopPeople(Array<float>& poseKeypoints, const Array<float>& poseScores) const\n    {\n        try\n        {\n            // Keep only top N people\n            if (spKeepTopNPeople)\n                poseKeypoints = spKeepTopNPeople->keepTopPeople(poseKeypoints, poseScores);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Array<long long> PoseExtractor::extractIds(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                               const unsigned long long imageViewIndex)\n    {\n        try\n        {\n            // Run person ID extractor\n            return (spPersonIdExtractor\n                ? spPersonIdExtractor->extractIds(poseKeypoints, cvMatInput, imageViewIndex)\n                : Array<long long>{poseKeypoints.getSize(0), -1});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<long long>{};\n        }\n    }\n\n    Array<long long> PoseExtractor::extractIdsLockThread(const Array<float>& poseKeypoints,\n                                                         const Matrix& cvMatInput,\n                                                         const unsigned long long imageViewIndex,\n                                                         const long long frameId)\n    {\n        try\n        {\n            // Run person ID extractor\n            return (spPersonIdExtractor\n                ? spPersonIdExtractor->extractIdsLockThread(poseKeypoints, cvMatInput, imageViewIndex, frameId)\n                : Array<long long>{poseKeypoints.getSize(0), -1});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<long long>{};\n        }\n    }\n\n    void PoseExtractor::track(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                              const Matrix& cvMatInput,\n                              const unsigned long long imageViewIndex)\n    {\n        try\n        {\n            if (!spPersonTrackers->empty())\n            {\n                // Resize if required\n                while (spPersonTrackers->size() <= imageViewIndex)\n                    spPersonTrackers->emplace_back(std::make_shared<PersonTracker>(\n                        (*spPersonTrackers)[0]->getMergeResults()));\n                // Sanity check\n                if (!poseKeypoints.empty() && poseIds.empty() && mNumberPeopleMax != 1)\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                // Reset poseIds if keypoints is empty\n                if (poseKeypoints.empty())\n                    poseIds.reset();\n                // Run person tracker\n                if (spPersonTrackers->at(imageViewIndex))\n                    (*spPersonTrackers)[imageViewIndex]->track(poseKeypoints, poseIds, cvMatInput);\n                // Run person tracker\n                (*spPersonTrackers)[imageViewIndex]->track(poseKeypoints, poseIds, cvMatInput);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractor::trackLockThread(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                                        const Matrix& cvMatInput,\n                                        const unsigned long long imageViewIndex, const long long frameId)\n    {\n        try\n        {\n            if (!spPersonTrackers->empty())\n            {\n                // Resize if required\n                while (spPersonTrackers->size() <= imageViewIndex)\n                    spPersonTrackers->emplace_back(std::make_shared<PersonTracker>(\n                        (*spPersonTrackers)[0]->getMergeResults()));\n                // Sanity check\n                if (!poseKeypoints.empty() && poseIds.empty() && mNumberPeopleMax != 1)\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                // Reset poseIds if keypoints is empty\n                if (poseKeypoints.empty())\n                    poseIds.reset();\n                // Run person tracker\n                if (spPersonTrackers->at(imageViewIndex))\n                    (*spPersonTrackers)[imageViewIndex]->trackLockThread(\n                        poseKeypoints, poseIds, cvMatInput, frameId);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseExtractorCaffe.cpp",
    "content": "#include <openpose/pose/poseExtractorCaffe.hpp>\n#include <limits> // std::numeric_limits\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose/utilities/standard.hpp>\n#include <openpose_private/utilities/openCvPrivate.hpp>\n\nnamespace op\n{\n    const bool TOP_DOWN_REFINEMENT = false; // Note: +5% acc 1 scale, -2% max acc setting\n\n    #ifdef USE_CAFFE\n        std::vector<ArrayCpuGpu<float>*> arraySharedToPtr(\n            const std::vector<std::shared_ptr<ArrayCpuGpu<float>>>& caffeNetOutputBlob)\n        {\n            try\n            {\n                // Prepare spCaffeNetOutputBlobss\n                std::vector<ArrayCpuGpu<float>*> caffeNetOutputBlobs(caffeNetOutputBlob.size());\n                for (auto i = 0u ; i < caffeNetOutputBlobs.size() ; i++)\n                    caffeNetOutputBlobs[i] = caffeNetOutputBlob[i].get();\n                return caffeNetOutputBlobs;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return {};\n            }\n        }\n\n        inline void reshapePoseExtractorCaffe(\n            std::shared_ptr<ResizeAndMergeCaffe<float>>& resizeAndMergeCaffe,\n            std::shared_ptr<NmsCaffe<float>>& nmsCaffe,\n            std::shared_ptr<BodyPartConnectorCaffe<float>>& bodyPartConnectorCaffe,\n            std::shared_ptr<MaximumCaffe<float>>& maximumCaffe,\n            std::vector<std::shared_ptr<ArrayCpuGpu<float>>>& caffeNetOutputBlobsShared,\n            std::shared_ptr<ArrayCpuGpu<float>>& heatMapsBlob, std::shared_ptr<ArrayCpuGpu<float>>& peaksBlob,\n            std::shared_ptr<ArrayCpuGpu<float>>& maximumPeaksBlob, const float scaleInputToNetInput,\n            const PoseModel poseModel, const int gpuId, const float upsamplingRatio)\n        {\n            try\n            {\n                const auto netDescreaseFactor = (\n                    upsamplingRatio <= 0.f ? getPoseNetDecreaseFactor(poseModel) : upsamplingRatio);\n                // HeatMaps extractor blob and layer\n                // Caffe modifies bottom - Heatmap gets resized\n                const auto caffeNetOutputBlobs = arraySharedToPtr(caffeNetOutputBlobsShared);\n                resizeAndMergeCaffe->Reshape(\n                    caffeNetOutputBlobs, {heatMapsBlob.get()},\n                    netDescreaseFactor, 1.f/scaleInputToNetInput, true, gpuId);\n                // Pose extractor blob and layer\n                nmsCaffe->Reshape({heatMapsBlob.get()}, {peaksBlob.get()}, getPoseMaxPeaks(),\n                                  getPoseNumberBodyParts(poseModel), gpuId);\n                // Pose extractor blob and layer\n                bodyPartConnectorCaffe->Reshape({heatMapsBlob.get(), peaksBlob.get()}, gpuId);\n                if (TOP_DOWN_REFINEMENT)\n                    maximumCaffe->Reshape({heatMapsBlob.get()}, {maximumPeaksBlob.get()});\n                // Cuda check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void addCaffeNetOnThread(\n            std::vector<std::shared_ptr<Net>>& net,\n            std::vector<std::shared_ptr<ArrayCpuGpu<float>>>& caffeNetOutputBlob,\n            const PoseModel poseModel, const int gpuId, const std::string& modelFolder,\n            const std::string& protoTxtPath, const std::string& caffeModelPath, const bool enableGoogleLogging)\n        {\n            try\n            {\n                // Add Caffe Net\n                net.emplace_back(\n                    std::make_shared<NetCaffe>(\n                        modelFolder + (protoTxtPath.empty() ? getPoseProtoTxt(poseModel) : protoTxtPath),\n                        modelFolder + (caffeModelPath.empty() ? getPoseTrainedModel(poseModel) : caffeModelPath),\n                        gpuId, enableGoogleLogging));\n                // net.emplace_back(\n                //     std::make_shared<NetOpenCv>(\n                //         modelFolder + (protoTxtPath.empty() ? getPoseProtoTxt(poseModel) : protoTxtPath),\n                //         modelFolder + (caffeModelPath.empty() ? getPoseTrainedModel(poseModel) : caffeModelPath),\n                //         gpuId));\n                // UNUSED(enableGoogleLogging);\n                // Initializing them on the thread\n                net.back()->initializationOnThread();\n                caffeNetOutputBlob.emplace_back((net.back().get())->getOutputBlobArray());\n                // Sanity check\n                if (net.size() != caffeNetOutputBlob.size())\n                    error(\"Weird error, this should not happen. Notify us.\", __LINE__, __FUNCTION__, __FILE__);\n                // Cuda check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    #endif\n\n    PoseExtractorCaffe::PoseExtractorCaffe(\n        const PoseModel poseModel, const std::string& modelFolder, const int gpuId,\n        const std::vector<HeatMapType>& heatMapTypes, const ScaleMode heatMapScaleMode, const bool addPartCandidates,\n        const bool maximizePositives, const std::string& protoTxtPath, const std::string& caffeModelPath,\n        const float upsamplingRatio, const bool enableNet, const bool enableGoogleLogging) :\n        PoseExtractorNet{poseModel, heatMapTypes, heatMapScaleMode, addPartCandidates, maximizePositives},\n        mPoseModel{poseModel},\n        mGpuId{gpuId},\n        mModelFolder{modelFolder},\n        mProtoTxtPath{protoTxtPath},\n        mCaffeModelPath{caffeModelPath},\n        mUpsamplingRatio{upsamplingRatio},\n        mEnableNet{enableNet},\n        mEnableGoogleLogging{enableGoogleLogging}\n        #ifdef USE_CAFFE\n            ,\n            spResizeAndMergeCaffe{std::make_shared<ResizeAndMergeCaffe<float>>()},\n            spNmsCaffe{std::make_shared<NmsCaffe<float>>()},\n            spBodyPartConnectorCaffe{std::make_shared<BodyPartConnectorCaffe<float>>()},\n            spMaximumCaffe{(TOP_DOWN_REFINEMENT ? std::make_shared<MaximumCaffe<float>>() : nullptr)}\n        #endif\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // Layers parameters\n                spBodyPartConnectorCaffe->setPoseModel(mPoseModel);\n                spBodyPartConnectorCaffe->setMaximizePositives(maximizePositives);\n            #else\n                UNUSED(poseModel);\n                UNUSED(modelFolder);\n                UNUSED(gpuId);\n                UNUSED(heatMapTypes);\n                UNUSED(heatMapScaleMode);\n                UNUSED(addPartCandidates);\n                UNUSED(maximizePositives);\n                UNUSED(protoTxtPath);\n                UNUSED(caffeModelPath);\n                UNUSED(enableGoogleLogging);\n                error(\"OpenPose must be compiled with the `USE_CAFFE` macro definition in order to use this\"\n                      \" functionality.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    PoseExtractorCaffe::~PoseExtractorCaffe()\n    {\n    }\n\n    void PoseExtractorCaffe::netInitializationOnThread()\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                if (mEnableNet)\n                {\n                    // Logging\n                    opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n                    // Initialize Caffe net\n                    addCaffeNetOnThread(\n                        spNets, spCaffeNetOutputBlobs, mPoseModel, mGpuId,\n                        mModelFolder, mProtoTxtPath, mCaffeModelPath,\n                        mEnableGoogleLogging);\n                    #ifdef USE_CUDA\n                        cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                    #endif\n                }\n                // Initialize blobs\n                spHeatMapsBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                spPeaksBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                if (TOP_DOWN_REFINEMENT)\n                    spMaximumPeaksBlob = {std::make_shared<ArrayCpuGpu<float>>(1,1,1,1)};\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Logging\n                opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractorCaffe::forwardPass(\n        const std::vector<Array<float>>& inputNetData, const Point<int>& inputDataSize,\n        const std::vector<double>& scaleInputToNetInputs, const Array<float>& poseNetOutput)\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                // const auto REPS = 1;\n                // double timeNormalize1 = 0.;\n                // double timeNormalize2 = 0.;\n                // double timeNormalize3 = 0.;\n                // double timeNormalize4 = 0.;\n                // OP_CUDA_PROFILE_INIT(REPS);\n                // Sanity checks\n                if (inputNetData.empty())\n                    error(\"Empty inputNetData.\", __LINE__, __FUNCTION__, __FILE__);\n                for (const auto& inputNetDataI : inputNetData)\n                    if (inputNetDataI.empty())\n                        error(\"Empty inputNetData.\", __LINE__, __FUNCTION__, __FILE__);\n                if (inputNetData.size() != scaleInputToNetInputs.size())\n                    error(\"Size(inputNetData) must be same than size(scaleInputToNetInputs).\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                if (poseNetOutput.empty() != mEnableNet)\n                {\n                    const std::string errorMsg = \". Either use OpenPose default network (`--body 1`) or fill the\"\n                        \" `poseNetOutput` argument (only 1 of those 2, not both).\";\n                    if (poseNetOutput.empty())\n                        error(\"The argument poseNetOutput cannot be empty if mEnableNet is true\" + errorMsg,\n                              __LINE__, __FUNCTION__, __FILE__);\n                    else\n                        error(\"The argument poseNetOutput is not empty and you have also explicitly chosen to run\"\n                              \" the OpenPose network\" + errorMsg, __LINE__, __FUNCTION__, __FILE__);\n                }\n\n                // Resize std::vectors if required\n                const auto numberScales = inputNetData.size();\n                mNetInput4DSizes.resize(numberScales);\n\n                // Process each image - Caffe deep network\n                if (mEnableNet)\n                {\n                    while (spNets.size() < numberScales)\n                        addCaffeNetOnThread(\n                            spNets, spCaffeNetOutputBlobs, mPoseModel, mGpuId,\n                            mModelFolder, mProtoTxtPath, mCaffeModelPath, false);\n\n                    for (auto i = 0u ; i < inputNetData.size(); i++)\n                        spNets.at(i)->forwardPass(inputNetData[i]);\n                }\n                // If custom network output\n                else\n                {\n                    // Sanity check\n                    if (inputNetData.size() != 1u)\n                        error(\"Size(inputNetData) must match the provided heatmaps batch size (\"\n                              + std::to_string(inputNetData.size()) + \" vs. \" + std::to_string(1) + \").\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    // Copy heatmap information\n                    spCaffeNetOutputBlobs.clear();\n                    const bool copyFromGpu = false;\n                    spCaffeNetOutputBlobs.emplace_back(\n                        std::make_shared<ArrayCpuGpu<float>>(poseNetOutput, copyFromGpu));\n                }\n                // Reshape blobs if required\n                for (auto i = 0u ; i < inputNetData.size(); i++)\n                {\n                    // Reshape blobs if required - For dynamic sizes (e.g., images of different aspect ratio)\n                    const auto changedVectors = !vectorsAreEqual(\n                        mNetInput4DSizes.at(i), inputNetData[i].getSize());\n                    if (changedVectors)\n                    {\n                        mNetInput4DSizes.at(i) = inputNetData[i].getSize();\n                        reshapePoseExtractorCaffe(\n                            spResizeAndMergeCaffe, spNmsCaffe, spBodyPartConnectorCaffe,\n                            spMaximumCaffe, spCaffeNetOutputBlobs, spHeatMapsBlob,\n                            spPeaksBlob, spMaximumPeaksBlob, 1.f, mPoseModel,\n                            mGpuId, mUpsamplingRatio);\n                            // In order to resize to input size to have same results as Matlab\n                            // scaleInputToNetInputs[i] vs. 1.f\n                    }\n                    // Get scale net to output (i.e., image input)\n                    const auto ratio = (\n                        mUpsamplingRatio <= 0.f\n                            ? 1 : mUpsamplingRatio / getPoseNetDecreaseFactor(mPoseModel));\n                    if (changedVectors || TOP_DOWN_REFINEMENT)\n                        mNetOutputSize = Point<int>{\n                            positiveIntRound(ratio*mNetInput4DSizes[0][3]),\n                            positiveIntRound(ratio*mNetInput4DSizes[0][2])};\n                }\n                // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n                // OP_CUDA_PROFILE_INIT(REPS);\n                // 2. Resize heat maps + merge different scales\n                // ~5ms (GPU) / ~20ms (CPU)\n                const auto caffeNetOutputBlobs = arraySharedToPtr(spCaffeNetOutputBlobs);\n                // Set and fill floatScaleRatios\n                    // Option 1/2 (warning for double-to-float conversion)\n                // const std::vector<float> floatScaleRatios(scaleInputToNetInputs.begin(), scaleInputToNetInputs.end());\n                    // Option 2/2\n                std::vector<float> floatScaleRatios;\n                std::for_each(\n                    scaleInputToNetInputs.begin(), scaleInputToNetInputs.end(),\n                    [&floatScaleRatios](const double value) { floatScaleRatios.emplace_back(float(value)); });\n                spResizeAndMergeCaffe->setScaleRatios(floatScaleRatios);\n                spResizeAndMergeCaffe->Forward(caffeNetOutputBlobs, {spHeatMapsBlob.get()});\n                // Get scale net to output (i.e., image input)\n                // Note: In order to resize to input size, (un)comment the following lines\n                const auto scaleProducerToNetInput = resizeGetScaleFactor(inputDataSize, mNetOutputSize);\n                const Point<int> netSize{\n                    positiveIntRound(scaleProducerToNetInput*inputDataSize.x),\n                    positiveIntRound(scaleProducerToNetInput*inputDataSize.y)};\n                mScaleNetToOutput = {(float)resizeGetScaleFactor(netSize, inputDataSize)};\n                // mScaleNetToOutput = 1.f;\n                // 3. Get peaks by Non-Maximum Suppression\n                // ~2ms (GPU) / ~7ms (CPU)\n                // OP_CUDA_PROFILE_END(timeNormalize2, 1e3, REPS);\n                const auto nmsThreshold = (float)get(PoseProperty::NMSThreshold);\n                const auto nmsOffset = float(0.5/double(mScaleNetToOutput));\n                // OP_CUDA_PROFILE_INIT(REPS);\n                spNmsCaffe->setThreshold(nmsThreshold);\n                spNmsCaffe->setOffset(Point<float>{nmsOffset, nmsOffset});\n                spNmsCaffe->Forward({spHeatMapsBlob.get()}, {spPeaksBlob.get()});\n                // 4. Connecting body parts\n                // OP_CUDA_PROFILE_END(timeNormalize3, 1e3, REPS);\n                // OP_CUDA_PROFILE_INIT(REPS);\n                spBodyPartConnectorCaffe->setScaleNetToOutput(mScaleNetToOutput);\n                spBodyPartConnectorCaffe->setDefaultNmsThreshold((float)get(PoseProperty::NMSThreshold));\n                spBodyPartConnectorCaffe->setInterMinAboveThreshold(\n                    (float)get(PoseProperty::ConnectInterMinAboveThreshold));\n                spBodyPartConnectorCaffe->setInterThreshold((float)get(PoseProperty::ConnectInterThreshold));\n                spBodyPartConnectorCaffe->setMinSubsetCnt((int)get(PoseProperty::ConnectMinSubsetCnt));\n                spBodyPartConnectorCaffe->setMinSubsetScore((float)get(PoseProperty::ConnectMinSubsetScore));\n                // Note: BODY_25D will crash (only implemented for CPU version)\n                spBodyPartConnectorCaffe->Forward(\n                    {spHeatMapsBlob.get(), spPeaksBlob.get()}, mPoseKeypoints, mPoseScores);\n                // OP_CUDA_PROFILE_END(timeNormalize4, 1e3, REPS);\n                // opLog(\"1(caf)= \" + std::to_string(timeNormalize1) + \"ms\");\n                // opLog(\"2(res) = \" + std::to_string(timeNormalize2) + \" ms\");\n                // opLog(\"3(nms) = \" + std::to_string(timeNormalize3) + \" ms\");\n                // opLog(\"4(bpp) = \" + std::to_string(timeNormalize4) + \" ms\");\n                // Re-run on each person\n                if (TOP_DOWN_REFINEMENT)\n                {\n                    // Get each person rectangle\n                    for (auto person = 0 ; person < mPoseKeypoints.getSize(0) ; person++)\n                    {\n                        // Get person rectangle resized to input size\n                        const auto rectangleF = getKeypointsRectangle(mPoseKeypoints, person, nmsThreshold)\n                                              / mScaleNetToOutput;\n                        // Make rectangle bigger to make sure the whole body is inside\n                        Rectangle<int> rectangleInt{\n                            positiveIntRound(rectangleF.x - 0.2*rectangleF.width),\n                            positiveIntRound(rectangleF.y - 0.2*rectangleF.height),\n                            positiveIntRound(rectangleF.width*1.4),\n                            positiveIntRound(rectangleF.height*1.4)\n                        };\n                        keepRoiInside(rectangleInt, inputNetData[0].getSize(3), inputNetData[0].getSize(2));\n                        // Input size\n                        // // Note: In order to preserve speed but maximize accuracy\n                        // // If e.g. rectangle = 10x1 and inputSize = 656x368 --> targetSize = 656x368\n                        // // Note: If e.g. rectangle = 1x10 and inputSize = 656x368 --> targetSize = 368x656\n                        // const auto width = ( ? rectangleInt.width : rectangleInt.height);\n                        // const auto height = (width == rectangleInt.width ? rectangleInt.height : rectangleInt.width);\n                        // const Point<int> inputSize{width, height};\n                        // Note: If inputNetData.size = -1x368 --> TargetSize = 368x-1\n                        const Point<int> inputSizeInit{rectangleInt.width, rectangleInt.height};\n                        // Target size\n                        Point<int> targetSize;\n                        // Optimal case (using training size)\n                        if (inputNetData[0].getSize(2) >= 368 || inputNetData[0].getVolume(2,3) >= 135424) // 368^2\n                            targetSize = Point<int>{368, 368};\n                        // Low resolution cases: Keep same area than biggest scale\n                        else\n                        {\n                            const auto minSide = fastMin(\n                                368, fastMin(inputNetData[0].getSize(2), inputNetData[0].getSize(3)));\n                            const auto maxSide = fastMin(\n                                368, fastMax(inputNetData[0].getSize(2), inputNetData[0].getSize(3)));\n                            // Person bounding box is vertical\n                            if (rectangleInt.width < rectangleInt.height)\n                                targetSize = Point<int>{minSide, maxSide};\n                            // Person bounding box is horizontal\n                            else\n                                targetSize = Point<int>{maxSide, minSide};\n                        }\n                        // Fill resizedImage\n                        /*const*/ auto scaleNetToRoi = resizeGetScaleFactor(inputSizeInit, targetSize);\n                        // Update rectangle to avoid black padding and instead take full advantage of the network area\n                        const auto padding = Point<int>{\n                            (int)std::round((targetSize.x-1) / scaleNetToRoi + 1 - inputSizeInit.x),\n                            (int)std::round((targetSize.y-1) / scaleNetToRoi + 1 - inputSizeInit.y)\n                        };\n                        // Width requires padding\n                        if (padding.x > 2 || padding.y > 2) // 2 pixels as threshold\n                        {\n                            if (padding.x > 2) // 2 pixels as threshold\n                            {\n                                rectangleInt.x -= padding.x/2;\n                                rectangleInt.width += padding.x;\n                            }\n                            else if (padding.y > 2) // 2 pixels as threshold\n                            {\n                                rectangleInt.y -= padding.y/2;\n                                rectangleInt.height += padding.y;\n                            }\n                            keepRoiInside(rectangleInt, inputNetData[0].getSize(3), inputNetData[0].getSize(2));\n                            scaleNetToRoi = resizeGetScaleFactor(\n                                Point<int>{rectangleInt.width, rectangleInt.height}, targetSize);\n                        }\n                        // No if scaleNetToRoi < 1 (image would be shrunken, so we assume best result already obtained)\n                        if (scaleNetToRoi > 1)\n                        {\n                            const auto areaInput = inputNetData[0].getVolume(2,3);\n                            const auto areaRoi = targetSize.area();\n                            Array<float> inputNetDataRoi{{1, 3, targetSize.y, targetSize.x}};\n                            for (auto c = 0u ; c < 3u ; c++)\n                            {\n                                // Input image\n                                const cv::Mat wholeInputCvMat(\n                                    inputNetData[0].getSize(2), inputNetData[0].getSize(3), CV_32FC1,\n                                    inputNetData[0].getPseudoConstPtr() + c * areaInput);\n                                // Input image cropped\n                                const cv::Mat inputCvMat(\n                                    wholeInputCvMat, cv::Rect{rectangleInt.x, rectangleInt.y, rectangleInt.width, rectangleInt.height});\n                                // Resize image for inputNetDataRoi\n                                cv::Mat resizedImageCvMat(\n                                    inputNetDataRoi.getSize(2), inputNetDataRoi.getSize(3), CV_32FC1,\n                                    inputNetDataRoi.getPtr() + c * areaRoi);\n                                resizeFixedAspectRatio(resizedImageCvMat, inputCvMat, scaleNetToRoi, targetSize);\n                            }\n\n                            // Re-Process image\n                            // 1. Caffe deep network\n                            spNets.at(0)->forwardPass(inputNetDataRoi);\n                            std::vector<std::shared_ptr<ArrayCpuGpu<float>>> caffeNetOutputBlob{\n                                spCaffeNetOutputBlobs[0]};\n                            // Reshape blobs\n                            if (!vectorsAreEqual(mNetInput4DSizes.at(0), inputNetDataRoi.getSize()))\n                            {\n                                mNetInput4DSizes.at(0) = inputNetDataRoi.getSize();\n                                reshapePoseExtractorCaffe(\n                                    spResizeAndMergeCaffe, spNmsCaffe,\n                                    spBodyPartConnectorCaffe, spMaximumCaffe,\n                                    // spCaffeNetOutputBlobs,\n                                    caffeNetOutputBlob, spHeatMapsBlob, spPeaksBlob,\n                                    spMaximumPeaksBlob, 1.f, mPoseModel, mGpuId,\n                                    mUpsamplingRatio);\n                            }\n                            // 2. Resize heat maps + merge different scales\n                            const auto caffeNetOutputBlobsNew = arraySharedToPtr(caffeNetOutputBlob);\n                            // const std::vector<float> floatScaleRatiosNew(\n                            //     scaleInputToNetInputs.begin(), scaleInputToNetInputs.end());\n                            const std::vector<float> floatScaleRatiosNew{(float)scaleInputToNetInputs[0]};\n                            spResizeAndMergeCaffe->setScaleRatios(floatScaleRatiosNew);\n                            spResizeAndMergeCaffe->Forward(\n                                caffeNetOutputBlobsNew, {spHeatMapsBlob.get()});\n                            // Get scale net to output (i.e., image input)\n                            const auto scaleRoiToOutput = float(mScaleNetToOutput / scaleNetToRoi);\n                            // 3. Get peaks by Non-Maximum Suppression\n                            const auto nmsThresholdRefined = 0.02f;\n                            spNmsCaffe->setThreshold(nmsThresholdRefined);\n                            const auto nmsOffsetNew = float(0.5/double(scaleRoiToOutput));\n                            spNmsCaffe->setOffset(Point<float>{nmsOffsetNew, nmsOffsetNew});\n                            spNmsCaffe->Forward({spHeatMapsBlob.get()}, {spPeaksBlob.get()});\n                            // Define poseKeypoints\n                            Array<float> poseKeypoints;\n                            Array<float> poseScores;\n                            // 4. Connecting body parts\n                            // Get scale net to output (i.e., image input)\n                            spBodyPartConnectorCaffe->setScaleNetToOutput(scaleRoiToOutput);\n                            spBodyPartConnectorCaffe->setInterThreshold(0.01f);\n                            spBodyPartConnectorCaffe->Forward(\n                                {spHeatMapsBlob.get(), spPeaksBlob.get()}, poseKeypoints, poseScores);\n                            // If detected people in new subnet\n                            if (!poseKeypoints.empty())\n                            {\n                                // // Scale back keypoints\n                                const auto xOffset = float(rectangleInt.x*mScaleNetToOutput);\n                                const auto yOffset = float(rectangleInt.y*mScaleNetToOutput);\n                                scaleKeypoints2d(poseKeypoints, 1.f, 1.f, xOffset, yOffset);\n                                // Re-assign person back\n                                // // Option a) Just use biggest person (simplest but fails with crowded people)\n                                // const auto personRefined = getBiggestPerson(poseKeypoints, nmsThreshold);\n                                // Option b) Get minimum keypoint distance\n                                // Get min distance\n                                int personRefined = -1;\n                                float personAverageDistance = std::numeric_limits<float>::max();\n                                for (auto person2 = 0 ; person2 < poseKeypoints.getSize(0) ; person2++)\n                                {\n                                    // Get average distance\n                                    const auto currentAverageDistance = getDistanceAverage(\n                                        mPoseKeypoints, person, poseKeypoints, person2, nmsThreshold);\n                                    // Update person\n                                    if (personAverageDistance > currentAverageDistance\n                                        && getNonZeroKeypoints(poseKeypoints, person2, nmsThreshold)\n                                            >= 0.75*getNonZeroKeypoints(mPoseKeypoints, person, nmsThreshold))\n                                    {\n                                        personRefined = person2;\n                                        personAverageDistance = currentAverageDistance;\n                                    }\n                                }\n                                // Get max ROI\n                                int personRefinedRoi = -1;\n                                float personRoi = -1.f;\n                                for (auto person2 = 0 ; person2 < poseKeypoints.getSize(0) ; person2++)\n                                {\n                                    // Get ROI\n                                    const auto currentRoi = getKeypointsRoi(\n                                        mPoseKeypoints, person, poseKeypoints, person2, nmsThreshold);\n                                    // Update person\n                                    if (personRoi < currentRoi\n                                        && getNonZeroKeypoints(poseKeypoints, person2, nmsThreshold)\n                                            >= 0.75*getNonZeroKeypoints(mPoseKeypoints, person, nmsThreshold))\n                                    {\n                                        personRefinedRoi = person2;\n                                        personRoi = currentRoi;\n                                    }\n                                }\n                                // If good refined candidate found\n                                // I.e., if both max ROI and min dist match on same person id\n                                if (personRefined == personRefinedRoi && personRefined > -1)\n                                {\n                                    // Update only if avg dist is small enough\n                                    const auto personRectangle = getKeypointsRectangle(\n                                        mPoseKeypoints, person, nmsThreshold);\n                                    const auto personRatio = 0.1f * (float)std::sqrt(\n                                        personRectangle.x*personRectangle.x + personRectangle.y*personRectangle.y);\n                                    // if (mPoseScores[person] < poseScores[personRefined]) // This harms accuracy\n                                    if (personAverageDistance < personRatio)\n                                    {\n                                        const auto personArea = mPoseKeypoints.getVolume(1,2);\n                                        const auto personIndex = person * personArea;\n                                        const auto personRefinedIndex = personRefined * personArea;\n                                        // mPoseKeypoints: Update keypoints\n                                        // Option a) Using refined ones\n                                        std::copy(\n                                            poseKeypoints.getPtr() + personRefinedIndex,\n                                            poseKeypoints.getPtr() + personRefinedIndex + personArea,\n                                            mPoseKeypoints.getPtr() + personIndex);\n                                        mPoseScores[person] = poseScores[personRefined];\n                                        // // Option b) Using ones with highest score (-6% acc single scale)\n                                        // // Fill gaps\n                                        // for (auto part = 0 ; part < mPoseKeypoints.getSize(1) ; part++)\n                                        // {\n                                        //     // For currently empty keypoints\n                                        //     const auto partIndex = personIndex+3*part;\n                                        //     const auto partRefinedIndex = personRefinedIndex+3*part;\n                                        //     const auto scoreDifference = poseKeypoints[partRefinedIndex+2]\n                                        //                                - mPoseKeypoints[partIndex+2];\n                                        //     if (scoreDifference > 0)\n                                        //     {\n                                        //         const auto x = poseKeypoints[partRefinedIndex];\n                                        //         const auto y = poseKeypoints[partRefinedIndex + 1];\n                                        //         mPoseKeypoints[partIndex] = x;\n                                        //         mPoseKeypoints[partIndex+1] = y;\n                                        //         mPoseKeypoints[partIndex+2] += scoreDifference;\n                                        //         mPoseScores[person] += scoreDifference;\n                                        //     }\n                                        // }\n\n                                        // No acc improvement (-0.05% acc single scale)\n                                        // // Finding all missing peaks (CPM-style)\n                                        // // Only if no other person in there (otherwise 2% accuracy drop)\n                                        // if (getNonZeroKeypoints(mPoseKeypoints, person, nmsThresholdRefined) > 0)\n                                        // {\n                                        //     // Get whether 0% ROI with other people\n                                        //     // Get max ROI\n                                        //     bool overlappingPerson = false;\n                                        //     for (auto person2 = 0 ; person2 < mPoseKeypoints.getSize(0) ; person2++)\n                                        //     {\n                                        //         if (person != person2)\n                                        //         {\n                                        //             // Get ROI\n                                        //             const auto currentRoi = getKeypointsRoi(\n                                        //                 mPoseKeypoints, person, person2, nmsThreshold);\n                                        //             // Update person\n                                        //             if (currentRoi > 0.f)\n                                        //             {\n                                        //                 overlappingPerson = true;\n                                        //                 break;\n                                        //             }\n                                        //         }\n                                        //     }\n                                        //     if (!overlappingPerson)\n                                        //     {\n                                        //         // Get keypoint with maximum probability per channel\n                                        //         spMaximumCaffe->Forward(\n                                        //             {spHeatMapsBlob.get()}, {spMaximumPeaksBlob.get()});\n                                        //         // Fill gaps\n                                        //         const auto* posePeaksPtr = spMaximumPeaksBlob->mutable_cpu_data();\n                                        //         for (auto part = 0 ; part < mPoseKeypoints.getSize(1) ; part++)\n                                        //         {\n                                        //             // For currently empty keypoints\n                                        //             if (mPoseKeypoints[personIndex+3*part+2] < nmsThresholdRefined)\n                                        //             {\n                                        //                 const auto xyIndex = 3*part;\n                                        //                 const auto x = posePeaksPtr[xyIndex]*scaleRoiToOutput + xOffset;\n                                        //                 const auto y = posePeaksPtr[xyIndex + 1]*scaleRoiToOutput + yOffset;\n                                        //                 const auto rectangle = getKeypointsRectangle(\n                                        //                     mPoseKeypoints, person, nmsThresholdRefined);\n                                        //                 if (x >= rectangle.x && x < rectangle.x + rectangle.width\n                                        //                     && y >= rectangle.y && y < rectangle.y + rectangle.height)\n                                        //                 {\n                                        //                     const auto score = posePeaksPtr[xyIndex + 2];\n                                        //                     const auto baseIndex = personIndex + 3*part;\n                                        //                     mPoseKeypoints[baseIndex] = x;\n                                        //                     mPoseKeypoints[baseIndex+1] = y;\n                                        //                     mPoseKeypoints[baseIndex+2] = score;\n                                        //                     mPoseScores[person] += score;\n                                        //                 }\n                                        //             }\n                                        //         }\n                                        //     }\n                                        // }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                // 5. CUDA sanity check\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n            #else\n                UNUSED(inputNetData);\n                UNUSED(inputDataSize);\n                UNUSED(scaleInputToNetInputs);\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    const float* PoseExtractorCaffe::getCandidatesCpuConstPtr() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                checkThread();\n                return spPeaksBlob->cpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    const float* PoseExtractorCaffe::getCandidatesGpuConstPtr() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                checkThread();\n                return spPeaksBlob->gpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    const float* PoseExtractorCaffe::getHeatMapCpuConstPtr() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                checkThread();\n                return spHeatMapsBlob->cpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    const float* PoseExtractorCaffe::getHeatMapGpuConstPtr() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                checkThread();\n                return spHeatMapsBlob->gpu_data();\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n\n    std::vector<int> PoseExtractorCaffe::getHeatMapSize() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                checkThread();\n                return spHeatMapsBlob->shape();\n            #else\n                return {};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    const float* PoseExtractorCaffe::getPoseGpuConstPtr() const\n    {\n        try\n        {\n            #ifdef USE_CAFFE\n                error(\"GPU pointer for people pose data not implemented yet.\", __LINE__, __FUNCTION__, __FILE__);\n                checkThread();\n                return nullptr;\n            #else\n                return nullptr;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseExtractorNet.cpp",
    "content": "#include <openpose/pose/poseExtractorNet.hpp>\n#include <cmath> // std::round\n#ifdef USE_CUDA\n    #include <cuda_runtime_api.h>\n    #include <openpose/gpu/cuda.hpp>\n#endif\n#include <openpose/core/enumClasses.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    bool heatMapTypesHas(const std::vector<HeatMapType>& heatMapTypes, const HeatMapType heatMapType)\n    {\n        try\n        {\n            for (auto heatMapTypeVector : heatMapTypes)\n                if (heatMapTypeVector == heatMapType)\n                    return true;\n            return false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    int getNumberHeatMapChannels(const std::vector<HeatMapType>& heatMapTypes, const PoseModel poseModel)\n    {\n        try\n        {\n            auto numberHeatMapChannels = 0;\n            if (heatMapTypesHas(heatMapTypes, HeatMapType::Parts))\n                numberHeatMapChannels += getPoseNumberBodyParts(poseModel);\n            if (heatMapTypesHas(heatMapTypes, HeatMapType::Background))\n                numberHeatMapChannels += 1;\n            if (heatMapTypesHas(heatMapTypes, HeatMapType::PAFs))\n                numberHeatMapChannels += (int)getPosePartPairs(poseModel).size();\n            return numberHeatMapChannels;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    PoseExtractorNet::PoseExtractorNet(const PoseModel poseModel, const std::vector<HeatMapType>& heatMapTypes,\n                                       const ScaleMode heatMapScaleMode, const bool addPartCandidates,\n                                       const bool maximizePositives) :\n        mPoseModel{poseModel},\n        mNetOutputSize{0,0},\n        mHeatMapTypes{heatMapTypes},\n        mHeatMapScaleMode{heatMapScaleMode},\n        mAddPartCandidates{addPartCandidates}\n    {\n        try\n        {\n            // Error check\n            if (mHeatMapScaleMode != ScaleMode::ZeroToOne\n                && mHeatMapScaleMode != ScaleMode::ZeroToOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOne\n                && mHeatMapScaleMode != ScaleMode::PlusMinusOneFixedAspect\n                && mHeatMapScaleMode != ScaleMode::UnsignedChar && mHeatMapScaleMode != ScaleMode::NoScale)\n                error(\"The ScaleMode heatMapScaleMode must be ZeroToOne, ZeroToOneFixedAspect, PlusMinusOne,\"\n                    \" PlusMinusOneFixedAspect or UnsignedChar.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Properties - Init to 0\n            for (auto& property : mProperties)\n                property = 0.;\n            // Properties - Fill default values\n            mProperties[(int)PoseProperty::NMSThreshold] = getPoseDefaultNmsThreshold(mPoseModel, maximizePositives);\n            mProperties[(int)PoseProperty::ConnectInterMinAboveThreshold]\n                = getPoseDefaultConnectInterMinAboveThreshold(maximizePositives);\n            mProperties[(int)PoseProperty::ConnectInterThreshold] = getPoseDefaultConnectInterThreshold(\n                mPoseModel, maximizePositives);\n            mProperties[(int)PoseProperty::ConnectMinSubsetCnt] = getPoseDefaultMinSubsetCnt(maximizePositives);\n            mProperties[(int)PoseProperty::ConnectMinSubsetScore] = getPoseDefaultConnectMinSubsetScore(\n                maximizePositives);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    PoseExtractorNet::~PoseExtractorNet()\n    {\n    }\n\n    void PoseExtractorNet::initializationOnThread()\n    {\n        try\n        {\n            // Get thread id\n            mThreadId = {std::this_thread::get_id()};\n            // Deep net initialization\n            netInitializationOnThread();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Array<float> PoseExtractorNet::getHeatMapsCopy() const\n    {\n        try\n        {\n            checkThread();\n            Array<float> heatMaps;\n            if (!mHeatMapTypes.empty())\n            {\n                #ifdef USE_CUDA\n                    cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                #endif\n                // Get heatmaps size\n                const auto heatMapSize = getHeatMapSize();\n\n                // Allocate memory\n                const auto numberHeatMapChannels = getNumberHeatMapChannels(mHeatMapTypes, mPoseModel);\n                heatMaps.reset({numberHeatMapChannels, heatMapSize[2], heatMapSize[3]});\n\n                // Copy memory\n                const auto channelOffset = heatMaps.getVolume(1, 2);\n                const auto volumeBodyParts = getPoseNumberBodyParts(mPoseModel) * channelOffset;\n                const auto volumePAFs = getPosePartPairs(mPoseModel).size() * channelOffset;\n                auto totalOffset = 0u;\n                // Body parts\n                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::Parts))\n                {\n                    #ifdef USE_CUDA\n                        cudaMemcpy(heatMaps.getPtr(), getHeatMapGpuConstPtr(),\n                                   volumeBodyParts * sizeof(float), cudaMemcpyDeviceToHost);\n                    #else\n                        const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();\n                        std::copy(heatMapCpuPtr, heatMapCpuPtr+volumeBodyParts, heatMaps.getPtr());\n                    #endif\n                    if (mHeatMapScaleMode != ScaleMode::NoScale)\n                    {\n                        // Change from [0,1] to [-1,1]\n                        if (mHeatMapScaleMode == ScaleMode::PlusMinusOne\n                            || mHeatMapScaleMode == ScaleMode::PlusMinusOneFixedAspect)\n                            for (auto i = 0u ; i < volumeBodyParts ; i++)\n                                heatMaps[i] = fastTruncate(heatMaps[i]) * 2.f - 1.f;\n                        // [0, 255]\n                        else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)\n                            for (auto i = 0u ; i < volumeBodyParts ; i++)\n                                heatMaps[i] = (float)positiveIntRound(fastTruncate(heatMaps[i]) * 255.f);\n                        // Avoid values outside original range\n                        else\n                            for (auto i = 0u ; i < volumeBodyParts ; i++)\n                                heatMaps[i] = fastTruncate(heatMaps[i]);\n                    }\n                    totalOffset += (unsigned int)volumeBodyParts;\n                }\n                // Background\n                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::Background))\n                {\n                    if (addBkgChannel(mPoseModel))\n                    {\n                        auto* heatMapsPtr = heatMaps.getPtr() + totalOffset;\n                        #ifdef USE_CUDA\n                            cudaMemcpy(heatMapsPtr, getHeatMapGpuConstPtr() + volumeBodyParts,\n                                       channelOffset * sizeof(float), cudaMemcpyDeviceToHost);\n                        #else\n                            const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();\n                            std::copy(\n                                heatMapCpuPtr + volumeBodyParts, heatMapCpuPtr + volumeBodyParts + channelOffset,\n                                heatMapsPtr);\n                        #endif\n                        if (mHeatMapScaleMode != ScaleMode::NoScale)\n                        {\n                            // Change from [0,1] to [-1,1]\n                            if (mHeatMapScaleMode == ScaleMode::PlusMinusOne\n                                || mHeatMapScaleMode == ScaleMode::PlusMinusOneFixedAspect)\n                                for (auto i = 0u ; i < channelOffset ; i++)\n                                    heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]) * 2.f - 1.f;\n                            // [0, 255]\n                            else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)\n                                for (auto i = 0u ; i < channelOffset ; i++)\n                                    heatMapsPtr[i] = (float)positiveIntRound(fastTruncate(heatMapsPtr[i]) * 255.f);\n                            // Avoid values outside original range\n                            else\n                                for (auto i = 0u ; i < channelOffset ; i++)\n                                    heatMapsPtr[i] = fastTruncate(heatMapsPtr[i]);\n                        }\n                        totalOffset += (unsigned int)channelOffset;\n                    }\n                    else\n                    {\n                        error(\"You enabled `--heatmaps_add_bkg` for a model that does not contain one. Please,\"\n                              \" remove this flag for this model.\", __LINE__, __FUNCTION__, __FILE__);\n                    }\n                }\n                // PAFs\n                if (heatMapTypesHas(mHeatMapTypes, HeatMapType::PAFs))\n                {\n                    auto* heatMapsPtr = heatMaps.getPtr() + totalOffset;\n                    #ifdef USE_CUDA\n                        cudaMemcpy(heatMapsPtr,\n                                   getHeatMapGpuConstPtr() + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0),\n                                   volumePAFs * sizeof(float), cudaMemcpyDeviceToHost);\n                    #else\n                        const auto* heatMapCpuPtr = getHeatMapCpuConstPtr();\n                        std::copy(heatMapCpuPtr + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0),\n                                  heatMapCpuPtr + volumeBodyParts + (addBkgChannel(mPoseModel) ? channelOffset : 0) + volumePAFs,\n                                  heatMapsPtr);\n                    #endif\n                    if (mHeatMapScaleMode != ScaleMode::NoScale)\n                    {\n                        // Change from [-1,1] to [0,1]. Note that PAFs are in [-1,1]\n                        if (mHeatMapScaleMode == ScaleMode::ZeroToOne\n                            || mHeatMapScaleMode == ScaleMode::ZeroToOneFixedAspect)\n                            for (auto i = 0u ; i < volumePAFs ; i++)\n                                heatMapsPtr[i] = fastTruncate(heatMapsPtr[i], -1.f) * 0.5f + 0.5f;\n                        // [0, 255]\n                        else if (mHeatMapScaleMode == ScaleMode::UnsignedChar)\n                            for (auto i = 0u ; i < volumePAFs ; i++)\n                                heatMapsPtr[i] = (float)positiveIntRound(\n                                    fastTruncate(heatMapsPtr[i], -1.f) * 128.5f + 128.5f\n                                );\n                        // Avoid values outside original range\n                        else\n                            for (auto i = 0u ; i < volumePAFs ; i++)\n                                heatMapsPtr[i] = fastTruncate(heatMapsPtr[i], -1.f);\n                    }\n                    totalOffset += (unsigned int)volumePAFs;\n                }\n                // Copy all at once\n                // cudaMemcpy(heatMaps.getPtr(), getHeatMapGpuConstPtr(), heatMaps.getVolume() * sizeof(float),\n                //            cudaMemcpyDeviceToHost);\n            }\n            #ifdef USE_CUDA\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n            return heatMaps;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    std::vector<std::vector<std::array<float,3>>> PoseExtractorNet::getCandidatesCopy() const\n    {\n        try\n        {\n            // Sanity check\n            checkThread();\n            // Initialization\n            std::vector<std::vector<std::array<float,3>>> candidates;\n            // Fill candidates\n            if (mAddPartCandidates)\n            {\n                const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel);\n                candidates.resize(numberBodyParts);\n                const auto peaksArea = (POSE_MAX_PEOPLE+1) * 3;\n                // Memory copy\n                const auto* candidatesCpuPtr = getCandidatesCpuConstPtr();\n                for (auto part = 0u ; part < numberBodyParts ; part++)\n                {\n                    const auto numberPartCandidates = (int)std::round(candidatesCpuPtr[part*peaksArea]);\n                    candidates[part].resize(numberPartCandidates);\n                    const auto* partCandidatesPtr = &candidatesCpuPtr[part*peaksArea+3];\n                    for (auto candidate = 0 ; candidate < numberPartCandidates ; candidate++)\n                        candidates[part][candidate] = {\n                            partCandidatesPtr[3*candidate] * mScaleNetToOutput,\n                            partCandidatesPtr[3*candidate+1] * mScaleNetToOutput,\n                            partCandidatesPtr[3*candidate+2]};\n                }\n            }\n            // Return\n            return candidates;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::vector<std::vector<std::array<float,3>>>{};\n        }\n    }\n\n    Array<float> PoseExtractorNet::getPoseKeypoints() const\n    {\n        try\n        {\n            checkThread();\n            return mPoseKeypoints;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    Array<float> PoseExtractorNet::getPoseScores() const\n    {\n        try\n        {\n            checkThread();\n            return mPoseScores;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<float>{};\n        }\n    }\n\n    float PoseExtractorNet::getScaleNetToOutput() const\n    {\n        try\n        {\n            checkThread();\n            return mScaleNetToOutput;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    double PoseExtractorNet::get(const PoseProperty property) const\n    {\n        try\n        {\n            return mProperties.at((int)property);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void PoseExtractorNet::set(const PoseProperty property, const double value)\n    {\n        try\n        {\n            auto& propertyElement = mProperties.at((int)property);\n            opLog(\"Property \" + std::to_string((int)property)\n                + \" set from \" + std::to_string(propertyElement)\n                + \" to \" + std::to_string(value), Priority::High);\n            propertyElement = value;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractorNet::increase(const PoseProperty property, const double value)\n    {\n        try\n        {\n            set(property, get(property) + value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractorNet::clear()\n    {\n        try\n        {\n            mPoseKeypoints.reset();\n            mPoseScores.reset();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseExtractorNet::checkThread() const\n    {\n        try\n        {\n            if (mThreadId != std::this_thread::get_id())\n                error(\"The CPU/GPU pointer data cannot be accessed from a different thread.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseGpuRenderer.cpp",
    "content": "#include <openpose/pose/poseGpuRenderer.hpp>\n#ifdef USE_CUDA\n    #include <cuda.h>\n    #include <cuda_runtime_api.h>\n#endif\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/renderPose.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    PoseGpuRenderer::PoseGpuRenderer(const PoseModel poseModel,\n                                     const std::shared_ptr<PoseExtractorNet>& poseExtractorNet,\n                                     const float renderThreshold, const bool blendOriginalFrame,\n                                     const float alphaKeypoint, const float alphaHeatMap,\n                                     const unsigned int elementToRender) :\n        // #body elements to render = #body parts (size()) + #body part pair connections\n        //                          + 3 (+whole pose +whole heatmaps +PAFs)\n        // POSE_BODY_PART_MAPPING crashes on Windows, replaced by getPoseBodyPartMapping\n        GpuRenderer{renderThreshold, alphaKeypoint, alphaHeatMap, blendOriginalFrame, elementToRender,\n                    getNumberElementsToRender(poseModel)}, // mNumberElementsToRender\n        PoseRenderer{poseModel},\n        spPoseExtractorNet{poseExtractorNet},\n        pGpuPose{nullptr},\n        pMaxPtr{nullptr},\n        pMinPtr{nullptr},\n        pScalePtr{nullptr}\n    {\n    }\n\n    PoseGpuRenderer::~PoseGpuRenderer()\n    {\n        try\n        {\n            // Free CUDA pointers - Note that if pointers are 0 (i.e., nullptr), no operation is performed.\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            #ifdef USE_CUDA\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n                if (pGpuPose != nullptr)\n                {\n                    cudaFree(pGpuPose);\n                    pGpuPose = nullptr;\n                }\n                if (pMaxPtr != nullptr)\n                {\n                    cudaFree(pMaxPtr);\n                    pMaxPtr = nullptr;\n                }\n                if (pMinPtr != nullptr)\n                {\n                    cudaFree(pMinPtr);\n                    pMinPtr = nullptr;\n                }\n                if (pScalePtr != nullptr)\n                {\n                    cudaFree(pScalePtr);\n                    pScalePtr = nullptr;\n                }\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PoseGpuRenderer::initializationOnThread()\n    {\n        try\n        {\n            opLog(\"Starting initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // GPU memory allocation for rendering\n            #ifdef USE_CUDA\n                const auto gpuPoseVolume = POSE_MAX_PEOPLE * getPoseNumberBodyParts(mPoseModel) * 3 * sizeof(float);\n                cudaMalloc((void**)(&pGpuPose), gpuPoseVolume);\n                cudaMalloc((void**)&pMaxPtr, sizeof(float) * 2 * POSE_MAX_PEOPLE);\n                cudaMalloc((void**)&pMinPtr, sizeof(float) * 2 * POSE_MAX_PEOPLE);\n                cudaMalloc((void**)&pScalePtr, sizeof(float) * POSE_MAX_PEOPLE);\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #endif\n            opLog(\"Finished initialization on thread.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::pair<int, std::string> PoseGpuRenderer::renderPose(\n        Array<float>& outputData, const Array<float>& poseKeypoints, const float scaleInputToOutput,\n        const float scaleNetToOutput)\n    {\n        try\n        {\n            // Sanity check\n            if (outputData.empty())\n                error(\"Empty Array<float> outputData.\", __LINE__, __FUNCTION__, __FILE__);\n            // GPU rendering\n            const auto elementRendered = spElementToRender->load();\n            std::string elementRenderedName;\n            #ifdef USE_CUDA\n                const auto numberPeople = poseKeypoints.getSize(0);\n                if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame)\n                {\n                    cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr(), outputData.getVolume());\n                    const auto numberBodyParts = getPoseNumberBodyParts(mPoseModel);\n                    const auto hasBkg = addBkgChannel(mPoseModel);\n                    const auto numberBodyPartsPlusBkg = numberBodyParts + (hasBkg ? 1 : 0);\n                    const auto numberBodyPAFChannels = getPosePartPairs(mPoseModel).size();\n                    const Point<unsigned int> frameSize{(unsigned int)outputData.getSize(1), (unsigned int)outputData.getSize(0)};\n                    // Draw poseKeypoints\n                    if (elementRendered == 0)\n                    {\n                        // Rescale keypoints to output size\n                        auto poseKeypointsRescaled = poseKeypoints.clone();\n                        scaleKeypoints(poseKeypointsRescaled, scaleInputToOutput);\n                        // Render keypoints\n                        if (!poseKeypoints.empty())\n                        {\n                            const auto gpuPoseVolume = numberPeople * numberBodyParts * 3 * sizeof(float);\n                            cudaMemcpy(\n                                pGpuPose, poseKeypointsRescaled.getConstPtr(), gpuPoseVolume, cudaMemcpyHostToDevice);\n                        }\n                        renderPoseKeypointsGpu(\n                            *spGpuMemory, pMaxPtr, pMinPtr, pScalePtr, mPoseModel, numberPeople, frameSize, pGpuPose,\n                            mRenderThreshold, mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint());\n                    }\n                    else\n                    {\n                        // If resized to input resolution: Replace scaleNetToOutput * scaleInputToOutput by\n                        // scaleInputToOutput, and comment the sanity check.\n                        // Sanity check\n                        if (scaleNetToOutput == -1.f)\n                            error(\"Non valid scaleNetToOutput.\", __LINE__, __FUNCTION__, __FILE__);\n                        // Parameters\n                        const auto& heatMapSizes = spPoseExtractorNet->getHeatMapSize();\n                        const Point<int> heatMapSize{heatMapSizes[3], heatMapSizes[2]};\n                        const auto lastPAFChannel = numberBodyPartsPlusBkg+2+numberBodyPAFChannels/2;\n                        // Add all heatmaps\n                        if (elementRendered == 2)\n                        // if (elementRendered == numberBodyPartsPlusBkg+1)\n                        {\n                            elementRenderedName = \"Heatmaps\";\n                            renderPoseHeatMapsGpu(\n                                *spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(),\n                                heatMapSize, scaleNetToOutput * scaleInputToOutput,\n                                (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));\n                        }\n                        // Draw PAFs (Part Affinity Fields)\n                        else if (elementRendered == 3)\n                        // else if (elementRendered == numberBodyPartsPlusBkg+2)\n                        {\n                            elementRenderedName = \"PAFs (Part Affinity Fields)\";\n                            renderPosePAFsGpu(\n                                *spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(),\n                                heatMapSize, scaleNetToOutput * scaleInputToOutput,\n                                (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));\n                        }\n                        // Draw specific body part or background\n                        else if (elementRendered <= numberBodyPartsPlusBkg+2)\n                        {\n                            const auto realElementRendered = (elementRendered == 1\n                                                                ? (hasBkg ? numberBodyParts : 0)\n                                                                : elementRendered - 3 - (hasBkg ? 1:0));\n                            elementRenderedName = mPartIndexToName.at(realElementRendered);\n                            renderPoseHeatMapGpu(\n                                *spGpuMemory, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize,\n                                scaleNetToOutput * scaleInputToOutput, realElementRendered,\n                                (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));\n                        }\n                        // Draw affinity between 2 body parts\n                        else if (elementRendered <= lastPAFChannel)\n                        {\n                            const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2;\n                            const auto affinityPartMapped = numberBodyPartsPlusBkg\n                                                          + getPoseMapIndex(mPoseModel).at(affinityPart);\n                            elementRenderedName = mPartIndexToName.at(affinityPartMapped);\n                            elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find(\"(\"));\n                            renderPosePAFGpu(\n                                *spGpuMemory, mPoseModel, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(),\n                                heatMapSize, scaleNetToOutput * scaleInputToOutput, affinityPartMapped,\n                                (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));\n                        }\n                        // Draw neck-part distance channel\n                        else\n                        {\n                            if (mPoseModel != PoseModel::BODY_25D)\n                                error(\"Neck-part distance channel only for BODY_25D.\",\n                                      __LINE__, __FUNCTION__, __FILE__);\n                            const auto distancePart = (elementRendered - lastPAFChannel - 1);\n                            const auto distancePartMapped = (unsigned int)(\n                                numberBodyPartsPlusBkg + numberBodyPAFChannels + distancePart);\n                            elementRenderedName = mPartIndexToName.at(distancePartMapped);\n                            renderPoseDistanceGpu(\n                                *spGpuMemory, frameSize, spPoseExtractorNet->getHeatMapGpuConstPtr(), heatMapSize,\n                                scaleNetToOutput * scaleInputToOutput, distancePartMapped,\n                                (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f));\n                        }\n                    }\n                }\n                // GPU memory to CPU if last renderer\n                gpuToCpuMemoryIfLastRenderer(outputData.getPtr(), outputData.getVolume());\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            #else\n                UNUSED(outputData);\n                UNUSED(poseKeypoints);\n                UNUSED(scaleInputToOutput);\n                UNUSED(scaleNetToOutput);\n                error(\"OpenPose must be compiled with the `USE_CUDA` macro definitions in order to run this\"\n                      \" functionality. You can alternatively use CPU rendering (flag `--render_pose 1`).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            #endif\n            // Return result\n            return std::make_pair(elementRendered, elementRenderedName);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(-1, \"\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseParameters.cpp",
    "content": "#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n\nnamespace op\n{\n    // Body parts mapping\n    const std::map<unsigned int, std::string> POSE_BODY_25_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"Neck\"},\n        {2,  \"RShoulder\"},\n        {3,  \"RElbow\"},\n        {4,  \"RWrist\"},\n        {5,  \"LShoulder\"},\n        {6,  \"LElbow\"},\n        {7,  \"LWrist\"},\n        {8,  \"MidHip\"},\n        {9,  \"RHip\"},\n        {10, \"RKnee\"},\n        {11, \"RAnkle\"},\n        {12, \"LHip\"},\n        {13, \"LKnee\"},\n        {14, \"LAnkle\"},\n        {15, \"REye\"},\n        {16, \"LEye\"},\n        {17, \"REar\"},\n        {18, \"LEar\"},\n        {19, \"LBigToe\"},\n        {20, \"LSmallToe\"},\n        {21, \"LHeel\"},\n        {22, \"RBigToe\"},\n        {23, \"RSmallToe\"},\n        {24, \"RHeel\"},\n        {25, \"Background\"}\n    };\n    const std::map<unsigned int, std::string> POSE_COCO_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"Neck\"},\n        {2,  \"RShoulder\"},\n        {3,  \"RElbow\"},\n        {4,  \"RWrist\"},\n        {5,  \"LShoulder\"},\n        {6,  \"LElbow\"},\n        {7,  \"LWrist\"},\n        {8,  \"RHip\"},\n        {9,  \"RKnee\"},\n        {10, \"RAnkle\"},\n        {11, \"LHip\"},\n        {12, \"LKnee\"},\n        {13, \"LAnkle\"},\n        {14, \"REye\"},\n        {15, \"LEye\"},\n        {16, \"REar\"},\n        {17, \"LEar\"},\n        {18, \"Background\"}\n    };\n    const std::map<unsigned int, std::string> POSE_MPI_BODY_PARTS {\n        {0,  \"Head\"},\n        {1,  \"Neck\"},\n        {2,  \"RShoulder\"},\n        {3,  \"RElbow\"},\n        {4,  \"RWrist\"},\n        {5,  \"LShoulder\"},\n        {6,  \"LElbow\"},\n        {7,  \"LWrist\"},\n        {8,  \"RHip\"},\n        {9,  \"RKnee\"},\n        {10, \"RAnkle\"},\n        {11, \"LHip\"},\n        {12, \"LKnee\"},\n        {13, \"LAnkle\"},\n        {14, \"Chest\"},\n        {15, \"Background\"}\n    };\n    const std::map<unsigned int, std::string> POSE_BODY_19_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"Neck\"},\n        {2,  \"RShoulder\"},\n        {3,  \"RElbow\"},\n        {4,  \"RWrist\"},\n        {5,  \"LShoulder\"},\n        {6,  \"LElbow\"},\n        {7,  \"LWrist\"},\n        {8,  \"MidHip\"},\n        {9,  \"RHip\"},\n        {10, \"RKnee\"},\n        {11, \"RAnkle\"},\n        {12, \"LHip\"},\n        {13, \"LKnee\"},\n        {14, \"LAnkle\"},\n        {15, \"REye\"},\n        {16, \"LEye\"},\n        {17, \"REar\"},\n        {18, \"LEar\"},\n        {19, \"Background\"}\n    };\n    const std::map<unsigned int, std::string> POSE_BODY_23_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"RShoulder\"},\n        {2,  \"RElbow\"},\n        {3,  \"RWrist\"},\n        {4,  \"LShoulder\"},\n        {5,  \"LElbow\"},\n        {6,  \"LWrist\"},\n        {7,  \"RHip\"},\n        {8,  \"RKnee\"},\n        {9,  \"RAnkle\"},\n        {10, \"LHip\"},\n        {11, \"LKnee\"},\n        {12, \"LAnkle\"},\n        {13, \"REye\"},\n        {14, \"LEye\"},\n        {15, \"REar\"},\n        {16, \"LEar\"},\n        {17, \"LBigToe\"},\n        {18, \"LSmallToe\"},\n        {19, \"LHeel\"},\n        {20, \"RBigToe\"},\n        {21, \"RSmallToe\"},\n        {22, \"RHeel\"},\n        {23, \"Background\"}\n    };\n    const std::map<unsigned int, std::string> POSE_BODY_25B_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"LEye\"},\n        {2,  \"REye\"},\n        {3,  \"LEar\"},\n        {4,  \"REar\"},\n        {5,  \"LShoulder\"},\n        {6,  \"RShoulder\"},\n        {7,  \"LElbow\"},\n        {8,  \"RElbow\"},\n        {9,  \"LWrist\"},\n        {10, \"RWrist\"},\n        {11, \"LHip\"},\n        {12, \"RHip\"},\n        {13, \"LKnee\"},\n        {14, \"RKnee\"},\n        {15, \"LAnkle\"},\n        {16, \"RAnkle\"},\n        {17, \"Neck\"},\n        {18, \"HeadTop\"},\n        {19, \"LBigToe\"},\n        {20, \"LSmallToe\"},\n        {21, \"LHeel\"},\n        {22, \"RBigToe\"},\n        {23, \"RSmallToe\"},\n        {24, \"RHeel\"},\n    };\n    const std::map<unsigned int, std::string> POSE_BODY_135_BODY_PARTS {\n        {0,  \"Nose\"},\n        {1,  \"LEye\"},\n        {2,  \"REye\"},\n        {3,  \"LEar\"},\n        {4,  \"REar\"},\n        {5,  \"LShoulder\"},\n        {6,  \"RShoulder\"},\n        {7,  \"LElbow\"},\n        {8,  \"RElbow\"},\n        {9,  \"LWrist\"},\n        {10, \"RWrist\"},\n        {11, \"LHip\"},\n        {12, \"RHip\"},\n        {13, \"LKnee\"},\n        {14, \"RKnee\"},\n        {15, \"LAnkle\"},\n        {16, \"RAnkle\"},\n        {17, \"UpperNeck\"},\n        {18, \"HeadTop\"},\n        {19, \"LBigToe\"},\n        {20, \"LSmallToe\"},\n        {21, \"LHeel\"},\n        {22, \"RBigToe\"},\n        {23, \"RSmallToe\"},\n        {24, \"RHeel\"},\n        // Left hand\n        {H135+0, \"LThumb1CMC\"},       {H135+1, \"LThumb2Knuckles\"}, {H135+2, \"LThumb3IP\"},   {H135+3, \"LThumb4FingerTip\"},\n        {H135+4, \"LIndex1Knuckles\"},  {H135+5, \"LIndex2PIP\"},      {H135+6, \"LIndex3DIP\"},  {H135+7, \"LIndex4FingerTip\"},\n        {H135+8, \"LMiddle1Knuckles\"}, {H135+9, \"LMiddle2PIP\"},     {H135+10, \"LMiddle3DIP\"},{H135+11, \"LMiddle4FingerTip\"},\n        {H135+12, \"LRing1Knuckles\"},  {H135+13, \"LRing2PIP\"},      {H135+14, \"LRing3DIP\"},  {H135+15, \"LRing4FingerTip\"},\n        {H135+16, \"LPinky1Knuckles\"}, {H135+17, \"LPinky2PIP\"},     {H135+18, \"LPinky3DIP\"}, {H135+19, \"LPinky4FingerTip\"},\n        // Right hand\n        {H135+20, \"RThumb1CMC\"},      {H135+21, \"RThumb2Knuckles\"},{H135+22, \"RThumb3IP\"},  {H135+23, \"RThumb4FingerTip\"},\n        {H135+24, \"RIndex1Knuckles\"}, {H135+25, \"RIndex2PIP\"},     {H135+26, \"RIndex3DIP\"}, {H135+27, \"RIndex4FingerTip\"},\n        {H135+28, \"RMiddle1Knuckles\"},{H135+29, \"RMiddle2PIP\"},    {H135+30, \"RMiddle3DIP\"},{H135+31, \"RMiddle4FingerTip\"},\n        {H135+32, \"RRing1Knuckles\"},  {H135+33, \"RRing2PIP\"},      {H135+34, \"RRing3DIP\"},  {H135+35, \"RRing4FingerTip\"},\n        {H135+36, \"RPinky1Knuckles\"}, {H135+37, \"RPinky2PIP\"},     {H135+38, \"RPinky3DIP\"}, {H135+39, \"RPinky4FingerTip\"},\n        // Face\n        {F135+0, \"FaceContour0\"},   {F135+1, \"FaceContour1\"},   {F135+2, \"FaceContour2\"},   {F135+3, \"FaceContour3\"},   {F135+4, \"FaceContour4\"},   {F135+5, \"FaceContour5\"},   // Contour 1/3\n        {F135+6, \"FaceContour6\"},   {F135+7, \"FaceContour7\"},   {F135+8, \"FaceContour8\"},   {F135+9, \"FaceContour9\"},   {F135+10, \"FaceContour10\"}, {F135+11, \"FaceContour11\"}, // Contour 2/3\n        {F135+12, \"FaceContour12\"}, {F135+13, \"FaceContour13\"}, {F135+14, \"FaceContour14\"}, {F135+15, \"FaceContour15\"}, {F135+16, \"FaceContour16\"},                             // Contour 3/3\n        {F135+17, \"REyeBrow0\"},  {F135+18, \"REyeBrow1\"},  {F135+19, \"REyeBrow2\"},  {F135+20, \"REyeBrow3\"},  {F135+21, \"REyeBrow4\"}, // Right eyebrow\n        {F135+22, \"LEyeBrow4\"},  {F135+23, \"LEyeBrow3\"},  {F135+24, \"LEyeBrow2\"},  {F135+25, \"LEyeBrow1\"},  {F135+26, \"LEyeBrow0\"}, // Left eyebrow\n        {F135+27, \"NoseUpper0\"}, {F135+28, \"NoseUpper1\"}, {F135+29, \"NoseUpper2\"}, {F135+30, \"NoseUpper3\"}, // Upper nose\n        {F135+31, \"NoseLower0\"}, {F135+32, \"NoseLower1\"}, {F135+33, \"NoseLower2\"}, {F135+34, \"NoseLower3\"}, {F135+35, \"NoseLower4\"}, // Lower nose\n        {F135+36, \"REye0\"}, {F135+37, \"REye1\"}, {F135+38, \"REye2\"}, {F135+39, \"REye3\"}, {F135+40, \"REye4\"}, {F135+41, \"REye5\"}, // Right eye\n        {F135+42, \"LEye0\"}, {F135+43, \"LEye1\"}, {F135+44, \"LEye2\"}, {F135+45, \"LEye3\"}, {F135+46, \"LEye4\"}, {F135+47, \"LEye5\"}, // Left eye\n        {F135+48, \"OMouth0\"}, {F135+49, \"OMouth1\"}, {F135+50, \"OMouth2\"}, {F135+51, \"OMouth3\"}, {F135+52, \"OMouth4\"}, {F135+53, \"OMouth5\"}, // Outer mouth 1/2\n        {F135+54, \"OMouth6\"}, {F135+55, \"OMouth7\"}, {F135+56, \"OMouth8\"}, {F135+57, \"OMouth9\"}, {F135+58, \"OMouth10\"}, {F135+59, \"OMouth11\"}, // Outer mouth 2/2\n        {F135+60, \"IMouth0\"}, {F135+61, \"IMouth1\"}, {F135+62, \"IMouth2\"}, {F135+63, \"IMouth3\"}, {F135+64, \"IMouth4\"}, {F135+65, \"IMouth5\"}, {F135+66, \"IMouth6\"}, {F135+67, \"IMouth7\"}, // Inner mouth\n        {F135+68, \"RPupil\"}, {F135+69, \"LPupil\"}, // Pupils\n    };\n    // Hand legend:\n    //     - Thumb:\n    //         - Carpometacarpal Joints (CMC)\n    //         - Interphalangeal Joints (IP)\n    //     - Other fingers:\n    //         - Knuckles or Metacarpophalangeal Joints (MCP)\n    //         - PIP (Proximal Interphalangeal Joints)\n    //         - DIP (Distal Interphalangeal Joints)\n    //     - All fingers:\n    //         - Fingertips\n    // More information: Page 6 of http://www.mccc.edu/~behrensb/documents/TheHandbig.pdf\n    const std::map<unsigned int, std::string> POSE_CAR_12_PARTS {\n        {0,  \"FRWheel\"},\n        {1,  \"FLWheel\"},\n        {2,  \"BRWheel\"},\n        {3,  \"BLWheel\"},\n        {4,  \"FRLight\"},\n        {5,  \"FLLight\"},\n        {6,  \"BRLight\"},\n        {7,  \"BLLight\"},\n        {8,  \"FRTop\"},\n        {9,  \"FLTop\"},\n        {10, \"BRTop\"},\n        {11, \"BLTop\"},\n        {12, \"Background\"},\n    };\n    const std::map<unsigned int, std::string> POSE_CAR_22_PARTS {\n        {0,  \"FLWheel\"},\n        {1,  \"BLWheel\"},\n        {2,  \"FRWheel\"},\n        {3,  \"BRWheel\"},\n        {4,  \"FRFogLight\"},\n        {5,  \"FLFogLight\"},\n        {6,  \"FRLight\"},\n        {7,  \"FLLight\"},\n        {8,  \"Grilles\"},\n        {9,  \"FBumper\"},\n        {10, \"LMirror\"},\n        {11, \"RMirror\"},\n        {12, \"FRTop\"},\n        {13, \"FLTop\"},\n        {14, \"BLTop\"},\n        {15, \"BRTop\"},\n        {16, \"BLLight\"},\n        {17, \"BRLight\"},\n        {18, \"Trunk\"},\n        {19, \"BBumper\"},\n        {20, \"BLCorner\"},\n        {21, \"BRCorner\"},\n        {22, \"Background\"},\n    };\n    const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_MAP_INDEX{\n        // BODY_25\n        std::vector<unsigned int>{\n            0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29, 40,41,42,43,44,45, 46,47,48,49,50,51\n        },\n        // COCO\n        std::vector<unsigned int>{\n            12,13, 20,21, 14,15, 16,17, 22,23, 24,25, 0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 28,29, 30,31, 34,35, 32,33, 36,37, 18,19, 26,27\n        },\n        // MPI_15\n        std::vector<unsigned int>{\n            0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 12,13, 14,15, 16,17, 18,19, 20,21, 22,23, 24,25, 26,27\n        },\n        // MPI_15_4\n        std::vector<unsigned int>{\n            0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 12,13, 14,15, 16,17, 18,19, 20,21, 22,23, 24,25, 26,27\n        },\n        // BODY_19\n        std::vector<unsigned int>{\n            0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29\n        },\n        // BODY_19_X2\n        std::vector<unsigned int>{\n            0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29\n        },\n        // BODY_19N\n        std::vector<unsigned int>{\n            0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29\n        },\n        // BODY_25E\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            0,1,   2,3,   4,5,   6,7,   8,9,  10,11,  12,13, 14,15, 16,17, 18,19, 20,21, 22,23, 24,25, 26,27, 28,29, 30,31, 32,33, 34,35, 36,37, 38,39, 40,41, 42,43, 44,45, 46,47,\n            // Redundant ones\n            48,49, 50,51, 52,53, 54,55, 56,57, 58,59, 60,61, 62,63, 64,65, 66,67, 68,69, 70,71, 72,73, 74,75\n        },\n        // CAR_12\n        std::vector<unsigned int>{\n            0,1,   2,3,   4,5,   6,7,   8,9,  10,11,  12,13, 14,15, 16,17, 18,19, 20,21\n        },\n        // BODY_25D\n        std::vector<unsigned int>{\n            0,1, 14,15, 22,23, 16,17, 18,19, 24,25, 26,27, 6,7, 2,3, 4,5, 8,9, 10,11, 12,13, 30,31, 32,33, 36,37, 34,35, 38,39, 20,21, 28,29, 40,41,42,43,44,45, 46,47,48,49,50,51\n        },\n        // BODY_23\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            0,1, 2,3, 4,5, 6,7, 8,9, 10,11, 12,13, 14,15, 16,17, 18,19, 20,21, 22,23, 24,25, 26,27, 28,29, 30,31, 32,33, 34,35, 36,37, 38,39, 40,41, 42,43,\n            // Redundant ones\n               44,45,46,47,    48,49,50,51,  52,53,54,55,    56,57,58,59,  60,61, 62,63,  64,65,66,67,    68,69, 70,71\n        },\n        // CAR_22\n        std::vector<unsigned int>{\n            0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,\n            38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63\n        },\n        // BODY_19E\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            0,1,   2,3,   4,5,   6,7,   8,9,  10,11,  12,13, 14,15, 16,17, 18,19, 20,21, 22,23, 24,25, 26,27, 28,29, 30,31, 32,33, 34,35, 36,37,\n            // Redundant ones\n            38,39, 40,41, 42,43, 44,45, 46,47, 48,49, 50,51, 52,53, 54,55, 56,57, 58,59, 60,61\n        },\n        // BODY_25B\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            // |------------------------------------------- COCO Body -------------------------------------------|\n            0,1, 2,3, 4,5, 6,7,   8,9,10,11, 12,13,14,15,16,17,18,19, 20,21, 22,23,  24,25, 26,27,   28,29, 30,31,\n            // Redundant ones\n            // |------------------ Foot ------------------| |-- MPII --|\n               32,33, 34,35, 36,37,   38,39, 40,41, 42,43,  44,45, 46,47,\n            // Redundant ones\n            // MPII redundant, ears, ears-shoulders, shoulders-wrists, wrists, wrists-hips, hips, ankles)\n                48,49, 50,51, 52,53,  54,55, 56,57,    58,59, 60,61,   62,63, 64,65, 66,67, 68,69, 70,71\n        },\n        // BODY_135\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            // |------------------------------------------- COCO Body -------------------------------------------|\n            0,1, 2,3, 4,5, 6,7,   8,9,10,11, 12,13,14,15,16,17,18,19, 20,21, 22,23,  24,25, 26,27,   28,29, 30,31,\n            // Redundant ones\n            // |------------------ Foot ------------------| |-- MPII --|\n               32,33, 34,35, 36,37,   38,39, 40,41, 42,43,  44,45, 46,47,\n            // Redundant ones\n            // MPII redundant, ears, ears-shoulders, shoulders-wrists, wrists, wrists-hips, hips, ankles)\n                   48,49,     50,51,  52,53, 54,55,    56,57, 58,59,   60,61, 62,63, 64,65, 66,67, 68,69,\n            // Hand\n            // Left Hand\n                70,71, 72,73, 74,75, 76,77, 78,79,   80,81, 82,83, 84,85, 86,87, 88,89,\n                90,91, 92,93, 94,95, 96,97, 98,99,   100,101, 102,103, 104,105, 106,107, 108,109,\n            // Right Hand\n                110,111, 112,113, 114,115, 116,117, 118,119,   120,121, 122,123, 124,125, 126,127, 128,129,\n                130,131, 132,133, 134,135, 136,137, 138,139,   140,141, 142,143, 144,145, 146,147, 148,149,\n            // Face\n            // COCO-Face\n               150,151, 152,153, 154,155,\n            // Contour\n               156,157, 158,159, 160,161, 162,163, 164,165, 166,167, 168,169, 170,171, 172,173, 174,175, 176,177, 178,179, 180,181,\n               182,183, 184,185, 186,187,\n            // Countour-Eyebrow + Eyebrows\n               188,189, 190,191, 192,193, 194,195, 196,197, 198,199, 200,201, 202,203, 204,205, 206,207, 208,209,\n            // Eyebrow-Nose + Nose\n               210,211, 212,213, 214,215, 216,217, 218,219, 220,221, 222,223, 224,225, 226,227, 228,229,\n            // Nose-Eyes + Eyes\n               230,231, 232,233, 234,235, 236,237, 238,239, 240,241, 242,243, 244,245, 246,247, 248,249, 250,251,\n               252,253,\n            // Nose-Mouth + Outer Mouth\n               254,255, 256,257, 258,259, 260,261, 262,263, 264,265, 266,267, 268,269, 270,271, 272,273, 274,275,\n               276,277,\n            // Outer-Inner + Inner Mouth\n               278,279, 280,281, 282,283, 284,285, 286,287, 288,289, 290,291, 292,293, 294,295,\n            // Eyes-Pupils\n               296,297, 298,299, 300,301, 302,303\n        },\n    };\n    // POSE_BODY_PART_MAPPING on HPP crashes on Windows at dynamic initialization if it's on hpp\n    const std::array<std::map<unsigned int, std::string>, (int)PoseModel::Size> POSE_BODY_PART_MAPPING{\n        POSE_BODY_25_BODY_PARTS,POSE_COCO_BODY_PARTS,   POSE_MPI_BODY_PARTS,    POSE_MPI_BODY_PARTS,\n        POSE_BODY_19_BODY_PARTS,POSE_BODY_19_BODY_PARTS,POSE_BODY_19_BODY_PARTS,POSE_BODY_25_BODY_PARTS,\n        POSE_CAR_12_PARTS,      POSE_BODY_25_BODY_PARTS,POSE_BODY_23_BODY_PARTS,POSE_CAR_22_PARTS,\n        POSE_BODY_19_BODY_PARTS,POSE_BODY_25B_BODY_PARTS,POSE_BODY_135_BODY_PARTS\n    };\n\n    const std::array<std::string, (int)PoseModel::Size> POSE_PROTOTXT{\n        \"pose/body_25/pose_deploy.prototxt\",\n        \"pose/coco/pose_deploy_linevec.prototxt\",\n        \"pose/mpi/pose_deploy_linevec.prototxt\",\n        \"pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt\",\n        \"pose/body_19/pose_deploy.prototxt\",\n        \"pose/body_19_x2/pose_deploy.prototxt\",\n        \"pose/body_19n/pose_deploy.prototxt\",\n        \"pose/body_25e/pose_deploy.prototxt\",\n        \"car/car_12/pose_deploy.prototxt\",\n        \"pose/body_25d/pose_deploy.prototxt\",\n        \"pose/body_23/pose_deploy.prototxt\",\n        \"car/car_22/pose_deploy.prototxt\",\n        \"pose/body_19e/pose_deploy.prototxt\",\n        \"pose/body_25b/pose_deploy.prototxt\",\n        \"pose/body_135/pose_deploy.prototxt\",\n    };\n    const std::array<std::string, (int)PoseModel::Size> POSE_TRAINED_MODEL{\n        \"pose/body_25/pose_iter_584000.caffemodel\",\n        \"pose/coco/pose_iter_440000.caffemodel\",\n        \"pose/mpi/pose_iter_160000.caffemodel\",\n        \"pose/mpi/pose_iter_160000.caffemodel\",\n        \"pose/body_19/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_19_x2/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_19n/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_25e/pose_iter_XXXXXX.caffemodel\",\n        \"car/car_12/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_25d/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_23/pose_iter_XXXXXX.caffemodel\",\n        \"car/car_22/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_19e/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_25b/pose_iter_XXXXXX.caffemodel\",\n        \"pose/body_135/pose_iter_XXXXXX.caffemodel\",\n    };\n\n    // Constant Array Parameters\n    // POSE_NUMBER_BODY_PARTS equivalent to size of std::map POSE_BODY_XX_BODY_PARTS - 1 (removing background)\n    const std::array<unsigned int, (int)PoseModel::Size> POSE_NUMBER_BODY_PARTS{\n        25, 18, 15, 15, 19, 19, 19, 25, 12, 25, 23, 22, 19, 25, 135\n    };\n    const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS{\n        // BODY_25\n        std::vector<unsigned int>{\n            1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18,   14,19,19,20,14,21, 11,22,22,23,11,24\n        },\n        // COCO\n        std::vector<unsigned int>{\n            1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   1,8,   8,9,   9,10,  1,11,  11,12, 12,13,  1,0,   0,14, 14,16,  0,15, 15,17,  2,16,  5,17\n        },\n        // MPI_15\n        std::vector<unsigned int>{POSE_MPI_PAIRS_RENDER_GPU},\n        // MPI_15_4\n        std::vector<unsigned int>{POSE_MPI_PAIRS_RENDER_GPU},\n        // BODY_19\n        std::vector<unsigned int>{\n            1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18\n        },\n        // BODY_19_X2\n        std::vector<unsigned int>{\n            1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18\n        },\n        // BODY_19N\n        std::vector<unsigned int>{\n            1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18\n        },\n        // BODY_25E\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            1,8,   1,2, 2,3, 3,4,   1,5, 5,6, 6,7,   8,9, 9,10, 10,11,   8,12, 12,13, 13,14,   1,0, 0,15, 15,17, 0,16, 16,18,\n            // Foot (minimum spanning tree)\n            14,19,19,20,14,21, 11,22,22,23,11,24,\n            // Redundant ones\n            // Ears-shoulders, shoulders-hips, shoulders-wrists, hips-ankles, wrists,  ankles, wrists-hips, small toes-ankles)\n                 2,17, 5,18,        2,9, 5,12,      2,4, 5,7,    9,11, 12,14,   4,7,   11,14,   4,9, 7,12,   11,23, 14,20\n        },\n        // CAR_12\n        std::vector<unsigned int>{\n            4,5,   4,6,   4,0,   0,2,   4,8,   8,10,   5,7,   5,1,   1,3,   5,9,   9,11\n        },\n        // BODY_25D\n        std::vector<unsigned int>{\n            1,8,   1,2,   1,5,   2,3,   3,4,   5,6,   6,7,   8,9,   9,10,  10,11, 8,12,  12,13, 13,14,  1,0,   0,15, 15,17,  0,16, 16,18,   2,17,  5,18,   14,19,19,20,14,21, 11,22,22,23,11,24\n        },\n        // BODY_23\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            0,1, 1,2, 2,3, 0,4, 4,5,  5,6,   7,8,   8,9,  10,11, 11,12,  0,13, 13,15,  0,14, 14,16, 12,17, 17,18, 12,19,  9,20, 20,21,  9,22,  1,7,   4,10,\n            // Redundant ones\n            // Ears-shoulders, ears,  hips, shoulders-wrists, hips-ankles, wrists, ankles, wrists-hips, small toes-ankles)\n            //     +2.4%       +0.2%  +0.3%      +0.1%       -0.1% (bad!)  +0.2%   +0.2%      +0.1%       -0.1% (bad!)\n                1,15, 4,16,    15,16, 7,10,    1,3, 4,6,      7,9, 10,12,   3,6,   9,12,    3,7, 6,10,     9,21, 12,18\n        },\n        // CAR_22\n        std::vector<unsigned int>{\n        //       Wheels                Lights                   Top                       Front                Mirrors\n            0,1,1,3,3,2,2,0,   6,7,7,16,16,17,17,6,   12,13,13,14,14,15,15,12,   6,8,7,8,6,9,7,9,6,4,7,5,   12,11,13,10,\n        //            Back                  Vertical         Back-light replacement\n            16,18,17,18,16,19,17,19,   0,7,3,17,6,12,16,14,   6,21,7,20,3,21,20,14\n        },\n        // BODY_19E\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            1,8,   1,2, 2,3, 3,4,   1,5, 5,6, 6,7,   8,9, 9,10, 10,11,   8,12, 12,13, 13,14,   1,0, 0,15, 15,17, 0,16, 16,18,\n            // Redundant ones\n            // Ears-shoulders, shoulders-hips, shoulders-wrists, hips-ankles, wrists,  ankles, wrists-hips, small toes-ankles)\n                 2,17, 5,18,        2,9, 5,12,      2,4, 5,7,    9,11, 12,14,   4,7,   11,14,   4,9, 7,12//,   11,23, 14,20\n        },\n        // BODY_25B\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            // |------------------------------------------- COCO Body -------------------------------------------|\n            0,1, 0,2, 1,3, 2,4,   0,5, 0,6,   5,7, 6,8,   7,9, 8,10,   5,11, 6,12,   11,13, 12,14,   13,15, 14,16,\n            // |------------------ Foot ------------------| |-- MPII --|\n               15,19, 19,20, 15,21,   16,22, 22,23, 16,24,   5,17, 5,18,\n            // Redundant ones\n            // MPII redundant, ears, ears-shoulders, shoulders-wrists, wrists, wrists-hips, hips, ankles)\n                 6,17, 6,18,   3,4,     3,5, 4,6,        5,9, 6,10,     9,10,  9,11, 10,12, 11,12, 15,16\n        },\n        // BODY_135\n        std::vector<unsigned int>{\n            // Minimum spanning tree\n            // |------------------------------------------- COCO Body -------------------------------------------|\n            0,1, 0,2, 1,3, 2,4,   0,5, 0,6,   5,7, 6,8,   7,9, 8,10,   5,11, 6,12,   11,13, 12,14,   13,15, 14,16,\n            // |------------------ Foot ------------------| |-- MPII --|\n               15,19, 19,20, 15,21,   16,22, 22,23, 16,24,   5,17,17,18,\n            // Redundant ones\n            // MPII redundant, ears, ears-shoulders, shoulders-wrists, wrists, wrists-hips, hips, ankles)\n                    6,17,      3,4,     3,5, 4,6,        5,9, 6,10,     9,10,  9,11, 10,12, 11,12, 15,16,\n            // Left Hand\n               9,H135+0, H135+0,H135+1, H135+1,H135+2, H135+2,H135+3,           9,H135+4, H135+4,H135+5, H135+5,H135+6, H135+6,H135+7,\n               9,H135+8, H135+8,H135+9, H135+9,H135+10, H135+10,H135+11,        9,H135+12, H135+12,H135+13, H135+13,H135+14, H135+14,H135+15,\n               9,H135+16, H135+16,H135+17, H135+17,H135+18, H135+18,H135+19,\n            // Right Hand\n               10,H135+20, H135+20,H135+21, H135+21,H135+22, H135+22,H135+23,   10,H135+24, H135+24,H135+25, H135+25,H135+26, H135+26,H135+27,\n               10,H135+28, H135+28,H135+29, H135+29,H135+30, H135+30,H135+31,   10,H135+32, H135+32,H135+33, H135+33,H135+34, H135+34,H135+35,\n               10,H135+36, H135+36,H135+37, H135+37,H135+38, H135+38,H135+39,\n            // Face\n            // COCO-Face\n            0,F135+30, 2,F135+39,1,F135+42,\n            // Contour\n               F135+0,F135+1, F135+1,F135+2, F135+2,F135+3, F135+3,F135+4, F135+4,F135+5, F135+5,F135+6, F135+6,F135+7, F135+7,F135+8,\n               F135+8,F135+9, F135+9,F135+10, F135+10,F135+11, F135+11,F135+12, F135+12,F135+13, F135+13,F135+14, F135+14,F135+15,\n               F135+15,F135+16,\n            // Countour-Eyebrow + Eyebrows\n               F135+0,F135+17, F135+16,F135+26, F135+17,F135+18, F135+18,F135+19, F135+19,F135+20, F135+20,F135+21, F135+21,F135+22,\n               F135+22,F135+23, F135+23,F135+24, F135+24,F135+25, F135+25,F135+26,\n            // Eyebrow-Nose + Nose\n               F135+21,F135+27, F135+22,F135+27, F135+27,F135+28, F135+28,F135+29, F135+29,F135+30, F135+30,F135+33, F135+33,F135+32,\n               F135+32,F135+31, F135+33,F135+34, F135+34,F135+35,\n            // Nose-Eyes + Eyes\n               F135+27,F135+39, F135+27,F135+42, F135+36,F135+37, F135+37,F135+38, F135+38,F135+39, F135+39,F135+40, F135+40,F135+41,\n               F135+42,F135+43, F135+43,F135+44, F135+44,F135+45, F135+45,F135+46, F135+46,F135+47,\n            // Nose-Mouth + Outer Mouth\n               F135+33,F135+51, F135+48,F135+49, F135+49,F135+50, F135+50,F135+51, F135+51,F135+52, F135+52,F135+53, F135+53,F135+54,\n               F135+54,F135+55, F135+55,F135+56, F135+56,F135+57, F135+57,F135+58, F135+58,F135+59,\n            // Outer-Inner + Inner Mouth\n               F135+48,F135+60, F135+54,F135+64, F135+60,F135+61, F135+61,F135+62, F135+62,F135+63, F135+63,F135+64, F135+64,F135+65,\n               F135+65,F135+66, F135+66,F135+67,\n            // Eyes-Pupils\n               F135+36,F135+68, F135+39,F135+68, F135+42,F135+69, F135+45,F135+69\n        }\n    };\n\n    const std::map<unsigned int, std::string>& getPoseBodyPartMapping(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_BODY_PART_MAPPING.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_BODY_PART_MAPPING[(int)poseModel];\n        }\n    }\n\n    const std::string& getPoseProtoTxt(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_PROTOTXT.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_PROTOTXT[(int)poseModel];\n        }\n    }\n\n    const std::string& getPoseTrainedModel(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_TRAINED_MODEL.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_TRAINED_MODEL[(int)poseModel];\n        }\n    }\n\n    unsigned int getPoseNumberBodyParts(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_NUMBER_BODY_PARTS.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0u;\n        }\n    }\n\n    const std::vector<unsigned int>& getPosePartPairs(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_BODY_PART_PAIRS.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_BODY_PART_PAIRS[(int)poseModel];\n        }\n    }\n\n    const std::vector<unsigned int>& getPoseMapIndex(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_MAP_INDEX.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_MAP_INDEX[(int)poseModel];\n        }\n    }\n\n    unsigned int getPoseMaxPeaks()\n    {\n        try\n        {\n            return POSE_MAX_PEOPLE;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0u;\n        }\n    }\n\n    float getPoseNetDecreaseFactor(const PoseModel poseModel)\n    {\n        try\n        {\n            return (poseModel != PoseModel::BODY_19_X2 ? 8.f : 4.f);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector<std::string>& strings)\n    {\n        try\n        {\n            const auto& poseBodyPartMapping = POSE_BODY_PART_MAPPING[(int)poseModel];\n            for (const auto& string : strings)\n                for (const auto& pair : poseBodyPartMapping)\n                    if (pair.second == string)\n                        return pair.first;\n            error(\"String(s) could not be found.\", __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string)\n    {\n        try\n        {\n            return poseBodyPartMapStringToKey(poseModel, std::vector<std::string>{string});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n\n    // Default Model Parameters\n    // They might be modified on running time\n    float getPoseDefaultNmsThreshold(const PoseModel poseModel, const bool maximizePositives)\n    {\n        try\n        {\n            // MPI models\n            if (poseModel == PoseModel::MPI_15)\n                return 0.6f;\n            else if (poseModel == PoseModel::MPI_15_4)\n                return 0.3f;\n            // Non-MPI models\n            else\n                return (maximizePositives ? 0.02f : 0.05f);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    float getPoseDefaultConnectInterMinAboveThreshold(const bool maximizePositives)\n    {\n        try\n        {\n            return (maximizePositives ? 0.75f : 0.95f);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    float getPoseDefaultConnectInterThreshold(const PoseModel poseModel, const bool maximizePositives)\n    {\n        try\n        {\n            // MPI models\n            if (poseModel == PoseModel::MPI_15 || poseModel == PoseModel::MPI_15_4)\n                return 0.01f;\n            // Non-MPI models\n            else\n                // return (maximizePositives ? 0.01f : 0.5f); // 0.485 but much less false positive connections\n                // return (maximizePositives ? 0.01f : 0.1f); // 0.518\n                // return (maximizePositives ? 0.01f : 0.075f); // 0.521\n                return (maximizePositives ? 0.01f : 0.05f); // 0.523\n                // return (maximizePositives ? 0.01f : 0.01f); // 0.527 but huge amount of false positives joints\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    unsigned int getPoseDefaultMinSubsetCnt(const bool maximizePositives)\n    {\n        try\n        {\n            return (maximizePositives ? 2u : 3u);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0u;\n        }\n    }\n\n    float getPoseDefaultConnectMinSubsetScore(const bool maximizePositives)\n    {\n        try\n        {\n            return (maximizePositives ? 0.05f : 0.4f);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    bool addBkgChannel(const PoseModel poseModel)\n    {\n        try\n        {\n            return (POSE_BODY_PART_MAPPING[(int)poseModel].size() != POSE_NUMBER_BODY_PARTS[(int)poseModel]);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseParametersRender.cpp",
    "content": "#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/pose/poseParameters.hpp>\n\nnamespace op\n{\n    const std::array<std::vector<float>, (int)PoseModel::Size> POSE_SCALES{\n        std::vector<float>{POSE_BODY_25_SCALES_RENDER_GPU},       // BODY_25\n        std::vector<float>{POSE_COCO_SCALES_RENDER_GPU},          // COCO\n        std::vector<float>{POSE_MPI_SCALES_RENDER_GPU},           // MPI_15\n        std::vector<float>{POSE_MPI_SCALES_RENDER_GPU},           // MPI_15_4\n        std::vector<float>{POSE_BODY_19_SCALES_RENDER_GPU},       // BODY_19\n        std::vector<float>{POSE_BODY_19_SCALES_RENDER_GPU},       // BODY_19_X2\n        std::vector<float>{POSE_BODY_19_SCALES_RENDER_GPU},       // BODY_19N\n        std::vector<float>{POSE_BODY_25_SCALES_RENDER_GPU},       // BODY_25E\n        std::vector<float>{POSE_CAR_12_SCALES_RENDER_GPU},        // CAR_12\n        std::vector<float>{POSE_BODY_25_SCALES_RENDER_GPU},       // BODY_25D\n        std::vector<float>{POSE_BODY_23_SCALES_RENDER_GPU},       // BODY_23\n        std::vector<float>{POSE_CAR_22_SCALES_RENDER_GPU},        // CAR_22\n        std::vector<float>{POSE_BODY_19_SCALES_RENDER_GPU},       // BODY_19E\n        std::vector<float>{POSE_BODY_25B_SCALES_RENDER_GPU},      // BODY_25B\n        std::vector<float>{POSE_BODY_135_SCALES_RENDER_GPU},      // BODY_135\n    };\n    const std::array<std::vector<float>, (int)PoseModel::Size> POSE_COLORS{\n        std::vector<float>{POSE_BODY_25_COLORS_RENDER_GPU},       // BODY_25\n        std::vector<float>{POSE_COCO_COLORS_RENDER_GPU},          // COCO\n        std::vector<float>{POSE_MPI_COLORS_RENDER_GPU},           // MPI_15\n        std::vector<float>{POSE_MPI_COLORS_RENDER_GPU},           // MPI_15_4\n        std::vector<float>{POSE_BODY_19_COLORS_RENDER_GPU},       // BODY_19\n        std::vector<float>{POSE_BODY_19_COLORS_RENDER_GPU},       // BODY_19_X2\n        std::vector<float>{POSE_BODY_19_COLORS_RENDER_GPU},       // BODY_19N\n        std::vector<float>{POSE_BODY_25_COLORS_RENDER_GPU},       // BODY_25E\n        std::vector<float>{POSE_CAR_12_COLORS_RENDER_GPU},        // CAR_12\n        std::vector<float>{POSE_BODY_25_COLORS_RENDER_GPU},       // BODY_25D\n        std::vector<float>{POSE_BODY_23_COLORS_RENDER_GPU},       // BODY_23\n        std::vector<float>{POSE_CAR_22_COLORS_RENDER_GPU},        // CAR_22\n        std::vector<float>{POSE_BODY_19_COLORS_RENDER_GPU},       // BODY_19E\n        std::vector<float>{POSE_BODY_25B_COLORS_RENDER_GPU},      // BODY_25B\n        std::vector<float>{POSE_BODY_135_COLORS_RENDER_GPU},      // BODY_135\n    };\n    const std::array<std::vector<unsigned int>, (int)PoseModel::Size> POSE_BODY_PART_PAIRS_RENDER{\n        std::vector<unsigned int>{POSE_BODY_25_PAIRS_RENDER_GPU},       // BODY_25\n        std::vector<unsigned int>{POSE_COCO_PAIRS_RENDER_GPU},          // COCO\n        std::vector<unsigned int>{POSE_MPI_PAIRS_RENDER_GPU},           // MPI_15\n        std::vector<unsigned int>{POSE_MPI_PAIRS_RENDER_GPU},           // MPI_15_4\n        std::vector<unsigned int>{POSE_BODY_19_PAIRS_RENDER_GPU},       // BODY_19\n        std::vector<unsigned int>{POSE_BODY_19_PAIRS_RENDER_GPU},       // BODY_19_X2\n        std::vector<unsigned int>{POSE_BODY_19_PAIRS_RENDER_GPU},       // BODY_19N\n        std::vector<unsigned int>{POSE_BODY_25_PAIRS_RENDER_GPU},       // BODY_25E\n        std::vector<unsigned int>{POSE_CAR_12_PAIRS_RENDER_GPU},        // CAR_12\n        std::vector<unsigned int>{POSE_BODY_25_PAIRS_RENDER_GPU},       // BODY_25D\n        std::vector<unsigned int>{POSE_BODY_23_PAIRS_RENDER_GPU},       // BODY_23\n        std::vector<unsigned int>{POSE_CAR_22_PAIRS_RENDER_GPU},        // CAR_22\n        std::vector<unsigned int>{POSE_BODY_19_PAIRS_RENDER_GPU},       // BODY_19E\n        std::vector<unsigned int>{POSE_BODY_25B_PAIRS_RENDER_GPU},      // BODY_25B\n        std::vector<unsigned int>{POSE_BODY_135_PAIRS_RENDER_GPU},      // BODY_135\n    };\n\n    // Rendering functions\n    const std::vector<float>& getPoseScales(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_SCALES.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_SCALES[(int)poseModel];\n        }\n    }\n\n    const std::vector<float>& getPoseColors(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_COLORS.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_COLORS[(int)poseModel];\n        }\n    }\n\n    const std::vector<unsigned int>& getPoseBodyPartPairsRender(const PoseModel poseModel)\n    {\n        try\n        {\n            return POSE_BODY_PART_PAIRS_RENDER.at((int)poseModel);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return POSE_BODY_PART_PAIRS_RENDER[(int)poseModel];\n        }\n    }\n\n    unsigned int getNumberElementsToRender(const PoseModel poseModel)\n    {\n        try\n        {\n            return (unsigned int)(getPoseBodyPartMapping(poseModel).size()\n                                  + getPosePartPairs(poseModel).size()/2 + 3\n                                  + (poseModel == PoseModel::BODY_25D\n                                     ? 2*(getPoseNumberBodyParts(poseModel) - 1) : 0)\n                                  );\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0u;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/poseRenderer.cpp",
    "content": "#include <openpose/pose/poseRenderer.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/pose/poseParametersRender.hpp>\n#include <openpose/pose/renderPose.hpp>\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    std::map<unsigned int, std::string> createPartToName(const PoseModel poseModel)\n    {\n        try\n        {\n            // Variables\n            auto partToName = getPoseBodyPartMapping(poseModel);\n            const auto& bodyPartPairs = getPosePartPairs(poseModel);\n            const auto& mapIdx = getPoseMapIndex(poseModel);\n            const auto numberBodyParts = getPoseNumberBodyParts(poseModel);\n            const auto numberBodyPartsPlusBkg = numberBodyParts+(addBkgChannel(poseModel) ? 1 : 0);\n            // Sanity checks\n            if (bodyPartPairs.size() != mapIdx.size())\n                error(\"The variables bodyPartPairs and mapIdx should have the same size (\"\n                      + std::to_string(bodyPartPairs.size()) + \" vs. \"\n                      + std::to_string(mapIdx.size()) + \").\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (partToName.empty())\n                error(\"Variable partToName is empty.\", __LINE__, __FUNCTION__, __FILE__);\n            // PAFs\n            for (auto bodyPart = 0u; bodyPart < bodyPartPairs.size(); bodyPart+=2)\n            {\n                const auto bodyPartPairsA = bodyPartPairs.at(bodyPart);\n                const auto bodyPartPairsB = bodyPartPairs.at(bodyPart+1);\n                const auto mapIdxA = numberBodyPartsPlusBkg + mapIdx.at(bodyPart);\n                const auto mapIdxB = numberBodyPartsPlusBkg + mapIdx.at(bodyPart+1);\n                const auto baseLine = partToName.at(bodyPartPairsA) + \"->\" + partToName.at(bodyPartPairsB);\n                partToName[mapIdxA] = baseLine + \"(X)\";\n                partToName[mapIdxB] = baseLine + \"(Y)\";\n            }\n            // Distance PAFs\n            if (poseModel == PoseModel::BODY_25D)\n            {\n                for (auto bodyPart = 0u; bodyPart < numberBodyParts; bodyPart++)\n                {\n                    if (bodyPart != 1u)\n                    {\n                        const auto mapIdxD = (unsigned int)\n                            (numberBodyPartsPlusBkg + bodyPartPairs.size() + 2*bodyPart - (bodyPart > 0 ? 2 : 0));\n                        const auto baseLine = partToName.at(1) + \"->\" + partToName.at(bodyPart);\n                        partToName[mapIdxD] = baseLine + \"(X)\";\n                        partToName[mapIdxD+1] = baseLine + \"(Y)\";\n                    }\n                }\n            }\n            // Return result\n            return partToName;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::map<unsigned int, std::string>();\n        }\n    }\n\n    PoseRenderer::PoseRenderer(const PoseModel poseModel) :\n        mPoseModel{poseModel},\n        mPartIndexToName{createPartToName(poseModel)}\n    {\n    }\n\n    PoseRenderer::~PoseRenderer()\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/renderPose.cpp",
    "content": "#include <openpose/pose/renderPose.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/keypoint.hpp>\n\nnamespace op\n{\n    void renderPoseKeypointsCpu(Array<float>& frameArray, const Array<float>& poseKeypoints, const PoseModel poseModel,\n                                const float renderThreshold, const bool blendOriginalFrame)\n    {\n        try\n        {\n            if (!frameArray.empty())\n            {\n                // Background\n                if (!blendOriginalFrame)\n                    frameArray.getCvMat().setTo(0.f); // [0-255]\n\n                // Parameters\n                const auto thicknessCircleRatio = 1.f/75.f;\n                const auto thicknessLineRatioWRTCircle = 0.75f;\n                const auto& pairs = getPoseBodyPartPairsRender(poseModel);\n                const auto& poseScales = getPoseScales(poseModel);\n\n                // Render keypoints\n                renderKeypointsCpu(frameArray, poseKeypoints, pairs, getPoseColors(poseModel), thicknessCircleRatio,\n                                   thicknessLineRatioWRTCircle, poseScales, renderThreshold);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/pose/renderPose.cu",
    "content": "#include <openpose/pose/renderPose.hpp>\n#include <openpose/gpu/cuda.hpp>\n#include <openpose/pose/poseParameters.hpp>\n#include <openpose_private/gpu/cuda.hu>\n#include <openpose_private/utilities/render.hu>\n\nnamespace op\n{\n    // PI digits: http://www.piday.org/million/\n    __constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f;\n    // Keypoint pairs\n    __constant__ const unsigned int BODY_25_PAIRS_GPU[] = {POSE_BODY_25_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int COCO_PAIRS_GPU[] = {POSE_COCO_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int BODY_19_PAIRS_GPU[] = {POSE_BODY_19_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int BODY_23_PAIRS_GPU[] = {POSE_BODY_23_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int BODY_25B_PAIRS_GPU[] = {POSE_BODY_25B_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int BODY_135_PAIRS_GPU[] = {POSE_BODY_135_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int MPI_PAIRS_GPU[] = {POSE_MPI_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int CAR_12_PAIRS_GPU[] = {POSE_CAR_12_PAIRS_RENDER_GPU};\n    __constant__ const unsigned int CAR_22_PAIRS_GPU[] = {POSE_CAR_22_PAIRS_RENDER_GPU};\n    // Keypoint scales\n    __constant__ const float BODY_25_SCALES[] = {POSE_BODY_25_SCALES_RENDER_GPU};\n    __constant__ const float COCO_SCALES[] = {POSE_COCO_SCALES_RENDER_GPU};\n    __constant__ const float BODY_19_SCALES[] = {POSE_BODY_19_SCALES_RENDER_GPU};\n    __constant__ const float BODY_23_SCALES[] = {POSE_BODY_23_SCALES_RENDER_GPU};\n    __constant__ const float BODY_25B_SCALES[] = {POSE_BODY_25B_SCALES_RENDER_GPU};\n    __constant__ const float BODY_135_SCALES[] = {POSE_BODY_135_SCALES_RENDER_GPU};\n    __constant__ const float MPI_SCALES[] = {POSE_MPI_SCALES_RENDER_GPU};\n    __constant__ const float CAR_12_SCALES[] = {POSE_CAR_12_SCALES_RENDER_GPU};\n    __constant__ const float CAR_22_SCALES[] = {POSE_CAR_22_SCALES_RENDER_GPU};\n    // RGB colors\n    __constant__ const float BODY_25_COLORS[] = {POSE_BODY_25_COLORS_RENDER_GPU};\n    __constant__ const float COCO_COLORS[] = {POSE_COCO_COLORS_RENDER_GPU};\n    __constant__ const float BODY_19_COLORS[] = {POSE_BODY_19_COLORS_RENDER_GPU};\n    __constant__ const float BODY_23_COLORS[] = {POSE_BODY_23_COLORS_RENDER_GPU};\n    __constant__ const float BODY_25B_COLORS[] = {POSE_BODY_25B_COLORS_RENDER_GPU};\n    __constant__ const float BODY_135_COLORS[] = {POSE_BODY_135_COLORS_RENDER_GPU};\n    __constant__ const float MPI_COLORS[] = {POSE_MPI_COLORS_RENDER_GPU};\n    __constant__ const float CAR_12_COLORS[] = {POSE_CAR_12_COLORS_RENDER_GPU};\n    __constant__ const float CAR_22_COLORS[] = {POSE_CAR_22_COLORS_RENDER_GPU};\n\n\n\n    inline __device__ void getColorHeatMap(float* colorPtr, const float v, const float vmin, const float vmax)\n    {\n        const auto vTrunc = fastTruncateCuda(v, vmin, vmax);\n        const auto dv = vmax - vmin;\n\n        if (vTrunc < (vmin + 0.125f * dv))\n        {\n            colorPtr[0] = 256.f * (0.5f + (vTrunc * 4.f)); //B: 0.5 ~ 1\n            colorPtr[1] = 0.f;\n            colorPtr[2] = 0.f;\n        }\n        else if (vTrunc < (vmin + 0.375f * dv))\n        {\n            colorPtr[0] = 255.f;\n            colorPtr[1] = 256.f * (vTrunc - 0.125f) * 4.f; //G: 0 ~ 1\n            colorPtr[2] = 0.f;\n        }\n        else if (vTrunc < (vmin + 0.625f * dv))\n        {\n            colorPtr[0] = 256.f * (-4.f * vTrunc + 2.5f); //B: 1 ~ 0\n            colorPtr[1] = 255.f;\n            colorPtr[2] = 256.f * (4.f * (vTrunc - 0.375f)); // R: 0 ~ 1\n        }\n        else if (vTrunc < (vmin + 0.875f * dv))\n        {\n            colorPtr[0] = 0.f;\n            colorPtr[1] = 256.f * (-4.f * vTrunc + 3.5f); //G: 1 ~ 0\n            colorPtr[2] = 255.f;\n        }\n        else\n        {\n            colorPtr[0] = 0.f;\n            colorPtr[1] = 0.f;\n            colorPtr[2] = 256.f * (-4.f * vTrunc + 4.5f); //R: 1 ~ 0.5\n        }\n    }\n\n    inline __device__ void getColorAffinity(float3& colorPtr, const float v, const float vmin, const float vmax)\n    {\n        const auto RY = 15;\n        const auto YG =  6;\n        const auto GC =  4;\n        const auto CB = 11;\n        const auto BM = 13;\n        const auto MR =  6;\n        const auto summed = RY+YG+GC+CB+BM+MR;       // 55\n        const auto vTrunc = fastTruncateCuda(v, vmin, vmax) * summed;\n\n        if (vTrunc < RY)\n            colorPtr = {255.f,                              255.f*(vTrunc/(RY)),                0.f};\n        else if (vTrunc < RY+YG)\n            colorPtr = {255.f*(1-((vTrunc-RY)/(YG))),       255.f,                              0.f};\n        else if (vTrunc < RY+YG+GC)\n            colorPtr = {0.f * (1-((vTrunc-RY)/(YG))),       255.f,                              255.f*((vTrunc-RY-YG)/(GC))};\n        else if (vTrunc < RY+YG+GC+CB)\n            colorPtr = {0.f,                                255.f*(1-((vTrunc-RY-YG-GC)/(CB))), 255.f};\n        else if (vTrunc < summed-MR)\n            colorPtr = {255.f*((vTrunc-RY-YG-GC-CB)/(BM)),  0.f,                                255.f};\n        else if (vTrunc < summed)\n            colorPtr = {255.f,                              0.f,                                255.f*(1-((vTrunc-RY-YG-GC-CB-BM)/(MR)))};\n        else\n            colorPtr = {255.f,                              0.f,                                0.f};\n    }\n\n    inline __device__ void getColorXYAffinity(float3& colorPtr, const float x, const float y)\n    {\n        const auto rad = fastMinCuda(1.f, sqrt( x*x + y*y ) );\n        const float a = atan2(-y,-x)/PI;\n        auto fk = (a+1.f)/2.f; // 0 to 1\n        if (::isnan(fk))\n            fk = 0.f;\n        getColorAffinity(colorPtr, fk, 0.f, 1.f);\n        colorPtr.x *= rad;\n        colorPtr.y *= rad;\n        colorPtr.z *= rad;\n    }\n\n    __global__ void getBoundingBoxPerPersonPose(\n        float* maxPtr, float* minPtr, float* scalePtr,const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const keypointsPtr, const int numberPeople, const int numberParts, const float threshold)\n    {\n        getBoundingBoxPerPerson(\n            maxPtr, minPtr, scalePtr, targetWidth, targetHeight, keypointsPtr, numberPeople, numberParts, threshold);\n    }\n\n    __global__ void renderPoseCoco(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(COCO_PAIRS_GPU) / (2*sizeof(COCO_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(COCO_SCALES) / sizeof(COCO_SCALES[0]);\n        const auto numberColors = sizeof(COCO_COLORS) / (3*sizeof(COCO_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, COCO_PAIRS_GPU, numberPeople, 18, numberPartPairs,\n            COCO_COLORS, numberColors, radius, lineWidth, COCO_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1));\n    }\n\n    __global__ void renderPoseBody19(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(BODY_19_PAIRS_GPU) / (2*sizeof(BODY_19_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(BODY_19_SCALES) / sizeof(BODY_19_SCALES[0]);\n        const auto numberColors = sizeof(BODY_19_COLORS) / (3*sizeof(BODY_19_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, BODY_19_PAIRS_GPU, numberPeople, 19, numberPartPairs,\n            BODY_19_COLORS, numberColors, radius, lineWidth, BODY_19_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 15 : -1),\n            (googlyEyes ? 16 : -1));\n    }\n\n    __global__ void renderPoseBody23(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(BODY_23_PAIRS_GPU) / (2*sizeof(BODY_23_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(BODY_23_SCALES) / sizeof(BODY_23_SCALES[0]);\n        const auto numberColors = sizeof(BODY_23_COLORS) / (3*sizeof(BODY_23_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, BODY_23_PAIRS_GPU, numberPeople, 23, numberPartPairs,\n            BODY_23_COLORS, numberColors, radius, lineWidth, BODY_23_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 13 : -1), (googlyEyes ? 14 : -1));\n    }\n\n    __global__ void renderPoseBody25(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const int targetWidth,\n        const int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(BODY_25_PAIRS_GPU) / (2*sizeof(BODY_25_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(BODY_25_SCALES) / sizeof(BODY_25_SCALES[0]);\n        const auto numberColors = sizeof(BODY_25_COLORS) / (3*sizeof(BODY_25_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight,\n            posePtr, BODY_25_PAIRS_GPU, numberPeople, 25, numberPartPairs, BODY_25_COLORS, numberColors,\n            radius, lineWidth, BODY_25_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 15 : -1), (googlyEyes ? 16 : -1));\n    }\n\n    __global__ void renderPoseBody25b(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(BODY_25B_PAIRS_GPU) / (2*sizeof(BODY_25B_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(BODY_25B_SCALES) / sizeof(BODY_25B_SCALES[0]);\n        const auto numberColors = sizeof(BODY_25B_COLORS) / (3*sizeof(BODY_25B_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, BODY_25B_PAIRS_GPU, numberPeople, 25, numberPartPairs,\n            BODY_25B_COLORS, numberColors, radius, lineWidth, BODY_25B_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 1 : -1), (googlyEyes ? 2 : -1));\n    }\n\n    __global__ void renderPoseBody135(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(BODY_135_PAIRS_GPU) / (2*sizeof(BODY_135_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(BODY_135_SCALES) / sizeof(BODY_135_SCALES[0]);\n        const auto numberColors = sizeof(BODY_135_COLORS) / (3*sizeof(BODY_135_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, BODY_135_PAIRS_GPU, numberPeople, 135,\n            numberPartPairs, BODY_135_COLORS, numberColors, radius, lineWidth, BODY_135_SCALES, numberScales,\n            threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 1 : -1), (googlyEyes ? 2 : -1));\n    }\n\n    __global__ void renderPoseMpi29Parts(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(MPI_PAIRS_GPU) / (2*sizeof(MPI_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(MPI_SCALES) / sizeof(MPI_SCALES[0]);\n        const auto numberColors = sizeof(MPI_COLORS) / (3*sizeof(MPI_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, MPI_PAIRS_GPU, numberPeople, 15, numberPartPairs,\n            MPI_COLORS, numberColors, radius, lineWidth, COCO_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame);\n    }\n\n    __global__ void renderPoseCar12(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(CAR_12_PAIRS_GPU) / (2*sizeof(CAR_12_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(CAR_12_SCALES) / sizeof(CAR_12_SCALES[0]);\n        const auto numberColors = sizeof(CAR_12_COLORS) / (3*sizeof(CAR_12_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, CAR_12_PAIRS_GPU, numberPeople, 12, numberPartPairs,\n            CAR_12_COLORS, numberColors, radius, lineWidth, CAR_12_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 4 : -1), (googlyEyes ? 5 : -1));\n    }\n\n    __global__ void renderPoseCar22(\n        float* targetPtr, float* minPtr, float* maxPtr, float* scalePtr, const unsigned int targetWidth,\n        const unsigned int targetHeight, const float* const posePtr, const int numberPeople, const float threshold,\n        const bool googlyEyes, const bool blendOriginalFrame, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n        const auto globalIdx = threadIdx.y * blockDim.x + threadIdx.x;\n\n        // Shared parameters\n        __shared__ float2 sharedMins[POSE_MAX_PEOPLE];\n        __shared__ float2 sharedMaxs[POSE_MAX_PEOPLE];\n        // __shared__ float sharedMins[2*POSE_MAX_PEOPLE];\n        // __shared__ float sharedMaxs[2*POSE_MAX_PEOPLE];\n        __shared__ float sharedScaleF[POSE_MAX_PEOPLE];\n\n        // Other parameters\n        const auto numberPartPairs = sizeof(CAR_22_PAIRS_GPU) / (2*sizeof(CAR_22_PAIRS_GPU[0]));\n        const auto numberScales = sizeof(CAR_22_SCALES) / sizeof(CAR_22_SCALES[0]);\n        const auto numberColors = sizeof(CAR_22_COLORS) / (3*sizeof(CAR_22_COLORS[0]));\n        const auto radius = fastMinCuda(targetWidth, targetHeight) / 100.f;\n        const auto lineWidth = fastMinCuda(targetWidth, targetHeight) / 120.f;\n\n        // Render key points\n        // Note: renderKeypoints is not working for videos with many people, renderKeypointsOld speed was slightly improved instead\n        renderKeypointsOld( // renderKeypoints(\n            targetPtr, sharedMaxs, sharedMins, sharedScaleF, // maxPtr, minPtr, scalePtr,\n            globalIdx, x, y, targetWidth, targetHeight, posePtr, CAR_22_PAIRS_GPU, numberPeople, 22, numberPartPairs,\n            CAR_22_COLORS, numberColors, radius, lineWidth, CAR_22_SCALES, numberScales, threshold, alphaColorToAdd,\n            blendOriginalFrame, (googlyEyes ? 6 : -1), (googlyEyes ? 7 : -1));\n    }\n\n    __global__ void renderBodyPartHeatMaps(\n        float* targetPtr, const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const heatMapPtr, const int widthHeatMap, const int heightHeatMap, const float scaleToKeepRatio,\n        const int numberBodyParts, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n\n        const auto numberColors = sizeof(COCO_COLORS)/(3*sizeof(COCO_COLORS[0]));\n\n        if (x < targetWidth && y < targetHeight)\n        {\n            float rgbColor [3] = {0.f,0.f,0.f};\n            const auto xSource = (x + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto ySource = (y + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto xHeatMap = fastTruncateCuda(int(xSource + 1e-5), 0, widthHeatMap);\n            const auto yHeatMap = fastTruncateCuda(int(ySource + 1e-5), 0, heightHeatMap);\n            const auto heatMapArea = widthHeatMap * heightHeatMap;\n            for (auto part = 0u ; part < numberBodyParts ; part++)\n            {\n                const auto offsetOrigin = part * heatMapArea;\n                // __saturatef = truncate to [0,1]\n                const auto value = __saturatef(heatMapPtr[offsetOrigin + yHeatMap*widthHeatMap + xHeatMap]);\n                const auto rgbColorIndex = (part%numberColors)*3;\n                rgbColor[0] += value*COCO_COLORS[rgbColorIndex];\n                rgbColor[1] += value*COCO_COLORS[rgbColorIndex+1];\n                rgbColor[2] += value*COCO_COLORS[rgbColorIndex+2];\n            }\n\n            const auto blueIndex = 3*(y * targetWidth + x);\n            addColorWeighted(targetPtr[blueIndex+2], targetPtr[blueIndex+1], targetPtr[blueIndex], rgbColor,\n                             alphaColorToAdd);\n        }\n    }\n\n    __global__ void renderBodyPartHeatMap(\n        float* targetPtr, const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const heatMapPtr, const int widthHeatMap, const int heightHeatMap, const float scaleToKeepRatio,\n        const unsigned int part, const float alphaColorToAdd, const bool absValue = false)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n\n        if (x < targetWidth && y < targetHeight)\n        {\n            const auto xSource = (x + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto ySource = (y + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto* const heatMapPtrOffsetted = heatMapPtr + part * widthHeatMap * heightHeatMap;\n            const auto interpolatedValue = bicubicInterpolate(heatMapPtrOffsetted, xSource, ySource, widthHeatMap,\n                                                              heightHeatMap, widthHeatMap);\n\n            float rgbColor[3];\n            if (absValue)\n                getColorHeatMap(rgbColor, fabsf(interpolatedValue), 0.f, 1.f);\n            else\n                getColorHeatMap(rgbColor, interpolatedValue, 0.f, 1.f);\n\n            const auto blueIndex = 3*(y * targetWidth + x);\n            addColorWeighted(targetPtr[blueIndex+2], targetPtr[blueIndex+1], targetPtr[blueIndex], rgbColor,\n                             alphaColorToAdd);\n        }\n    }\n\n    __global__ void renderPartAffinities(\n        float* targetPtr, const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const heatMapPtr, const int widthHeatMap, const int heightHeatMap,\n        const float scaleToKeepRatio, const int partsToRender, const int initPart, const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n\n        if (x < targetWidth && y < targetHeight)\n        {\n            float rgbColor [3] = {0.f,0.f,0.f};\n            const auto xSource = (x + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto ySource = (y + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto heatMapArea = widthHeatMap * heightHeatMap;\n\n            for (auto part = initPart ; part < initPart + partsToRender*2 ; part += 2)\n            {\n                int xIntArray[4];\n                int yIntArray[4];\n                float dx;\n                float dy;\n                cubicSequentialData(xIntArray, yIntArray, dx, dy, xSource, ySource, widthHeatMap, heightHeatMap);\n\n                const auto offsetOriginX = part * heatMapArea;\n                const auto offsetOriginY = (part+1) * heatMapArea;\n                auto valueX = heatMapPtr[offsetOriginX + yIntArray[1]*widthHeatMap + xIntArray[1]];\n                auto valueY = heatMapPtr[offsetOriginY + yIntArray[1]*widthHeatMap + xIntArray[1]];\n                if (partsToRender == 1)\n                {\n                    const auto xB = heatMapPtr[offsetOriginX + yIntArray[1]*widthHeatMap + xIntArray[2]];\n                    const auto xC = heatMapPtr[offsetOriginX + yIntArray[2]*widthHeatMap + xIntArray[1]];\n                    const auto xD = heatMapPtr[offsetOriginX + yIntArray[2]*widthHeatMap + xIntArray[2]];\n                    valueX = (1-dx)*(1-dy)*valueX\n                           + dx*(1-dy)*xB\n                           + (1-dx)*dy*xC\n                           + dx*dy*xD;\n                    const auto yB = heatMapPtr[offsetOriginY + yIntArray[1]*widthHeatMap + xIntArray[2]];\n                    const auto yC = heatMapPtr[offsetOriginY + yIntArray[2]*widthHeatMap + xIntArray[1]];\n                    const auto yD = heatMapPtr[offsetOriginY + yIntArray[2]*widthHeatMap + xIntArray[2]];\n                    valueY = (1-dx)*(1-dy)*valueY\n                           + dx*(1-dy)*yB\n                           + (1-dx)*dy*yC\n                           + dx*dy*yD;\n                }\n\n                float3 rgbColor2;\n                // if (forceNorm1)\n                // {\n                //     const auto norm = std::sqrt(valueX*valueX + valueY*valueY);\n                //     if (norm > 0.05f)\n                //         getColorXYAffinity(rgbColor2, valueX/norm, valueY/norm);\n                //     else\n                //         getColorXYAffinity(rgbColor2, valueX, valueY);\n                // }\n                // else\n                getColorXYAffinity(rgbColor2, valueX, valueY);\n                rgbColor[0] += rgbColor2.x;\n                rgbColor[1] += rgbColor2.y;\n                rgbColor[2] += rgbColor2.z;\n            }\n\n            const auto blueIndex = 3*(y * targetWidth + x);\n            addColorWeighted(targetPtr[blueIndex+2], targetPtr[blueIndex+1], targetPtr[blueIndex], rgbColor,\n                             alphaColorToAdd);\n        }\n    }\n\n    __global__ void renderDistance(\n        float* targetPtr, const unsigned int targetWidth, const unsigned int targetHeight,\n        const float* const heatMapPtr, const int widthHeatMap, const int heightHeatMap,\n        const float scaleToKeepRatio, const int part, const int numberBodyParts, const int numberBodyPAFChannels,\n        const float alphaColorToAdd)\n    {\n        const auto x = (blockIdx.x * blockDim.x) + threadIdx.x;\n        const auto y = (blockIdx.y * blockDim.y) + threadIdx.y;\n\n        if (x < targetWidth && y < targetHeight)\n        {\n            const auto xSource = (x + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto ySource = (y + 0.5f) / scaleToKeepRatio - 0.5f;\n            const auto heatMapOffset = part * widthHeatMap * heightHeatMap\n                                     + (numberBodyParts+1+numberBodyPAFChannels)*widthHeatMap * heightHeatMap;\n            const auto* const heatMapPtrOffsetted = heatMapPtr + heatMapOffset;\n            const auto interpolatedValue = 0.5f\n                                         + 0.5f * bicubicInterpolate(heatMapPtrOffsetted, xSource, ySource,\n                                                                     widthHeatMap, heightHeatMap, widthHeatMap);\n\n            float rgbColor[3];\n            getColorHeatMap(rgbColor, interpolatedValue, 0.f, 1.f);\n\n            const auto blueIndex = 3*(y * targetWidth + x);\n            addColorWeighted(targetPtr[blueIndex+2], targetPtr[blueIndex+1], targetPtr[blueIndex], rgbColor,\n                             alphaColorToAdd);\n        }\n    }\n\n    inline void checkAlpha(const float alphaColorToAdd)\n    {\n        if (alphaColorToAdd < 0.f || alphaColorToAdd > 1.f)\n            error(\"Alpha must be in the range [0, 1].\", __LINE__, __FUNCTION__, __FILE__);\n    }\n\n    inline void renderPosePAFGpuAux(float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize,\n                                    const float* const heatMapPtr, const Point<int>& heatMapSize,\n                                    const float scaleToKeepRatio, const int part, const int partsToRender,\n                                    const float alphaBlending)\n    {\n        try\n        {\n            //framePtr      =   width * height * 3\n            //heatMapPtr    =   heatMapSize.x * heatMapSize.y * #body parts\n            checkAlpha(alphaBlending);\n            const auto heatMapOffset = getPoseNumberBodyParts(poseModel) * heatMapSize.area();\n            dim3 threadsPerBlock;\n            dim3 numBlocks;\n            getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n            renderPartAffinities<<<threadsPerBlock, numBlocks>>>(framePtr, frameSize.x, frameSize.y, heatMapPtr,\n                                                                 heatMapSize.x, heatMapSize.y, scaleToKeepRatio,\n                                                                 partsToRender, part, alphaBlending);\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPoseKeypointsGpu(\n        float* framePtr, float* maxPtr, float* minPtr, float* scalePtr, const PoseModel poseModel,\n        const int numberPeople, const Point<unsigned int>& frameSize, const float* const posePtr,\n        const float renderThreshold, const bool googlyEyes, const bool blendOriginalFrame, const float alphaBlending)\n    {\n        try\n        {\n            if (numberPeople > 0 || !blendOriginalFrame)\n            {\n                // framePtr      =   width * height * 3\n                // heatMapPtr    =   heatMapSize.x * heatMapSize.y * #body parts\n                // posePtr       =   3 (x,y,score) * #Body parts * numberPeople\n                if (googlyEyes && (poseModel == PoseModel::MPI_15 || poseModel == PoseModel::MPI_15_4))\n                    error(\"Bool googlyEyes not compatible with MPI models.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                if (numberPeople > POSE_MAX_PEOPLE)\n                    error(\"Rendering assumes that numberPeople <= POSE_MAX_PEOPLE = \" + std::to_string(POSE_MAX_PEOPLE)\n                          + \".\", __LINE__, __FUNCTION__, __FILE__);\n\n                //// Get bounding box per person\n                //const dim3 threadsPerBlockBoundBox = {1, 1, 1};\n                //const dim3 numBlocksBox{getNumberCudaBlocks(POSE_MAX_PEOPLE, threadsPerBlockBoundBox.x)};\n                //getBoundingBoxPerPersonPose<<<threadsPerBlockBoundBox, numBlocksBox>>>(\n                //    maxPtr, minPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                //    getPoseNumberBodyParts(poseModel), renderThreshold);\n\n                // Body pose\n                dim3 threadsPerBlock;\n                dim3 numBlocks;\n                getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n                if (poseModel == PoseModel::BODY_25 || poseModel == PoseModel::BODY_25D\n                    || poseModel == PoseModel::BODY_25E)\n                {\n                    // const auto REPS = 1000;\n                    // double timeNormalize0 = 0.;\n                    // double timeNormalize1 = 0.;\n\n                    // // Non-optimized code\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    // renderPoseBody25Old<<<threadsPerBlock, numBlocks>>>(\n                    //     framePtr, frameSize.x, frameSize.y, posePtr, numberPeople, renderThreshold, googlyEyes,\n                    //     blendOriginalFrame, alphaBlending\n                    // );\n                    // OP_CUDA_PROFILE_END(timeNormalize0, 1e3, REPS);\n\n                    // Optimized code\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    // const dim3 threadsPerBlockBoundBox = {1, 1, 1};\n                    // const dim3 numBlocksBox{getNumberCudaBlocks(POSE_MAX_PEOPLE, threadsPerBlockBoundBox.x)};\n                    // getBoundingBoxPerPersonPose<<<threadsPerBlockBoundBox, numBlocksBox>>>(\n                    //     maxPtr, minPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople, 25,\n                    //     renderThreshold);\n                    renderPoseBody25<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                    // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n\n                    // // Profiling code\n                    // opLog(\"  renderOld=\" + std::to_string(timeNormalize0) + \"ms\");\n                    // opLog(\"  renderNew=\" + std::to_string(timeNormalize1) + \"ms\");\n                }\n                else if (poseModel == PoseModel::COCO_18)\n                    renderPoseCoco<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                else if (poseModel == PoseModel::BODY_19 || poseModel == PoseModel::BODY_19E\n                         || poseModel == PoseModel::BODY_19N || poseModel == PoseModel::BODY_19_X2)\n                    renderPoseBody19<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                else if (poseModel == PoseModel::BODY_23)\n                    renderPoseBody23<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                else if (poseModel == PoseModel::BODY_25B)\n                    renderPoseBody25b<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                else if (poseModel == PoseModel::BODY_135)\n                {\n                    // const auto REPS = 500;\n                    // double timeNormalize1 = 0.;\n                    // double timeNormalize2 = 0.;\n\n                    // // Non-optimized code\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    //  renderPoseBody135Old<<<threadsPerBlock, numBlocks>>>(\n                    //      framePtr, frameSize.x, frameSize.y, posePtr, numberPeople, renderThreshold, googlyEyes,\n                    //      blendOriginalFrame, alphaBlending\n                    // );\n                    // OP_CUDA_PROFILE_END(timeNormalize1, 1e3, REPS);\n\n                    // Optimized code\n                    // OP_CUDA_PROFILE_INIT(REPS);\n                    // const dim3 threadsPerBlockBoundBox = {1, 1, 1};\n                    // const dim3 numBlocksBox{getNumberCudaBlocks(POSE_MAX_PEOPLE, threadsPerBlockBoundBox.x)};\n                    // getBoundingBoxPerPersonPose<<<threadsPerBlockBoundBox, numBlocksBox>>>(\n                    //     maxPtr, minPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople, 135,\n                    //     renderThreshold);\n                    renderPoseBody135<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                    // OP_CUDA_PROFILE_END(timeNormalize2, 1e3, REPS);\n\n                    // // Profiling code\n                    // opLog(\"  renderOld=\" + std::to_string(timeNormalize1) + \"ms\");\n                    // opLog(\"  renderNew=\" + std::to_string(timeNormalize2) + \"ms\");\n                }\n                else if (poseModel == PoseModel::MPI_15 || poseModel == PoseModel::MPI_15_4)\n                    renderPoseMpi29Parts<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, blendOriginalFrame, alphaBlending\n                    );\n                // Car pose\n                else if (poseModel == PoseModel::CAR_12)\n                    renderPoseCar12<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                else if (poseModel == PoseModel::CAR_22)\n                    renderPoseCar22<<<threadsPerBlock, numBlocks>>>(\n                        framePtr, minPtr, maxPtr, scalePtr, frameSize.x, frameSize.y, posePtr, numberPeople,\n                        renderThreshold, googlyEyes, blendOriginalFrame, alphaBlending\n                    );\n                // Unknown\n                else\n                    error(\"Invalid Model.\", __LINE__, __FUNCTION__, __FILE__);\n                cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPoseHeatMapGpu(\n        float* framePtr, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio, const unsigned int part, const float alphaBlending)\n    {\n        try\n        {\n            //framePtr      =   width * height * 3\n            //heatMapPtr    =   heatMapSize.x * heatMapSize.y * #body parts\n            checkAlpha(alphaBlending);\n            dim3 threadsPerBlock;\n            dim3 numBlocks;\n            getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n\n            renderBodyPartHeatMap<<<threadsPerBlock, numBlocks>>>(\n                framePtr, frameSize.x, frameSize.y, heatMapPtr, heatMapSize.x, heatMapSize.y, scaleToKeepRatio,\n                part, alphaBlending\n            );\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPoseHeatMapsGpu(float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize,\n                               const float* const heatMapPtr, const Point<int>& heatMapSize,\n                               const float scaleToKeepRatio, const float alphaBlending)\n    {\n        try\n        {\n            //framePtr      =   width * height * 3\n            //heatMapPtr    =   heatMapSize.x * heatMapSize.y * #body parts\n            checkAlpha(alphaBlending);\n            dim3 threadsPerBlock;\n            dim3 numBlocks;\n            getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n            const auto numberBodyParts = getPoseNumberBodyParts(poseModel);\n            const auto heatMapOffset = numberBodyParts * heatMapSize.area();\n\n            renderBodyPartHeatMaps<<<threadsPerBlock, numBlocks>>>(\n                framePtr, frameSize.x, frameSize.y, heatMapPtr, heatMapSize.x, heatMapSize.y, scaleToKeepRatio,\n                numberBodyParts, alphaBlending\n            );\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPosePAFGpu(\n        float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending)\n    {\n        try\n        {\n            renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1,\n                                alphaBlending);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPosePAFsGpu(\n        float* framePtr, const PoseModel poseModel, const Point<unsigned int>& frameSize, const float* const heatMapPtr,\n        const Point<int>& heatMapSize, const float scaleToKeepRatio, const float alphaBlending)\n    {\n        try\n        {\n            const auto numberBodyPartPairs = (int)getPosePartPairs(poseModel).size()/2;\n            renderPosePAFGpuAux(\n                framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio,\n                getPoseNumberBodyParts(poseModel) + (addBkgChannel(poseModel) ? 1 : 0),\n                numberBodyPartPairs, alphaBlending);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void renderPoseDistanceGpu(\n        float* framePtr, const Point<unsigned int>& frameSize, const float* const heatMapPtr, const Point<int>& heatMapSize,\n        const float scaleToKeepRatio, const unsigned int part, const float alphaBlending)\n    {\n        try\n        {\n            // // As PAF\n            // const bool forceNorm1 = true;\n            // renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1,\n            //                     alphaBlending, forceNorm1);\n\n            // As body part\n            // framePtr      =   width * height * 3\n            // heatMapPtr    =   heatMapSize.x * heatMapSize.y * #body parts\n            checkAlpha(alphaBlending);\n            dim3 threadsPerBlock;\n            dim3 numBlocks;\n            getNumberCudaThreadsAndBlocks(threadsPerBlock, numBlocks, frameSize);\n\n            const auto absValue = true;\n            renderBodyPartHeatMap<<<threadsPerBlock, numBlocks>>>(\n                framePtr, frameSize.x, frameSize.y, heatMapPtr, heatMapSize.x, heatMapSize.y, scaleToKeepRatio,\n                part, alphaBlending, absValue);\n            cudaCheck(__LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/CMakeLists.txt",
    "content": "set(SOURCES_OP_PRODUCER\n    datumProducer.cpp\n    defineTemplates.cpp\n    flirReader.cpp\n    imageDirectoryReader.cpp\n    ipCameraReader.cpp\n    producer.cpp\n    spinnakerWrapper.cpp\n    videoCaptureReader.cpp\n    videoReader.cpp\n    webcamReader.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_PRODUCER_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_PRODUCER})\nset(SOURCES_OP_PRODUCER_WITH_CP ${SOURCES_OP_PRODUCER_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_PRODUCER_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  add_library(openpose_producer ${SOURCES_OP_PRODUCER})\n  target_link_libraries(openpose_producer ${OpenCV_LIBS} openpose_core\n      openpose_thread openpose_filestream)\n\n  install(TARGETS openpose_producer\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/producer/datumProducer.cpp",
    "content": "#include <openpose/producer/datumProducer.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    void datumProducerConstructor(\n        const std::shared_ptr<Producer>& producerSharedPtr,\n        const unsigned long long frameFirst, const unsigned long long frameStep, const unsigned long long frameLast)\n    {\n        try\n        {\n            // Sanity check\n            if (frameLast < frameFirst)\n                error(\"The desired initial frame must be lower than the last one (flags `--frame_first` vs.\"\n                      \" `--frame_last`). Current: \" + std::to_string(frameFirst) + \" vs. \" + std::to_string(frameLast)\n                      + \".\", __LINE__, __FUNCTION__, __FILE__);\n            if (frameLast != std::numeric_limits<unsigned long long>::max()\n                && frameLast > producerSharedPtr->get(getCvCapPropFrameCount())-1)\n                error(\"The desired last frame must be lower than the length of the video or the number of images.\"\n                      \" Current: \" + std::to_string(frameLast) + \" vs. \"\n                      + std::to_string(positiveIntRound(producerSharedPtr->get(getCvCapPropFrameCount()))-1) + \".\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Set frame first and step\n            if (producerSharedPtr->getType() != ProducerType::FlirCamera\n                && producerSharedPtr->getType() != ProducerType::IPCamera\n                && producerSharedPtr->getType() != ProducerType::Webcam)\n            {\n                // Frame first\n                producerSharedPtr->set(CV_CAP_PROP_POS_FRAMES, (double)frameFirst);\n                // Frame step\n                producerSharedPtr->set(ProducerProperty::FrameStep, (double)frameStep);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void datumProducerConstructorTooManyConsecutiveEmptyFrames(\n        unsigned int& numberConsecutiveEmptyFrames, const bool emptyFrame)\n    {\n        try\n        {\n            numberConsecutiveEmptyFrames = (emptyFrame ? numberConsecutiveEmptyFrames+1 : 0);\n            const auto threshold = 500u;\n            if (numberConsecutiveEmptyFrames >= threshold)\n                error(\"Detected too many (\" + std::to_string(numberConsecutiveEmptyFrames)\n                    + \") empty frames in a row.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool datumProducerConstructorRunningAndGetDatumIsDatumProducerRunning(\n        const std::shared_ptr<Producer>& producerSharedPtr, const unsigned long long numberFramesToProcess,\n        const unsigned long long globalCounter)\n    {\n        try\n        {\n            // Check last desired frame has not been reached\n            if (numberFramesToProcess != std::numeric_limits<unsigned long long>::max()\n                && globalCounter > numberFramesToProcess)\n            {\n                producerSharedPtr->release();\n            }\n            // If producer released -> it sends an empty Mat + a datumProducerRunning signal\n            return producerSharedPtr->isOpened();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void datumProducerConstructorRunningAndGetDatumApplyPlayerControls(\n        const std::shared_ptr<Producer>& producerSharedPtr,\n        const std::shared_ptr<std::pair<std::atomic<bool>, std::atomic<int>>>& videoSeekSharedPtr)\n    {\n        try\n        {\n            // Fast forward/backward - Seek to specific frame index desired\n            if (videoSeekSharedPtr != nullptr)\n            {\n                // Fake pause vs. normal mode\n                const auto increment = videoSeekSharedPtr->second - (videoSeekSharedPtr->first ? 1 : 0);\n                // Normal mode\n                if (increment != 0)\n                    producerSharedPtr->set(\n                        CV_CAP_PROP_POS_FRAMES, producerSharedPtr->get(CV_CAP_PROP_POS_FRAMES) + increment);\n                // It must be always reset or bug in fake pause\n                videoSeekSharedPtr->second = 0;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    unsigned long long datumProducerConstructorRunningAndGetNextFrameNumber(\n        const std::shared_ptr<Producer>& producerSharedPtr)\n    {\n        try\n        {\n            // Get next frame number\n            return (unsigned long long)producerSharedPtr->get(CV_CAP_PROP_POS_FRAMES);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0ull;\n        }\n    }\n\n    void datumProducerConstructorRunningAndGetDatumFrameIntegrity(Matrix& inputDataMatrix)\n    {\n        try\n        {\n            // Image integrity\n            if (inputDataMatrix.channels() != 3)\n            {\n                const std::string commonMessage{\"Input images must be 3-channel BGR.\"};\n                // Grey to RGB if required\n                if (inputDataMatrix.channels() == 1)\n                {\n                    opLog(commonMessage + \" Converting grey image into BGR.\", Priority::High);\n                    cv::Mat inputData = OP_OP2CVMAT(inputDataMatrix);\n                    cv::cvtColor(inputData, inputData, CV_GRAY2BGR);\n                    // Different memory size --> new cv::Mat raw ptr memory --> new Matrix\n                    inputDataMatrix = OP_CV2OPMAT(inputData);\n                }\n                else\n                    error(commonMessage, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/defineTemplates.cpp",
    "content": "#include <openpose/producer/headers.hpp>\n\nnamespace op\n{\n    template class OP_API DatumProducer<BASE_DATUM>;\n    template class OP_API WDatumProducer<BASE_DATUM>;\n}\n"
  },
  {
    "path": "src/openpose/producer/flirReader.cpp",
    "content": "#include <openpose/producer/flirReader.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/string.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    FlirReader::FlirReader(const std::string& cameraParameterPath, const Point<int>& cameraResolution,\n                           const bool undistortImage, const int cameraIndex) :\n        Producer{ProducerType::FlirCamera, cameraParameterPath, undistortImage, -1},\n        mSpinnakerWrapper{cameraParameterPath, cameraResolution, undistortImage, cameraIndex},\n        mFrameNameCounter{0ull}\n    {\n        try\n        {\n            // Get resolution\n            const auto resolution = mSpinnakerWrapper.getResolution();\n            // Set resolution\n            set(CV_CAP_PROP_FRAME_WIDTH, resolution.x);\n            set(CV_CAP_PROP_FRAME_HEIGHT, resolution.y);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    FlirReader::~FlirReader()\n    {\n        try\n        {\n            release();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::vector<Matrix> FlirReader::getCameraMatrices()\n    {\n        try\n        {\n            return mSpinnakerWrapper.getCameraMatrices();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> FlirReader::getCameraExtrinsics()\n    {\n        try\n        {\n            return mSpinnakerWrapper.getCameraExtrinsics();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> FlirReader::getCameraIntrinsics()\n    {\n        try\n        {\n            return mSpinnakerWrapper.getCameraIntrinsics();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::string FlirReader::getNextFrameName()\n    {\n        try\n        {\n            const auto stringLength = 12u;\n            return toFixedLengthString(mFrameNameCounter, stringLength);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    bool FlirReader::isOpened() const\n    {\n        try\n        {\n            return mSpinnakerWrapper.isOpened();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void FlirReader::release()\n    {\n        try\n        {\n            mSpinnakerWrapper.release();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix FlirReader::getRawFrame()\n    {\n        try\n        {\n            return mSpinnakerWrapper.getRawFrames().at(0);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> FlirReader::getRawFrames()\n    {\n        try\n        {\n            mFrameNameCounter++; // Simple counter: 0,1,2,3,...\n            return mSpinnakerWrapper.getRawFrames();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    double FlirReader::get(const int capProperty)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n            {\n                if (Producer::get(ProducerProperty::Rotation) == 0.\n                    || Producer::get(ProducerProperty::Rotation) == 180.)\n                    return mResolution.x;\n                else\n                    return mResolution.y;\n            }\n            else if (capProperty == CV_CAP_PROP_FRAME_HEIGHT)\n            {\n                if (Producer::get(ProducerProperty::Rotation) == 0.\n                    || Producer::get(ProducerProperty::Rotation) == 180.)\n                    return mResolution.y;\n                else\n                    return mResolution.x;\n            }\n            else if (capProperty == CV_CAP_PROP_POS_FRAMES)\n                return (double)mFrameNameCounter;\n            else if (capProperty == CV_CAP_PROP_FRAME_COUNT)\n                return -1.;\n            else if (capProperty == CV_CAP_PROP_FPS)\n                return -1.;\n            else\n            {\n                opLog(\"Unknown property.\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n                return -1.;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void FlirReader::set(const int capProperty, const double value)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n                mResolution.x = {(int)value};\n            else if (capProperty == CV_CAP_PROP_FRAME_HEIGHT)\n                mResolution.y = {(int)value};\n            else if (capProperty == CV_CAP_PROP_POS_FRAMES)\n                opLog(\"This property is read-only.\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n            else if (capProperty == CV_CAP_PROP_FRAME_COUNT || capProperty == CV_CAP_PROP_FPS)\n                opLog(\"This property is read-only.\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n            else\n                opLog(\"Unknown property.\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/imageDirectoryReader.cpp",
    "content": "#include <openpose/producer/imageDirectoryReader.hpp>\n#include <openpose/filestream/fileStream.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    std::vector<std::string> getImagePathsOnDirectory(const std::string& imageDirectoryPath)\n    {\n        try\n        {\n            // Get files on directory with the desired extensions\n            const auto imagePaths = getFilesOnDirectory(imageDirectoryPath, Extensions::Images);\n            // Check #files > 0\n            if (imagePaths.empty())\n                error(\"No images were found on \" + imageDirectoryPath, __LINE__, __FUNCTION__, __FILE__);\n            // Return result\n            return imagePaths;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    ImageDirectoryReader::ImageDirectoryReader(const std::string& imageDirectoryPath,\n                                               const std::string& cameraParameterPath,\n                                               const bool undistortImage,\n                                               const int numberViews) :\n        Producer{ProducerType::ImageDirectory, cameraParameterPath, undistortImage, numberViews},\n        mImageDirectoryPath{imageDirectoryPath},\n        mFilePaths{getImagePathsOnDirectory(imageDirectoryPath)},\n        mFrameNameCounter{0ll}\n    {\n    }\n\n    ImageDirectoryReader::~ImageDirectoryReader()\n    {\n    }\n\n    std::string ImageDirectoryReader::getNextFrameName()\n    {\n        try\n        {\n            return getFileNameNoExtension(mFilePaths.at(mFrameNameCounter));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    Matrix ImageDirectoryReader::getRawFrame()\n    {\n        try\n        {\n            // Read frame\n            auto frame = loadImage(mFilePaths.at(mFrameNameCounter++).c_str(), CV_LOAD_IMAGE_COLOR);\n            // Skip frames if frame step > 1\n            const auto frameStep = Producer::get(ProducerProperty::FrameStep);\n            if (frameStep > 1)\n                set(CV_CAP_PROP_POS_FRAMES, mFrameNameCounter + frameStep-1);\n            // Check frame integrity. This function also checks width/height changes. However, if it is performed\n            // after setWidth/setHeight this is performed over the new resolution (so they always match).\n            checkFrameIntegrity(frame);\n            // Update size, since images might have different size between each one of them\n            mResolution = Point<int>{frame.cols(), frame.rows()};\n            // Return final frame\n            return frame;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> ImageDirectoryReader::getRawFrames()\n    {\n        try\n        {\n            std::vector<Matrix> rawFrames;\n            for (auto i = 0 ; i < positiveIntRound(Producer::get(ProducerProperty::NumberViews)) ; i++)\n                rawFrames.emplace_back(getRawFrame());\n            return rawFrames;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    double ImageDirectoryReader::get(const int capProperty)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n            {\n                if (Producer::get(ProducerProperty::Rotation) == 0.\n                    || Producer::get(ProducerProperty::Rotation) == 180.)\n                    return mResolution.x;\n                else\n                    return mResolution.y;\n            }\n            else if (capProperty == CV_CAP_PROP_FRAME_HEIGHT)\n            {\n                if (Producer::get(ProducerProperty::Rotation) == 0.\n                    || Producer::get(ProducerProperty::Rotation) == 180.)\n                    return mResolution.y;\n                else\n                    return mResolution.x;\n            }\n            else if (capProperty == CV_CAP_PROP_POS_FRAMES)\n                return (double)mFrameNameCounter;\n            else if (capProperty == CV_CAP_PROP_FRAME_COUNT)\n                return (double)mFilePaths.size();\n            else if (capProperty == CV_CAP_PROP_FPS)\n                return -1.;\n            else\n            {\n                opLog(\"Unknown property\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n                return -1.;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void ImageDirectoryReader::set(const int capProperty, const double value)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n                mResolution.x = {(int)value};\n            else if (capProperty == CV_CAP_PROP_FRAME_HEIGHT)\n                mResolution.y = {(int)value};\n            else if (capProperty == CV_CAP_PROP_POS_FRAMES)\n                mFrameNameCounter = fastTruncate((long long)value, 0ll, (long long)mFilePaths.size()-1);\n            else if (capProperty == CV_CAP_PROP_FRAME_COUNT || capProperty == CV_CAP_PROP_FPS)\n                opLog(\"This property is read-only.\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n            else\n                opLog(\"Unknown property\", Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/ipCameraReader.cpp",
    "content": "#include <openpose/producer/ipCameraReader.hpp>\n\nnamespace op\n{\n    // Public IP cameras for testing (add ?x.mjpeg):\n    // http://iris.not.iac.es/axis-cgi/mjpg/video.cgi?resolution=320x240?x.mjpeg\n    // http://www.webcamxp.com/publicipcams.aspx\n\n    IpCameraReader::IpCameraReader(const std::string & cameraPath, const std::string& cameraParameterPath,\n                                   const bool undistortImage) :\n        VideoCaptureReader{cameraPath, ProducerType::IPCamera, cameraParameterPath, undistortImage, 1},\n        mPathName{cameraPath}\n    {\n    }\n\n    IpCameraReader::~IpCameraReader()\n    {\n    }\n\n    std::string IpCameraReader::getNextFrameName()\n    {\n        try\n        {\n            return VideoCaptureReader::getNextFrameName();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    Matrix IpCameraReader::getRawFrame()\n    {\n        try\n        {\n            return VideoCaptureReader::getRawFrame();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> IpCameraReader::getRawFrames()\n    {\n        try\n        {\n            return VideoCaptureReader::getRawFrames();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/producer.cpp",
    "content": "#include <openpose/producer/producer.hpp>\n#include <openpose/producer/headers.hpp>\n#include <openpose/utilities/check.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    void reset(unsigned int& numberEmptyFrames, bool& trackingFps)\n    {\n        try\n        {\n            // Reset number empty frames\n            numberEmptyFrames = 0;\n            // Reset keepDesiredFrameRate\n            trackingFps = false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Producer::Producer(const ProducerType type, const std::string& cameraParameterPath, const bool undistortImage,\n                       const int numberViews) :\n        mType{type},\n        mProducerFpsMode{ProducerFpsMode::RetrievalFps},\n        mNumberEmptyFrames{0},\n        mTrackingFps{false}\n    {\n        try\n        {\n            // Basic properties\n            mProperties[(unsigned int)ProducerProperty::AutoRepeat] = (double) false;\n            mProperties[(unsigned int)ProducerProperty::Flip] = (double) false;\n            mProperties[(unsigned int)ProducerProperty::Rotation] = 0.;\n            mProperties[(unsigned int)ProducerProperty::NumberViews] = numberViews;\n            auto& mNumberViews = mProperties[(unsigned int)ProducerProperty::NumberViews];\n            // Camera (distortion, intrinsic, and extrinsic) parameters\n            if (mType != ProducerType::FlirCamera)\n            {\n                // Undistort image?\n                mCameraParameterReader.setUndistortImage(undistortImage);\n                // If no stereo --> Set to 1\n                if (mNumberViews <= 0)\n                    mNumberViews = 1;\n                // Get camera parameters\n                if (mNumberViews > 1 || undistortImage)\n                {\n                    const auto extension = getFileExtension(cameraParameterPath);\n                    // Get camera parameters\n                    if (extension == \"xml\" || extension == \"XML\")\n                        mCameraParameterReader.readParameters(\n                            getFileParentFolderPath(cameraParameterPath), getFileNameNoExtension(cameraParameterPath));\n                    else // if (mNumberViews > 1)\n                    {\n                        const auto cameraParameterPathCleaned = formatAsDirectory(cameraParameterPath);\n                        // Read camera parameters from SN\n                        auto serialNumbers = getFilesOnDirectory(cameraParameterPathCleaned, \".xml\");\n                        // Get serial numbers\n                        for (auto& serialNumber : serialNumbers)\n                            serialNumber = getFileNameNoExtension(serialNumber);\n                        // Get camera parameters\n                        mCameraParameterReader.readParameters(cameraParameterPathCleaned, serialNumbers);\n                    }\n                    // Sanity check\n                    if ((int)mCameraParameterReader.getNumberCameras() != mNumberViews)\n                        error(\"Found a different number of camera parameter files than the number indicated by\"\n                              \" `--3d_views` (\"\n                              + std::to_string(mCameraParameterReader.getNumberCameras()) + \" vs. \"\n                              + std::to_string(mNumberViews) + \"). Make sure they are the same number of files and/or\"\n                              + \" set `--frame_undistort` to false.\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Producer::~Producer(){}\n\n    Matrix Producer::getFrame()\n    {\n        try\n        {\n            // Return first element from getFrames (if any)\n            const auto frames = getFrames();\n            return (frames.empty() ? Matrix() : frames[0]);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> Producer::getFrames()\n    {\n        try\n        {\n            std::vector<Matrix> frames;\n\n            if (isOpened())\n            {\n                // If ProducerFpsMode::OriginalFps, then force producer to keep the frame rate of the frames producer\n                // sources (e.g., a video)\n                keepDesiredFrameRate();\n                // Get frame\n                frames = getRawFrames();\n                // Undistort frames\n                // TODO: Multi-thread if > 1 frame\n                for (auto i = 0u ; i < frames.size() ; i++)\n                    if (!frames[i].empty() && mCameraParameterReader.getUndistortImage())\n                        mCameraParameterReader.undistort(frames[i], i);\n                // Post-process frames\n                for (auto& frame : frames)\n                {\n                    // Flip + rotate frame\n                    const auto rotationAngle = mProperties[(unsigned char)ProducerProperty::Rotation];\n                    const auto flipFrame = (mProperties[(unsigned char)ProducerProperty::Flip] == 1.);\n                    rotateAndFlipFrame(frame, rotationAngle, flipFrame);\n                    // Check frame integrity\n                    checkFrameIntegrity(frame);\n                    // If any frame invalid --> exit\n                    if (frame.empty())\n                    {\n                        frames.clear();\n                        break;\n                    }\n                }\n                // Check if video capture did finish and close/restart it\n                ifEndedResetOrRelease();\n            }\n            return frames;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> Producer::getCameraMatrices()\n    {\n        try\n        {\n            return mCameraParameterReader.getCameraMatrices();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> Producer::getCameraExtrinsics()\n    {\n        try\n        {\n            return mCameraParameterReader.getCameraExtrinsics();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> Producer::getCameraIntrinsics()\n    {\n        try\n        {\n            return mCameraParameterReader.getCameraIntrinsics();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    void Producer::setProducerFpsMode(const ProducerFpsMode fpsMode)\n    {\n        try\n        {\n            checkBool(\n                fpsMode == ProducerFpsMode::RetrievalFps || fpsMode == ProducerFpsMode::OriginalFps,\n                \"Unknown ProducerFpsMode.\", __LINE__, __FUNCTION__, __FILE__);\n            // For webcam, ProducerFpsMode::OriginalFps == ProducerFpsMode::RetrievalFps, since the internal webcam\n            // cache will overwrite frames after it gets full\n            if (mType == ProducerType::Webcam)\n            {\n                mProducerFpsMode = {ProducerFpsMode::RetrievalFps};\n                if (fpsMode == ProducerFpsMode::OriginalFps)\n                    opLog(\"The producer fps mode set to `OriginalFps` (flag `process_real_time` on the demo) is not\"\n                        \" necessary, it is already assumed for webcam.\",\n                        Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n            }\n            // If no webcam\n            else\n            {\n                checkBool(\n                    fpsMode == ProducerFpsMode::RetrievalFps || get(CV_CAP_PROP_FPS) > 0,\n                    \"Selected to keep the source fps but get(CV_CAP_PROP_FPS) <= 0, i.e., the source did not set\"\n                    \" its fps property.\", __LINE__, __FUNCTION__, __FILE__);\n                mProducerFpsMode = {fpsMode};\n            }\n            reset(mNumberEmptyFrames, mTrackingFps);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    double Producer::get(const ProducerProperty property)\n    {\n        try\n        {\n            if (property < ProducerProperty::Size)\n                return mProperties[(unsigned char)property];\n            else\n            {\n                error(\"Unknown ProducerProperty.\", __LINE__, __FUNCTION__, __FILE__);\n                return 0.;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void Producer::set(const ProducerProperty property, double value)\n    {\n        try\n        {\n            if (property < ProducerProperty::Size)\n            {\n                // Individual checks\n                if (property == ProducerProperty::AutoRepeat)\n                {\n                    checkBool(\n                        value != 1. || (mType == ProducerType::ImageDirectory || mType == ProducerType::Video),\n                        \"ProducerProperty::AutoRepeat only implemented for ProducerType::ImageDirectory and\"\n                        \" Video.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                else if (property == ProducerProperty::Rotation)\n                {\n                    checkBool(\n                        value == 0. || value == 90. || value == 180. || value == 270.,\n                        \"ProducerProperty::Rotation only implemented for {0, 90, 180, 270} degrees.\",\n                        __LINE__, __FUNCTION__, __FILE__);\n                }\n                else if (property == ProducerProperty::FrameStep)\n                {\n                    // Sanity check\n                    if (value < 1)\n                    {\n                        const auto message = \"The frame step must be greater than 0 (`--frame_step`). Use 1 by default.\";\n                        error(message, __LINE__, __FUNCTION__, __FILE__);\n                    }\n                }\n\n                // Common operation\n                mProperties[(unsigned char)property] = value;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Producer::checkFrameIntegrity(Matrix& frame)\n    {\n        try\n        {\n            // Process wrong frames\n            if (frame.empty())\n            {\n                opLog(\"Empty frame detected, frame number \" + std::to_string((int)get(CV_CAP_PROP_POS_FRAMES))\n                    + \" of \" + std::to_string((int)get(CV_CAP_PROP_FRAME_COUNT)) + \".\",\n                    Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n                mNumberEmptyFrames++;\n            }\n            else\n            {\n                mNumberEmptyFrames = 0;\n\n                if (mType != ProducerType::ImageDirectory\n                      && ((frame.cols() != get(CV_CAP_PROP_FRAME_WIDTH) && get(CV_CAP_PROP_FRAME_WIDTH) > 0)\n                          || (frame.rows() != get(CV_CAP_PROP_FRAME_HEIGHT) && get(CV_CAP_PROP_FRAME_HEIGHT) > 0)))\n                {\n                    opLog(\"Frame size changed. Returning empty frame.\\nExpected vs. received sizes: \"\n                        + std::to_string(positiveIntRound(get(CV_CAP_PROP_FRAME_WIDTH)))\n                        + \"x\" + std::to_string(positiveIntRound(get(CV_CAP_PROP_FRAME_HEIGHT)))\n                        + \" vs. \" + std::to_string(frame.cols()) + \"x\" + std::to_string(frame.rows()),\n                        Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n                    frame = Matrix();\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Producer::ifEndedResetOrRelease()\n    {\n        try\n        {\n            if (isOpened())\n            {\n                // OpenCV closing issue: OpenCV goes in the range [1, get(CV_CAP_PROP_FRAME_COUNT) - 1] in some\n                // videos (i.e., there is a frame missing), mNumberEmptyFrames allows the program to be properly\n                // closed keeping the 0-index frame counting\n                if (mNumberEmptyFrames > 2\n                    || (mType != ProducerType::FlirCamera && mType != ProducerType::IPCamera\n                        && mType != ProducerType::Webcam\n                        && get(CV_CAP_PROP_POS_FRAMES) >= get(CV_CAP_PROP_FRAME_COUNT)))\n                {\n                    // Repeat video\n                    if (mProperties[(unsigned char)ProducerProperty::AutoRepeat])\n                        set(CV_CAP_PROP_POS_FRAMES, 0);\n\n                    // Warning + release mVideoCapture\n                    else\n                        release();\n                    reset(mNumberEmptyFrames, mTrackingFps);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void Producer::keepDesiredFrameRate()\n    {\n        try\n        {\n            if (isOpened())\n            {\n                // Be sure fps is not slower than desired\n                if (mProducerFpsMode == ProducerFpsMode::OriginalFps)\n                {\n                    if (mTrackingFps)\n                    {\n                        mNumberFramesTrackingFps++;\n                        // Current #frames\n                        const auto currentFrames = get(CV_CAP_PROP_POS_FRAMES) - mFirstFrameTrackingFps;\n                        // Expected #frames\n                        const auto nsPerFrame = 1e9/get(CV_CAP_PROP_FPS);\n                        const auto timeNs = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(\n                            std::chrono::high_resolution_clock::now()-mClockTrackingFps\n                        ).count();\n                        const auto expectedFrames = timeNs / nsPerFrame;\n\n                        const auto difference = expectedFrames - currentFrames;\n                        const auto numberSetPositionThreshold = 3u;\n                        // Speed up frame extraction\n                        if (difference > 1)\n                        {\n                            if (difference > 15)\n                            {\n                                set(CV_CAP_PROP_POS_FRAMES, std::floor(expectedFrames) + mFirstFrameTrackingFps);\n                                mNumberSetPositionTrackingFps = fastMin(mNumberSetPositionTrackingFps+1,\n                                                                        numberSetPositionThreshold);\n                            }\n                            else\n                            {\n                                std::vector<Matrix> frames;\n                                for (auto i = 0 ; i < std::floor(difference) ; i++)\n                                    frames = getRawFrames();\n                            }\n                        }\n                        // Low down frame extraction - sleep thread unless it is too slow in most frames (using\n                        // set(frames, X) sets to frame X+delta, due to codecs issues)\n                        else if (difference < -0.45 && mNumberSetPositionTrackingFps < numberSetPositionThreshold)\n                        {\n                            const auto sleepMs = positiveIntRound( (-difference*nsPerFrame*1e-6)*0.99 );\n                            std::this_thread::sleep_for(std::chrono::milliseconds{sleepMs});\n                        }\n                    }\n                    else\n                    {\n                        mTrackingFps = true;\n                        mFirstFrameTrackingFps = 0;\n                        mNumberFramesTrackingFps = 0;\n                        mNumberSetPositionTrackingFps = 0;\n                        mClockTrackingFps = std::chrono::high_resolution_clock::now();\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::shared_ptr<Producer> createProducer(\n        const ProducerType producerType, const std::string& producerString, const Point<int>& cameraResolution,\n        const std::string& cameraParameterPath, const bool undistortImage, const int numberViews)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n            // Directory of images\n            if (producerType == ProducerType::ImageDirectory)\n                return std::make_shared<ImageDirectoryReader>(\n                    producerString, cameraParameterPath, undistortImage, numberViews);\n            // Video\n            else if (producerType == ProducerType::Video)\n                return std::make_shared<VideoReader>(\n                    producerString, cameraParameterPath, undistortImage, numberViews);\n            // IP camera\n            else if (producerType == ProducerType::IPCamera)\n                return std::make_shared<IpCameraReader>(producerString, cameraParameterPath, undistortImage);\n            // Flir camera\n            else if (producerType == ProducerType::FlirCamera)\n                return std::make_shared<FlirReader>(\n                    cameraParameterPath, cameraResolution, undistortImage, std::stoi(producerString));\n            // Webcam\n            else if (producerType == ProducerType::Webcam)\n            {\n                const auto webcamIndex = std::stoi(producerString);\n                auto cameraResolutionFinal = cameraResolution;\n                if (cameraResolutionFinal.x < 0 || cameraResolutionFinal.y < 0)\n                    cameraResolutionFinal = Point<int>{1280,720};\n                if (webcamIndex >= 0)\n                {\n                    const auto throwExceptionIfNoOpened = true;\n                    return std::make_shared<WebcamReader>(\n                        webcamIndex, cameraResolutionFinal, throwExceptionIfNoOpened, cameraParameterPath,\n                        undistortImage);\n                }\n                else\n                {\n                    const auto throwExceptionIfNoOpened = false;\n                    std::shared_ptr<WebcamReader> webcamReader;\n                    for (auto index = 0 ; index < 10 ; index++)\n                    {\n                        webcamReader = std::make_shared<WebcamReader>(\n                            index, cameraResolutionFinal, throwExceptionIfNoOpened, cameraParameterPath,\n                            undistortImage);\n                        if (webcamReader->isOpened())\n                        {\n                            opLog(\"Auto-detecting camera index... Detected and opened camera \" + std::to_string(index)\n                                + \".\", Priority::High);\n                            return webcamReader;\n                        }\n                    }\n                    error(\"No camera found.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n            // Unknown\n            else if (producerType != ProducerType::None)\n                error(\"Undefined Producer selected.\", __LINE__, __FUNCTION__, __FILE__);\n            // None\n            return nullptr;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return nullptr;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/spinnakerWrapper.cpp",
    "content": "#include <openpose/producer/spinnakerWrapper.hpp>\n#include <atomic>\n#include <mutex>\n#include <opencv2/imgproc/imgproc.hpp> // cv::undistort, cv::initUndistortRectifyMap\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp> // OPEN_CV_IS_4_OR_HIGHER\n#ifdef OPEN_CV_IS_4_OR_HIGHER\n    #include <opencv2/calib3d.hpp> // cv::initUndistortRectifyMap for OpenCV 4\n#endif\n#ifdef USE_FLIR_CAMERA\n    #include <Spinnaker.h>\n#endif\n#include <openpose/3d/cameraParameterReader.hpp>\n\nnamespace op\n{\n    #ifdef USE_FLIR_CAMERA\n        std::vector<std::string> getSerialNumbers(const Spinnaker::CameraList& cameraList,\n                                                  const bool sorted)\n        {\n            try\n            {\n                // Get strSerialNumbers\n                std::vector<Spinnaker::GenICam::gcstring> strSerialNumbers(cameraList.GetSize());\n                for (auto i = 0u; i < strSerialNumbers.size(); i++)\n                {\n                    // Select camera\n                    auto cameraPtr = cameraList.GetByIndex(i);\n\n                    strSerialNumbers[i] = \"\";\n\n                    Spinnaker::GenApi::CStringPtr ptrStringSerial = cameraPtr->GetTLDeviceNodeMap().GetNode(\n                        \"DeviceSerialNumber\"\n                    );\n\n                    if (Spinnaker::GenApi::IsAvailable(ptrStringSerial)\n                        && Spinnaker::GenApi::IsReadable(ptrStringSerial))\n                    {\n                        strSerialNumbers[i] = ptrStringSerial->GetValue();\n                    }\n                }\n\n                // Spinnaker::GenICam::gcstring to std::string\n                std::vector<std::string> serialNumbers(strSerialNumbers.size());\n                for (auto i = 0u ; i < serialNumbers.size() ; i++)\n                    serialNumbers[i] = strSerialNumbers[i];\n\n                // Sort serial numbers\n                if (sorted)\n                    std::sort(serialNumbers.begin(), serialNumbers.end());\n\n                // Return result\n                return serialNumbers;\n            }\n            catch (Spinnaker::Exception &e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return {};\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return {};\n            }\n        }\n\n        // This function prints the device information of the camera from the transport\n        // layer; please see NodeMapInfo example for more in-depth comments on printing\n        // device information from the nodemap.\n        int printDeviceInfo(Spinnaker::GenApi::INodeMap &iNodeMap, const unsigned int camNum)\n        {\n            try\n            {\n                int result = 0;\n\n                opLog(\"Printing device information for camera \" + std::to_string(camNum) + \"...\\n\", Priority::High);\n\n                Spinnaker::GenApi::FeatureList_t features;\n                Spinnaker::GenApi::CCategoryPtr cCategoryPtr = iNodeMap.GetNode(\"DeviceInformation\");\n                if (Spinnaker::GenApi::IsAvailable(cCategoryPtr) && Spinnaker::GenApi::IsReadable(cCategoryPtr))\n                {\n                    cCategoryPtr->GetFeatures(features);\n\n                    Spinnaker::GenApi::FeatureList_t::const_iterator it;\n                    for (it = features.begin(); it != features.end(); ++it)\n                    {\n                        Spinnaker::GenApi::CNodePtr pfeatureNode = *it;\n                        const auto cValuePtr = (Spinnaker::GenApi::CValuePtr)pfeatureNode;\n                        opLog(pfeatureNode->GetName() + \" : \" +\n                                (IsReadable(cValuePtr) ? cValuePtr->ToString() : \"Node not readable\"), Priority::High);\n                    }\n                }\n                else\n                    opLog(\"Device control information not available.\", Priority::High);\n                opLog(\" \", Priority::High);\n\n                return result;\n            }\n            catch (Spinnaker::Exception &e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n        }\n\n        // This function returns the camera to a normal state by turning off trigger\n        // mode.\n        int resetTrigger(Spinnaker::GenApi::INodeMap &iNodeMap)\n        {\n            try\n            {\n                int result = 0;\n                //\n                // Turn trigger mode back off\n                //\n                // *** NOTES ***\n                // Once all images have been captured, turn trigger mode back off to\n                // restore the camera to a clean state.\n                //\n                Spinnaker::GenApi::CEnumerationPtr ptrTriggerMode = iNodeMap.GetNode(\"TriggerMode\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerMode)\n                    || !Spinnaker::GenApi::IsReadable(ptrTriggerMode))\n                    error(\"Unable to disable trigger mode (node retrieval). Non-fatal error...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                Spinnaker::GenApi::CEnumEntryPtr ptrTriggerModeOff = ptrTriggerMode->GetEntryByName(\"Off\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerModeOff)\n                    || !Spinnaker::GenApi::IsReadable(ptrTriggerModeOff))\n                    error(\"Unable to disable trigger mode (enum entry retrieval). Non-fatal error...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                ptrTriggerMode->SetIntValue(ptrTriggerModeOff->GetValue());\n\n                // opLog(\"Trigger mode disabled...\", Priority::High);\n\n                return result;\n            }\n            catch (Spinnaker::Exception &e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n        }\n\n        Spinnaker::ImagePtr spinnakerImagePtrToColor(const Spinnaker::ImagePtr &imagePtr)\n        {\n            // Original image --> BGR uchar image\n            // Print image information\n            // Convert image to RGB\n            // Interpolation methods\n            // http://softwareservices.ptgrey.com/Spinnaker/latest/group___spinnaker_defs.html\n            // DEFAULT     Default method.\n            // NO_COLOR_PROCESSING     No color processing.\n            // NEAREST_NEIGHBOR    Fastest but lowest quality. Equivalent to\n            //                     FLYCAPTURE_NEAREST_NEIGHBOR_FAST in FlyCapture.\n            // EDGE_SENSING    Weights surrounding pixels based on localized edge orientation.\n            // HQ_LINEAR   Well-balanced speed and quality.\n            // RIGOROUS    Slowest but produces good results.\n            // IPP     Multi-threaded with similar results to edge sensing.\n            // DIRECTIONAL_FILTER  Best quality but much faster than rigorous.\n            // Colors\n            // http://softwareservices.ptgrey.com/Spinnaker/latest/group___camera_defs__h.html#ggabd5af55aaa20bcb0644c46241c2cbad1a33a1c8a1f6dbcb4a4eaaaf6d4d7ff1d1\n            // PixelFormat_BGR8\n\n            // // Time tests\n            // // DEFAULT\n            // const auto reps = 1e2;\n            // const auto begin1 = std::chrono::high_resolution_clock::now();\n            // for (auto asdf = 0 ; asdf < reps ; asdf++)\n            //     const auto imagePtrTemp = imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::DEFAULT);\n            // const auto durationMs1 = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            //     std::chrono::high_resolution_clock::now()-begin1\n            // ).count() * 1e-6;\n            // // EDGE_SENSING\n            // const auto begin2 = std::chrono::high_resolution_clock::now();\n            // for (auto asdf = 0 ; asdf < reps ; asdf++)\n            //     const auto imagePtrTemp = imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::EDGE_SENSING);\n            // const auto durationMs2 = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            //     std::chrono::high_resolution_clock::now()-begin2\n            // ).count() * 1e-6;\n            // // IPP\n            // const auto begin3 = std::chrono::high_resolution_clock::now();\n            // for (auto asdf = 0 ; asdf < reps ; asdf++)\n            //     const auto imagePtrTemp = imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::IPP);\n            // const auto durationMs3 = std::chrono::duration_cast<std::chrono::nanoseconds>(\n            //     std::chrono::high_resolution_clock::now()-begin3\n            // ).count() * 1e-6;\n            // // Print times\n            // opLog(\"Time (ms) 1: \" + std::to_string(durationMs1 / reps), Priority::High);\n            // opLog(\"Time (ms) 2: \" + std::to_string(durationMs2 / reps), Priority::High);\n            // opLog(\"Time (ms) 3: \" + std::to_string(durationMs3 / reps), Priority::High);\n\n            // Return right one\n            // ~ 1.3 ms but pixeled\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::DEFAULT);\n            // ~0.5 ms but BW\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::NO_COLOR_PROCESSING);\n            // ~6 ms, looks as good as best\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::HQ_LINEAR);\n            // ~2.2 ms default << edge << best\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::EDGE_SENSING);\n            // ~115, too slow\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::RIGOROUS);\n            // ~1.7 ms, slightly worse than HQ_LINEAR\n            return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::IPP);\n            // ~30 ms, ideally best quality?\n            // return imagePtr->Convert(Spinnaker::PixelFormat_BGR8, Spinnaker::DIRECTIONAL_FILTER);\n        }\n\n        /*\n         * This function converts between Spinnaker::ImagePtr container to cv::Mat container used in OpenCV.\n        */\n        cv::Mat spinnakerWrapperToCvMat(const Spinnaker::ImagePtr &imagePtr)\n        {\n            try\n            {\n                const auto XPadding = imagePtr->GetXPadding();\n                const auto YPadding = imagePtr->GetYPadding();\n                const auto rowsize = imagePtr->GetWidth();\n                const auto colsize = imagePtr->GetHeight();\n\n                // Image data contains padding. When allocating cv::Mat container size, you need to account for the X,Y\n                // image data padding.\n                return cv::Mat((int)(colsize + YPadding), (int)(rowsize + XPadding), CV_8UC3, imagePtr->GetData(),\n                               imagePtr->GetStride());\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return cv::Mat();\n            }\n        }\n\n        // This function configures the camera to use a trigger. First, trigger mode is\n        // set to off in order to select the trigger source. Once the trigger source\n        // has been selected, trigger mode is then enabled, which has the camera\n        // capture only a single image upon the execution of the chosen trigger.\n        int configureTrigger(Spinnaker::GenApi::INodeMap &iNodeMap)\n        {\n            try\n            {\n                int result = 0;\n                opLog(\"*** CONFIGURING TRIGGER ***\", Priority::High);\n                opLog(\"Configuring trigger...\", Priority::High);\n                // opLog(\"Configuring hardware trigger...\", Priority::High);\n                // Ensure trigger mode off\n                // *** NOTES ***\n                // The trigger must be disabled in order to configure whether the source\n                // is software or hardware.\n                Spinnaker::GenApi::CEnumerationPtr ptrTriggerMode = iNodeMap.GetNode(\"TriggerMode\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerMode) || !Spinnaker::GenApi::IsReadable(ptrTriggerMode))\n                    error(\"Unable to disable trigger mode (node retrieval). Aborting...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                Spinnaker::GenApi::CEnumEntryPtr ptrTriggerModeOff = ptrTriggerMode->GetEntryByName(\"Off\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerModeOff)\n                    || !Spinnaker::GenApi::IsReadable(ptrTriggerModeOff))\n                    error(\"Unable to disable trigger mode (enum entry retrieval). Aborting...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                ptrTriggerMode->SetIntValue(ptrTriggerModeOff->GetValue());\n\n                opLog(\"Trigger mode disabled...\", Priority::High);\n\n                // Select trigger source\n                // *** NOTES ***\n                // The trigger source must be set to hardware or software while trigger\n                // mode is off.\n                Spinnaker::GenApi::CEnumerationPtr ptrTriggerSource = iNodeMap.GetNode(\"TriggerSource\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerSource)\n                    || !Spinnaker::GenApi::IsWritable(ptrTriggerSource))\n                    error(\"Unable to set trigger mode (node retrieval). Aborting...\",\n                          __LINE__, __FUNCTION__, __FILE__);\n\n                // // Set trigger mode to hardware ('Line0')\n                // Spinnaker::GenApi::CEnumEntryPtr ptrTriggerSourceHardware = ptrTriggerSource->GetEntryByName(\"Line0\");\n                // if (!Spinnaker::GenApi::IsAvailable(ptrTriggerSourceHardware)\n                //     || !Spinnaker::GenApi::IsReadable(ptrTriggerSourceHardware))\n                //     error(\"Unable to set trigger mode (enum entry retrieval). Aborting...\",\n                //               __LINE__, __FUNCTION__, __FILE__);\n                // ptrTriggerSource->SetIntValue(ptrTriggerSourceHardware->GetValue());\n                // opLog(\"Trigger source set to hardware...\", Priority::High);\n\n                // Set trigger mode to software\n                Spinnaker::GenApi::CEnumEntryPtr ptrTriggerSourceSoftware = ptrTriggerSource->GetEntryByName(\"Software\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerSourceSoftware)\n                    || !Spinnaker::GenApi::IsReadable(ptrTriggerSourceSoftware))\n                    error(\"Unable to set trigger mode (enum entry retrieval). Aborting...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                ptrTriggerSource->SetIntValue(ptrTriggerSourceSoftware->GetValue());\n                // opLog(\"Trigger source set to source...\", Priority::High);\n\n                // Turn trigger mode on\n                // *** LATER ***\n                // Once the appropriate trigger source has been set, turn trigger mode\n                // on in order to retrieve images using the trigger.\n                Spinnaker::GenApi::CEnumEntryPtr ptrTriggerModeOn = ptrTriggerMode->GetEntryByName(\"On\");\n                if (!Spinnaker::GenApi::IsAvailable(ptrTriggerModeOn)\n                    || !Spinnaker::GenApi::IsReadable(ptrTriggerModeOn))\n                {\n                    error(\"Unable to enable trigger mode (enum entry retrieval). Aborting...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n                    return -1;\n                }\n\n                ptrTriggerMode->SetIntValue(ptrTriggerModeOn->GetValue());\n\n                opLog(\"Trigger mode turned back on...\", Priority::High);\n\n                return result;\n            }\n            catch (const Spinnaker::Exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n        }\n\n        int GrabNextImageByTrigger(Spinnaker::GenApi::INodeMap& nodeMap)\n        {\n            try\n            {\n                int result = 0;\n\n                // Execute software trigger\n                Spinnaker::GenApi::CCommandPtr ptrSoftwareTriggerCommand = nodeMap.GetNode(\"TriggerSoftware\");\n                if (!IsAvailable(ptrSoftwareTriggerCommand) || !IsWritable(ptrSoftwareTriggerCommand))\n                    error(\"Unable to enable trigger. Aborting...\",\n                              __LINE__, __FUNCTION__, __FILE__);\n\n                ptrSoftwareTriggerCommand->Execute();\n\n                return result;\n            }\n            catch (const Spinnaker::Exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return -1;\n            }\n        }\n    #else\n        const std::string USE_FLIR_CAMERA_ERROR{\"OpenPose CMake must be compiled with the `USE_FLIR_CAMERA`\"\n            \" flag in order to use the FLIR camera. Alternatively, disable `--flir_camera`.\"};\n    #endif\n\n    struct SpinnakerWrapper::ImplSpinnakerWrapper\n    {\n        #ifdef USE_FLIR_CAMERA\n            bool mInitialized;\n            CameraParameterReader mCameraParameterReader;\n            Point<int> mResolution;\n            Spinnaker::CameraList mCameraList;\n            Spinnaker::SystemPtr mSystemPtr;\n            std::vector<cv::Mat> mCvMats;\n            std::vector<std::string> mSerialNumbers;\n            // Camera index\n            const int mCameraIndex;\n            // Undistortion\n            const bool mUndistortImage;\n            std::vector<cv::Mat> mRemoveDistortionMaps1;\n            std::vector<cv::Mat> mRemoveDistortionMaps2;\n            // Thread\n            bool mThreadOpened;\n            std::vector<Spinnaker::ImagePtr> mBuffer;\n            std::mutex mBufferMutex;\n            std::atomic<bool> mCloseThread;\n            std::thread mThread;\n\n            ImplSpinnakerWrapper(const bool undistortImage, const int cameraIndex) :\n                mInitialized{false},\n                mCameraIndex{cameraIndex},\n                mUndistortImage{undistortImage}\n            {\n            }\n\n            void readAndUndistortImage(const int i, const Spinnaker::ImagePtr& imagePtr,\n                                       const cv::Mat& cameraIntrinsics = cv::Mat(),\n                                       const cv::Mat& cameraDistorsions = cv::Mat())\n            {\n                try\n                {\n                    // Original image --> BGR uchar image\n                    const auto imagePtrColor = spinnakerImagePtrToColor(imagePtr);\n                    // Spinnaker to cv::Mat\n                    const auto cvMatDistorted = spinnakerWrapperToCvMat(imagePtrColor);\n                    // const auto cvMatDistorted = spinnakerWrapperToCvMat(imagePtr);\n                    // Undistort\n                    if (mUndistortImage)\n                    {\n                        // Sanity check\n                        if (cameraIntrinsics.empty() || cameraDistorsions.empty())\n                            error(\"Camera intrinsics/distortions were empty.\", __LINE__, __FUNCTION__, __FILE__);\n                        // // Option a - 80 ms / 3 images\n                        // // http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#undistort\n                        // cv::undistort(cvMatDistorted, mCvMats[i], cameraIntrinsics, cameraDistorsions);\n                        // // In OpenCV 2.4, cv::undistort is exactly equal than cv::initUndistortRectifyMap\n                        // (with CV_16SC2) + cv::remap (with LINEAR). I.e., opLog(cv::norm(cvMatMethod1-cvMatMethod2)) = 0.\n                        // Option b - 15 ms / 3 images (LINEAR) or 25 ms (CUBIC)\n                        // Distortion removal - not required and more expensive (applied to the whole image instead of\n                        // only to our interest points)\n                        if (mRemoveDistortionMaps1[i].empty() || mRemoveDistortionMaps2[i].empty())\n                        {\n                            const auto imageSize = cvMatDistorted.size();\n                            cv::initUndistortRectifyMap(cameraIntrinsics,\n                                                        cameraDistorsions,\n                                                        cv::Mat(),\n                                                        // cameraIntrinsics instead of cv::getOptimalNewCameraMatrix to\n                                                        // avoid black borders\n                                                        cameraIntrinsics,\n                                                        // #include <opencv2/calib3d/calib3d.hpp> for next line\n                                                        // cv::getOptimalNewCameraMatrix(cameraIntrinsics,\n                                                        //                               cameraDistorsions,\n                                                        //                               imageSize, 1,\n                                                        //                               imageSize, 0),\n                                                        imageSize,\n                                                        CV_16SC2, // Faster, less memory\n                                                        // CV_32FC1, // More accurate\n                                                        mRemoveDistortionMaps1[i],\n                                                        mRemoveDistortionMaps2[i]);\n                        }\n                        cv::remap(cvMatDistorted, mCvMats[i],\n                                  mRemoveDistortionMaps1[i], mRemoveDistortionMaps2[i],\n                                  // cv::INTER_NEAREST);\n                                  cv::INTER_LINEAR);\n                                  // cv::INTER_CUBIC);\n                                  // cv::INTER_LANCZOS4); // Smoother, but we do not need this quality & its >>expensive\n                    }\n                    // Baseline (do not undistort)\n                    else\n                        mCvMats[i] = cvMatDistorted.clone();\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n\n            void bufferingThread()\n            {\n                #ifdef USE_FLIR_CAMERA\n                    try\n                    {\n                        mCloseThread = false;\n                        // Get cameras - ~0.005 ms (3 cameras)\n                        std::vector<Spinnaker::CameraPtr> cameraPtrs(mCameraList.GetSize());\n                        for (auto i = 0u; i < cameraPtrs.size(); i++)\n                            cameraPtrs.at(i) = mCameraList.GetBySerial(mSerialNumbers.at(i)); // Sorted by Serial Number\n                            // cameraPtrs.at(i) = mCameraList.GetByIndex(i); // Sorted by however Spinnaker decided\n                        while (!mCloseThread)\n                        {\n                            // Trigger\n                            for (auto i = 0u; i < cameraPtrs.size(); i++)\n                            {\n                                // Retrieve GenICam nodemap\n                                auto& iNodeMap = cameraPtrs[i]->GetNodeMap();\n                                Spinnaker::GenApi::CEnumerationPtr ptrAcquisitionMode = iNodeMap.GetNode(\"AcquisitionMode\");\n                                const auto result = GrabNextImageByTrigger(iNodeMap);\n                                if (result != 0)\n                                    error(\"Error in GrabNextImageByTrigger.\", __LINE__, __FUNCTION__, __FILE__);\n                            }\n                            // Get frame\n                            std::vector<Spinnaker::ImagePtr> imagePtrs(cameraPtrs.size());\n                            for (auto i = 0u; i < cameraPtrs.size(); i++)\n                                imagePtrs.at(i) = cameraPtrs.at(i)->GetNextImage();\n                            // Move to buffer\n                            bool imagesExtracted = true;\n                            for (auto& imagePtr : imagePtrs)\n                            {\n                                if (imagePtr->IsIncomplete())\n                                {\n                                    opLog(\"Image incomplete with image status \" + std::to_string(imagePtr->GetImageStatus())\n                                        + \"...\", Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                                    imagesExtracted = false;\n                                    break;\n                                }\n                            }\n                            if (imagesExtracted)\n                            {\n                                std::unique_lock<std::mutex> lock{mBufferMutex};\n                                std::swap(mBuffer, imagePtrs);\n                                lock.unlock();\n                                std::this_thread::sleep_for(std::chrono::microseconds{1});\n                            }\n                        }\n                    }\n                    catch (const std::exception& e)\n                    {\n                        error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                    }\n                #endif\n            }\n\n            // This function acquires and displays images from each device.\n            std::vector<Matrix> acquireImages(\n                const std::vector<Matrix>& opCameraIntrinsics,\n                const std::vector<Matrix>& opCameraDistorsions,\n                const int cameraIndex = -1)\n            {\n                try\n                {\n                    OP_OP2CVVECTORMAT(cameraIntrinsics, opCameraIntrinsics)\n                    OP_OP2CVVECTORMAT(cameraDistorsions, opCameraDistorsions)\n                    // std::vector<cv::Mat> cvMats;\n\n                    // Retrieve, convert, and return an image for each camera\n                    // In order to work with simultaneous camera streams, nested loops are\n                    // needed. It is important that the inner loop be the one iterating\n                    // through the cameras; otherwise, all images will be grabbed from a\n                    // single camera before grabbing any images from another.\n\n                    // // Get cameras - ~0.005 ms (3 cameras)\n                    // std::vector<Spinnaker::CameraPtr> cameraPtrs(cameraList.GetSize());\n                    // for (auto i = 0u; i < cameraPtrs.size(); i++)\n                    //     cameraPtrs.at(i) = cameraList.GetByIndex(i);\n\n                    // Read raw images - ~0.15 ms (3 cameras)\n                    // std::vector<Spinnaker::ImagePtr> imagePtrs(cameraPtrs.size());\n                    // for (auto i = 0u; i < cameraPtrs.size(); i++)\n                    //     imagePtrs.at(i) = cameraPtrs.at(i)->GetNextImage();\n                    std::vector<Spinnaker::ImagePtr> imagePtrs;\n                    // Retrieve frame\n                    auto cvMatRetrieved = false;\n                    while (!cvMatRetrieved)\n                    {\n                        // Retrieve frame\n                        std::unique_lock<std::mutex> lock{mBufferMutex};\n                        if (!mBuffer.empty())\n                        {\n                            std::swap(imagePtrs, mBuffer);\n                            cvMatRetrieved = true;\n                        }\n                        // No frames available -> sleep & wait\n                        else\n                        {\n                            lock.unlock();\n                            std::this_thread::sleep_for(std::chrono::microseconds{5});\n                        }\n                    }\n                    // Getting frames\n                    // Retrieve next received image and ensure image completion\n                    // Spinnaker::ImagePtr imagePtr = cameraPtrs.at(i)->GetNextImage();\n\n                    // All images completed\n                    bool imagesExtracted = true;\n                    for (auto& imagePtr : imagePtrs)\n                    {\n                        if (imagePtr->IsIncomplete())\n                        {\n                            opLog(\"Image incomplete with image status \" + std::to_string(imagePtr->GetImageStatus())\n                                + \"...\", Priority::High, __LINE__, __FUNCTION__, __FILE__);\n                            imagesExtracted = false;\n                            break;\n                        }\n                    }\n                    mCvMats.clear();\n                    // Convert to cv::Mat\n                    if (imagesExtracted)\n                    {\n                        // // Original image --> BGR uchar image - ~4 ms (3 cameras)\n                        // for (auto& imagePtr : imagePtrs)\n                        //     imagePtr = spinnakerImagePtrToColor(imagePtr);\n\n                        // Init anti-distortion matrices first time\n                        if (mRemoveDistortionMaps1.empty())\n                            mRemoveDistortionMaps1.resize(imagePtrs.size());\n                        if (mRemoveDistortionMaps2.empty())\n                            mRemoveDistortionMaps2.resize(imagePtrs.size());\n\n                        // Multi-thread undistort (slowest function in the class)\n                        //     ~7.7msec (3 cameras + multi-thread + (initUndistortRectifyMap + remap) + LINEAR)\n                        //     ~23.2msec (3 cameras + multi-thread + (initUndistortRectifyMap + remap) + CUBIC)\n                        //     ~35msec (3 cameras + multi-thread + undistort)\n                        //     ~59msec (2 cameras + single-thread + undistort)\n                        //     ~75msec (3 cameras + single-thread + undistort)\n                        mCvMats.resize(imagePtrs.size());\n                        // All cameras\n                        if (cameraIndex < 0)\n                        {\n                            // Undistort image\n                            if (mUndistortImage)\n                            {\n                                std::vector<std::thread> threads(imagePtrs.size()-1);\n                                for (auto i = 0u; i < threads.size(); i++)\n                                {\n                                    // Multi-thread option\n                                    threads.at(i) = std::thread{&ImplSpinnakerWrapper::readAndUndistortImage, this, i,\n                                                                imagePtrs.at(i), cameraIntrinsics.at(i),\n                                                                cameraDistorsions.at(i)};\n                                    // // Single-thread option\n                                    // readAndUndistortImage(i, imagePtrs.at(i), cameraIntrinsics.at(i), cameraDistorsions.at(i));\n                                }\n                                readAndUndistortImage((int)imagePtrs.size()-1, imagePtrs.back(), cameraIntrinsics.back(),\n                                                      cameraDistorsions.back());\n                                // Close threads\n                                for (auto& thread : threads)\n                                    if (thread.joinable())\n                                        thread.join();\n                            }\n                            // Do not undistort image\n                            else\n                            {\n                                for (auto i = 0u; i < imagePtrs.size(); i++)\n                                    readAndUndistortImage(i, imagePtrs.at(i));\n                            }\n                        }\n                        // Only 1 camera\n                        else\n                        {\n                            // Sanity check\n                            if ((unsigned int)cameraIndex >= imagePtrs.size())\n                                error(\"There are only \" + std::to_string(imagePtrs.size())\n                                      + \" cameras, but you asked for the \"\n                                      + std::to_string(cameraIndex+1) +\"-th camera (i.e., `--flir_camera_index \"\n                                      + std::to_string(cameraIndex) +\"`), which doesn't exist. Note that the index is\"\n                                      + \" 0-based.\", __LINE__, __FUNCTION__, __FILE__);\n                            // Undistort image\n                            if (mUndistortImage)\n                                readAndUndistortImage(cameraIndex, imagePtrs.at(cameraIndex), cameraIntrinsics.at(cameraIndex),\n                                                      cameraDistorsions.at(cameraIndex));\n                            // Do not undistort image\n                            else\n                                readAndUndistortImage(cameraIndex, imagePtrs.at(cameraIndex));\n                            mCvMats = std::vector<cv::Mat>{mCvMats[cameraIndex]};\n                        }\n                    }\n                    OP_CV2OPVECTORMAT(opMats, mCvMats)\n                    return opMats;\n                }\n                catch (Spinnaker::Exception &e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                    return {};\n                }\n                catch (const std::exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                    return {};\n                }\n            }\n        #endif\n    };\n\n    SpinnakerWrapper::SpinnakerWrapper(const std::string& cameraParameterPath, const Point<int>& resolution,\n                                       const bool undistortImage, const int cameraIndex)\n        #ifdef USE_FLIR_CAMERA\n            : upImpl{new ImplSpinnakerWrapper{undistortImage, cameraIndex}}\n        #endif\n    {\n        #ifdef USE_FLIR_CAMERA\n            try\n            {\n                // Clean previous unclosed builds (e.g., if core dumped in the previous code using the cameras)\n                release();\n\n                upImpl->mInitialized = true;\n\n                // Print application build information\n                opLog(std::string{ \"Application build date: \" } + __DATE__ + \" \" + __TIME__, Priority::High);\n\n                // Retrieve singleton reference to upImpl->mSystemPtr object\n                upImpl->mSystemPtr = Spinnaker::System::GetInstance();\n\n                // Retrieve list of cameras from the upImpl->mSystemPtr\n                upImpl->mCameraList = upImpl->mSystemPtr->GetCameras();\n\n                const unsigned int numCameras = upImpl->mCameraList.GetSize();\n\n                opLog(\"Number of cameras detected: \" + std::to_string(numCameras), Priority::High);\n\n                // Finish if there are no cameras\n                if (numCameras == 0)\n                {\n                    // Clear camera list before releasing upImpl->mSystemPtr\n                    upImpl->mCameraList.Clear();\n\n                    // Release upImpl->mSystemPtr\n                    upImpl->mSystemPtr->ReleaseInstance();\n\n                    // opLog(\"Not enough cameras!\\nPress Enter to exit...\", Priority::High);\n                    // getchar();\n\n                    error(\"No cameras detected.\", __LINE__, __FUNCTION__, __FILE__);\n                }\n                opLog(\"Camera system initialized...\", Priority::High);\n\n                //\n                // Retrieve transport layer nodemaps and print device information for\n                // each camera\n                //\n                // *** NOTES ***\n                // This example retrieves information from the transport layer nodemap\n                // twice: once to print device information and once to grab the device\n                // serial number. Rather than caching the nodemap, each nodemap is\n                // retrieved both times as needed.\n                //\n                opLog(\"\\n*** DEVICE INFORMATION ***\\n\", Priority::High);\n\n                for (auto i = 0; i < upImpl->mCameraList.GetSize(); i++)\n                {\n                    // Select camera\n                    auto cameraPtr = upImpl->mCameraList.GetByIndex(i);\n\n                    // Retrieve TL device nodemap\n                    auto& iNodeMapTLDevice = cameraPtr->GetTLDeviceNodeMap();\n\n                    // Print device information\n                    auto result = printDeviceInfo(iNodeMapTLDevice, i);\n                    if (result < 0)\n                        error(\"Result > 0, error \" + std::to_string(result) + \" occurred...\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                }\n\n                for (auto i = 0; i < upImpl->mCameraList.GetSize(); i++)\n                {\n                    // Select camera\n                    auto cameraPtr = upImpl->mCameraList.GetByIndex(i);\n\n                    // Initialize each camera\n                    // You may notice that the steps in this function have more loops with\n                    // less steps per loop; this contrasts the acquireImages() function\n                    // which has less loops but more steps per loop. This is done for\n                    // demonstrative purposes as both work equally well.\n                    // Later: Each camera needs to be deinitialized once all images have been\n                    // acquired.\n                    cameraPtr->Init();\n\n                    // Retrieve GenICam nodemap\n                    auto& iNodeMap = cameraPtr->GetNodeMap();\n\n                    // Configure trigger\n                    int result = configureTrigger(iNodeMap);\n                    if (result < 0)\n                        error(\"Result > 0, error \" + std::to_string(result) + \" occurred...\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n\n                    // // Configure chunk data\n                    // result = configureChunkData(iNodeMap);\n                    // if (result < 0)\n                    //     return result;\n\n                    // // Remove buffer --> Always get newest frame\n                    // Spinnaker::GenApi::INodeMap& snodeMap = cameraPtr->GetTLStreamNodeMap();\n                    // Spinnaker::GenApi::CEnumerationPtr ptrBufferHandlingMode = snodeMap.GetNode(\n                    //     \"StreamBufferHandlingMode\");\n                    // if (!Spinnaker::GenApi::IsAvailable(ptrBufferHandlingMode)\n                    //     || !Spinnaker::GenApi::IsWritable(ptrBufferHandlingMode))\n                    //     error(\"Unable to change buffer handling mode\", __LINE__, __FUNCTION__, __FILE__);\n\n                    // Spinnaker::GenApi::CEnumEntryPtr ptrBufferHandlingModeNewest = ptrBufferHandlingMode->GetEntryByName(\n                    //     \"NewestFirstOverwrite\");\n                    // if (!Spinnaker::GenApi::IsAvailable(ptrBufferHandlingModeNewest)\n                    //     || !IsReadable(ptrBufferHandlingModeNewest))\n                    //     error(\"Unable to set buffer handling mode to newest (entry 'NewestFirstOverwrite' retrieval).\"\n                    //               \" Aborting...\", __LINE__, __FUNCTION__, __FILE__);\n                    // int64_t bufferHandlingModeNewest = ptrBufferHandlingModeNewest->GetValue();\n\n                    // ptrBufferHandlingMode->SetIntValue(bufferHandlingModeNewest);\n                }\n\n                // Prepare each camera to acquire images\n                //\n                // *** NOTES ***\n                // For pseudo-simultaneous streaming, each camera is prepared as if it\n                // were just one, but in a loop. Notice that cameras are selected with\n                // an index. We demonstrate pseduo-simultaneous streaming because true\n                // simultaneous streaming would require multiple process or threads,\n                // which is too complex for an example.\n                //\n                // Serial numbers are the only persistent objects we gather in this\n                // example, which is why a std::vector is created.\n                for (auto i = 0; i < upImpl->mCameraList.GetSize(); i++)\n                {\n                    // Select camera\n                    auto cameraPtr = upImpl->mCameraList.GetByIndex(i);\n\n                    // Set acquisition mode to continuous\n                    Spinnaker::GenApi::CEnumerationPtr ptrAcquisitionMode = cameraPtr->GetNodeMap().GetNode(\n                        \"AcquisitionMode\");\n                    if (!Spinnaker::GenApi::IsAvailable(ptrAcquisitionMode)\n                        || !Spinnaker::GenApi::IsWritable(ptrAcquisitionMode))\n                        error(\"Unable to set acquisition mode to continuous (node retrieval; camera \"\n                              + std::to_string(i) + \"). Aborting...\", __LINE__, __FUNCTION__, __FILE__);\n\n                    Spinnaker::GenApi::CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName(\n                        \"Continuous\");\n                    if (!Spinnaker::GenApi::IsAvailable(ptrAcquisitionModeContinuous)\n                        || !Spinnaker::GenApi::IsReadable(ptrAcquisitionModeContinuous))\n                        error(\"Unable to set acquisition mode to continuous (entry 'continuous' retrieval \"\n                                  + std::to_string(i) + \"). Aborting...\", __LINE__, __FUNCTION__, __FILE__);\n\n                    const int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();\n\n                    ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);\n\n                    opLog(\"Camera \" + std::to_string(i) + \" acquisition mode set to continuous...\", Priority::High);\n\n                    // Set camera resolution\n                    // Retrieve GenICam nodemap\n                    auto& iNodeMap = cameraPtr->GetNodeMap();\n                    // Set offset\n                    Spinnaker::GenApi::CIntegerPtr ptrOffsetX = iNodeMap.GetNode(\"OffsetX\");\n                    ptrOffsetX->SetValue(0);\n                    Spinnaker::GenApi::CIntegerPtr ptrOffsetY = iNodeMap.GetNode(\"OffsetY\");\n                    ptrOffsetY->SetValue(0);\n                    // Set resolution\n                    if (resolution.x > 0 && resolution.y > 0)\n                    {\n                        // WARNING: setting the obset would require auto-change in the camera matrix parameters\n                        // Set offset\n                        // const Spinnaker::GenApi::CIntegerPtr ptrWidthMax = iNodeMap.GetNode(\"WidthMax\");\n                        // const Spinnaker::GenApi::CIntegerPtr ptrHeightMax = iNodeMap.GetNode(\"HeightMax\");\n                        // ptrOffsetX->SetValue((ptrWidthMax->GetValue() - resolution.x) / 2);\n                        // ptrOffsetY->SetValue((ptrHeightMax->GetValue() - resolution.y) / 2);\n                        // Set Width\n                        Spinnaker::GenApi::CIntegerPtr ptrWidth = iNodeMap.GetNode(\"Width\");\n                        ptrWidth->SetValue(resolution.x);\n                        // Set width\n                        Spinnaker::GenApi::CIntegerPtr ptrHeight = iNodeMap.GetNode(\"Height\");\n                        ptrHeight->SetValue(resolution.y);\n                    }\n                    else\n                    {\n                        const Spinnaker::GenApi::CIntegerPtr ptrWidthMax = iNodeMap.GetNode(\"WidthMax\");\n                        const Spinnaker::GenApi::CIntegerPtr ptrHeightMax = iNodeMap.GetNode(\"HeightMax\");\n                        // Set Width\n                        Spinnaker::GenApi::CIntegerPtr ptrWidth = iNodeMap.GetNode(\"Width\");\n                        ptrWidth->SetValue(ptrWidthMax->GetValue());\n                        // Set width\n                        Spinnaker::GenApi::CIntegerPtr ptrHeight = iNodeMap.GetNode(\"Height\");\n                        ptrHeight->SetValue(ptrHeightMax->GetValue());\n                        opLog(\"Choosing maximum resolution for flir camera (\" + std::to_string(ptrWidth->GetValue())\n                            + \" x \" + std::to_string(ptrHeight->GetValue()) + \").\", Priority::High);\n                    }\n\n                    // Begin acquiring images\n                    cameraPtr->BeginAcquisition();\n\n                    opLog(\"Camera \" + std::to_string(i) + \" started acquiring images...\", Priority::High);\n                }\n\n                // Retrieve device serial number for filename\n                opLog(\"\\nReading (and sorting by) serial numbers...\", Priority::High);\n                const bool sorted = true;\n                upImpl->mSerialNumbers = getSerialNumbers(upImpl->mCameraList, sorted);\n                const auto& serialNumbers = upImpl->mSerialNumbers;\n                for (auto i = 0u; i < serialNumbers.size(); i++)\n                    opLog(\"Camera \" + std::to_string(i) + \" serial number set to \"\n                        + serialNumbers[i] + \"...\", Priority::High);\n                if (upImpl->mCameraIndex >= 0)\n                    opLog(\"Only using camera index \" + std::to_string(upImpl->mCameraIndex) + \", i.e., serial number \"\n                        + serialNumbers[upImpl->mCameraIndex] + \"...\", Priority::High);\n\n                // Read camera parameters from SN\n                if (upImpl->mUndistortImage)\n                {\n                    // If all images required\n                    if (upImpl->mCameraIndex < 0)\n                        upImpl->mCameraParameterReader.readParameters(cameraParameterPath, serialNumbers);\n                    // If only one required\n                    else\n                    {\n                        upImpl->mCameraParameterReader.readParameters(\n                            cameraParameterPath,\n                            std::vector<std::string>(serialNumbers.size(), serialNumbers.at(upImpl->mCameraIndex)));\n                    }\n                }\n\n                // Start buffering thread\n                upImpl->mThreadOpened = true;\n                upImpl->mThread = std::thread{&SpinnakerWrapper::ImplSpinnakerWrapper::bufferingThread, this->upImpl};\n\n                // Get resolution\n                const auto cvMats = getRawFrames();\n                // Sanity check\n                if (cvMats.empty())\n                    error(\"Cameras could not be opened.\", __LINE__, __FUNCTION__, __FILE__);\n                // Get resolution\n                upImpl->mResolution = Point<int>{cvMats[0].cols(), cvMats[0].rows()};\n\n                const std::string numberCameras = std::to_string(upImpl->mCameraIndex < 0 ? serialNumbers.size() : 1);\n                opLog(\"\\nRunning for \" + numberCameras + \" out of \" + std::to_string(serialNumbers.size())\n                    + \" camera(s)...\\n\\n*** IMAGE ACQUISITION ***\\n\", Priority::High);\n            }\n            catch (const Spinnaker::Exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #else\n            UNUSED(cameraParameterPath);\n            UNUSED(resolution);\n            UNUSED(undistortImage);\n            UNUSED(cameraIndex);\n            error(USE_FLIR_CAMERA_ERROR, __LINE__, __FUNCTION__, __FILE__);\n        #endif\n    }\n\n    SpinnakerWrapper::~SpinnakerWrapper()\n    {\n        try\n        {\n            release();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::vector<Matrix> SpinnakerWrapper::getRawFrames()\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                try\n                {\n                    // Sanity check\n                    if (upImpl->mUndistortImage &&\n                        (unsigned long long) upImpl->mCameraList.GetSize()\n                            != upImpl->mCameraParameterReader.getNumberCameras())\n                        error(\"The number of cameras must be the same as the INTRINSICS vector size.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                    // Return frames\n                    return upImpl->acquireImages(upImpl->mCameraParameterReader.getCameraIntrinsics(),\n                                                 upImpl->mCameraParameterReader.getCameraDistortions(),\n                                                 upImpl->mCameraIndex);\n                }\n                catch (const Spinnaker::Exception& e)\n                {\n                    error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                    return {};\n                }\n            #else\n                error(USE_FLIR_CAMERA_ERROR, __LINE__, __FUNCTION__, __FILE__);\n                return {};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> SpinnakerWrapper::getCameraMatrices() const\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                return upImpl->mCameraParameterReader.getCameraMatrices();\n            #else\n                return {};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> SpinnakerWrapper::getCameraExtrinsics() const\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                return upImpl->mCameraParameterReader.getCameraExtrinsics();\n            #else\n                return {};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<Matrix> SpinnakerWrapper::getCameraIntrinsics() const\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                return upImpl->mCameraParameterReader.getCameraIntrinsics();\n            #else\n                return {};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    Point<int> SpinnakerWrapper::getResolution() const\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                return upImpl->mResolution;\n            #else\n                return Point<int>{};\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<int>{};\n        }\n    }\n\n    bool SpinnakerWrapper::isOpened() const\n    {\n        try\n        {\n            #ifdef USE_FLIR_CAMERA\n                return upImpl->mInitialized;\n            #else\n                return false;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    void SpinnakerWrapper::release()\n    {\n        #ifdef USE_FLIR_CAMERA\n            try\n            {\n                if (upImpl->mInitialized)\n                {\n                    // Stop thread\n                    // Close and join thread\n                    if (upImpl->mThreadOpened)\n                    {\n                        upImpl->mCloseThread = true;\n                        upImpl->mThread.join();\n                    }\n\n                    // End acquisition for each camera\n                    // Notice that what is usually a one-step process is now two steps\n                    // because of the additional step of selecting the camera. It is worth\n                    // repeating that camera selection needs to be done once per loop.\n                    // It is possible to interact with cameras through the camera list with\n                    // GetByIndex(); this is an alternative to retrieving cameras as\n                    // Spinnaker::CameraPtr objects that can be quick and easy for small tasks.\n                    //\n                    for (auto i = 0; i < upImpl->mCameraList.GetSize(); i++)\n                    {\n                        // Select camera\n                        auto cameraPtr = upImpl->mCameraList.GetByIndex(i);\n\n                        cameraPtr->EndAcquisition();\n\n                        // Retrieve GenICam nodemap\n                        auto& iNodeMap = cameraPtr->GetNodeMap();\n\n                        // // Disable chunk data\n                        // result = disableChunkData(iNodeMap);\n                        // // if (result < 0)\n                        // //     return result;\n\n                        // Reset trigger\n                        auto result = resetTrigger(iNodeMap);\n                        if (result < 0)\n                            error(\"Error happened...\" + std::to_string(result), __LINE__, __FUNCTION__, __FILE__);\n\n                        // Deinitialize each camera\n                        // Each camera must be deinitialized separately by first\n                        // selecting the camera and then deinitializing it.\n                        cameraPtr->DeInit();\n                    }\n\n                    opLog(\"FLIR (Point-grey) capture completed. Releasing cameras...\", Priority::High);\n\n                    // Clear camera list before releasing upImpl->mSystemPtr\n                    upImpl->mCameraList.Clear();\n\n                    // Release upImpl->mSystemPtr\n                    upImpl->mSystemPtr->ReleaseInstance();\n\n                    // Setting the class as released\n                    upImpl->mInitialized = false;\n\n                    opLog(\"Cameras released! Exiting program.\", Priority::High);\n                }\n                else\n                {\n                    // Open general system\n                    auto systemPtr = Spinnaker::System::GetInstance();\n                    auto cameraList = systemPtr->GetCameras();\n                    if (cameraList.GetSize() > 0)\n                    {\n\n                        for (auto i = 0; i < cameraList.GetSize(); i++)\n                        {\n                            // Select camera\n                            auto cameraPtr = cameraList.GetByIndex(i);\n                            // Begin\n                            cameraPtr->Init();\n                            cameraPtr->BeginAcquisition();\n                            // End\n                            cameraPtr->EndAcquisition();\n                            cameraPtr->DeInit();\n                        }\n                    }\n                    cameraList.Clear();\n                    systemPtr->ReleaseInstance();\n                }\n            }\n            catch (const Spinnaker::Exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        #endif\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/videoCaptureReader.cpp",
    "content": "#include <openpose/producer/videoCaptureReader.hpp>\n#include <iostream>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/string.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    struct VideoCaptureReader::ImplVideoCaptureReader\n    {\n        cv::VideoCapture mVideoCapture;\n\n        ImplVideoCaptureReader()\n        {\n        }\n\n        ImplVideoCaptureReader(const std::string& path) :\n            mVideoCapture{path}\n        {\n        }\n    };\n\n    VideoCaptureReader::VideoCaptureReader(const int index, const bool throwExceptionIfNoOpened,\n                                           const std::string& cameraParameterPath, const bool undistortImage,\n                                           const int numberViews) :\n        Producer{ProducerType::Webcam, cameraParameterPath, undistortImage, numberViews},\n        upImpl{new ImplVideoCaptureReader{}}\n    {\n        try\n        {\n            resetWebcam(index, throwExceptionIfNoOpened);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    VideoCaptureReader::VideoCaptureReader(const std::string& path, const ProducerType producerType,\n                                           const std::string& cameraParameterPath, const bool undistortImage,\n                                           const int numberViews) :\n        Producer{producerType, cameraParameterPath, undistortImage, numberViews},\n        upImpl{new ImplVideoCaptureReader{path}}\n    {\n        try\n        {\n            // Make sure only video or IP camera\n            if (producerType != ProducerType::IPCamera && producerType != ProducerType::Video)\n                error(\"VideoCapture with an input path must be IP camera or video.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            // Make sure video capture was opened\n            if (!isOpened())\n                error(\"VideoCapture (IP camera/video) could not be opened for path: '\" + path + \"'. If\"\n                      \" it is a video path, is the path correct?\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    VideoCaptureReader::~VideoCaptureReader()\n    {\n        try\n        {\n            release();\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::string VideoCaptureReader::getNextFrameName()\n    {\n        try\n        {\n            const auto stringLength = 12u;\n            return toFixedLengthString(   fastMax(0ull, uLongLongRound(get(CV_CAP_PROP_POS_FRAMES))),   stringLength);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    bool VideoCaptureReader::isOpened() const\n    {\n        try\n        {\n            return upImpl->mVideoCapture.isOpened();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    Matrix VideoCaptureReader::getRawFrame()\n    {\n        try\n        {\n            // Get frame\n            cv::Mat frame;\n            upImpl->mVideoCapture >> frame;\n            // Skip frames if frame step > 1\n            const auto frameStep = Producer::get(ProducerProperty::FrameStep);\n            if (frameStep > 1 && !frame.empty() && get(CV_CAP_PROP_POS_FRAMES) < get(CV_CAP_PROP_FRAME_COUNT)-1)\n            {\n                // Close if end of video\n                if (get(CV_CAP_PROP_POS_FRAMES) + frameStep-1 >= get(CV_CAP_PROP_FRAME_COUNT))\n                    upImpl->mVideoCapture.release();\n                // Frame step usually more efficient if just reading sequentially\n                else if (frameStep < 51)\n                    for (auto i = 1 ; i < frameStep ; i++)\n                        upImpl->mVideoCapture >> frame;\n                // Using set(CV_CAP_PROP_POS_FRAMES, value) is efficient only if step is big\n                else\n                    set(CV_CAP_PROP_POS_FRAMES, get(CV_CAP_PROP_POS_FRAMES) + frameStep-1);\n            }\n            // Return frame\n            Matrix opFrame = OP_CV2OPMAT(frame);\n            return opFrame;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> VideoCaptureReader::getRawFrames()\n    {\n        try\n        {\n            return std::vector<Matrix>{getRawFrame()};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    void VideoCaptureReader::resetWebcam(const int index, const bool throwExceptionIfNoOpened)\n    {\n        try\n        {\n            // Open webcam\n            upImpl->mVideoCapture = cv::VideoCapture{index};\n            // Make sure video capture was opened\n            if (throwExceptionIfNoOpened && !isOpened())\n                error(\"VideoCapture (webcam) could not be opened.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void VideoCaptureReader::release()\n    {\n        try\n        {\n            if (upImpl->mVideoCapture.isOpened())\n            {\n                upImpl->mVideoCapture.release();\n                opLog(\"cv::VideoCapture released.\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    double VideoCaptureReader::get(const int capProperty)\n    {\n        try\n        {\n            // Specific cases\n            // If rotated 90 or 270 degrees, then width and height is exchanged\n            if ((capProperty == CV_CAP_PROP_FRAME_WIDTH || capProperty == CV_CAP_PROP_FRAME_HEIGHT)\n                && (Producer::get(ProducerProperty::Rotation) != 0.\n                    && Producer::get(ProducerProperty::Rotation) != 180.))\n            {\n                if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n                    return upImpl->mVideoCapture.get(CV_CAP_PROP_FRAME_HEIGHT);\n                else\n                    return upImpl->mVideoCapture.get(CV_CAP_PROP_FRAME_WIDTH);\n            }\n\n            // Generic cases\n            return upImpl->mVideoCapture.get(capProperty);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void VideoCaptureReader::set(const int capProperty, const double value)\n    {\n        try\n        {\n            upImpl->mVideoCapture.set(capProperty, value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/videoReader.cpp",
    "content": "#include <openpose/producer/videoReader.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/fileSystem.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    VideoReader::VideoReader(const std::string& videoPath, const std::string& cameraParameterPath,\n                             const bool undistortImage, const int numberViews) :\n        VideoCaptureReader{videoPath, ProducerType::Video, cameraParameterPath, undistortImage, numberViews},\n        mPathName{getFileNameNoExtension(videoPath)}\n    {\n    }\n\n    VideoReader::~VideoReader()\n    {\n    }\n\n    std::string VideoReader::getNextFrameName()\n    {\n        try\n        {\n            return mPathName + \"_\" + VideoCaptureReader::getNextFrameName();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    double VideoReader::get(const int capProperty)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_FRAME_WIDTH)\n                return VideoCaptureReader::get(capProperty)\n                    / positiveIntRound(Producer::get(ProducerProperty::NumberViews));\n            else\n                return VideoCaptureReader::get(capProperty);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void VideoReader::set(const int capProperty, const double value)\n    {\n        try\n        {\n            VideoCaptureReader::set(capProperty, value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix VideoReader::getRawFrame()\n    {\n        try\n        {\n            return VideoCaptureReader::getRawFrame();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> VideoReader::getRawFrames()\n    {\n        try\n        {\n            const auto numberViews = positiveIntRound(Producer::get(ProducerProperty::NumberViews));\n            auto cvMats = VideoCaptureReader::getRawFrames();\n            // Split image\n            if (cvMats.size() == 1 && numberViews > 1)\n            {\n                Matrix opMatConcatenated = cvMats.at(0);\n                cv::Mat matConcatenated = OP_OP2CVMAT(opMatConcatenated);\n                cvMats.clear();\n                const auto individualWidth = matConcatenated.cols/numberViews;\n                for (auto i = 0 ; i < numberViews ; i++)\n                {\n                    cv::Mat cvMat(\n                        matConcatenated,\n                        cv::Rect{\n                            (int)(i*individualWidth), 0,\n                            (int)individualWidth, (int)matConcatenated.rows });\n                    const Matrix opMat = OP_CV2OPMAT(cvMat);\n                    cvMats.emplace_back(opMat);\n                }\n            }\n            // Sanity check\n            else if (cvMats.size() != 1u && numberViews > 1)\n                error(\"Unexpected error. Notify us (\" + std::to_string(numberViews) + \" vs. \"\n                      + std::to_string(numberViews) + \").\", __LINE__, __FUNCTION__, __FILE__);\n            // Return images\n            return cvMats;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/producer/webcamReader.cpp",
    "content": "#include <openpose/producer/webcamReader.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose/utilities/openCv.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n#include <openpose_private/utilities/openCvPrivate.hpp>\n\nnamespace op\n{\n    WebcamReader::WebcamReader(const int webcamIndex, const Point<int>& webcamResolution,\n                               const bool throwExceptionIfNoOpened, const std::string& cameraParameterPath,\n                               const bool undistortImage) :\n        VideoCaptureReader{webcamIndex, throwExceptionIfNoOpened, cameraParameterPath, undistortImage, 1},\n        mIndex{webcamIndex},\n        mWebcamStarted{VideoCaptureReader::isOpened()},\n        mFrameNameCounter{-1},\n        mThreadOpened{std::atomic<bool>{false}},\n        mDisconnectedCounter{0},\n        mResolution{webcamResolution}\n    {\n        try\n        {\n            if (isOpened())\n            {\n                mFrameNameCounter = 0;\n                if (mResolution != Point<int>{})\n                {\n                    set(CV_CAP_PROP_FRAME_WIDTH, mResolution.x);\n                    set(CV_CAP_PROP_FRAME_HEIGHT, mResolution.y);\n                    if ((int)get(CV_CAP_PROP_FRAME_WIDTH) != mResolution.x\n                        || (int)get(CV_CAP_PROP_FRAME_HEIGHT) != mResolution.y)\n                    {\n                        const std::string logMessage{\n                            \"Desired webcam resolution \" + std::to_string(mResolution.x) + \"x\"\n                            + std::to_string(mResolution.y) + \" could not being set. Final resolution: \"\n                            + std::to_string(positiveIntRound(get(CV_CAP_PROP_FRAME_WIDTH))) + \"x\"\n                            + std::to_string(positiveIntRound(get(CV_CAP_PROP_FRAME_HEIGHT))) };\n                        opLog(logMessage, Priority::Max, __LINE__, __FUNCTION__, __FILE__);\n                    }\n                }\n                // Set resolution\n                mResolution = Point<int>{\n                    positiveIntRound(get(CV_CAP_PROP_FRAME_WIDTH)),\n                    positiveIntRound(get(CV_CAP_PROP_FRAME_HEIGHT))};\n                // Start buffering thread\n                mThreadOpened = true;\n                mThread = std::thread{&WebcamReader::bufferingThread, this};\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    WebcamReader::~WebcamReader()\n    {\n        try\n        {\n            // Close and join thread\n            if (mThreadOpened)\n            {\n                mCloseThread = true;\n                mThread.join();\n            }\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    std::string WebcamReader::getNextFrameName()\n    {\n        try\n        {\n            return VideoCaptureReader::getNextFrameName();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    bool WebcamReader::isOpened() const\n    {\n        try\n        {\n            return (VideoCaptureReader::isOpened() || (mDisconnectedCounter > 0 && mWebcamStarted));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    double WebcamReader::get(const int capProperty)\n    {\n        try\n        {\n            if (capProperty == CV_CAP_PROP_POS_FRAMES)\n                return (double)mFrameNameCounter;\n            else\n                return VideoCaptureReader::get(capProperty);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void WebcamReader::set(const int capProperty, const double value)\n    {\n        try\n        {\n            VideoCaptureReader::set(capProperty, value);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    Matrix WebcamReader::getRawFrame()\n    {\n        try\n        {\n            mFrameNameCounter++; // Simple counter: 0,1,2,3,...\n\n            // Retrieve frame from buffer\n            Matrix opMat;\n            auto cvMatRetrieved = false;\n            while (!cvMatRetrieved)\n            {\n                // Retrieve frame\n                std::unique_lock<std::mutex> lock{mBufferMutex};\n                if (!mBuffer.empty())\n                {\n                    std::swap(opMat, mBuffer);\n                    cvMatRetrieved = true;\n                }\n                // No frames available -> sleep & wait\n                else\n                {\n                    lock.unlock();\n                    std::this_thread::sleep_for(std::chrono::microseconds{5});\n                }\n            }\n            return opMat;\n\n            // Naive implementation - No flashing buffers\n            // return VideoCaptureReader::getRawFrame();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Matrix();\n        }\n    }\n\n    std::vector<Matrix> WebcamReader::getRawFrames()\n    {\n        try\n        {\n            return std::vector<Matrix>{getRawFrame()};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    const auto DISCONNETED_THRESHOLD = 100;\n    void WebcamReader::bufferingThread()\n    {\n        try\n        {\n            mCloseThread = false;\n            while (!mCloseThread)\n            {\n                // Reset camera if disconnected\n                bool cameraConnected = true;\n                if (mDisconnectedCounter > DISCONNETED_THRESHOLD)\n                    cameraConnected = reset();\n                // Get frame\n                auto opMat = VideoCaptureReader::getRawFrame();\n                // Detect whether camera is connected\n                // Equivalent code:\n                // const auto newNorm = (\n                //     opMat.empty() ? mLastNorm : cv::norm(opMat.row(opMat.rows() / 2)));\n                double newNorm;\n                if (opMat.empty())\n                    newNorm = mLastNorm;\n                else\n                {\n                    cv::Mat rowMat;\n                    OP_CONST_MAT_RETURN_FUNCTION(rowMat, opMat, row(opMat.rows() / 2));\n                    newNorm = cv::norm(rowMat);\n                }\n                if (mLastNorm == newNorm)\n                {\n                    mDisconnectedCounter++;\n                    if (mDisconnectedCounter > 1 && opMat.empty())\n                        opLog(\"Camera frame empty (it has occurred for the last \" + std::to_string(mDisconnectedCounter)\n                            + \" consecutive frames).\", Priority::Max);\n                }\n                else\n                {\n                    mLastNorm = newNorm;\n                    mDisconnectedCounter = 0;\n                }\n                // If camera disconnected: black image\n                if (!cameraConnected)\n                {\n                    cv::Mat cvMat(mResolution.y, mResolution.x, CV_8UC3, cv::Scalar{0,0,0});\n                    putTextOnCvMat(cvMat, \"Camera disconnected, reconnecting...\", {cvMat.cols/16, cvMat.rows/2},\n                                   cv::Scalar{255, 255, 255}, false, positiveIntRound(2.3*cvMat.cols));\n                    // Anti flip + anti rotate frame (so it is balanced with the final flip + rotate)\n                    auto rotationAngle = -Producer::get(ProducerProperty::Rotation);\n                    // Not using 0 or 180 might provoke a row/col dimension swap, thus an OP error\n                    if (int(std::round(rotationAngle)) % 180 != 0.)\n                        rotationAngle = 0;\n                    const auto flipFrame = ((unsigned char)Producer::get(ProducerProperty::Flip) == 1.);\n                    opMat = OP_CV2OPMAT(cvMat);\n                    rotateAndFlipFrame(opMat, rotationAngle, flipFrame);\n                }\n                // Move to buffer\n                if (!opMat.empty())\n                {\n                    const std::lock_guard<std::mutex> lock{mBufferMutex};\n                    std::swap(mBuffer, opMat);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool WebcamReader::reset()\n    {\n        try\n        {\n            // If unplugged\n            opLog(\"Webcam was unplugged, trying to reconnect it.\", Priority::Max);\n            // Sleep\n            std::this_thread::sleep_for(std::chrono::milliseconds{1000});\n            // Reset camera\n            VideoCaptureReader::resetWebcam(mIndex, false);\n            // Re-set resolution\n            if (isOpened())\n            {\n                set(CV_CAP_PROP_FRAME_WIDTH, mResolution.x);\n                set(CV_CAP_PROP_FRAME_HEIGHT, mResolution.y);\n            }\n            // Camera replugged?\n            return (!isOpened()\n                    && (mResolution.x != positiveIntRound(get(CV_CAP_PROP_FRAME_WIDTH))\n                        || mResolution.y != positiveIntRound(get(CV_CAP_PROP_FRAME_HEIGHT))));\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/thread/CMakeLists.txt",
    "content": "set(SOURCES_OP_THREAD\n    defineTemplates.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_THREAD_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_THREAD})\nset(SOURCES_OP_THREAD_WITH_CP ${SOURCES_OP_THREAD_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_THREAD_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n    add_library(openpose_thread ${SOURCES_OP_THREAD})\n\n    target_link_libraries(openpose_thread openpose_core)\n\n    install(TARGETS openpose_thread\n        EXPORT OpenPose\n        RUNTIME DESTINATION bin\n        LIBRARY DESTINATION lib\n        ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/thread/defineTemplates.cpp",
    "content": "#include <openpose/thread/headers.hpp>\n\nnamespace op\n{\n    // Queues\n    DEFINE_TEMPLATE_DATUM(PriorityQueue);\n    DEFINE_TEMPLATE_DATUM(Queue);\n    template class OP_API QueueBase<BASE_DATUMS_SH, std::queue<BASE_DATUMS_SH>>;\n    template class OP_API QueueBase<\n        BASE_DATUMS_SH,\n        std::priority_queue<BASE_DATUMS_SH, std::vector<BASE_DATUMS_SH>,\n        std::greater<BASE_DATUMS_SH>>>;\n    // Subthread\n    DEFINE_TEMPLATE_DATUM(SubThread);\n    DEFINE_TEMPLATE_DATUM(SubThreadNoQueue);\n    DEFINE_TEMPLATE_DATUM(SubThreadQueueIn);\n    DEFINE_TEMPLATE_DATUM(SubThreadQueueInOut);\n    DEFINE_TEMPLATE_DATUM(SubThreadQueueOut);\n    // Thread\n    DEFINE_TEMPLATE_DATUM(Thread);\n    DEFINE_TEMPLATE_DATUM(ThreadManager);\n    // Main workers\n    DEFINE_TEMPLATE_DATUM(Worker);\n    DEFINE_TEMPLATE_DATUM(WorkerConsumer);\n    DEFINE_TEMPLATE_DATUM(WorkerProducer);\n    // W-classes\n    DEFINE_TEMPLATE_DATUM(WFpsMax);\n    DEFINE_TEMPLATE_DATUM(WIdGenerator);\n    template class OP_API WQueueAssembler<BASE_DATUMS>;\n    DEFINE_TEMPLATE_DATUM(WQueueOrderer);\n}\n"
  },
  {
    "path": "src/openpose/tracking/CMakeLists.txt",
    "content": "set(SOURCES_OP_TRACKING\n    defineTemplates.cpp\n    personIdExtractor.cpp\n    personTracker.cpp\n    pyramidalLK.cpp\n    pyramidalLK.cu)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_TRACKING_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_TRACKING})\nset(SOURCES_OP_TRACKING_WITH_CP ${SOURCES_OP_TRACKING_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_TRACKING_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n    add_library(openpose_tracking ${SOURCES_OP_TRACKING})\n\n    target_link_libraries(openpose_tracking openpose_core)\n\n    install(TARGETS openpose_tracking\n        EXPORT OpenPose\n        RUNTIME DESTINATION bin\n        LIBRARY DESTINATION lib\n        ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/tracking/defineTemplates.cpp",
    "content": "#include <openpose/tracking/headers.hpp>\n\nnamespace op\n{\n    DEFINE_TEMPLATE_DATUM(WPersonIdExtractor);\n}\n"
  },
  {
    "path": "src/openpose/tracking/personIdExtractor.cpp",
    "content": "#include <openpose/tracking/personIdExtractor.hpp>\n#include <atomic>\n#include <tuple>\n#include <unordered_map>\n#include <unordered_set>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/tracking/pyramidalLK.hpp>\n\n// #define LK_CUDA\n\nnamespace op\n{\n    struct PersonEntry\n    {\n        long long counterLastDetection;\n        std::vector<cv::Point2f> keypoints;\n        std::vector<char> status;\n        /*\n        PersonEntry(long long _last_frame,\n                    std::vector<cv::Point2f> _keypoints,\n                    std::vector<char> _active):\n                    last_frame(_last_frame), keypoints(_keypoints),\n                    active(_active)\n                    {}\n        */\n    };\n\n    const std::string errorMessage = \"ID extractor function (`--identification` flag) not implemented\"\n                                     \" for multiple-view processing.\";\n\n    float getEuclideanDistance(const cv::Point2f& a, const cv::Point2f& b)\n    {\n        try\n        {\n            const auto difference = a - b;\n            return std::sqrt(difference.x * difference.x + difference.y * difference.y);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n\n    std::vector<PersonEntry> captureKeypoints(const Array<float>& poseKeypoints, const float confidenceThreshold)\n    {\n        try\n        {\n            // Define result\n            std::vector<PersonEntry> personEntries(poseKeypoints.getSize(0));\n            // Fill personEntries\n            for (auto p = 0; p < (int)personEntries.size(); p++)\n            {\n                // Create person entry in the tracking map\n                auto& personEntry = personEntries[p];\n                auto& keypoints = personEntry.keypoints;\n                auto& status = personEntry.status;\n                personEntry.counterLastDetection = 0;\n\n                for (auto kp = 0; kp < poseKeypoints.getSize(1); kp++)\n                {\n                    cv::Point2f cp;\n                    cp.x = poseKeypoints[{p,kp,0}];\n                    cp.y = poseKeypoints[{p,kp,1}];\n                    keypoints.emplace_back(cp);\n\n                    if (poseKeypoints[{p,kp,2}] < confidenceThreshold)\n                        status.emplace_back(char(1));\n                    else\n                        status.emplace_back(char(0));\n                }\n            }\n            // Return result\n            return personEntries;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    void updateLK(std::unordered_map<int,PersonEntry>& personEntries, std::vector<cv::Mat>& pyramidImagesPrevious,\n                  std::vector<cv::Mat>& pyramidImagesCurrent, const cv::Mat& imagePrevious,\n                  const cv::Mat& imageCurrent, const int numberFramesToDeletePerson)\n    {\n        try\n        {\n            // Get all key values\n            // Otherwise, `erase` provokes core dumped when removing elements\n            std::vector<int> keyValues;\n            keyValues.reserve(personEntries.size());\n            for (const auto& entry : personEntries)\n                keyValues.emplace_back(entry.first);\n            // Update or remove elements\n            for (auto& key : keyValues)\n            {\n                auto& element = personEntries[key];\n\n                // Remove keypoint\n                if (element.counterLastDetection++ > numberFramesToDeletePerson)\n                    personEntries.erase(key);\n                // Update all keypoints for that entry\n                else\n                {\n                    PersonEntry personEntry;\n                    personEntry.counterLastDetection = element.counterLastDetection;\n                    #ifdef LK_CUDA\n                        UNUSED(pyramidImagesPrevious);\n                        UNUSED(pyramidImagesCurrent);\n                        pyramidalLKGpu(element.keypoints, personEntry.keypoints, element.status,\n                                       imagePrevious, imageCurrent, 3, 21);\n                    #else\n                        pyramidalLKCpu(element.keypoints, personEntry.keypoints, pyramidImagesPrevious,\n                                       pyramidImagesCurrent, element.status, imagePrevious, imageCurrent, 3, 21);\n                    #endif\n                    personEntry.status = element.status;\n                    element = personEntry;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void initializeLK(std::unordered_map<int,PersonEntry>& personEntries,\n                      long long& mNextPersonId,\n                      const Array<float>& poseKeypoints,\n                      const float confidenceThreshold)\n    {\n        try\n        {\n            for (auto p = 0; p < poseKeypoints.getSize(0); p++)\n            {\n                const auto currentPerson = int(mNextPersonId++);\n\n                // Create person entry in the tracking map\n                auto& personEntry = personEntries[currentPerson];\n                auto& keypoints = personEntry.keypoints;\n                auto& status = personEntry.status;\n                personEntry.counterLastDetection = 0;\n\n                for (auto kp = 0; kp < poseKeypoints.getSize(1); kp++)\n                {\n                    const cv::Point2f cp{poseKeypoints[{p,kp,0}], poseKeypoints[{p,kp,1}]};\n                    keypoints.emplace_back(cp);\n\n                    if (poseKeypoints[{p,kp,2}] < confidenceThreshold)\n                        status.emplace_back(char(1));\n                    else\n                        status.emplace_back(char(0));\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool compareCandidates(std::tuple<float, int, int> a, std::tuple<float, int, int> b)\n    {\n        return std::get<0>(a) > std::get<0>(b);\n    }\n\n    Array<long long> matchLKAndOPGreedy(std::unordered_map<int,PersonEntry>& personEntries,\n                                        long long& nextPersonId,\n                                        const std::vector<PersonEntry>& openposePersonEntries,\n                                        const cv::Mat& imagePrevious,\n                                        const float inlierRatioThreshold,\n                                        const float distanceThreshold)\n    {\n        try\n        {\n            Array<long long> poseIds{(int)openposePersonEntries.size(), -1};\n            std::unordered_map<int, PersonEntry> pendingQueue;\n            std::vector<bool> processed((int)openposePersonEntries.size(), false);\n            std::unordered_set<int> used;\n            bool converged = false;\n\n            while (!openposePersonEntries.empty() && !converged)\n            {\n                const auto numberKeypoints = openposePersonEntries[0].keypoints.size();\n                std::vector<std::tuple<float, int, int>> candidates;\n                float bestScore = 0.0f;\n                converged = true;\n\n                for (auto i = 0u; i < openposePersonEntries.size(); i++)\n                {\n                    if (poseIds.at(i) != -1)\n                        continue;\n\n                    const auto& openposePersonEntry = openposePersonEntries.at(i);\n                    const auto personDistanceThreshold = fastMax(10.f,\n                        distanceThreshold*float(std::sqrt(imagePrevious.cols*imagePrevious.rows)) / 960.f);\n\n                    // Find best correspondence in the LK set\n                    for (const auto& personEntry : personEntries)\n                    {\n                        if (used.find(personEntry.first) != used.end())\n                            continue;\n\n                        const auto& element = personEntry.second;\n                        auto inliers = 0;\n                        auto active = 0;\n                        auto distance = 0.f;\n                        auto total_distance = 0.0f;\n\n                        // Sanity checks\n                        if (element.status.size() != numberKeypoints)\n                            error(\"element.status.size() != numberKeypoints ||\", __LINE__, __FUNCTION__, __FILE__);\n                        if (openposePersonEntry.status.size() != numberKeypoints)\n                            error(\"openposePersonEntry.status.size() != numberKeypoints\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n                        if (element.keypoints.size() != numberKeypoints)\n                            error(\"element.keypoints.size() != numberKeypoints ||\", __LINE__, __FUNCTION__, __FILE__);\n                        if (openposePersonEntry.keypoints.size() != numberKeypoints)\n                            error(\"openposePersonEntry.keypoints.size() != numberKeypoints\",\n                                  __LINE__, __FUNCTION__, __FILE__);\n\n                        // Iterate through all keypoints\n                        for (auto kp = 0u; kp < numberKeypoints; kp++)\n                        {\n                            // If enough threshold\n                            if (!element.status[kp] && !openposePersonEntry.status[kp])\n                            {\n                                active++;\n                                distance = getEuclideanDistance(element.keypoints[kp],\n                                                                openposePersonEntry.keypoints[kp]);\n                                total_distance += distance;\n\n                                if (distance < personDistanceThreshold)\n                                    inliers++;\n                            }\n                        }\n\n                        if (active > 0)\n                        {\n                            const auto score = inliers / (float)active;\n\n                            if (score == bestScore && score >= inlierRatioThreshold)\n                            {\n                                candidates.push_back(std::make_tuple(total_distance,i, personEntry.first));\n                                bestScore = score;\n                            }\n                            else if (score > bestScore && score >= inlierRatioThreshold)\n                            {\n                                bestScore = score;\n                                candidates.clear();\n                                candidates.push_back(std::make_tuple(total_distance, i, personEntry.first));\n                            }\n                        }\n                    }\n                }\n                std::sort(candidates.begin(), candidates.end(), compareCandidates);\n\n                while (candidates.size())\n                {\n                    auto top_candidate = candidates.back();\n                    candidates.pop_back();\n                    auto idx_lk = std::get<2>(top_candidate);\n                    auto idx_op = std::get<1>(top_candidate);\n\n                    if (used.find(idx_lk) != used.end())\n                        continue;\n\n                    poseIds[idx_op] = idx_lk;\n                    used.insert(idx_lk);\n                    converged = false;\n\n                }\n            }\n            for (auto i = 0u; i < openposePersonEntries.size(); i++)\n            {\n                if (poseIds[i] == -1)\n                    poseIds[i] = nextPersonId++;\n                const auto& openposePersonEntry = openposePersonEntries.at(i);\n                personEntries[(int)poseIds[i]] = openposePersonEntry;\n            }\n\n            return poseIds;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<long long>{};\n        }\n    }\n\n\n    // Array<long long> matchLKAndOP(std::unordered_map<int,PersonEntry>& personEntries,\n    //                               long long& nextPersonId,\n    //                               const std::vector<PersonEntry>& openposePersonEntries,\n    //                               const cv::Mat& imagePrevious,\n    //                               const float inlierRatioThreshold,\n    //                               const float distanceThreshold)\n    // {\n    //     try\n    //     {\n    //         Array<long long> poseIds{(int)openposePersonEntries.size(), -1};\n    //         std::unordered_map<int, PersonEntry> pendingQueue;\n\n    //         if (!openposePersonEntries.empty())\n    //         {\n    //             const auto numberKeypoints = openposePersonEntries[0].keypoints.size();\n    //             for (auto i = 0u; i < openposePersonEntries.size(); i++)\n    //             {\n    //                 auto& poseId = poseIds.at(i);\n\n    //                 const auto& openposePersonEntry = openposePersonEntries.at(i);\n    //                 const auto personDistanceThreshold = fastMax(10.f,\n    //                     distanceThreshold*float(std::sqrt(imagePrevious.cols*imagePrevious.rows)) / 960.f);\n\n    //                 // Find best correspondence in the LK set\n    //                 auto bestMatch = -1ll;\n    //                 auto bestScore = 0.f;\n    //                 for (const auto& personEntry : personEntries)\n    //                 {\n    //                     const auto& element = personEntry.second;\n    //                     auto inliers = 0;\n    //                     auto active = 0;\n\n    //                     // Sanity checks\n    //                     if (element.status.size() != numberKeypoints)\n    //                         error(\"element.status.size() != numberKeypoints ||\", __LINE__, __FUNCTION__, __FILE__);\n    //                     if (openposePersonEntry.status.size() != numberKeypoints)\n    //                         error(\"openposePersonEntry.status.size() != numberKeypoints\",\n    //                               __LINE__, __FUNCTION__, __FILE__);\n    //                     if (element.keypoints.size() != numberKeypoints)\n    //                         error(\"element.keypoints.size() != numberKeypoints ||\", __LINE__, __FUNCTION__, __FILE__);\n    //                     if (openposePersonEntry.keypoints.size() != numberKeypoints)\n    //                         error(\"openposePersonEntry.keypoints.size() != numberKeypoints\",\n    //                               __LINE__, __FUNCTION__, __FILE__);\n    //                     // Iterate through all keypoints\n    //                     for (auto kp = 0u; kp < numberKeypoints; kp++)\n    //                     {\n    //                         // If enough threshold\n    //                         if (!element.status[kp] && !openposePersonEntry.status[kp])\n    //                         {\n    //                             active++;\n    //                             const auto distance = getEuclideanDistance(element.keypoints[kp],\n    //                                                                        openposePersonEntry.keypoints[kp]);\n    //                             if (distance < personDistanceThreshold)\n    //                                 inliers++;\n    //                         }\n    //                     }\n\n    //                     if (active > 0)\n    //                     {\n    //                         const auto score = inliers / (float)active;\n    //                         if (score > bestScore && score >= inlierRatioThreshold)\n    //                         {\n    //                             bestScore = score;\n    //                             bestMatch = personEntry.first;\n    //                         }\n    //                     }\n    //                 }\n    //                 // Found a best match, update LK table and poseIds\n    //                 if (bestMatch != -1)\n    //                     poseId = bestMatch;\n    //                 else\n    //                     poseId = nextPersonId++;\n\n    //                 pendingQueue[poseId] = openposePersonEntry;\n    //             }\n    //         }\n\n    //         // Update LK table with pending queue\n    //         for (auto& pendingQueueEntry: pendingQueue)\n    //             personEntries[pendingQueueEntry.first] = pendingQueueEntry.second;\n\n    //         return poseIds;\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //         return Array<long long>{};\n    //     }\n    // }\n\n    struct PersonIdExtractor::ImplPersonIdExtractor\n    {\n        const float mConfidenceThreshold;\n        const float mInlierRatioThreshold;\n        const float mDistanceThreshold;\n        const int mNumberFramesToDeletePerson;\n        long long mNextPersonId;\n        cv::Mat mImagePrevious;\n        std::vector<cv::Mat> mPyramidImagesPrevious;\n        std::unordered_map<int, PersonEntry> mPersonEntries;\n        // Thread-safe variables\n        std::atomic<long long> mLastFrameId;\n\n        ImplPersonIdExtractor(\n            const float confidenceThreshold, const float inlierRatioThreshold, const float distanceThreshold,\n            const int numberFramesToDeletePerson) :\n            mConfidenceThreshold{confidenceThreshold},\n            mInlierRatioThreshold{inlierRatioThreshold},\n            mDistanceThreshold{distanceThreshold},\n            mNumberFramesToDeletePerson{numberFramesToDeletePerson},\n            mNextPersonId{0ll},\n            mLastFrameId{-1ll}\n        {\n        }\n    };\n\n    PersonIdExtractor::PersonIdExtractor(const float confidenceThreshold, const float inlierRatioThreshold,\n                                         const float distanceThreshold, const int numberFramesToDeletePerson) :\n        spImpl{new ImplPersonIdExtractor{confidenceThreshold, inlierRatioThreshold, distanceThreshold,\n            numberFramesToDeletePerson}}\n    {\n        try\n        {\n            error(\"PersonIdExtractor (`identification` flag) buggy and not working yet, but we are working on it!\"\n                  \" Coming soon!\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    PersonIdExtractor::~PersonIdExtractor()\n    {\n    }\n\n    Array<long long> PersonIdExtractor::extractIds(const Array<float>& poseKeypoints, const Matrix& cvMatInput,\n                                                   const unsigned long long imageViewIndex)\n    {\n        try\n        {\n            // Sanity check\n            if (imageViewIndex > 0)\n                error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n\n            // Result initialization\n            Array<long long> poseIds;\n            const auto openposePersonEntries = captureKeypoints(poseKeypoints, spImpl->mConfidenceThreshold);\n\n            // First frame\n            const cv::Mat cvMatcvMatInput = OP_OP2CVCONSTMAT(cvMatInput);\n            if (spImpl->mImagePrevious.empty())\n            {\n                // Add first persons to the LK set\n                initializeLK(spImpl->mPersonEntries, spImpl->mNextPersonId, poseKeypoints, spImpl->mConfidenceThreshold);\n                // Capture current frame as floating point\n                cvMatcvMatInput.convertTo(spImpl->mImagePrevious, CV_32F);\n            }\n            // Rest\n            else\n            {\n                cv::Mat imageCurrent;\n                std::vector<cv::Mat> pyramidImagesCurrent;\n                cvMatcvMatInput.convertTo(imageCurrent, CV_32F);\n                updateLK(spImpl->mPersonEntries, spImpl->mPyramidImagesPrevious, pyramidImagesCurrent, spImpl->mImagePrevious, imageCurrent,\n                         spImpl->mNumberFramesToDeletePerson);\n                spImpl->mImagePrevious = imageCurrent;\n                spImpl->mPyramidImagesPrevious = pyramidImagesCurrent;\n            }\n\n            // Get poseIds and update LKset according to OpenPose set\n            // poseIds = matchLKAndOP(\n            poseIds = matchLKAndOPGreedy(\n                spImpl->mPersonEntries, spImpl->mNextPersonId, openposePersonEntries, spImpl->mImagePrevious, spImpl->mInlierRatioThreshold,\n                spImpl->mDistanceThreshold);\n\n            return poseIds;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<long long>{};\n        }\n    }\n\n    Array<long long> PersonIdExtractor::extractIdsLockThread(const Array<float>& poseKeypoints,\n                                                             const Matrix& cvMatInput,\n                                                             const unsigned long long imageViewIndex,\n                                                             const long long frameId)\n    {\n        try\n        {\n            // Sanity check\n            if (imageViewIndex > 0)\n                error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n            // Wait for desired order\n            while (spImpl->mLastFrameId < frameId - 1)\n                std::this_thread::sleep_for(std::chrono::microseconds{100});\n            // Extract IDs\n            const auto ids = extractIds(poseKeypoints, cvMatInput, imageViewIndex);\n            // Update last frame id\n            spImpl->mLastFrameId = frameId;\n            // Return person ids\n            return ids;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<long long>{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/tracking/personTracker.cpp",
    "content": "#include <openpose/tracking/personTracker.hpp>\n#include <atomic>\n#include <iostream>\n#include <unordered_map>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/tracking/pyramidalLK.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    struct PersonTrackerEntry\n    {\n        std::vector<cv::Point2f> keypoints;\n        std::vector<cv::Point2f> lastKeypoints;\n        std::vector<char> status;\n        std::vector<cv::Point2f> getPredicted() const\n        {\n            std::vector<cv::Point2f> predictedKeypoints(keypoints);\n            if (!lastKeypoints.size())\n                return predictedKeypoints;\n            for (size_t i=0; i<keypoints.size(); i++)\n            {\n                predictedKeypoints[i] = cv::Point2f{predictedKeypoints[i].x + (keypoints[i].x-lastKeypoints[i].x),\n                                                    predictedKeypoints[i].y + (keypoints[i].y-lastKeypoints[i].y)};\n            }\n            return predictedKeypoints;\n        }\n    };\n\n    int roundUp(const int numToRound, const int multiple)\n    {\n        if (multiple == 0)\n            return numToRound;\n\n        const int remainder = numToRound % multiple;\n        if (remainder == 0)\n            return numToRound;\n\n        return numToRound + multiple - remainder;\n    }\n\n    int computePersonScale(const PersonTrackerEntry& personEntry, const cv::Mat& imageCurrent)\n    {\n        int layerCount = 0;\n        if (personEntry.status[0] || personEntry.status[14] ||\n            personEntry.status[15] || personEntry.status[16] || personEntry.status[17])\n            layerCount++;\n        if (personEntry.status[2] || personEntry.status[3] || personEntry.status[4] ||\n            personEntry.status[5] || personEntry.status[6] || personEntry.status[7])\n            layerCount++;\n        if (personEntry.status[8] || personEntry.status[11])\n            layerCount++;\n        if (personEntry.status[9] || personEntry.status[10] ||\n            personEntry.status[12] || personEntry.status[13])\n            layerCount++;\n\n        float minX = (float)imageCurrent.size().width;\n        float maxX = 0.f;\n        float minY = (float)imageCurrent.size().height;\n        float maxY = 0.f;\n        int totalKp = 0;\n        for (size_t i=0; i<personEntry.keypoints.size(); i++)\n        {\n            if (personEntry.status[i])\n            {\n                const auto kp = personEntry.keypoints[i];\n                if (kp.x < minX)\n                    minX = kp.x;\n                if (kp.x > maxX)\n                    maxX = kp.x;\n                if (kp.y < minY)\n                    minY = kp.y;\n                if (kp.y > maxY)\n                    maxY = kp.y;\n                totalKp++;\n            }\n        }\n        const float xDist = (maxX - minX);\n        const float yDist = (maxY - minY);\n        float maxDist;\n        if (xDist > yDist)\n            maxDist = (xDist)*(4/layerCount);\n        else\n            maxDist = (yDist)*(4/layerCount);\n        return roundUp(int(maxDist / 10.), 3);\n    }\n\n    void updateLK(std::unordered_map<int,PersonTrackerEntry>& personEntries,\n                  std::vector<cv::Mat>& pyramidImagesPrevious, std::vector<cv::Mat>& pyramidImagesCurrent,\n                  const cv::Mat& imagePrevious, const cv::Mat& imageCurrent,\n                  const int levels, const int patchSize, const bool trackVelocity, const bool scaleVarying)\n    {\n        try\n        {\n            // Inefficient version, do it per person\n            for (auto& kv : personEntries)\n            {\n                PersonTrackerEntry newPersonEntry;\n                PersonTrackerEntry& oldPersonEntry = kv.second;\n                int lkSize = patchSize;\n                if (scaleVarying)\n                {\n                    pyramidImagesPrevious.clear();\n                    lkSize = computePersonScale(oldPersonEntry, imageCurrent);\n                }\n                if (trackVelocity)\n                {\n                    newPersonEntry.keypoints = oldPersonEntry.getPredicted();\n                    pyramidalLKOcv(oldPersonEntry.keypoints, newPersonEntry.keypoints, pyramidImagesPrevious,\n                                   pyramidImagesCurrent, oldPersonEntry.status, imagePrevious, imageCurrent, levels,\n                                   patchSize, true);\n                }\n                else\n                    pyramidalLKOcv(oldPersonEntry.keypoints, newPersonEntry.keypoints, pyramidImagesPrevious,\n                                   pyramidImagesCurrent, oldPersonEntry.status, imagePrevious, imageCurrent, levels,\n                                   lkSize, false);\n\n                newPersonEntry.lastKeypoints = oldPersonEntry.keypoints;\n                newPersonEntry.status = oldPersonEntry.status;\n                oldPersonEntry = newPersonEntry;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // void vizPersonEntries(cv::Mat& debugImage, const std::unordered_map<int, PersonTrackerEntry>& personEntries,\n    //                       const bool mTrackVelocity)\n    // {\n    //     try\n    //     {\n    //         for (auto& kv : personEntries)\n    //         {\n    //             const PersonTrackerEntry& pe = kv.second;\n    //             const std::vector<cv::Point2f> predictedKeypoints = pe.getPredicted();\n    //             for (size_t i=0; i<pe.keypoints.size(); i++)\n    //             {\n    //                 cv::circle(debugImage, pe.keypoints[i], 3, cv::Scalar(255,0,0),CV_FILLED);\n    //                 cv::putText(debugImage, std::to_string((int)pe.status[i]), pe.keypoints[i],\n    //                             cv::FONT_HERSHEY_DUPLEX, 0.4, cv::Scalar(0,0,255),1);\n\n    //                 if (pe.lastKeypoints.size())\n    //                 {\n    //                     cv::line(debugImage, pe.keypoints[i], pe.lastKeypoints[i],cv::Scalar(255,0,0));\n    //                     cv::circle(debugImage, pe.lastKeypoints[i], 3, cv::Scalar(255,255,0),CV_FILLED);\n    //                 }\n    //                 if (predictedKeypoints.size() && mTrackVelocity)\n    //                 {\n    //                     cv::line(debugImage, pe.keypoints[i], predictedKeypoints[i],cv::Scalar(255,0,0));\n    //                     cv::circle(debugImage, predictedKeypoints[i], 3, cv::Scalar(255,0,255),CV_FILLED);\n    //                 }\n    //             }\n    //         }\n    //     }\n    //     catch (const std::exception& e)\n    //     {\n    //         error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n    //     }\n    // }\n\n    void personEntriesFromOP(std::unordered_map<int, PersonTrackerEntry>& personEntries,\n                             const Array<float>& poseKeypoints, const Array<long long>& poseIds,\n                             float confidenceThreshold)\n    {\n        try\n        {\n            personEntries.clear();\n            for (int i=0; i<poseKeypoints.getSize(0); i++)\n            {\n                const auto id = int(poseIds[i]);\n                personEntries[id] = PersonTrackerEntry();\n                personEntries[id].keypoints.resize(poseKeypoints.getSize(1));\n                personEntries[id].status.resize(poseKeypoints.getSize(1));\n                for (int j=0; j<poseKeypoints.getSize(1); j++)\n                {\n                    personEntries[id].keypoints[j].x = poseKeypoints[\n                            i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                            j*poseKeypoints.getSize(2) + 0];\n                    personEntries[id].keypoints[j].y = poseKeypoints[\n                            i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                            j*poseKeypoints.getSize(2) + 1];\n                    const float prob = poseKeypoints[\n                            i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                            j*poseKeypoints.getSize(2) + 2];\n                    if (prob < confidenceThreshold)\n                        personEntries[id].status[j] = 0;\n                    else\n                        personEntries[id].status[j] = 1;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void syncPersonEntriesWithOP(std::unordered_map<int, PersonTrackerEntry>& personEntries,\n                                 const Array<float>& poseKeypoints, const Array<long long>& poseIds,\n                                 float confidenceThreshold, bool mergeResults)\n    {\n        try\n        {\n            if (!poseIds.empty())\n            {\n                // Delete\n                for (auto kv = personEntries.cbegin(); kv != personEntries.cend() /* not hoisted */; /* no increment */)\n                {\n                    bool exists = false;\n                    for (int i=0; i<poseIds.getSize(0); i++)\n                    {\n                        const auto id = poseIds[i];\n                        if (id == kv->first)\n                            exists = true;\n                    }\n                    if (!exists)\n                        personEntries.erase(kv++);\n                    else\n                        ++kv;\n                }\n\n                // Update or Add\n                for (int i=0; i<poseIds.getSize(0); i++)\n                {\n                    const auto id = int(poseIds[i]);\n\n                    // Update\n                    if (personEntries.count(id) && mergeResults)\n                    {\n                        PersonTrackerEntry& personEntry = personEntries[id];\n                        for (int j=0; j<poseKeypoints.getSize(1); j++)\n                        {\n                            const float x = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 0];\n                            const float y = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 1];\n                            const float prob = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 2];\n                            const cv::Point lkPoint = personEntry.keypoints[j];\n                            const cv::Point opPoint{positiveIntRound(x), positiveIntRound(y)};\n\n                            if (prob < confidenceThreshold)\n                                personEntries[id].status[j] = 0;\n                            else\n                            {\n                                personEntries[id].status[j] = 1;\n                                const auto distance = sqrt(pow(lkPoint.x-opPoint.x,2)+pow(lkPoint.y-opPoint.y,2));\n                                if (distance < 5)\n                                    personEntries[id].keypoints[j] = lkPoint;\n                                else if (distance < 10)\n                                    personEntries[id].keypoints[j] = cv::Point{\n                                        positiveIntRound((lkPoint.x+opPoint.x)/2.),\n                                        positiveIntRound((lkPoint.y+opPoint.y)/2.)};\n                                else\n                                    personEntries[id].keypoints[j] = opPoint;\n                            }\n                        }\n\n                    }\n                    // Add\n                    else\n                    {\n                        personEntries[id] = PersonTrackerEntry();\n                        personEntries[id].keypoints.resize(poseKeypoints.getSize(1));\n                        personEntries[id].status.resize(poseKeypoints.getSize(1));\n                        for (int j=0; j<poseKeypoints.getSize(1); j++)\n                        {\n                            personEntries[id].keypoints[j].x = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 0];\n                            personEntries[id].keypoints[j].y = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 1];\n                            const float prob = poseKeypoints[\n                                    i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2) +\n                                    j*poseKeypoints.getSize(2) + 2];\n                            if (prob < confidenceThreshold)\n                                personEntries[id].status[j] = 0;\n                            else\n                                personEntries[id].status[j] = 1;\n                        }\n\n                    }\n                }\n\n                // Sanity Check Start\n                if ((int)personEntries.size() != poseIds.getSize(0))\n                {\n                    // Print\n                    for (auto& kv : personEntries)\n                        std::cout << kv.first << \" \";\n                    std::cout << std::endl;\n                    for (int i=0; i<poseIds.getSize(0); i++)\n                        std::cout << poseIds.at(i) << \" \";\n                    std::cout << std::endl;\n                    std::cout << \"---\" << std::endl;\n                    error(\"Size Mismatch. THere is an error in your poseId formatting.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void opFromPersonEntries(Array<float>& poseKeypoints,\n                             const std::unordered_map<int, PersonTrackerEntry>& personEntries,\n                             const Array<long long>& poseIds)\n    {\n        try\n        {\n            if (personEntries.size() && !poseIds.empty())\n            {\n                poseKeypoints.reset(\n                    {(int)personEntries.size(), (int)personEntries.begin()->second.keypoints.size(), 3});\n                for (auto i=0; i<poseIds.getSize(0); i++)\n                {\n                    const auto id = int(poseIds[i]);\n                    const PersonTrackerEntry& pe = personEntries.at(id);\n                    const int baseIndexY = i*poseKeypoints.getSize(1)*poseKeypoints.getSize(2);\n                    for (int j=0 ; j<poseKeypoints.getSize(1) ; j++)\n                    {\n                        const auto baseIndex = baseIndexY + j*poseKeypoints.getSize(2);\n                        poseKeypoints[baseIndex] = pe.keypoints[j].x;\n                        poseKeypoints[baseIndex+1] = pe.keypoints[j].y;\n                        poseKeypoints[baseIndex+2] = float(int(pe.status[j]));\n                        if (pe.keypoints[j].x == 0 && pe.keypoints[j].y == 0)\n                            poseKeypoints[baseIndex+2] = 0;\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void scaleKeypoints(std::unordered_map<int, PersonTrackerEntry>& personEntries,\n                        const float xScale, const float yScale)\n    {\n        try\n        {\n            for (auto& kv : personEntries)\n            {\n                for (size_t i=0; i<kv.second.keypoints.size(); i++)\n                {\n                    kv.second.keypoints[i].x *= xScale;\n                    kv.second.keypoints[i].y *= yScale;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    struct PersonTracker::ImplPersonTracker\n    {\n\n        const bool mMergeResults;\n        const int mLevels;\n        const int mPatchSize;\n        const bool mTrackVelocity;\n        const float mConfidenceThreshold;\n        const bool mScaleVarying;\n        const float mRescale;\n\n        cv::Mat mImagePrevious;\n        std::vector<cv::Mat> mPyramidImagesPrevious;\n        std::unordered_map<int, PersonTrackerEntry> mPersonEntries;\n        Array<long long> mLastPoseIds;\n\n        // Thread-safe variables\n        std::atomic<long long> mLastFrameId;\n\n        ImplPersonTracker(\n            const bool mergeResults, const int levels, const int patchSize, const float confidenceThreshold,\n            const bool trackVelocity, const bool scaleVarying, const float rescale) :\n            mMergeResults{mergeResults},\n            mLevels{levels},\n            mPatchSize{patchSize},\n            mTrackVelocity{trackVelocity},\n            mConfidenceThreshold{confidenceThreshold},\n            mScaleVarying{scaleVarying},\n            mRescale{rescale},\n            mLastFrameId{-1ll}\n        {\n        }\n    };\n\n    PersonTracker::PersonTracker(\n        const bool mergeResults, const int levels, const int patchSize, const float confidenceThreshold,\n        const bool trackVelocity, const bool scaleVarying, const float rescale) :\n        spImpl{new ImplPersonTracker{mergeResults, levels, patchSize, confidenceThreshold, trackVelocity,\n            scaleVarying, rescale}}\n    {\n        try\n        {\n            opLog(\"Person tracking (`tracking` flag) is in experimental phase. Please, let us know if you\"\n                \" find any bug on this alpha version.\", op::Priority::High);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    PersonTracker::~PersonTracker()\n    {\n    }\n\n    void PersonTracker::track(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                              const Matrix& cvMatInput)\n    {\n        try\n        {\n            // Sanity Checks\n            if (poseKeypoints.getSize(0) > 1)\n                 error(\"Person tracking (`--tracking` flag) is in experimental phase and only allows tracking of up\"\n                       \" to 1 person at the time. Please, also include the `--number_people_max 1` flag when using\"\n                       \" the `--tracking` flag. Tracking more than one person at the time is not expected as\"\n                       \" short- nor medium-term goal.\",\n                       __LINE__, __FUNCTION__, __FILE__);\n\n            /*\n             * 1. Get poseKeypoints for all people - Checks\n             * 2. If last image is empty or mPersonEntries is empty (& poseKeypoints and poseIds has data or crash it)\n             *      Create mPersonEntries referencing poseIds\n             *      Initialize LK points\n             * 3. If poseKeypoints is not empty and poseIds has data\n             *      1. Update LK\n             *      2. CRUD/Sync - Check mMergeResults flag to smooth or not\n             * 4. If poseKeypoints is empty\n             *      1. Update LK\n             *      2. replace poseKeypoints\n             */\n\n            // TODO: This case: if mMergeResults == false --> Run LK tracker ONLY IF poseKeypoints.empty() doesn't\n            // consider the case of poseKeypoints being empty BECAUSE there were no people on the image\n\n            // if mMergeResults == true --> Combine OP + LK tracker\n            // if mMergeResults == false --> Run LK tracker ONLY IF poseKeypoints.empty()\n\n            bool mergeResults = spImpl->mMergeResults;\n            mergeResults = true;\n\n            // Sanity Checks\n            if (poseKeypoints.getSize(0) != poseIds.getSize(0))\n                 error(\"poseKeypoints and poseIds should have the same number of people\",\n                       __LINE__, __FUNCTION__, __FILE__);\n\n            // First frame\n            const cv::Mat cvMatcvMatInput = OP_OP2CVCONSTMAT(cvMatInput);\n            if (spImpl->mImagePrevious.empty())\n            {\n                // Create mPersonEntries\n                personEntriesFromOP(spImpl->mPersonEntries, poseKeypoints, poseIds, spImpl->mConfidenceThreshold);\n                // Capture current frame as floating point\n                cvMatcvMatInput.convertTo(spImpl->mImagePrevious, CV_8UC3);\n                // Rescale\n                if (spImpl->mRescale)\n                {\n                    cv::Size rescaleSize{\n                        positiveIntRound(spImpl->mRescale),\n                        positiveIntRound(spImpl->mImagePrevious.size().height/(spImpl->mImagePrevious.size().width/ spImpl->mRescale))};\n                    cv::resize(spImpl->mImagePrevious, spImpl->mImagePrevious, rescaleSize, 0, 0, cv::INTER_CUBIC);\n                }\n                // Save Last Ids\n                spImpl->mLastPoseIds = poseIds.clone();\n            }\n            // Any other frame\n            else\n            {\n                // Update LK\n                const bool newOPData = !poseKeypoints.empty() && !poseIds.empty();\n                if ((newOPData && mergeResults) || (!newOPData))\n                {\n                    cv::Mat imageCurrent;\n                    std::vector<cv::Mat> pyramidImagesCurrent;\n                    cvMatcvMatInput.convertTo(imageCurrent, CV_8UC3);\n                    float xScale = 1., yScale = 1.;\n                    if (spImpl->mRescale)\n                    {\n                        cv::Size rescaleSize{\n                            positiveIntRound(spImpl->mRescale),\n                            positiveIntRound(imageCurrent.size().height/(imageCurrent.size().width/ spImpl->mRescale))};\n                        xScale = imageCurrent.size().width / (float)rescaleSize.width;\n                        yScale = imageCurrent.size().height / (float)rescaleSize.height;\n                        cv::resize(imageCurrent, imageCurrent, rescaleSize, 0, 0, cv::INTER_CUBIC);\n                    }\n                    scaleKeypoints(spImpl->mPersonEntries, 1.f/xScale, 1.f/yScale);\n                    updateLK(spImpl->mPersonEntries, spImpl->mPyramidImagesPrevious, pyramidImagesCurrent, spImpl->mImagePrevious,\n                             imageCurrent, spImpl->mLevels, spImpl->mPatchSize, spImpl->mTrackVelocity, spImpl->mScaleVarying);\n                    scaleKeypoints(spImpl->mPersonEntries, xScale, yScale);\n                    spImpl->mImagePrevious = imageCurrent;\n                    spImpl->mPyramidImagesPrevious = pyramidImagesCurrent;\n                }\n\n                // There is new OP Data\n                if (newOPData)\n                {\n                    spImpl->mLastPoseIds = poseIds.clone();\n                    syncPersonEntriesWithOP(spImpl->mPersonEntries, poseKeypoints, spImpl->mLastPoseIds, spImpl->mConfidenceThreshold,\n                                            mergeResults);\n                    opFromPersonEntries(poseKeypoints, spImpl->mPersonEntries, spImpl->mLastPoseIds);\n                }\n                // There is no new OP Data\n                else\n                {\n                    opFromPersonEntries(poseKeypoints, spImpl->mPersonEntries, spImpl->mLastPoseIds);\n                    poseIds = spImpl->mLastPoseIds.clone();\n                }\n            }\n\n            // cv::Mat debugImage = cvMatInput.clone();\n            // vizPersonEntries(debugImage, spImpl->mPersonEntries, spImpl->mTrackVelocity);\n            // cv::imshow(\"win\", debugImage);\n            // cv::waitKey(15);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void PersonTracker::trackLockThread(Array<float>& poseKeypoints, Array<long long>& poseIds,\n                                        const Matrix& cvMatInput, const long long frameId)\n    {\n        try\n        {\n            // Wait for desired order\n            while (spImpl->mLastFrameId < frameId - 1)\n                std::this_thread::sleep_for(std::chrono::microseconds{100});\n            // Extract IDs\n            track(poseKeypoints, poseIds, cvMatInput);\n            // Update last frame id\n            spImpl->mLastFrameId = frameId;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool PersonTracker::getMergeResults() const\n    {\n        try\n        {\n            return spImpl->mMergeResults;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/tracking/pyramidalLK.cpp",
    "content": "#include <openpose_private/tracking/pyramidalLK.hpp>\n#ifdef WITH_SSE4\n    #include <emmintrin.h>\n    #include \"smmintrin.h\"\n#endif\n\n#ifdef WITH_AVX\n    #include <immintrin.h>\n#endif\n\n#include <iostream>\n#include <opencv2/core/core.hpp> // cv::Point2f, cv::Mat\n#include <opencv2/imgproc/imgproc.hpp> // cv::pyrDown\n#include <opencv2/video/video.hpp> // cv::buildOpticalFlowPyramid\n#include <openpose/utilities/profiler.hpp>\n\n//#define DEBUG\n// #ifdef DEBUG\n// // When debugging is enabled, these form aliases to useful functions\n// #define dbg_printf(...) printf(__VA_ARGS__);\n// #else\n// // When debugging is disabled, no code gets generated for these\n// #define dbg_printf(...)\n// #endif\n\n#define SUCCESS 0\n#define INVALID_PATCH_SIZE 1\n#define OUT_OF_FRAME 2\n#define ZERO_DENOMINATOR 3\n#define UNDEFINED_ERROR 4\n\nnamespace op\n{\n#ifdef WITH_SSE4\n    float sse_dot_product(std::vector<float> &av, std::vector<float> &bv)\n    {\n\n      /* Get SIMD-vector pointers to the start of each vector */\n      unsigned int niters = av.size() / 4;\n      float zeros[] = {0.0, 0.0, 0.0, 0.0};\n\n      float *a = (float *) aligned_alloc(16, av.size()*sizeof(float));\n      float *b = (float *) aligned_alloc(16, av.size()*sizeof(float));\n      memcpy(a,&av[0],av.size()*sizeof(float));\n      memcpy(b,&bv[0],bv.size()*sizeof(float));\n\n      __m128 *ptrA = (__m128*) &a[0], *ptrB = (__m128*) &b[0];\n      __m128 res = _mm_load_ps(zeros);\n\n      /* Do SIMD dot product */\n      for (unsigned int i = 0; i < niters; i++, ptrA++,ptrB++)\n        res = _mm_add_ps(_mm_dp_ps(*ptrA, *ptrB, 255), res);\n\n\n      /* Get result back from the SIMD vector */\n      float fres[4];\n      _mm_store_ps (fres, res);\n      int q = 4 * niters;\n\n      for (unsigned int i = 0; i < av.size() % 4; i++)\n        fres[0] += (a[i+q]*b[i+q]);\n\n      free(a);\n      free(b);\n\n      return fres[0];\n    }\n#endif\n\n// Function aligned_alloc requires C++17 in VS\n#if defined (WITH_AVX) && !defined (_WIN32)\n    float avx_dot_product(std::vector<float> &av, std::vector<float> &bv)\n    {\n        /* Get SIMD-vector pointers to the start of each vector */\n        const size_t niters = av.size() / 8;\n\n        float *a = (float *)aligned_alloc(32, av.size() * sizeof(float));\n        float *b = (float *)aligned_alloc(32, av.size() * sizeof(float));\n        memcpy(a, &av[0], av.size() * sizeof(float));\n        memcpy(b, &bv[0], bv.size() * sizeof(float));\n\n        __m256 *ptrA = (__m256*) &a[0], *ptrB = (__m256*) &b[0];\n        __m256 res = _mm256_set1_ps(0.0);\n\n        for (size_t i = 0; i < niters; i++, ptrA++, ptrB++)\n            res = _mm256_add_ps(_mm256_dp_ps(*ptrA, *ptrB, 255), res);\n\n        /* Get result back from the SIMD vector */\n        float fres[8];\n        _mm256_storeu_ps(fres, res);\n        const size_t q = 8 * niters;\n\n        for (size_t i = 0; i < av.size() % 8; i++)\n            fres[0] += (a[i + q] * b[i + q]);\n\n        free(a);\n        free(b);\n\n        return fres[0] + fres[4];\n    }\n#endif\n\n    char computeLK(cv::Point2f& delta,  std::vector<float>& ix,\n                  std::vector<float>& iy, std::vector<float>& it)\n    {\n        try\n        {\n            // Calculate sums\n#if defined (WITH_AVX) && !defined (_WIN32)\n            const float sumXX = avx_dot_product(ix,ix);\n            const float sumYY = avx_dot_product(iy,iy);\n            const float sumXY = avx_dot_product(ix,iy);\n            const float sumXT = avx_dot_product(ix,it);\n            const float sumYT = avx_dot_product(iy,it);\n#elif defined (WITH_SSE4)\n            const float sumXX = sse_dot_product(ix,ix);\n            const float sumYY = sse_dot_product(iy,iy);\n            const float sumXY = sse_dot_product(ix,iy);\n            const float sumXT = sse_dot_product(ix,it);\n            const float sumYT = sse_dot_product(iy,it);\n#else\n            auto sumXX = 0.f;\n            auto sumYY = 0.f;\n            auto sumXT = 0.f;\n            auto sumYT = 0.f;\n            auto sumXY = 0.f;\n            for (auto i = 0u; i < ix.size(); i++)\n            {\n                sumXX += ix[i] * ix[i];\n                sumYY += iy[i] * iy[i];\n                sumXY += ix[i] * iy[i];\n                sumXT += ix[i] * it[i];\n                sumYT += iy[i] * it[i];\n            }\n#endif\n\n            // Get numerator and denominator of u and v\n            const auto den = (sumXX*sumYY) - (sumXY * sumXY);\n\n            if (std::abs(den) < 1e-9f)\n                return ZERO_DENOMINATOR;\n\n            const auto numU = (-1.f * sumYY * sumXT) + (sumXY * sumYT);\n            const auto numV = (-1.f * sumXX * sumYT) + (sumXT * sumXY);\n\n            delta.x = numU / den;\n            delta.y = numV / den;\n\n            return SUCCESS;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return UNDEFINED_ERROR;\n        }\n    }\n\n    void getVectors(std::vector<float>& ix, std::vector<float>& iy, std::vector<float>& it,\n                    const std::vector<std::vector<float>>& patch, const std::vector<std::vector<float>>& patchIt,\n                    const int patchSize)\n    {\n        try\n        {\n            // Performance: resize faster than emplace_back/push_back\n            const auto numberElements = patchSize*patchSize;\n            // Get `ix` and `iy`\n            ix.resize(numberElements);\n            iy.resize(numberElements);\n            for (auto i = 1; i <= patchSize; i++)\n            {\n                const auto baseIndex = (i-1)*patchSize;\n                for (auto j = 1; j <= patchSize; j++)\n                {\n                    ix[baseIndex+j-1] = (patch[i][j+1] - patch[i][j-1])/2.f;\n                    iy[baseIndex+j-1] = (patch[i+1][j] - patch[i-1][j])/2.f;\n                }\n            }\n            // Get `it`\n            it.resize(numberElements);\n            for (auto i = 0; i < patchSize; i++)\n            {\n                const auto baseIndex = i*patchSize;\n                for (auto j = 0; j < patchSize; j++)\n                    it[baseIndex+j] = patchIt[i][j];\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    char extractPatch(std::vector< std::vector<float>>& patch, const int x, const int y, const int patchSize,\n                      const cv::Mat& image)\n    {\n        try\n        {\n            int radix = patchSize / 2;\n\n            if ( ((x - radix) < 0) ||\n                 ((x + radix) >= image.cols) ||\n                 ((y - radix) < 0) ||\n                 ((y + radix) >= image.rows))\n                return OUT_OF_FRAME;\n\n            for (auto i = -radix; i <= radix; i++)\n                for (auto j = -radix; j <= radix; j++)\n                    patch[i+radix][j+radix] = image.at<float>(y+i,x+j);\n\n            return SUCCESS;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return UNDEFINED_ERROR;\n        }\n    }\n\n    char extractPatchIt(std::vector<std::vector<float>>& patch, const int xI, const int yI, const int xJ,\n                        const int yJ, const cv::Mat& I, const cv::Mat& J, const int patchSize)\n    {\n        try\n        {\n            const int radix = patchSize / 2;\n\n            if (((xI - radix) < 0) ||\n                 ((xI + radix) >= I.cols) ||\n                 ((yI - radix) < 0) ||\n                 ((yI + radix) >= I.rows))\n                return OUT_OF_FRAME;\n\n            if (((xJ - radix) < 0) ||\n                 ((xJ + radix) >= J.cols) ||\n                 ((yJ - radix) < 0) ||\n                 ((yJ + radix) >= J.rows))\n                return OUT_OF_FRAME;\n\n            for (auto i = -radix; i <= radix; i++)\n                for (auto j = -radix; j <= radix; j++)\n                    patch[i+radix][j+radix] = J.at<float>(yJ+i,xJ+j) - I.at<float>(yI+i,xI+j);\n\n            return SUCCESS;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return UNDEFINED_ERROR;\n        }\n    }\n\n    // Given an OpenCV image, build a gaussian pyramid of size 'levels'\n    void buildGaussianPyramid(std::vector<cv::Mat>& pyramidImages, const cv::Mat& image, const int levels)\n    {\n        try\n        {\n            pyramidImages.clear();\n            pyramidImages.emplace_back(image);\n\n            for (auto i = 0; i < levels - 1; i++)\n            {\n                cv::Mat pyredImage;\n                cv::pyrDown(pyramidImages.back(), pyredImage);\n                pyramidImages.emplace_back(pyredImage);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    cv::Point2f pyramidIteration(char& status, const cv::Point2f& pointI, const cv::Point2f& pointJ, const cv::Mat& I,\n                                 const cv::Mat& J, const int patchSize = 5)\n    {\n        try\n        {\n            cv::Point2f result;\n\n            // Extract a patch around the image\n            std::vector<std::vector<float>> patch(patchSize + 2, std::vector<float>(patchSize + 2));\n            std::vector<std::vector<float>> patchIt(patchSize, std::vector<float>(patchSize));\n\n            status = extractPatch(patch, (int)pointI.x,(int)pointI.y, patchSize + 2, I);\n            // if (status)\n            //     return result;\n\n            status = extractPatchIt(patchIt, int(pointI.x), int(pointI.y), int(pointJ.x), int(pointJ.y), I, J, patchSize);\n\n            // if (status)\n            //     return result;\n\n            // Get the Ix, Iy and It vectors\n            std::vector<float> ix, iy, it;\n            getVectors(ix, iy, it, patch, patchIt, patchSize);\n\n            // Calculate optical flow\n            cv::Point2f delta;\n            status = computeLK(delta, ix, iy, it);\n\n            // if (status)\n            //     return result;\n\n            result = pointJ + delta;\n\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return cv::Point2f{};\n        }\n    }\n\n    void pyramidalLKCpu(std::vector<cv::Point2f>& coordI, std::vector<cv::Point2f>& coordJ,\n                        std::vector<cv::Mat>& pyramidImagesPrevious, std::vector<cv::Mat>& pyramidImagesCurrent,\n                        std::vector<char>& status, const cv::Mat& imagePrevious,\n                        const cv::Mat& imageCurrent, const int levels, const int patchSize)\n    {\n        try\n        {\n            // Empty coordinates\n            if (coordI.size() == 0)\n                return;\n\n            std::vector<cv::Point2f> I;\n            I.assign(coordI.begin(), coordI.end());\n\n            const auto rescaleScale = 1.0/(float)(1<<(levels-1));\n            for (auto& coordenate : I)\n                coordenate *= rescaleScale;\n\n            coordJ.clear();\n            coordJ.assign(I.begin(), I.end());\n\n            if (pyramidImagesPrevious.empty())\n                buildGaussianPyramid(pyramidImagesPrevious, imagePrevious, levels);\n            if (pyramidImagesCurrent.empty())\n                buildGaussianPyramid(pyramidImagesCurrent, imageCurrent, levels);\n\n\n            // Process all pixel requests\n            for (auto i = 0u; i < coordI.size(); i++)\n            {\n                for (auto l = levels - 1; l >= 0; l--)\n                {\n                    char status_point = 0;\n                    cv::Point2f result;\n\n                    result = pyramidIteration(status_point, I[i], coordJ[i],pyramidImagesPrevious[l],\n                                              pyramidImagesCurrent[l], patchSize);\n                    if (status_point)\n                        status[i] = status_point;\n\n                    coordJ[i] = result;\n\n                    if (l == 0)\n                        break;\n\n                    I[i] *= 2.f;\n                    coordJ[i] *= 2.f;\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // old, nwekp, pyramidPrev, pyramidCurr, status, imagePrev, imageCurr\n    void pyramidalLKOcv(std::vector<cv::Point2f>& coordI, std::vector<cv::Point2f>& coordJ,\n                        std::vector<cv::Mat>& pyramidImagesPrevious, std::vector<cv::Mat>& pyramidImagesCurrent,\n                        std::vector<char>& status, const cv::Mat& imagePrevious,\n                        const cv::Mat& imageCurrent, const int levels, const int patchSize, const bool initFlow)\n    {\n        try\n        {\n            // Empty coordinates\n            if (coordI.size() != 0)\n            {\n                // const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__);\n\n                std::vector<cv::Point2f> I;\n                I.assign(coordI.begin(), coordI.end());\n\n                if (!initFlow)\n                {\n                    coordJ.clear();\n                    coordJ.assign(I.begin(), I.end());\n                }\n\n                const cv::Mat& imagePrevGray = imagePrevious;\n                const cv::Mat& imageCurrGray = imageCurrent;\n\n                // Compute Pyramids\n                if (pyramidImagesPrevious.empty())\n                    cv::buildOpticalFlowPyramid(imagePrevGray, pyramidImagesPrevious, cv::Size{patchSize,patchSize}, levels);\n                if (pyramidImagesCurrent.empty())\n                    cv::buildOpticalFlowPyramid(imageCurrGray, pyramidImagesCurrent, cv::Size{patchSize,patchSize}, levels);\n\n                // Compute Flow\n                std::vector<uchar> st;\n                std::vector<float> err;\n                if (initFlow)\n                    cv::calcOpticalFlowPyrLK(pyramidImagesPrevious, pyramidImagesCurrent, coordI, coordJ, st, err,\n                                             cv::Size{patchSize,patchSize},levels,\n                                             cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS,30,0.01),\n                                             cv::OPTFLOW_USE_INITIAL_FLOW);\n                else\n                    cv::calcOpticalFlowPyrLK(pyramidImagesPrevious, pyramidImagesCurrent, coordI, coordJ, st, err,\n                                             cv::Size{patchSize,patchSize},levels);\n\n                // Check distance\n                for (size_t i=0; i<status.size(); i++)\n                {\n                    const double distance = std::sqrt(\n                        std::pow(coordI[i].x-coordJ[i].x,2) + std::pow(coordI[i].y-coordJ[i].y,2));\n\n                    // Check if lk loss track, if distance is close keep it\n                    if (st[i] != (status[i]))\n                        if (distance <= patchSize*2)\n                            st[i] = 1;\n\n                    // If distance too far discard it\n                    if (distance > patchSize*2)\n                        st[i] = 0;\n                }\n\n                // Stupid hack because apparently in this tracker 0 means 1 and 1 is 0 wtf\n                if (st.size() != status.size())\n                    error(\"st.size() != status.size().\", __LINE__, __FUNCTION__, __FILE__);\n                for (size_t i=0; i<status.size(); i++)\n                {\n                    // If its 0 to begin with (Because OP lost track?)\n                    if (status[i] != 0)\n                    {\n                        if (st[i] == 0)\n                            st[i] = 0;\n                        else if (st[i] == 1)\n                            st[i] = 1;\n                        else\n                            error(\"Wrong CV Type.\", __LINE__, __FUNCTION__, __FILE__);\n                        status[i] = st[i];\n                    }\n                }\n\n                // Profiler::timerEnd(profilerKey);\n                // Profiler::printAveragedTimeMsEveryXIterations(profilerKey, __LINE__, __FUNCTION__, __FILE__, 5);\n\n                // // Debug\n                // std::cout << \"LK: \";\n                // for (int i=0; i<status.size(); i++) std::cout << !(int)status[i];\n                // std::cout << std::endl;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/tracking/pyramidalLK.cu",
    "content": "#include <openpose_private/tracking/pyramidalLK.hpp>\n#ifdef WITH_TRACKING\n    #include <iostream>\n    #include <cuda.h>\n    #include <cuda_runtime.h>\n    #include <cuda_runtime_api.h>\n    #include <opencv2/opencv.hpp>\n    // OpenCV 2.X\n    #if (defined(CV_VERSION_EPOCH) && CV_VERSION_EPOCH == 2)\n        #include <opencv2/gpu/gpu.hpp>\n        #define cvCuda cv::gpu\n    // OpenCV > 2\n    #else\n        #include <opencv2/core/cuda.hpp>\n        #include <opencv2/cudaimgproc.hpp>\n        #include <opencv2/cudawarping.hpp>\n        #define cvCuda cv::cuda\n    #endif\n#endif\n\n// Error codes for kernel caller\n#define IMAGE_SIZES_NEQUAL -1\n// Point error status\n#define OUT_OF_FRAME 2\n#define ZERO_DENOMINATOR 3\n#define UNDEFINED_ERROR 4\n\nnamespace op\n{\n    // Global parameters\n    int block_size = 128;\n\n    #ifdef WITH_TRACKING\n        __global__ void pyramidalLKKernel(float* I, float* J, const int w, const int h,\n                                          float2* ptsI, float2* ptsJ, const int npoints,\n                                          char* status, const int patchSize, const float scale)\n        {\n            // 2D Index of current thread\n            const int idx = blockIdx.x * blockDim.x + threadIdx.x;\n\n            if (idx >= npoints || status[idx] > 0)\n                return;\n\n            if (scale != 1.0)\n            {\n                ptsI[idx].x *= scale;\n                ptsI[idx].y *= scale;\n                ptsJ[idx].x *= scale;\n                ptsJ[idx].y *= scale;\n            }\n\n            // Get frame I and frame J coordinates\n            const float xi = ptsI[idx].x;\n            const float yi = ptsI[idx].y;\n            const float xj = ptsJ[idx].x;\n            const float yj = ptsJ[idx].y;\n\n            // Validate patch area, +-1 up/down left/right required for x and y gradient.\n            if ((int)xi-1 < 0 || (int) yi-1 < 0 || (int)xi+1 >= w ||  (int)yi+1 >= h)\n            {\n                status[idx] = OUT_OF_FRAME;\n                return;\n            }\n            // Validate patch area for J\n            if ((int)xj < 0 || (int)yj < 0 || (int)xj >= w ||(int)yj >= h)\n            {\n                status[idx] = OUT_OF_FRAME;\n                return;\n            }\n\n            // Sum terms to calculate delta_u and delta_v\n            float sum_xx = 0.0, sum_yy = 0.0, sum_xt = 0.0,\n                  sum_yt = 0.0, sum_xy = 0.0;\n\n            // Radius (r) = floor(patchSize/2)\n            const int r = patchSize / 2;\n\n            // Temporal scalars\n            float dx = 0.0, dy = 0.0, dt = 0.0;\n\n            // Accumulate sum over patch\n            for (int i = -r; i <= r; i++)\n            {\n                for (int j = -r; j <= r; j++)\n                {\n                    dx = (I[((int)yi+i)*w + ((int)xi+1+j)] -\n                          I[((int)yi+i)*w + ((int)xi-1+j)]) / 2.0;\n                    dy = (I[((int)yi+i+1)*w + ((int)xi+j)] -\n                          I[((int)yi+i-1)*w + ((int)xi+j)]) / 2.0;\n                    dt = J[((int)yj+i)*w + ((int)xj+j)] -\n                         I[((int)yi+i)*w + ((int)xi+j)];\n                    sum_xx += dx*dx;\n                    sum_yy += dy*dy;\n                    sum_xy += dx*dy;\n                    sum_yt += dy*dt;\n                    sum_xt += dx*dt;\n                }\n            }\n\n            // Calculate displacement in 'x':u and displacement in 'y':x\n\n            // Get numerator and denominator of u and v\n            float den = (sum_xx*sum_yy) - (sum_xy * sum_xy);\n\n            if (den == 0.0)\n            {\n                status[idx] = ZERO_DENOMINATOR;\n                return;\n            }\n\n            float num_u = (-1.0 * sum_yy * sum_xt) + (sum_xy * sum_yt);\n            float num_v = (-1.0 * sum_xx * sum_yt) + (sum_xt * sum_xy);\n            float u = num_u / den;\n            float v = num_v / den;\n\n            ptsJ[idx].x += u;\n            ptsJ[idx].y += v;\n        }\n\n        // Given an OpenCV image 'img', build a gaussian pyramid of size 'levels'\n        void buildGaussianPyramid(std::vector<cvCuda::GpuMat>& pyramid, const cv::Mat& img, const int levels)\n        {\n            try\n            {\n                cvCuda::GpuMat current;\n                pyramid.clear();\n\n                current.upload(img);\n                pyramid.push_back(current);\n\n                for (int i = 0; i < levels - 1; i++)\n                {\n                    cvCuda::GpuMat tmp;\n                    cvCuda::pyrDown(pyramid.back(), tmp);\n                    pyramid.push_back(tmp);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        int pyramidalLKIterationGpu(cvCuda::GpuMat& I, cvCuda::GpuMat& J,\n                                    float2* ptsI,\n                                    float2* ptsJ,\n                                    const int patchSize,\n                                    const int npoints,\n                                    char* status,\n                                    const float scale)\n        {\n            try\n            {\n                // Get float pointers of I and J\n                float* ptrI = (float*) I.ptr<float>();\n                float* ptrJ = (float*) J.ptr<float>();\n\n                // Validate equal dimension for both images and assign width and height\n                int w = I.cols;\n                int h = I.rows;\n\n                if (w != J.cols || h != I.rows)\n                    return IMAGE_SIZES_NEQUAL;\n\n                // Block size and number of blocks\n                int bsize = block_size;\n                int nblocks = (npoints + bsize -1) / bsize;\n\n                // Launch kernel\n                pyramidalLKKernel<<<nblocks, bsize>>>(ptrI,ptrJ,w,h,ptsI,ptsJ,\n                                                      npoints,status, patchSize, scale);\n                // Wait for all cuda threads to finish\n                cudaDeviceSynchronize();\n\n                return 0;\n            }\n            catch (const std::exception& e)\n            {\n                error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                return UNDEFINED_ERROR;\n            }\n        }\n    #endif\n\n    int pyramidalLKGpu(std::vector<cv::Point2f>& ptsI, std::vector<cv::Point2f>& ptsJ,\n                       std::vector<char>& status,\n                       const cv::Mat& I, const cv::Mat& J,\n                       const int levels, const int patchSize)\n    {\n        try\n        {\n            #ifdef WITH_TRACKING\n                std::vector<cvCuda::GpuMat> pyrI;\n                std::vector<cvCuda::GpuMat> pyrJ;\n\n                // Allocate ptsJ and initialize\n                ptsJ.clear();\n                ptsJ.assign(ptsI.begin(), ptsI.end());\n\n                // Build Gaussian pyramid for both I and J\n                buildGaussianPyramid(pyrI, I, levels);\n                buildGaussianPyramid(pyrJ, J, levels);\n                // Convert cv::Point2f std::vector to float2 array\n                int pts_size = sizeof(float2) * ptsI.size();\n                float2* ptsI_f2 = (float2*) malloc(pts_size);\n                float2* ptsJ_f2 = (float2*) malloc(pts_size);\n\n                for (int i = 0; i < ptsI.size(); i++)\n                {\n                    ptsI_f2[i].x = ptsI[i].x;\n                    ptsI_f2[i].y = ptsI[i].y;\n                }\n\n                // Allocate pts on the GPU\n                float2* ptsI_gpu;\n                float2* ptsJ_gpu;\n                cudaMalloc(&ptsI_gpu, pts_size);\n                cudaMalloc(&ptsJ_gpu, pts_size);\n                // Copy pts CPU -> GPU\n                cudaMemcpy(ptsI_gpu, ptsI_f2, pts_size, cudaMemcpyHostToDevice);\n                cudaMemcpy(ptsJ_gpu, ptsI_f2, pts_size, cudaMemcpyHostToDevice);\n                // Move status std::vector to the gpu\n                char* status_gpu;\n                cudaMalloc(&status_gpu, status.size());\n                cudaMemcpy(status_gpu, status.data(), status.size(), cudaMemcpyHostToDevice);\n\n                float scale = 1.0 / (float) (1<<(levels));\n\n                int npoints = ptsI.size();\n\n                // Iterate level by level\n                for (int l = levels - 1; l >= 0; l--)\n                {\n                    scale *= 2.0;\n\n                    if (l != levels - 1)\n                        scale = 2.0;\n\n                    pyramidalLKIterationGpu(pyrI[l], pyrJ[l], ptsI_gpu, ptsJ_gpu,\n                                            patchSize, npoints, status_gpu,scale);\n                }\n\n                // Copy points and status back\n                cudaMemcpy(ptsI_f2, ptsI_gpu, pts_size, cudaMemcpyDeviceToHost);\n                cudaMemcpy(ptsJ_f2, ptsJ_gpu, pts_size, cudaMemcpyDeviceToHost);\n\n                cudaMemcpy(status.data(),status_gpu, status.size(), cudaMemcpyDeviceToHost);\n\n                // Recover cv::Point2f I and J\n                for (int i = 0; i < ptsI.size(); i++)\n                {\n                    ptsI[i].x = ptsI_f2[i].x;\n                    ptsI[i].y = ptsI_f2[i].y;\n                    ptsJ[i].x = ptsJ_f2[i].x;\n                    ptsJ[i].y = ptsJ_f2[i].y;\n                }\n\n                // Free GPU allocated memory\n                cudaFree(ptsI_gpu);\n                cudaFree(ptsJ_gpu);\n                cudaFree(status_gpu);\n\n                return 0;\n            #else\n                UNUSED(ptsI);\n                UNUSED(ptsJ);\n                UNUSED(status);\n                UNUSED(I);\n                UNUSED(J);\n                UNUSED(levels);\n                UNUSED(patchSize);\n                return UNDEFINED_ERROR;\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return UNDEFINED_ERROR;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/unity/CMakeLists.txt",
    "content": "set(SOURCES_OP_UNITY\n    unityBinding.cpp\n)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nset(SOURCES_OP_UNITY_WITH_CP \"\" PARENT_SCOPE)\nprepend(SOURCES_OP_UNITY_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_UNITY})\nset(SOURCES_OP_UNITY_WITH_CP ${SOURCES_OP_UNITY_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OP_FILESTREAM_WITH_CP ${SOURCES_OP_FILESTREAM_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_UNITY_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  add_library(openpose_unity ${SOURCES_OP_UNITY})\n  target_link_libraries(openpose_unity openpose_pose ${OpenPose_3rdparty_libraries})\n\n  install(TARGETS openpose_unity\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/unity/unityBinding.cpp",
    "content": "#ifdef USE_UNITY_SUPPORT\n// ------------------------- OpenPose Unity Binding -------------------------\n\n// OpenPose dependencies\n#include <openpose/headers.hpp>\n\nnamespace op\n{\n    #ifdef _WIN32\n        // Output callback register in Unity\n        typedef void(__stdcall * OutputCallback) (void * ptrs, int ptrSize, int * sizes, int sizeSize,\n                                                  unsigned char outputType);\n        // Global output callback\n        OutputCallback sUnityOutputCallback;\n    #endif\n\n    // Other global parameters\n    bool sMultiThreadDisabled = false;\n    bool sUnityOutputEnabled = true;\n    bool sImageOutput = false;\n\n    enum class OutputType : unsigned char\n    {\n        None,\n        DatumsInfo,\n        Name,\n        PoseKeypoints,\n        PoseIds,\n        PoseScores,\n        PoseHeatMaps,\n        PoseCandidates,\n        FaceRectangles,\n        FaceKeypoints,\n        FaceHeatMaps,\n        HandRectangles,\n        HandKeypoints,\n        HandHeightMaps,\n        PoseKeypoints3D,\n        FaceKeypoints3D,\n        HandKeypoints3D,\n        CameraMatrix,\n        CameraExtrinsics,\n        CameraIntrinsics,\n        Image\n    };\n\n    // This worker will just read and return all the jpg files in a directory\n    class UnityPluginUserOutput : public WorkerConsumer<std::shared_ptr<std::vector<std::shared_ptr<Datum>>>>\n    {\n    public:\n        void initializationOnThread()\n        {\n        }\n\n        void workConsumer(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                if (datumsPtr != nullptr && !datumsPtr->empty())\n                {\n                    if (sUnityOutputEnabled)\n                    {\n                        sendDatumsInfoAndName(datumsPtr);\n                        sendPoseKeypoints(datumsPtr);\n                        sendPoseIds(datumsPtr);\n                        sendPoseScores(datumsPtr);\n                        sendPoseHeatMaps(datumsPtr);\n                        sendPoseCandidates(datumsPtr);\n                        sendFaceRectangles(datumsPtr);\n                        sendFaceKeypoints(datumsPtr);\n                        sendFaceHeatMaps(datumsPtr);\n                        sendHandRectangles(datumsPtr);\n                        sendHandKeypoints(datumsPtr);\n                        sendHandHeatMaps(datumsPtr);\n                        if (sImageOutput)\n                            sendImage(datumsPtr);\n                        sendEndOfFrame();\n                    }\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n    private:\n        template<class T>\n        void outputValue(T** ptrs, const int ptrSize, int* sizes, const int sizeSize, const OutputType outputType)\n        {\n            try\n            {\n                #ifdef _WIN32\n                    if (sUnityOutputCallback)\n                        sUnityOutputCallback(\n                            static_cast<void*>(ptrs), ptrSize, sizes, sizeSize, (unsigned char)outputType);\n                #else\n                    UNUSED(ptrs);\n                    UNUSED(ptrSize);\n                    UNUSED(sizes);\n                    UNUSED(sizeSize);\n                    UNUSED(outputType);\n                    error(\"Function only available on Windows.\", __LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendDatumsInfoAndName(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& datum = datumsPtr->at(0);\n                int sizes[] = { 1 };\n                const int sizeSize = 1;\n                unsigned long long* val[] = {&(datum->id), &(datum->subId), &(datum->subIdMax), &(datum->frameNumber)};\n                const int ptrSize = 4;\n                outputValue(&val[0], ptrSize, &sizes[0], sizeSize, OutputType::DatumsInfo);\n\n                const char* a[] = { datum->name.c_str() };\n                outputValue(&a[0], 1, &sizes[0], sizeSize, OutputType::Name);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendPoseKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->poseKeypoints; // Array<float>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    float* val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::PoseKeypoints);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendPoseIds(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->poseIds; // Array<long long>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    long long* val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::PoseIds);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendPoseScores(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->poseScores; // Array<float>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    float* val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::PoseScores);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendPoseHeatMaps(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->poseHeatMaps; // Array<float>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    float* val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::PoseHeatMaps);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendPoseCandidates(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->poseCandidates; // std::vector<std::vector<std::array<float, 3>>>\n                if (!data.empty())\n                {\n                    // TODO\n                    /*auto a = data[0][0].data();\n                    auto sizeVector = data.getSize();\n                    int sizeSize = sizeVector.size();\n                    int * sizes = &sizeVector[0];\n                    long long * val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::PoseIds);*/\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendFaceRectangles(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->faceRectangles; // std::vector<Rectangle<float>>\n                if (data.size() > 0)\n                {\n                    int sizes[] = { (int)data.size(), 4 };\n                    std::vector<float> vals(data.size() * 4);\n                    for (auto i = 0u; i < data.size(); i++)\n                    {\n                        vals[4 * i + 0] = data[i].x;\n                        vals[4 * i + 1] = data[i].y;\n                        vals[4 * i + 2] = data[i].width;\n                        vals[4 * i + 3] = data[i].height;\n                    }\n                    float * val = &vals[0];\n                    outputValue(&val, 1, sizes, 2, OutputType::FaceRectangles);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendFaceKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->faceKeypoints; // Array<float>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    int sizeSize = (int)sizeVector.size();\n                    int * sizes = &sizeVector[0];\n                    float * val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::FaceKeypoints);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendFaceHeatMaps(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->faceHeatMaps; // Array<float>\n                if (!data.empty())\n                {\n                    auto sizeVector = data.getSize();\n                    int sizeSize = (int)sizeVector.size();\n                    int * sizes = &sizeVector[0];\n                    float * val = data.getPtr();\n                    outputValue(&val, 1, sizes, sizeSize, OutputType::FaceHeatMaps);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendHandRectangles(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->handRectangles; // std::vector<std::array<Rectangle<float>, 2>>\n                if (!data.empty())\n                {\n                    std::vector<float*> valPtrs;\n                    for (auto i = 0u; i < data.size(); i++)\n                    {\n                        float vals[8];\n                        for (auto j = 0; j < 2; j++)\n                        {\n                            vals[4 * j + 0] = data[i][j].x;\n                            vals[4 * j + 1] = data[i][j].y;\n                            vals[4 * j + 2] = data[i][j].width;\n                            vals[4 * j + 3] = data[i][j].height;\n                        }\n                        valPtrs.push_back(vals);\n                    }\n                    int sizes[] = {2, 4};\n                    const int sizeSize = 2;\n                    outputValue(valPtrs.data(), (int)valPtrs.size(), sizes, sizeSize, OutputType::HandRectangles);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendHandKeypoints(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->handKeypoints; // std::array<Array<float>, 2>\n                if (data.size() == 2 && !data[0].empty())\n                {\n                    auto sizeVector = data[0].getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    float* ptrs[] = { data[0].getPtr(), data[1].getPtr() };\n                    outputValue(ptrs, 2, sizes, sizeSize, OutputType::HandKeypoints);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendHandHeatMaps(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->handHeatMaps; // std::array<Array<float>, 2>\n                if (data.size() == 2 && !data[0].empty())\n                {\n                    auto sizeVector = data[0].getSize();\n                    const int sizeSize = (int)sizeVector.size();\n                    int* sizes = &sizeVector[0];\n                    float* ptrs[] = { data[0].getPtr(), data[1].getPtr() };\n                    outputValue(ptrs, 2, sizes, sizeSize, OutputType::HandHeightMaps);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendImage(const std::shared_ptr<std::vector<std::shared_ptr<Datum>>>& datumsPtr)\n        {\n            try\n            {\n                auto& data = datumsPtr->at(0)->cvInputData; // cv::Mat\n                if (!data.empty())\n                {\n                    int sizeVector[] = { data.rows(), data.cols(), 3 };\n                    const int sizeSize = 3;\n                    auto valPtr = data.data();\n                    outputValue(&valPtr, 1, sizeVector, sizeSize, OutputType::Image);\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        void sendEndOfFrame()\n        {\n            try\n            {\n                outputValue((void**)nullptr, 0, nullptr, 0, OutputType::None);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    };\n\n    // Global user output\n    UnityPluginUserOutput* ptrUserOutput = nullptr;\n\n    // Global setting structs\n    std::shared_ptr<WrapperStructPose> spWrapperStructPose;\n    std::shared_ptr<WrapperStructHand> spWrapperStructHand;\n    std::shared_ptr<WrapperStructFace> spWrapperStructFace;\n    std::shared_ptr<WrapperStructExtra> spWrapperStructExtra;\n    std::shared_ptr<WrapperStructInput> spWrapperStructInput;\n    std::shared_ptr<WrapperStructOutput> spWrapperStructOutput;\n    std::shared_ptr<WrapperStructGui> spWrapperStructGui;\n\n    // Main\n    void openpose_main()\n    {\n        try\n        {\n            // Starting\n            opLog(\"Starting OpenPose...\");\n\n            // OpenPose wrapper\n            auto spWrapper = std::make_shared<Wrapper>();\n\n            // Initializing the user custom classes\n            auto spUserOutput = std::make_shared<UnityPluginUserOutput>();\n            ptrUserOutput = spUserOutput.get();\n\n            // Add custom processing\n            const auto workerOutputOnNewThread = true;\n            spWrapper->setWorker(WorkerType::Output, spUserOutput, workerOutputOnNewThread);\n\n            // Apply configurations\n            spWrapper->configure(*spWrapperStructPose);\n            spWrapper->configure(*spWrapperStructHand);\n            spWrapper->configure(*spWrapperStructFace);\n            spWrapper->configure(*spWrapperStructExtra);\n            spWrapper->configure(*spWrapperStructInput);\n            spWrapper->configure(*spWrapperStructOutput);\n\n            // Multi-threading\n            if (sMultiThreadDisabled)\n                spWrapper->disableMultiThreading();\n\n            // Processing...\n            spWrapper->exec();\n\n            // Ending\n            opLog(\"OpenPose finished\");\n        }\n        catch (const std::exception& e)\n        {\n            errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    // Functions called from Unity\n    extern \"C\" {\n        // Start openpose safely\n        OP_API void _OPRun()\n        {\n            try\n            {\n                openpose_main();\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        // Stop openpose safely\n        OP_API void _OPShutdown()\n        {\n            try\n            {\n                if (ptrUserOutput != nullptr)\n                {\n                    opLog(\"Stopping...\");\n                    ptrUserOutput->stop();\n                }\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        // Register Unity output callback function\n        #ifdef _WIN32\n            OP_API void _OPRegisterOutputCallback(OutputCallback callback)\n            {\n                try\n                {\n                    sUnityOutputCallback = callback;\n                }\n                catch (const std::exception& e)\n                {\n                    errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        #endif\n\n        // Enable/disable output callback\n        OP_API void _OPSetOutputEnable(bool enable)\n        {\n            try\n            {\n                sUnityOutputEnabled = enable;\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        // Enable/disable image output\n        OP_API void _OPSetImageOutputEnable(bool enable)\n        {\n            try\n            {\n                sImageOutput = enable;\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        // Configs\n        OP_API void _OPConfigurePose(\n            unsigned char poseMode,\n            int netInputSizeX, int netInputSizeY, // Point\n            double netInputSizeDynamicBehavior,\n            int outputSizeX, int outputSizeY, // Point\n            unsigned char keypointScaleMode, // ScaleMode\n            int gpuNumber, int gpuNumberStart, int scalesNumber, float scaleGap,\n            unsigned char renderMode, // RenderMode\n            unsigned char poseModel, // PoseModel\n            bool blendOriginalFrame, float alphaKeypoint, float alphaHeatMap, int defaultPartToRender,\n            char* modelFolder, bool heatMapAddParts, bool heatMapAddBkg,\n            bool heatMapAddPAFs, // HeatMapType // unsigned char heatmap_type,\n            unsigned char heatMapScaleMode, // ScaleMode\n            bool addPartCandidates, float renderThreshold, int numberPeopleMax,\n            bool maximizePositives, double fpsMax, char* protoTxtPath, char* caffeModelPath, float upsamplingRatio)\n        {\n            try\n            {\n                spWrapperStructPose = std::make_shared<WrapperStructPose>(\n                    (PoseMode)poseMode, Point<int>{netInputSizeX, netInputSizeY}, netInputSizeDynamicBehavior,\n                    Point<int>{outputSizeX, outputSizeY}, (ScaleMode) keypointScaleMode, gpuNumber, gpuNumberStart,\n                    scalesNumber, scaleGap, (RenderMode) renderMode, (PoseModel) poseModel, blendOriginalFrame,\n                    alphaKeypoint, alphaHeatMap, defaultPartToRender, modelFolder,\n                    // HeatMapType // (HeatMapType) heatmap_type,\n                    flagsToHeatMaps(heatMapAddParts, heatMapAddBkg, heatMapAddPAFs),\n                    (ScaleMode) heatMapScaleMode, addPartCandidates, renderThreshold, numberPeopleMax,\n                    maximizePositives, fpsMax, protoTxtPath, caffeModelPath, upsamplingRatio, true\n                );\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureHand(\n            bool enable, unsigned char detector, int netInputSizeX, int netInputSizeY, // Point\n            int scalesNumber, float scaleRange,\n            unsigned char renderMode, // RenderMode\n            float alphaKeypoint, float alphaHeatMap, float renderThreshold)\n        {\n            try\n            {\n                spWrapperStructHand = std::make_shared<WrapperStructHand>(\n                    enable, (Detector) detector, Point<int>{ netInputSizeX, netInputSizeY }, scalesNumber, scaleRange,\n                    (RenderMode) renderMode, alphaKeypoint, alphaHeatMap, renderThreshold);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureFace(\n            bool enable, unsigned char detector, int netInputSizeX, int netInputSizeY, // Point\n            unsigned char renderMode, // RenderMode\n            float alphaKeypoint, float alphaHeatMap, float renderThreshold)\n        {\n            try\n            {\n                spWrapperStructFace = std::make_shared<WrapperStructFace>(\n                    enable, (Detector) detector, Point<int>{ netInputSizeX, netInputSizeY }, (RenderMode) renderMode,\n                    alphaKeypoint, alphaHeatMap, renderThreshold\n                );\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureExtra(\n            bool reconstruct3d, int minViews3d, bool identification, int tracking, int ikThreads)\n        {\n            try\n            {\n                spWrapperStructExtra = std::make_shared<WrapperStructExtra>(\n                    reconstruct3d, minViews3d, identification, tracking, ikThreads\n                );\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureInput(\n            unsigned char producerType, char* producerString, // ProducerType\n            unsigned long long frameFirst, unsigned long long frameStep, unsigned long long frameLast,\n            bool realTimeProcessing, bool frameFlip, int frameRotate, bool framesRepeat,\n            int cameraResolutionX, int cameraResolutionY, // Point\n            char* cameraParameterPath, bool undistortImage, int numberViews)\n        {\n            try\n            {\n                spWrapperStructInput = std::make_shared<WrapperStructInput>(\n                    (ProducerType) producerType, producerString, frameFirst, frameStep, frameLast, realTimeProcessing,\n                    frameFlip, frameRotate, framesRepeat, Point<int>{ cameraResolutionX, cameraResolutionY },\n                    cameraParameterPath, undistortImage, numberViews\n                );\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureOutput(\n            double verbose, char* writeKeypoint, unsigned char writeKeypointFormat, // DataFormat\n            char* writeJson, char* writeCocoJson, int writeCocoJsonVariants, int writeCocoJsonVariant, char* writeImages,\n            char* writeImagesFormat, char* writeVideo, double writeVideoFps, bool writeVideoWithAudio,\n            char* writeHeatMaps, char* writeHeatMapsFormat, char* writeVideo3D, char* writeVideoAdam, char* writeBvh,\n            char* udpHost, char* udpPort)\n        {\n            try\n            {\n                spWrapperStructOutput = std::make_shared<WrapperStructOutput>(\n                    verbose, writeKeypoint, (DataFormat) writeKeypointFormat, writeJson, writeCocoJson,\n                    writeCocoJsonVariants, writeCocoJsonVariant, writeImages, writeImagesFormat, writeVideo, writeVideoFps,\n                    writeVideoWithAudio, writeHeatMaps, writeHeatMapsFormat, writeVideo3D, writeVideoAdam, writeBvh,\n                    udpHost, udpPort);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureGui(\n            unsigned short displayMode, // DisplayMode\n            bool guiVerbose, bool fullScreen)\n        {\n            try\n            {\n                spWrapperStructGui = std::make_shared<WrapperStructGui>(\n                    (DisplayMode) displayMode, guiVerbose, fullScreen);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n\n        OP_API void _OPConfigureDebugging(\n            unsigned char loggingLevel, // Priority\n            bool disableMultiThread,\n            unsigned long long profileSpeed)\n        {\n            try\n            {\n                ConfigureLog::setPriorityThreshold((Priority)loggingLevel);\n                sMultiThreadDisabled = disableMultiThread;\n                Profiler::setDefaultX(profileSpeed);\n            }\n            catch (const std::exception& e)\n            {\n                errorDestructor(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n    }\n}\n#endif\n"
  },
  {
    "path": "src/openpose/utilities/CMakeLists.txt",
    "content": "set(SOURCES_OP_UTILITIES\n    errorAndLog.cpp\n    fileSystem.cpp\n    flagsToOpenPose.cpp\n    keypoint.cpp\n    openCv.cpp\n    openCvPrivate.cpp\n    profiler.cpp\n    string.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_UTILITIES_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_UTILITIES})\nset(SOURCES_OP_UTILITIES_WITH_CP ${SOURCES_OP_UTILITIES_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_UTILITIES_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  if (${GPU_MODE} MATCHES \"CUDA\")\n    cuda_add_library(openpose_utilities ${SOURCES_OP_UTILITIES})\n  else ()\n    add_library(openpose_utilities ${SOURCES_OP_UTILITIES})\n  endif ()\n\n  target_link_libraries(openpose_utilities openpose_producer openpose_filestream)\n\n  install(TARGETS openpose_utilities\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/utilities/errorAndLog.cpp",
    "content": "#include <openpose/utilities/errorAndLog.hpp>\n#include <atomic>\n#include <mutex>\n#include <ctime> // std::tm, std::time_t\n#include <fstream> // std::ifstream, std::ofstream\n#include <iostream> // std::cout, std::endl\n#include <stdexcept> // std::runtime_error\n\nnamespace op\n{\n    std::atomic<bool> sThreadErrors;\n    std::mutex sMutex;\n    std::vector<std::string> sThreadErrorMessages;\n    std::string sMainThreadId;\n\n    #ifdef USE_UNITY_SUPPORT\n        namespace UnityDebugger\n        {\n            #ifdef _WIN32\n                typedef void(__stdcall * DebugCallback) (const char* const str, int type);\n                DebugCallback unityDebugCallback;\n            #endif\n            bool unityDebugEnabled = true;\n\n            #ifdef _WIN32\n                extern \"C\" void OP_API _OPRegisterDebugCallback(DebugCallback debugCallback)\n                {\n                    if (debugCallback)\n                    unityDebugCallback = debugCallback;\n                }\n\n                extern \"C\" void OP_API _OPSetDebugEnable(bool enable)\n                {\n                    unityDebugEnabled = enable;\n                }\n            #endif\n\n            void DebugInUnity(const std::string& message, const int type)\n            {\n                #ifdef _WIN32\n                    if (unityDebugEnabled)\n                        if (unityDebugCallback)\n                            unityDebugCallback(message.c_str(), type);\n                #else\n                    UNUSED(message);\n                    UNUSED(type);\n                    error(\"Unity plugin only available on Windows.\", __LINE__, __FUNCTION__, __FILE__);\n                #endif\n            }\n\n            void opLog(const std::string& message) { DebugInUnity(message, 0); }\n            void logWarning(const std::string& message) { DebugInUnity(message, 1); }\n            void logError(const std::string& message) { DebugInUnity(message, -1); }\n        }\n    #endif\n\n    // Private auxiliary functions\n    bool checkIfErrorHas(const ErrorMode errorMode)\n    {\n        for (const auto& sErrorMode : ConfigureError::getErrorModes())\n            if (sErrorMode == errorMode || sErrorMode == ErrorMode::All)\n                return true;\n        return false;\n    }\n\n    bool checkIfLoggingHas(const LogMode loggingMode)\n    {\n        for (const auto& sLoggingMode : ConfigureLog::getLogModes())\n            if (sLoggingMode == loggingMode || sLoggingMode == LogMode::All)\n                return true;\n        return false;\n    }\n\n    // Note: createFullMessage(message) = message\n    std::string createFullMessage(const std::string& message, const int line = -1, const std::string& function = \"\",\n                                  const std::string& file = \"\")\n    {\n        const auto hasMessage = (!message.empty());\n        const auto hasLocation = (line != -1 || !function.empty() || !file.empty());\n\n        std::string fullMessage;\n\n        if (hasMessage)\n        {\n            fullMessage += message;\n            // // Add dot at the end if the sentence does not finish in a programming file path (this happens when the\n            // error is propagated over several error)\n            // if (*message.crbegin() != '.'\n            //     && (message.size() < 4\n            //         || (message.substr(message.size() - 4, 4) != \".cpp\"\n            //             && message.substr(message.size() - 4, 4) != \".hpp\"\n            //             && message.substr(message.size() - 4, 4) != \".h\"\n            //             && message.substr(message.size() - 4, 4) != \".c\")))\n            //     fullMessage += \".\";\n\n            if (hasLocation)\n            {\n                if (*message.crbegin() != '.')\n                    fullMessage += \" in \";\n                else\n                    fullMessage += \" In \";\n            }\n        }\n\n        if (hasLocation)\n            fullMessage += file + \":\" + function + \"():\" + std::to_string(line);\n\n        else if (!hasMessage) // else assumed !hasLocation\n            fullMessage += \"[Undefined]\";\n\n        return fullMessage;\n    }\n\n    std::string getTime()\n    {\n        // Ubuntu version\n        std::time_t rawtime;\n        struct std::tm timeStruct;\n        std::time(&rawtime);\n        timeStruct = *localtime(&rawtime);\n\n        // // Windows version\n        // struct std::tm timeStruct;\n        // std::time_t time_create{std::time(NULL)};\n        // localtime_s(&timeStruct, &time_create);\n\n        // Common\n        timeStruct.tm_mon++;\n        timeStruct.tm_year += 1900;\n        return std::to_string(timeStruct.tm_year) + '_' + std::to_string(timeStruct.tm_mon)\n               + '_' + std::to_string(timeStruct.tm_mday) + \"___\" + std::to_string(timeStruct.tm_hour)\n               + '_' + std::to_string(timeStruct.tm_min) + '_' + std::to_string(timeStruct.tm_sec);\n    }\n\n    void fileLogging(const std::string& message)\n    {\n        std::string fileToOpen{\"errorLogging.txt\"};\n\n        // Get current file size\n        std::ifstream in{fileToOpen, std::ios::binary | std::ios::ate};\n        const auto currentSizeBytes = in.tellg();\n        in.close();\n\n        // Continue at the end of the file or delete it and re-write it (according to current file size)\n        const auto maxLogSize = 15 * 1024 * 1024; // 15 MB\n        std::ofstream loggingFile{\n            fileToOpen, (currentSizeBytes < maxLogSize ? std::ios_base::app : std::ios_base::trunc)};\n\n        // Message to write\n        loggingFile << getTime();\n        loggingFile << \"\\n\";\n        loggingFile << message;\n        loggingFile << \"\\n\\n\\n\\n\\n\";\n\n        loggingFile.close();\n    }\n\n    void errorAux(\n        const int errorMode, const std::string& message, const int line, const std::string& function,\n        const std::string& file)\n    {\n        // errorMode:\n        // 0: error\n        // 1: errorWorker\n        // 2: checkWorkerErrors\n        // 3: errorDestructor\n\n        const std::string errorInitBase = \"\\nError\";\n        const std::string errorInit = errorInitBase + \":\\n\";\n        const std::string errorEnum = \"- \";\n\n        // Compose error message\n        std::string errorMessageToPropagate;\n        std::string errorMessageToPrint;\n        // If first error\n        if (message.size() < errorInitBase.size() || message.substr(0, errorInitBase.size()) != errorInitBase)\n        {\n            errorMessageToPrint = errorInit + createFullMessage(message) + \"\\n\\nComing from:\\n\" + errorEnum\n                                + createFullMessage(\"\", line, function, file);\n            errorMessageToPropagate = errorMessageToPrint + \"\\n\";\n        }\n        // If error propagated among different errors\n        else\n        {\n            errorMessageToPrint = errorEnum + createFullMessage(\"\", line, function, file);\n            if (errorMode == 2)\n            {\n                const std::string errorThreadLine =\n                    \"[All threads closed and control returned to main thread]\";\n                errorMessageToPrint = errorEnum + errorThreadLine + \"\\n\" + errorMessageToPrint;\n            }\n            else if (errorMode == 3)\n                errorMessageToPrint += \"\\n\" + errorEnum + \"[Error occurred in a destructor or in the OpenPose\"\n                    \" Unity Plugin, so no std::exception has been thrown. Returning with exit status 0]\";\n            errorMessageToPropagate = createFullMessage(message) + errorMessageToPrint + \"\\n\";\n            if (errorMode == 1)\n            {\n                errorMessageToPropagate = errorInitBase + \" occurred on a thread. OpenPose closed all its\"\n                    \" threads and then propagated the error to the main thread. Error description:\\n\\n\"\n                    + errorMessageToPropagate.substr(errorInit.size(), errorMessageToPropagate.size()-1);\n            }\n            if (errorMode == 2)\n                errorMessageToPrint = errorMessageToPropagate.substr(0, errorMessageToPropagate.size()-1);\n        }\n\n        // std::cerr\n        if (checkIfErrorHas(ErrorMode::StdCerr))\n            #ifdef NDEBUG\n            if (!getIfNotInMainThreadOrEmpty())\n            #endif\n                std::cerr << errorMessageToPrint << std::endl;\n\n        // File logging\n        if (checkIfErrorHas(ErrorMode::FileLogging))\n            fileLogging(errorMessageToPrint);\n\n        // std::runtime_error\n        if (errorMode == 1)\n        {\n            sThreadErrors = true;\n            std::lock_guard<std::mutex> lock{sMutex};\n            sThreadErrorMessages.emplace_back(errorMessageToPropagate);\n        }\n        else\n        {\n            // Unity logError\n            #ifdef USE_UNITY_SUPPORT\n                if (errorMode == 3)\n                    UnityDebugger::logError(errorMessageToPropagate);\n            #endif\n\n            if (checkIfErrorHas(ErrorMode::StdRuntimeError) && errorMode != 3)\n                throw std::runtime_error{errorMessageToPropagate};\n        }\n    }\n\n\n\n\n\n    // Public functions\n    void setMainThread()\n    {\n        std::lock_guard<std::mutex> lock{sMutex};\n        sMainThreadId = getThreadId();\n    }\n\n    std::string getThreadId()\n    {\n        std::stringstream threadId;\n        threadId << std::this_thread::get_id();\n        return threadId.str();\n    }\n\n    bool getIfInMainThreadOrEmpty()\n    {\n        std::lock_guard<std::mutex> lock{sMutex};\n        return (!sMainThreadId.empty() && sMainThreadId == getThreadId());\n    }\n\n    bool getIfNotInMainThreadOrEmpty()\n    {\n        std::lock_guard<std::mutex> lock{sMutex};\n        return (!sMainThreadId.empty() && sMainThreadId != getThreadId());\n    }\n\n    void error(const std::string& message, const int line, const std::string& function, const std::string& file)\n    {\n        errorAux(0, message, line, function, file);\n    }\n\n    void checkWorkerErrors()\n    {\n        if (sThreadErrors)\n        {\n            std::unique_lock<std::mutex> lock{sMutex};\n            std::string fullMessage = sThreadErrorMessages.at(0);\n            lock.unlock();\n            sThreadErrors = false; // Avoid infinity loop throwing the same error over and over.\n            errorAux(2, fullMessage, __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void errorWorker(const std::string& message, const int line, const std::string& function, const std::string& file)\n    {\n        // If we are 100% sure that we are in main thread, then normal error.\n        // Otherwise, worker error\n        errorAux((getIfInMainThreadOrEmpty() ? 0 : 1), message, line, function, file);\n    }\n\n    void errorDestructor(const std::string& message, const int line, const std::string& function, const std::string& file)\n    {\n        // If we are 100% sure that we are in main thread, then normal error.\n        // Otherwise, worker error\n        errorAux(3, message, line, function, file);\n    }\n\n    void opLog(\n        const std::string& message, const Priority priority, const int line, const std::string& function,\n        const std::string& file)\n    {\n        if (priority >= ConfigureLog::getPriorityThreshold())\n        {\n            const auto infoMessage = createFullMessage(message, line, function, file);\n\n            // std::cout\n            if (checkIfLoggingHas(LogMode::StdCout))\n                std::cout << infoMessage << std::endl;\n\n            // File logging\n            if (checkIfLoggingHas(LogMode::FileLogging))\n                fileLogging(infoMessage);\n\n            // Unity log\n            #ifdef USE_UNITY_SUPPORT\n                UnityDebugger::opLog(infoMessage);\n            #endif\n        }\n    }\n\n\n\n\n\n    namespace ConfigureError\n    {\n        // ConfigureError - Private variables\n        // std::vector<ErrorMode> sErrorModes              {ErrorMode::StdRuntimeError};\n        std::vector<ErrorMode> sErrorModes              {ErrorMode::StdCerr, ErrorMode::StdRuntimeError};\n        std::mutex sErrorModesMutex                     {};\n\n        std::vector<ErrorMode> getErrorModes()\n        {\n            const std::lock_guard<std::mutex> lock{sErrorModesMutex};\n            return sErrorModes;\n        }\n\n        void setErrorModes(const std::vector<ErrorMode>& errorModes)\n        {\n            const std::lock_guard<std::mutex> lock{sErrorModesMutex};\n            sErrorModes = errorModes;\n        }\n    }\n\n\n\n\n\n    namespace ConfigureLog\n    {\n        // ConfigureLog - Private variables\n        std::atomic<Priority> sPriorityThreshold    {Priority::High};\n        // std::atomic<Priority> sPriorityThreshold   {Priority::None};\n        std::vector<LogMode> sLoggingModes          {LogMode::StdCout};\n        // std::mutex sConfigureLogMutex              {}; // In addition, getLogModes() should return copy (no ref)\n\n        Priority getPriorityThreshold()\n        {\n            return sPriorityThreshold;\n        }\n\n        const std::vector<LogMode>& getLogModes()\n        {\n            // const std::lock_guard<std::mutex> lock{sConfigureLogMutex};\n            return sLoggingModes;\n        }\n\n        void setPriorityThreshold(const Priority priorityThreshold)\n        {\n            sPriorityThreshold = priorityThreshold;\n        }\n\n        void setLogModes(const std::vector<LogMode>& loggingModes)\n        {\n            // const std::lock_guard<std::mutex> lock{sConfigureLogMutex};\n            sLoggingModes = loggingModes;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/fileSystem.cpp",
    "content": "#include <openpose/utilities/fileSystem.hpp>\n#include <algorithm> // std::replace\n#include <cctype> // std::isdigit\n#include <cstdio> // std::fopen\n#include <cstring> // std::strncmp\n#ifdef _WIN32\n    #include <direct.h> // _mkdir\n    #include <windows.h> // DWORD, GetFileAttributesA\n#elif defined __unix__ || defined __APPLE__\n    #include <dirent.h> // opendir\n    #include <sys/stat.h> // mkdir\n#else\n    #error Unknown environment!\n#endif\n#include <openpose/utilities/string.hpp>\n\nnamespace op\n{\n    bool compareNat(const std::string& a, const std::string& b)\n    {\n        // If any is empty, that one is shorter\n        if (a.empty())\n            return true;\n        else if (b.empty())\n            return false;\n        // If one is digit, return that one\n        else if (std::isdigit(a[0]) && !std::isdigit(b[0]))\n            return true;\n        else if (!std::isdigit(a[0]) && std::isdigit(b[0]))\n            return false;\n        // If none is digit, compare those strings\n        else if (!std::isdigit(a[0]) && !std::isdigit(b[0]))\n        {\n            if (std::toupper(a[0]) == std::toupper(b[0]))\n                return compareNat(a.substr(1), b.substr(1));\n            return (std::toupper(a[0]) < std::toupper(b[0]));\n        }\n        // Both strings begin with digit\n        else\n        {\n            // Remove 0s at the beginning\n            const std::string aNo0s = remove0sFromString(a);\n            const std::string bNo0s = remove0sFromString(b);\n            // Get only number\n            const std::string aNumberAsString = getFirstNumberOnString(aNo0s);\n            const std::string bNumberAsString = getFirstNumberOnString(bNo0s);\n            // 1 number is longer --> it is bigger\n            if (aNumberAsString.size() != bNumberAsString.size())\n                return aNumberAsString.size() < bNumberAsString.size();\n            // Both same length --> Compare them\n            for (auto i = 0u ; i < aNumberAsString.size() ; ++i)\n                if (aNumberAsString[i] != bNumberAsString[i])\n                    return aNumberAsString[i] < bNumberAsString[i];\n            // Both same number --> Remove and return compareNat after removing those characters\n            const std::string aWithoutFirstNumber = aNo0s.substr(aNumberAsString.size(), aNo0s.size());\n            const std::string bWithoutFirstNumber = bNo0s.substr(bNumberAsString.size(), bNo0s.size());\n            // Number removed, compared the rest of the string\n            return compareNat(aWithoutFirstNumber, bWithoutFirstNumber);\n        }\n    }\n\n    void makeDirectory(const std::string& directoryPath)\n    {\n        try\n        {\n            if (!directoryPath.empty())\n            {\n                // Format the path first\n                const auto formatedPath = formatAsDirectory(directoryPath);\n                // Create dir if it doesn't exist yet\n                if (!existDirectory(formatedPath))\n                {\n                    #ifdef _WIN32\n                        const auto status = _mkdir(formatedPath.c_str());\n                    #elif defined __unix__ || defined __APPLE__\n                        // Create folder\n                        // Access permission - 775 (7, 7, 4+1)\n                        // https://www.gnu.org/software/libc/manual/html_node/Permission-Bits.html\n                        const auto status = mkdir(formatedPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n                    #endif\n                    // Error if folder cannot be created\n                    if (status != 0)\n                        error(\"Could not create directory: \" + formatedPath + \". Status error = \"\n                              + std::to_string(status) + \". Does the parent folder exist and/or do you have writing\"\n                              \" access to that path?\", __LINE__, __FUNCTION__, __FILE__);\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    bool existDirectory(const std::string& directoryPath)\n    {\n        try\n        {\n            // Format the path first\n            const auto formatedPath = formatAsDirectory(directoryPath);\n            #ifdef _WIN32\n                DWORD status = GetFileAttributesA(formatedPath.c_str());\n                // It is not a directory\n                if (status == INVALID_FILE_ATTRIBUTES)\n                    return false;\n                // It is a directory\n                else if (status & FILE_ATTRIBUTE_DIRECTORY)\n                    return true;\n                // It is not a directory\n                return false;    // this is not a directory!\n            #elif defined __unix__ || defined __APPLE__\n                // It is a directory\n                if (auto* directory = opendir(formatedPath.c_str()))\n                {\n                    closedir(directory);\n                    return true;\n                }\n                // It is not a directory\n                else\n                    return false;\n            #else\n                #error Unknown environment!\n            #endif\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    bool existFile(const std::string& filePath)\n    {\n        try\n        {\n            if (auto* file = fopen(filePath.c_str(), \"r\"))\n            {\n                fclose(file);\n                return true;\n            }\n            else\n                return false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    std::string formatAsDirectory(const std::string& directoryPathString)\n    {\n        try\n        {\n            std::string directoryPath = directoryPathString;\n            if (!directoryPath.empty())\n            {\n                // Replace all '\\\\' to '/'\n                std::replace(directoryPath.begin(), directoryPath.end(), '\\\\', '/');\n                if (directoryPath.back() != '/')\n                    directoryPath = directoryPath + \"/\";\n                // Windows - Replace all '/' to '\\\\'\n                #ifdef _WIN32\n                    std::replace(directoryPath.begin(), directoryPath.end(), '/', '\\\\');\n                #endif\n            }\n            return directoryPath;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFileNameAndExtension(const std::string& fullPath)\n    {\n        try\n        {\n            size_t lastSlashPos = fullPath.find_last_of(\"\\\\/\");\n            if (lastSlashPos != std::string::npos)\n                return fullPath.substr(lastSlashPos+1, fullPath.size() - lastSlashPos - 1);\n            else\n                return fullPath;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFileNameNoExtension(const std::string& fullPath)\n    {\n        try\n        {\n            // Name + extension\n            const std::string nameExt = getFileNameAndExtension(fullPath);\n            // Name\n            return getFullFilePathNoExtension(nameExt);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFileExtension(const std::string& fullPath)\n    {\n        try\n        {\n            // Name + extension\n            const std::string nameExt = getFileNameAndExtension(fullPath);\n            // Extension\n            const size_t dotPos = nameExt.find_last_of(\".\");\n            if (dotPos != std::string::npos)\n                return nameExt.substr(dotPos + 1, nameExt.size() - dotPos - 1);\n            else\n                return \"\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFullFilePathNoExtension(const std::string& fullPath)\n    {\n        try\n        {\n            // Name\n            const size_t dotPos = fullPath.find_last_of(\".\");\n            if (dotPos != std::string::npos)\n                return fullPath.substr(0, dotPos);\n            else\n                return fullPath;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFileParentFolderPath(const std::string& fullPath)\n    {\n        try\n        {\n            if (fullPath.size() > 0)\n            {\n                // Clean string\n                std::string fullPathAux = fullPath;\n                if (fullPathAux.at(fullPathAux.size() - 1) == '/'\n                        || fullPathAux.at(fullPathAux.size() - 1) == '\\\\')\n                    fullPathAux = {fullPathAux.substr(0, fullPathAux.size() - 1)};\n                // Find last `/` (Unix) or `\\` (Windows)\n                const std::size_t posFound{fullPathAux.find_last_of(\"/\\\\\")};\n                // Return substring\n                if (posFound != std::string::npos)\n                    return fullPathAux.substr(0, posFound+1);\n                else\n                    return fullPathAux;\n            }\n            else\n                return \"\";\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    // This function just removes the initial '.' in the std::string (if any)\n    // To avoid errors for not finding extensions because of comparing \".jpg\" vs \"jpg\"\n    std::string removeExtensionDot(const std::string& extension)\n    {\n        try\n        {\n            // Extension is empty\n            if (extension.empty())\n                return \"\";\n            // Return string without initial character\n            else if (*extension.cbegin() == '.')\n                return extension.substr(1, extension.size() - 1);\n            // Return string itself\n            else\n                return extension;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    bool extensionIsDesired(const std::string& extension, const std::vector<std::string>& extensions)\n    {\n        try\n        {\n            const auto cleanedExtension = toLower(removeExtensionDot(extension));\n            for (auto& extensionI : extensions)\n                if (cleanedExtension == toLower(removeExtensionDot(extensionI)))\n                    return true;\n            return false;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return false;\n        }\n    }\n\n    std::vector<std::string> getFilesOnDirectory(const std::string& directoryPath,\n                                                 const std::vector<std::string>& extensions)\n    {\n        try\n        {\n            // Format the path first\n            const auto formatedPath = formatAsDirectory(directoryPath);\n            // Check folder exits\n            if (!existDirectory(formatedPath))\n                error(\"Folder \" + formatedPath + \" does not exist.\", __LINE__, __FUNCTION__, __FILE__);\n            // Read all files in folder\n            std::vector<std::string> filePaths;\n            #ifdef _WIN32\n                auto formatedPathWindows = formatedPath;\n                formatedPathWindows.append(\"\\\\*\");\n                WIN32_FIND_DATA data;\n                HANDLE hFind;\n                if ((hFind = FindFirstFile(formatedPathWindows.c_str(), &data)) != INVALID_HANDLE_VALUE)\n                {\n                    do\n                        filePaths.emplace_back(formatedPath + data.cFileName);\n                    while (FindNextFile(hFind, &data) != 0);\n                    FindClose(hFind);\n                }\n            #elif defined __unix__ || defined __APPLE__\n                std::shared_ptr<DIR> directoryPtr(\n                    opendir(formatedPath.c_str()),\n                    [](DIR* formatedPath){ formatedPath && closedir(formatedPath); }\n                );\n                struct dirent* direntPtr;\n                while ((direntPtr = readdir(directoryPtr.get())) != nullptr)\n                {\n                    std::string currentPath = formatedPath + direntPtr->d_name;\n                    if ((strncmp(direntPtr->d_name, \".\", 1) == 0) || existDirectory(currentPath))\n                            continue;\n                    filePaths.emplace_back(currentPath);\n                }\n            #else\n                #error Unknown environment!\n            #endif\n            // Check #files > 0\n            if (filePaths.empty())\n                error(\"No files were found on \" + formatedPath, __LINE__, __FUNCTION__, __FILE__);\n            // If specific extensions specified\n            if (!extensions.empty())\n            {\n                // Read images\n                std::vector<std::string> specificExtensionPaths;\n                specificExtensionPaths.reserve(filePaths.size());\n                for (const auto& filePath : filePaths)\n                    if (extensionIsDesired(getFileExtension(filePath), extensions))\n                        specificExtensionPaths.emplace_back(filePath);\n                std::swap(filePaths, specificExtensionPaths);\n            }\n            // // Sort alphabetically\n            // std::sort(filePaths.begin(), filePaths.end());\n            // Natural sort\n            std::sort(filePaths.begin(), filePaths.end(), compareNat);\n            // Return result\n            return filePaths;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<std::string> getFilesOnDirectory(const std::string& directoryPath, const std::string& extension)\n    {\n        try\n        {\n            return getFilesOnDirectory(directoryPath, std::vector<std::string>{extension});\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::vector<std::string> getFilesOnDirectory(const std::string& directoryPath, const Extensions extensions)\n    {\n        try\n        {\n            // Get files on directory with the desired extensions\n            if (extensions == Extensions::Images)\n            {\n                const std::vector<std::string> extensionNames{\n                    // Completely supported by OpenCV\n                    \"bmp\", \"dib\", \"pbm\", \"pgm\", \"ppm\", \"sr\", \"ras\",\n                    // Most of them supported by OpenCV\n                    \"jpg\", \"jpeg\", \"png\"};\n                return getFilesOnDirectory(directoryPath, extensionNames);\n            }\n            // Unknown kind of extensions\n            else\n            {\n                error(\"Unknown kind of extensions (id = \" + std::to_string(int(extensions))\n                      + \"). Notify us of this error.\", __LINE__, __FUNCTION__, __FILE__);\n                return {};\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::string removeSpecialsCharacters(const std::string& stringToVariate)\n    {\n        try\n        {\n            auto result(stringToVariate);\n\n            auto i = 0u;\n            auto len = result.length();\n            while (i < len)\n            {\n                const char c=result.at(i);\n                if (((c>='0')&&(c<='9'))||((c>='A')&&(c<='Z'))||((c>='a')&&(c<='z')))\n                {\n                    // Assuming dictionary contains small letters only.\n                    if ((c>='A')&&(c<='Z')) result.at(i) += 32;\n                        ++i;\n                }\n                else\n                {\n                    result.erase(i,1);\n                    --len;\n                }\n            }\n\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    void removeAllOcurrencesOfSubString(std::string& stringToModify, const std::string& substring)\n    {\n        try\n        {\n            auto pos(stringToModify.find(substring));\n            while (pos != std::string::npos)\n            {\n                stringToModify.erase(pos, substring.size());\n                pos = {stringToModify.find(substring)};\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void replaceAll(std::string& stringText, const char charToChange, const char charToAdd)\n    {\n        try\n        {\n            // replace all charToChange to charToAdd\n            std::replace( stringText.begin(), stringText.end(), charToChange, charToAdd);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/flagsToOpenPose.cpp",
    "content": "#include <openpose/utilities/flagsToOpenPose.hpp>\n#include <cstdio> // sscanf\n#include <openpose/utilities/check.hpp>\n\nnamespace op\n{\n    PoseMode flagsToPoseMode(const int poseModeInt)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            if (poseModeInt >= 0 && poseModeInt < (int)PoseMode::Size)\n                return (PoseMode)poseModeInt;\n            else\n            {\n                error(\"Value (\" + std::to_string(poseModeInt) + \") does not correspond with any PoseMode.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n                return PoseMode::Enabled;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return PoseMode::Enabled;\n        }\n    }\n\n    PoseModel flagsToPoseModel(const String& poseModeString)\n    {\n        try\n        {\n            const std::string& poseModeStdString = poseModeString.getStdString();\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            // Body pose\n            if (poseModeStdString == \"BODY_25\")\n                return PoseModel::BODY_25;\n            else if (poseModeStdString == \"COCO\")\n                return PoseModel::COCO_18;\n            else if (poseModeStdString == \"MPI\")\n                return PoseModel::MPI_15;\n            else if (poseModeStdString == \"MPI_4_layers\")\n                return PoseModel::MPI_15_4;\n            else if (poseModeStdString == \"BODY_19\")\n                return PoseModel::BODY_19;\n            else if (poseModeStdString == \"BODY_19E\")\n                return PoseModel::BODY_19E;\n            else if (poseModeStdString == \"BODY_19N\")\n                return PoseModel::BODY_19N;\n            else if (poseModeStdString == \"BODY_19_X2\")\n                return PoseModel::BODY_19_X2;\n            else if (poseModeStdString == \"BODY_23\")\n                return PoseModel::BODY_23;\n            else if (poseModeStdString == \"BODY_25B\")\n                return PoseModel::BODY_25B;\n            else if (poseModeStdString == \"BODY_25D\")\n                return PoseModel::BODY_25D;\n            else if (poseModeStdString == \"BODY_25E\")\n                return PoseModel::BODY_25E;\n            else if (poseModeStdString == \"BODY_135\")\n                return PoseModel::BODY_135;\n            // Car pose\n            else if (poseModeStdString == \"CAR_12\")\n                return PoseModel::CAR_12;\n            else if (poseModeStdString == \"CAR_22\")\n                return PoseModel::CAR_22;\n            // else\n            error(\"String (`\" + poseModeStdString + \"`) does not correspond to any model (BODY_25, COCO, MPI,\"\n                  \" MPI_4_layers).\", __LINE__, __FUNCTION__, __FILE__);\n            return PoseModel::BODY_25;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return PoseModel::BODY_25;\n        }\n    }\n\n    ScaleMode flagsToScaleMode(const int keypointScaleMode)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            if (keypointScaleMode == 0)\n                return ScaleMode::InputResolution;\n            else if (keypointScaleMode == 1)\n                return ScaleMode::NetOutputResolution;\n            else if (keypointScaleMode == 2)\n                return ScaleMode::OutputResolution;\n            else if (keypointScaleMode == 3)\n                return ScaleMode::ZeroToOne;\n            else if (keypointScaleMode == 4)\n                return ScaleMode::PlusMinusOne;\n            else if (keypointScaleMode == 5)\n                return ScaleMode::ZeroToOneFixedAspect;\n            else if (keypointScaleMode == 6)\n                return ScaleMode::PlusMinusOneFixedAspect;\n            // else\n            const std::string message = \"Integer does not correspond to any scale mode: set to (0, 1, 2, 3, 4, 5, 6)\"\n                                        \" for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne,\"\n                                        \" PlusMinusOne, ZeroToOneFixedAspect, PlusMinusOneFixedAspect),\"\n                                        \" respectively.\";\n            error(message, __LINE__, __FUNCTION__, __FILE__);\n            return ScaleMode::InputResolution;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return ScaleMode::InputResolution;\n        }\n    }\n\n    ScaleMode flagsToHeatMapScaleMode(const int heatMapScaleMode)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            if (heatMapScaleMode == 0)\n                return ScaleMode::PlusMinusOne;\n            else if (heatMapScaleMode == 1)\n                return ScaleMode::ZeroToOne;\n            else if (heatMapScaleMode == 2)\n                return ScaleMode::UnsignedChar;\n            else if (heatMapScaleMode == 3)\n                return ScaleMode::NoScale;\n            else if (heatMapScaleMode == 4)\n                return ScaleMode::ZeroToOneFixedAspect;\n            else if (heatMapScaleMode == 5)\n                return ScaleMode::PlusMinusOneFixedAspect;\n            // else\n            const std::string message = \"Integer does not correspond to any scale mode: set to (0, 1, 2, 3, 4, 5)\"\n                                        \" for (PlusMinusOne, ZeroToOne, UnsignedChar, NoScale, PlusMinusOneFixedAspect,\"\n                                        \" ZeroToOneFixedAspect), respectively.\";\n            error(message, __LINE__, __FUNCTION__, __FILE__);\n            return ScaleMode::PlusMinusOneFixedAspect;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return ScaleMode::PlusMinusOneFixedAspect;\n        }\n    }\n\n    Detector flagsToDetector(const int detector)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            if (detector >= 0 && detector < (int)Detector::Size)\n                return (Detector)detector;\n            else\n            {\n                error(\"Value (\" + std::to_string(detector) + \") does not correspond with any Detector.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n                return Detector::Body;\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Detector::Body;\n        }\n    }\n\n    ProducerType flagsToProducerType(\n        const String& imageDirectory, const String& videoPath, const String& ipCameraPath,\n        const int webcamIndex, const bool flirCamera)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const std::string& imageDirectoryStd = imageDirectory.getStdString();\n            const std::string& videoPathStd = videoPath.getStdString();\n            const std::string& ipCameraPathStd = ipCameraPath.getStdString();\n            // Avoid duplicates (e.g., selecting at the time camera & video)\n            if (int(!imageDirectoryStd.empty()) + int(!videoPathStd.empty()) + int(webcamIndex > 0)\n                + int(flirCamera) + int(!ipCameraPathStd.empty()) > 1)\n                error(\"Selected simultaneously\"\n                      \" image directory (seletected: \" + (imageDirectoryStd.empty() ? \"no\" : imageDirectoryStd) + \"),\"\n                      \" video (seletected: \" + (videoPathStd.empty() ? \"no\" : videoPathStd) + \"),\"\n                      \" camera (selected: \" + (webcamIndex > 0 ? std::to_string(webcamIndex) : \"no\") + \"),\"\n                      \" flirCamera (selected: \" + (flirCamera ? \"yes\" : \"no\") + \",\"\n                      \" and/or IP camera (selected: \" + (ipCameraPathStd.empty() ? \"no\" : ipCameraPathStd) + \").\"\n                      \" Please, select only one.\", __LINE__, __FUNCTION__, __FILE__);\n\n            // Get desired ProducerType\n            if (!imageDirectoryStd.empty())\n                return ProducerType::ImageDirectory;\n            else if (!videoPathStd.empty())\n                return ProducerType::Video;\n            else if (!ipCameraPathStd.empty())\n                return ProducerType::IPCamera;\n            else if (flirCamera)\n                return ProducerType::FlirCamera;\n            else\n                return ProducerType::Webcam;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return ProducerType::Webcam;\n        }\n    }\n\n    std::pair<ProducerType, String> flagsToProducer(\n        const String& imageDirectory, const String& videoPath, const String& ipCameraPath,\n        const int webcamIndex, const bool flirCamera, const int flirCameraIndex)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n            const auto type = flagsToProducerType(\n                imageDirectory, videoPath, ipCameraPath, webcamIndex, flirCamera);\n\n            if (type == ProducerType::ImageDirectory)\n                return std::make_pair(ProducerType::ImageDirectory, imageDirectory);\n            else if (type == ProducerType::Video)\n                return std::make_pair(ProducerType::Video, videoPath);\n            else if (type == ProducerType::IPCamera)\n                return std::make_pair(ProducerType::IPCamera, ipCameraPath);\n            // Flir camera\n            else if (type == ProducerType::FlirCamera)\n                return std::make_pair(ProducerType::FlirCamera, String(std::to_string(flirCameraIndex)));\n            // Webcam\n            else if (type == ProducerType::Webcam)\n                return std::make_pair(ProducerType::Webcam, String(std::to_string(webcamIndex)));\n            // else\n            error(\"Undefined Producer selected.\", __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(ProducerType::None, \"\");\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::make_pair(ProducerType::None, \"\");\n        }\n    }\n\n    std::vector<HeatMapType> flagsToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg,\n                                             const bool heatMapsAddPAFs)\n    {\n        try\n        {\n            std::vector<HeatMapType> heatMapTypes;\n            if (heatMapsAddParts)\n                heatMapTypes.emplace_back(HeatMapType::Parts);\n            if (heatMapsAddBkg)\n                heatMapTypes.emplace_back(HeatMapType::Background);\n            if (heatMapsAddPAFs)\n                heatMapTypes.emplace_back(HeatMapType::PAFs);\n            return heatMapTypes;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    RenderMode flagsToRenderMode(const int renderFlag, const bool gpuBuggy, const int renderPoseFlag)\n    {\n        try\n        {\n            // Body: to auto-pick CPU/GPU depending on CPU_ONLY/CUDA\n            // Auto auto-picks CPU/CUDA depending on the compiled version (CPU_ONLY/CUDA)\n            if (renderFlag == -1 && renderPoseFlag == -2)\n                return (gpuBuggy ? RenderMode::Cpu : RenderMode::Auto);\n            // Face and hand: to pick same than body\n            else if (renderFlag == -1 && renderPoseFlag != -2)\n                return flagsToRenderMode(renderPoseFlag, gpuBuggy, -2);\n            // No render\n            else if (renderFlag == 0)\n                return RenderMode::None;\n            // CPU render\n            else if (renderFlag == 1)\n                return RenderMode::Cpu;\n            // GPU render\n            else if (renderFlag == 2)\n                return RenderMode::Gpu;\n            // else\n            error(\"Undefined RenderMode selected.\", __LINE__, __FUNCTION__, __FILE__);\n            return RenderMode::None;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return RenderMode::None;\n        }\n    }\n\n    DisplayMode flagsToDisplayMode(const int display, const bool enabled3d)\n    {\n        try\n        {\n            // Automatic --> All if 3d enabled, 2d otherwise\n            if (display == -1)\n            {\n                if (enabled3d)\n                    return DisplayMode::DisplayAll;\n                else\n                    return DisplayMode::Display2D;\n            }\n            // No render\n            else if (display == 0)\n                return DisplayMode::NoDisplay;\n            // All (2-D + 3-D)\n            else if (display == 1)\n                return DisplayMode::DisplayAll;\n            // 2-D\n            else if (display == 2)\n                return DisplayMode::Display2D;\n            // 3-D\n            else if (display == 3)\n                return DisplayMode::Display3D;\n            // else\n            error(\"Undefined RenderMode selected.\", __LINE__, __FUNCTION__, __FILE__);\n            return DisplayMode::NoDisplay;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return DisplayMode::NoDisplay;\n        }\n    }\n\n    Point<int> flagsToPoint(const String& pointString, const String& pointExample)\n    {\n        try\n        {\n            const std::string& pointStringStd = pointString.getStdString();\n            const std::string& pointExampleStd = pointExample.getStdString();\n            Point<int> point;\n            const auto nRead = sscanf(pointStringStd.c_str(), \"%dx%d\", &point.x, &point.y);\n            checkEqual(\n                nRead, 2, \"Invalid resolution format: `\" +  pointStringStd + \"`, it should be e.g., `\"\n                + pointExampleStd + \"`.\", __LINE__, __FUNCTION__, __FILE__);\n            return point;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Point<int>{};\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/keypoint.cpp",
    "content": "#include <openpose/utilities/keypoint.hpp>\n#include <limits> // std::numeric_limits\n#include <opencv2/imgproc/imgproc.hpp> // cv::line, cv::circle\n#include <openpose/utilities/fastMath.hpp>\n\nnamespace op\n{\n    const std::string errorMessage = \"The Array<T> is not a RGB image or 3-channel keypoint array. This function\"\n                                     \" is only for array of dimension: [sizeA x sizeB x 3].\";\n\n    template <typename T>\n    T getDistance(const Array<T>& keypoints, const int person, const int elementA, const int elementB)\n    {\n        try\n        {\n            const auto keypointPtr = keypoints.getConstPtr() + person * keypoints.getSize(1) * keypoints.getSize(2);\n            const auto pixelX = keypointPtr[elementA*3] - keypointPtr[elementB*3];\n            const auto pixelY = keypointPtr[elementA*3+1] - keypointPtr[elementB*3+1];\n            return std::sqrt(pixelX*pixelX+pixelY*pixelY);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(-1);\n        }\n    }\n    template OP_API float getDistance(\n        const Array<float>& keypoints, const int person, const int elementA, const int elementB);\n    template OP_API double getDistance(\n        const Array<double>& keypoints, const int person, const int elementA, const int elementB);\n\n    template <typename T>\n    void averageKeypoints(Array<T>& keypointsA, const Array<T>& keypointsB, const int personA)\n    {\n        try\n        {\n            // Sanity checks\n            if (keypointsA.getNumberDimensions() != keypointsB.getNumberDimensions())\n                error(\"keypointsA.getNumberDimensions() != keypointsB.getNumberDimensions().\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            for (auto dimension = 1u ; dimension < keypointsA.getNumberDimensions() ; dimension++)\n                if (keypointsA.getSize(dimension) != keypointsB.getSize(dimension))\n                    error(\"keypointsA.getSize() != keypointsB.getSize().\", __LINE__, __FUNCTION__, __FILE__);\n            // For each body part\n            const auto numberParts = keypointsA.getSize(1);\n            for (auto part = 0 ; part < numberParts ; part++)\n            {\n                const auto finalIndexA = keypointsA.getSize(2)*(personA*numberParts + part);\n                const auto finalIndexB = keypointsA.getSize(2)*part;\n                if (keypointsB[finalIndexB+2] - keypointsA[finalIndexA+2] > T(0.05))\n                {\n                    keypointsA[finalIndexA] = keypointsB[finalIndexB];\n                    keypointsA[finalIndexA+1] = keypointsB[finalIndexB+1];\n                    keypointsA[finalIndexA+2] = keypointsB[finalIndexB+2];\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n    template OP_API void averageKeypoints(\n        Array<float>& keypointsA, const Array<float>& keypointsB, const int personA);\n    template OP_API void averageKeypoints(\n        Array<double>& keypointsA, const Array<double>& keypointsB, const int personA);\n\n    template <typename T>\n    void scaleKeypoints(Array<T>& keypoints, const T scale)\n    {\n        try\n        {\n            if (!keypoints.empty() && scale != T(1))\n            {\n                // Error check\n                if (keypoints.getSize(2) != 3 && keypoints.getSize(2) != 4)\n                    error(\"The Array<T> is not a (x,y,score) or (x,y,z,score) format array. This\"\n                          \" function is only for those 2 dimensions: [sizeA x sizeB x 3or4].\",\n                          __LINE__, __FUNCTION__, __FILE__);\n                // Get #people and #parts\n                const auto numberPeople = keypoints.getSize(0);\n                const auto numberParts = keypoints.getSize(1);\n                const auto xyzChannels = keypoints.getSize(2);\n                // For each person\n                for (auto person = 0 ; person < numberPeople ; person++)\n                {\n                    // For each body part\n                    for (auto part = 0 ; part < numberParts ; part++)\n                    {\n                        const auto finalIndex = xyzChannels*(person*numberParts + part);\n                        for (auto xyz = 0 ; xyz < xyzChannels-1 ; xyz++)\n                            keypoints[finalIndex+xyz] *= scale;\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n    template OP_API void scaleKeypoints(Array<float>& keypoints, const float scale);\n    template OP_API void scaleKeypoints(Array<double>& keypoints, const double scale);\n\n    template <typename T>\n    void scaleKeypoints2d(Array<T>& keypoints, const T scaleX, const T scaleY)\n    {\n        try\n        {\n            if (!keypoints.empty() && (scaleX != T(1) || scaleY != T(1)))\n            {\n                // Error check\n                if (keypoints.getSize(2) != 3)\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                // Get #people and #parts\n                const auto numberPeople = keypoints.getSize(0);\n                const auto numberParts = keypoints.getSize(1);\n                // For each person\n                for (auto person = 0 ; person < numberPeople ; person++)\n                {\n                    // For each body part\n                    for (auto part = 0 ; part < numberParts ; part++)\n                    {\n                        const auto finalIndex = 3*(person*numberParts + part);\n                        keypoints[finalIndex] *= scaleX;\n                        keypoints[finalIndex+1] *= scaleY;\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n    template OP_API void scaleKeypoints2d(Array<float>& keypoints, const float scaleX, const float scaleY);\n    template OP_API void scaleKeypoints2d(Array<double>& keypoints, const double scaleX, const double scaleY);\n\n    template <typename T>\n    void scaleKeypoints2d(Array<T>& keypoints, const T scaleX, const T scaleY, const T offsetX, const T offsetY)\n    {\n        try\n        {\n            if (!keypoints.empty() && (scaleX != T(1) || scaleY != T(1) || offsetX != T(0) || offsetY != T(0)))\n            {\n                // Error check\n                if (keypoints.getSize(2) != 3)\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                // Get #people and #parts\n                const auto numberPeople = keypoints.getSize(0);\n                const auto numberParts = keypoints.getSize(1);\n                // For each person\n                for (auto person = 0 ; person < numberPeople ; person++)\n                {\n                    // For each body part\n                    for (auto part = 0 ; part < numberParts ; part++)\n                    {\n                        const auto finalIndex = keypoints.getSize(2)*(person*numberParts + part);\n                        keypoints[finalIndex] = keypoints[finalIndex] * scaleX + offsetX;\n                        keypoints[finalIndex+1] = keypoints[finalIndex+1] * scaleY + offsetY;\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n    template OP_API void scaleKeypoints2d(\n        Array<float>& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY);\n    template OP_API void scaleKeypoints2d(\n        Array<double>& keypoints, const double scaleX, const double scaleY, const double offsetX,\n        const double offsetY);\n\n    template <typename T>\n    void renderKeypointsCpu(\n        Array<T>& frameArray, const Array<T>& keypoints, const std::vector<unsigned int>& pairs,\n        const std::vector<T> colors, const T thicknessCircleRatio, const T thicknessLineRatioWRTCircle,\n        const std::vector<T>& poseScales, const T threshold)\n    {\n        try\n        {\n            if (!frameArray.empty())\n            {\n                // Array<T> --> cv::Mat\n                auto frame = frameArray.getCvMat();\n                cv::Mat cvFrame = OP_OP2CVMAT(frame);\n\n                // Sanity check\n                if (cvFrame.channels() != 3)\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n\n                // Get frame channels\n                const auto width = cvFrame.size[1];\n                const auto height = cvFrame.size[0];\n                const auto area = width * height;\n                cv::Mat frameBGR(height, width, CV_32FC3, cvFrame.data);\n\n                // Parameters\n                const auto lineType = 8;\n                const auto shift = 0;\n                const auto numberColors = colors.size();\n                const auto numberScales = poseScales.size();\n                const auto thresholdRectangle = T(0.1);\n                const auto numberKeypoints = keypoints.getSize(1);\n\n                // Keypoints\n                for (auto person = 0 ; person < keypoints.getSize(0) ; person++)\n                {\n                    const auto personRectangle = getKeypointsRectangle(keypoints, person, thresholdRectangle);\n                    if (personRectangle.area() > 0)\n                    {\n                        const auto ratioAreas = fastMin(\n                            T(1), fastMax(\n                                personRectangle.width/(T)width, personRectangle.height/(T)height));\n                        // Size-dependent variables\n                        const auto thicknessRatio = fastMax(\n                            positiveIntRound(std::sqrt(area)* thicknessCircleRatio * ratioAreas), 2);\n                        // Negative thickness in cv::circle means that a filled circle is to be drawn.\n                        const auto thicknessCircle = fastMax(1, (ratioAreas > T(0.05) ? thicknessRatio : -1));\n                        const auto thicknessLine = fastMax(\n                            1, positiveIntRound(thicknessRatio * thicknessLineRatioWRTCircle));\n                        const auto radius = thicknessRatio / 2;\n\n                        // Draw lines\n                        for (auto pair = 0u ; pair < pairs.size() ; pair+=2)\n                        {\n                            const auto index1 = (person * numberKeypoints + pairs[pair]) * keypoints.getSize(2);\n                            const auto index2 = (person * numberKeypoints + pairs[pair+1]) * keypoints.getSize(2);\n                            if (keypoints[index1+2] > threshold && keypoints[index2+2] > threshold)\n                            {\n                                const auto thicknessLineScaled = positiveIntRound(\n                                    thicknessLine * poseScales[pairs[pair+1] % numberScales]);\n                                const auto colorIndex = pairs[pair+1]*3; // Before: colorIndex = pair/2*3;\n                                const cv::Scalar color{\n                                    colors[(colorIndex+2) % numberColors],\n                                    colors[(colorIndex+1) % numberColors],\n                                    colors[colorIndex % numberColors]\n                                };\n                                const cv::Point keypoint1{\n                                    positiveIntRound(keypoints[index1]), positiveIntRound(keypoints[index1+1])};\n                                const cv::Point keypoint2{\n                                    positiveIntRound(keypoints[index2]), positiveIntRound(keypoints[index2+1])};\n                                cv::line(frameBGR, keypoint1, keypoint2, color, thicknessLineScaled, lineType, shift);\n                            }\n                        }\n\n                        // Draw circles\n                        for (auto part = 0 ; part < numberKeypoints ; part++)\n                        {\n                            const auto faceIndex = (person * numberKeypoints + part) * keypoints.getSize(2);\n                            if (keypoints[faceIndex+2] > threshold)\n                            {\n                                const auto radiusScaled = positiveIntRound(radius * poseScales[part % numberScales]);\n                                const auto thicknessCircleScaled = positiveIntRound(\n                                    thicknessCircle * poseScales[part % numberScales]);\n                                const auto colorIndex = part*3;\n                                const cv::Scalar color{\n                                    colors[(colorIndex+2) % numberColors],\n                                    colors[(colorIndex+1) % numberColors],\n                                    colors[colorIndex % numberColors]\n                                };\n                                const cv::Point center{positiveIntRound(keypoints[faceIndex]),\n                                                       positiveIntRound(keypoints[faceIndex+1])};\n                                cv::circle(frameBGR, center, radiusScaled, color, thicknessCircleScaled, lineType,\n                                           shift);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n    template OP_API void renderKeypointsCpu(\n        Array<float>& frameArray, const Array<float>& keypoints, const std::vector<unsigned int>& pairs,\n        const std::vector<float> colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle,\n        const std::vector<float>& poseScales, const float threshold);\n    template OP_API void renderKeypointsCpu(\n        Array<double>& frameArray, const Array<double>& keypoints, const std::vector<unsigned int>& pairs,\n        const std::vector<double> colors, const double thicknessCircleRatio, const double thicknessLineRatioWRTCircle,\n        const std::vector<double>& poseScales, const double threshold);\n\n    template <typename T>\n    Rectangle<T> getKeypointsRectangle(\n        const Array<T>& keypoints, const int person, const T threshold, const int firstIndex, const int lastIndex)\n    {\n        try\n        {\n            // Params\n            const auto numberKeypoints = keypoints.getSize(1);\n            const auto lastIndexClean = (lastIndex < 0 ? numberKeypoints : lastIndex);\n            // Sanity checks\n            if (numberKeypoints < 1)\n                error(\"Number body parts must be > 0.\", __LINE__, __FUNCTION__, __FILE__);\n            if (lastIndexClean > numberKeypoints)\n                error(\"The value of `lastIndex` must be less or equal than `numberKeypoints`. Currently: \"\n                    + std::to_string(lastIndexClean) + \" vs. \" + std::to_string(numberKeypoints),\n                    __LINE__, __FUNCTION__, __FILE__);\n            if (firstIndex > lastIndexClean)\n                error(\"The value of `firstIndex` must be less or equal than `lastIndex`. Currently: \"\n                    + std::to_string(firstIndex) + \" vs. \" + std::to_string(lastIndex),\n                    __LINE__, __FUNCTION__, __FILE__);\n            // Define keypointPtr\n            const auto keypointPtr = keypoints.getConstPtr() + person * keypoints.getSize(1) * keypoints.getSize(2);\n            T minX = std::numeric_limits<T>::max();\n            T maxX = std::numeric_limits<T>::lowest();\n            T minY = minX;\n            T maxY = maxX;\n            for (auto part = firstIndex ; part < lastIndexClean ; part++)\n            {\n                const auto score = keypointPtr[3*part + 2];\n                if (score > threshold)\n                {\n                    const auto x = keypointPtr[3*part];\n                    const auto y = keypointPtr[3*part + 1];\n                    // Set X\n                    if (maxX < x)\n                        maxX = x;\n                    if (minX > x)\n                        minX = x;\n                    // Set Y\n                    if (maxY < y)\n                        maxY = y;\n                    if (minY > y)\n                        minY = y;\n                }\n            }\n            if (maxX >= minX && maxY >= minY)\n                return Rectangle<T>{minX, minY, maxX-minX, maxY-minY};\n            else\n                return Rectangle<T>{};\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Rectangle<T>{};\n        }\n    }\n    template OP_API Rectangle<float> getKeypointsRectangle(\n        const Array<float>& keypoints, const int person, const float threshold, const int firstIndex,\n        const int lastIndex);\n    template OP_API Rectangle<double> getKeypointsRectangle(\n        const Array<double>& keypoints, const int person, const double threshold, const int firstIndex,\n        const int lastIndex);\n\n    template <typename T>\n    T getAverageScore(const Array<T>& keypoints, const int person)\n    {\n        try\n        {\n            // Sanity check\n            if (person >= keypoints.getSize(0))\n                error(\"Person index out of bounds.\", __LINE__, __FUNCTION__, __FILE__);\n            // Get average score\n            T score = T(0);\n            const auto numberKeypoints = keypoints.getSize(1);\n            const auto area = numberKeypoints * keypoints.getSize(2);\n            const auto personOffset = person * area;\n            for (auto part = 0 ; part < numberKeypoints ; part++)\n                score += keypoints[personOffset + part*keypoints.getSize(2) + 2];\n            return score / numberKeypoints;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(0);\n        }\n    }\n    template OP_API float getAverageScore(const Array<float>& keypoints, const int person);\n    template OP_API double getAverageScore(const Array<double>& keypoints, const int person);\n\n    template <typename T>\n    T getKeypointsArea(const Array<T>& keypoints, const int person, const T threshold)\n    {\n        try\n        {\n            return getKeypointsRectangle(keypoints, person, threshold).area();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(0);\n        }\n    }\n    template OP_API float getKeypointsArea(const Array<float>& keypoints, const int person, const float threshold);\n    template OP_API double getKeypointsArea(const Array<double>& keypoints, const int person, const double threshold);\n\n    template <typename T>\n    int getBiggestPerson(const Array<T>& keypoints, const T threshold)\n    {\n        try\n        {\n            if (!keypoints.empty())\n            {\n                const auto numberPeople = keypoints.getSize(0);\n                auto biggestPoseIndex = -1;\n                auto biggestArea = T(-1);\n                for (auto person = 0 ; person < numberPeople ; person++)\n                {\n                    const auto newPersonArea = getKeypointsArea(keypoints, person, threshold);\n                    if (newPersonArea > biggestArea)\n                    {\n                        biggestArea = newPersonArea;\n                        biggestPoseIndex = person;\n                    }\n                }\n                return biggestPoseIndex;\n            }\n            else\n                return -1;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n    template OP_API int getBiggestPerson(const Array<float>& keypoints, const float threshold);\n    template OP_API int getBiggestPerson(const Array<double>& keypoints, const double threshold);\n\n    template <typename T>\n    int getNonZeroKeypoints(const Array<T>& keypoints, const int person, const T threshold)\n    {\n        try\n        {\n            if (!keypoints.empty())\n            {\n                // Sanity check\n                if (keypoints.getSize(0) <= person)\n                    error(\"Person index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n                // Count keypoints\n                auto nonZeroCounter = 0;\n                const auto baseIndex = person * (int)keypoints.getVolume(1,2);\n                for (auto part = 0 ; part < keypoints.getSize(1) ; part++)\n                    if (keypoints[baseIndex + 3*part + 2] >= threshold)\n                        nonZeroCounter++;\n                return nonZeroCounter;\n            }\n            else\n                return 0;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0;\n        }\n    }\n    template OP_API int getNonZeroKeypoints(const Array<float>& keypoints, const int person, const float threshold);\n    template OP_API int getNonZeroKeypoints(const Array<double>& keypoints, const int person, const double threshold);\n\n    template <typename T>\n    T getDistanceAverage(const Array<T>& keypoints, const int personA, const int personB, const T threshold)\n    {\n        try\n        {\n            return getDistanceAverage(keypoints, personA, keypoints, personB, threshold);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(0);\n        }\n    }\n    template OP_API float getDistanceAverage(\n        const Array<float>& keypoints, const int personA, const int personB, const float threshold);\n    template OP_API double getDistanceAverage(\n        const Array<double>& keypoints, const int personA, const int personB, const double threshold);\n\n    template <typename T>\n    T getDistanceAverage(const Array<T>& keypointsA, const int personA, const Array<T>& keypointsB, const int personB,\n                         const T threshold)\n    {\n        try\n        {\n            // Sanity checks\n            if (keypointsA.getSize(0) <= personA)\n                error(\"PersonA index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n            if (keypointsB.getSize(0) <= personB)\n                error(\"PersonB index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n            if (keypointsA.getSize(1) != keypointsB.getSize(1))\n                error(\"Keypoints should have the same number of keypoints.\", __LINE__, __FUNCTION__, __FILE__);\n            // Get total distance\n            T totalDistance = 0;\n            int nonZeroCounter = 0;\n            const auto baseIndexA = personA * (int)keypointsA.getVolume(1,2);\n            const auto baseIndexB = personB * (int)keypointsB.getVolume(1,2);\n            for (auto part = 0 ; part < keypointsA.getSize(1) ; part++)\n            {\n                if (keypointsA[baseIndexA+3*part+2] >= threshold && keypointsB[baseIndexB+3*part+2] >= threshold)\n                {\n                    const auto x = keypointsA[baseIndexA+3*part] - keypointsB[baseIndexB+3*part];\n                    const auto y = keypointsA[baseIndexA+3*part+1] - keypointsB[baseIndexB+3*part+1];\n                    totalDistance += T(std::sqrt(x*x+y*y));\n                    nonZeroCounter++;\n                }\n            }\n            // Get distance average\n            return totalDistance / nonZeroCounter;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return T(0);\n        }\n    }\n    template OP_API float getDistanceAverage(\n        const Array<float>& keypointsA, const int personA, const Array<float>& keypointsB, const int personB,\n        const float threshold);\n    template OP_API double getDistanceAverage(\n        const Array<double>& keypointsA, const int personA, const Array<double>& keypointsB, const int personB,\n        const double threshold);\n\n    template <typename T>\n    Array<T> getKeypointsPerson(const Array<T>& keypoints, const int person, const bool noCopy)\n    {\n        try\n        {\n            return Array<T>(keypoints, person, noCopy);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return Array<T>{};\n        }\n    }\n    template OP_API Array<float> getKeypointsPerson(\n        const Array<float>& keypoints, const int person, const bool noCopy);\n    template OP_API Array<double> getKeypointsPerson(\n        const Array<double>& keypoints, const int person, const bool noCopy);\n\n    template <typename T>\n    float getKeypointsRoi(const Array<T>& keypoints, const int personA, const int personB, const T threshold)\n    {\n        try\n        {\n            return getKeypointsRoi(keypoints, personA, keypoints, personB, threshold);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n    template OP_API float getKeypointsRoi(\n        const Array<float>& keypoints, const int personA, const int personB, const float threshold);\n    template OP_API float getKeypointsRoi(\n        const Array<double>& keypoints, const int personA, const int personB, const double threshold);\n\n    template <typename T>\n    float getKeypointsRoi(\n        const Array<T>& keypointsA, const int personA, const Array<T>& keypointsB, const int personB,\n        const T threshold)\n    {\n        try\n        {\n            // Sanity checks\n            if (keypointsA.getSize(0) <= personA)\n                error(\"PersonA index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n            if (keypointsB.getSize(0) <= personB)\n                error(\"PersonB index out of range.\", __LINE__, __FUNCTION__, __FILE__);\n            if (keypointsA.getSize(1) != keypointsB.getSize(1))\n                error(\"Keypoints should have the same number of keypoints.\", __LINE__, __FUNCTION__, __FILE__);\n            // Get ROI\n            const auto rectangleA = getKeypointsRectangle(keypointsA, personA, threshold);\n            const auto rectangleB = getKeypointsRectangle(keypointsB, personB, threshold);\n            return getKeypointsRoi(rectangleA, rectangleB);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n    template OP_API float getKeypointsRoi(\n        const Array<float>& keypointsA, const int personA, const Array<float>& keypointsB, const int personB,\n        const float threshold);\n    template OP_API float getKeypointsRoi(\n        const Array<double>& keypointsA, const int personA, const Array<double>& keypointsB, const int personB,\n        const double threshold);\n\n    template <typename T>\n    float getKeypointsRoi(const Rectangle<T>& rectangleA, const Rectangle<T>& rectangleB)\n    {\n        try\n        {\n            // Check if negative values, then normalize it\n            auto rectangleANorm = rectangleA;\n            auto rectangleBNorm = rectangleB;\n            // E.g., [-10,-10,W1,H1] and [-20,-20,W2,H2] should be equivalent to [10,10,W1,H1] and [0,0,W2,H2]\n            const auto biasX = std::min(std::min(T{0}, rectangleA.x), rectangleB.x);\n            if (biasX != 0)\n            {\n                rectangleANorm.x -= biasX;\n                rectangleBNorm.x -= biasX;\n            }\n            const auto biasY = std::min(std::min(T{0}, rectangleA.y), rectangleB.y);\n            if (biasY != 0)\n            {\n                rectangleANorm.y -= biasY;\n                rectangleBNorm.y -= biasY;\n            }\n            // Get ROI\n            const Point<T> pointAIntersection{\n                fastMax(rectangleANorm.x, rectangleBNorm.x),\n                fastMax(rectangleANorm.y, rectangleBNorm.y)\n            };\n            const Point<T> pointBIntersection{\n                fastMin(rectangleANorm.x+rectangleANorm.width, rectangleBNorm.x+rectangleBNorm.width),\n                fastMin(rectangleANorm.y+rectangleANorm.height, rectangleBNorm.y+rectangleBNorm.height)\n            };\n            // Make sure there is overlap\n            if (pointAIntersection.x < pointBIntersection.x && pointAIntersection.y < pointBIntersection.y)\n            {\n                const Rectangle<T> rectangleIntersection{\n                    pointAIntersection.x,\n                    pointAIntersection.y,\n                    pointBIntersection.x-pointAIntersection.x,\n                    pointBIntersection.y-pointAIntersection.y\n                };\n                const auto areaA = rectangleANorm.area();\n                const auto areaB = rectangleBNorm.area();\n                const auto intersection = rectangleIntersection.area();\n                return float(intersection) / float(areaA + areaB - intersection);\n            }\n            // If non overlap --> Return 0\n            else\n                return 0.f;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.f;\n        }\n    }\n    template OP_API float getKeypointsRoi(\n        const Rectangle<int>& rectangleA, const Rectangle<int>& rectangleB);\n    template OP_API float getKeypointsRoi(\n        const Rectangle<unsigned int>& rectangleA, const Rectangle<unsigned int>& rectangleB);\n    template OP_API float getKeypointsRoi(\n        const Rectangle<float>& rectangleA, const Rectangle<float>& rectangleB);\n    template OP_API float getKeypointsRoi(\n        const Rectangle<double>& rectangleA, const Rectangle<double>& rectangleB);\n}\n"
  },
  {
    "path": "src/openpose/utilities/openCv.cpp",
    "content": "#include <openpose/utilities/openCv.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/utilities/avx.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    void unrollArrayToUCharCvMat(Matrix& matResult, const Array<float>& array)\n    {\n        try\n        {\n            if (array.getNumberDimensions() != 3)\n                error(\"Only implemented for array.getNumberDimensions() == 3 so far.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n\n            if (!array.empty())\n            {\n                const auto channels = array.getSize(0);\n                const auto height = array.getSize(1);\n                const auto width = array.getSize(2);\n                const auto areaInput = height * width;\n                const auto areaOutput = channels * width;\n                // Allocate cv::Mat if it was not initialized yet\n                cv::Mat cvMatResult = OP_OP2CVMAT(matResult);\n                if (cvMatResult.empty() || cvMatResult.cols != channels * width || cvMatResult.rows != height)\n                    cvMatResult = cv::Mat(height, areaOutput, CV_8UC1);\n                // Fill cvMatResult from array\n                for (auto channel = 0 ; channel < channels ; channel++)\n                {\n                    // Get memory to be modified\n                    cv::Mat cvMatROI(cvMatResult, cv::Rect{channel * width, 0, width, height});\n                    // Modify memory\n                    const auto* arrayPtr = array.getConstPtr() + channel * areaInput;\n                    for (auto y = 0 ; y < height ; y++)\n                    {\n                        auto* cvMatROIPtr = cvMatROI.ptr<uchar>(y);\n                        const auto offsetHeight = y * width;\n                        for (auto x = 0 ; x < width ; x++)\n                        {\n                            const auto value = uchar(\n                                fastTruncate(positiveIntRound(arrayPtr[offsetHeight + x]), 0, 255));\n                            cvMatROIPtr[x] = (unsigned char)(value);\n                        }\n                    }\n                }\n                matResult = OP_CV2OPMAT(cvMatResult);\n            }\n            else\n                matResult = Matrix();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void uCharCvMatToFloatPtr(float* floatPtrImage, const Matrix& matImage, const int normalize)\n    {\n        try\n        {\n            const cv::Mat cvImage = OP_OP2CVCONSTMAT(matImage);\n            // float* (deep net format): C x H x W\n            // cv::Mat (OpenCV format): H x W x C\n            const int width = cvImage.cols;\n            const int height = cvImage.rows;\n            const int channels = cvImage.channels();\n\n            const auto* const originFramePtr = cvImage.data;    // cv::Mat.data is always uchar\n            for (auto c = 0; c < channels; c++)\n            {\n                const auto floatPtrImageOffsetC = c * height;\n                for (auto y = 0; y < height; y++)\n                {\n                    const auto floatPtrImageOffsetY = (floatPtrImageOffsetC + y) * width;\n                    const auto originFramePtrOffsetY = y * width;\n                    for (auto x = 0; x < width; x++)\n                        floatPtrImage[floatPtrImageOffsetY + x] = float(\n                            originFramePtr[(originFramePtrOffsetY + x) * channels + c]);\n                }\n            }\n            // Normalizing if desired\n            // VGG\n            if (normalize == 1)\n            {\n                #ifdef WITH_AVX\n                    // // To check results are the same (norm(x1-x2) = 0)\n                    // cv::Mat floatPtrImageCvWrapper(height, width, CV_32FC3, floatPtrImage);\n                    // cv::Mat floatPtrImageCvWrapperTest = floatPtrImageCvWrapper*(1/256.f) - 0.5f;\n                    // // Speed profiling\n                    // const auto REPS = 2000;\n                    // double timeNormalize0 = 0.;\n                    // double timeNormalize1 = 0.;\n                    // double timeNormalize2 = 0.;\n                    // double timeNormalize3 = 0.;\n                    // // OpenCV wrapper\n                    // OP_PROFILE_INIT(REPS);\n                    // cv::Mat floatPtrImageCvWrapper(height, width, CV_32FC3, floatPtrImage);\n                    // floatPtrImageCvWrapper = floatPtrImageCvWrapper*(1/256.f) - 0.5f;\n                    // OP_PROFILE_END(timeNormalize0, 1e6, REPS);\n                    // // C++ sequential code\n                    // OP_PROFILE_INIT(REPS);\n                    // const auto ratio = 1.f/256.f;\n                    // for (auto pixel = 0 ; pixel < width*height*channels ; ++pixel)\n                    //     floatPtrImage[pixel] = floatPtrImage[pixel]*ratio - 0.5f;\n                    // OP_PROFILE_END(timeNormalize1, 1e6, REPS);\n                    // // OpenCV wrapper\n                    // OP_PROFILE_INIT(REPS);\n                    // cv::Mat floatPtrImageCvWrapper(height, width, CV_32FC3, floatPtrImage);\n                    // floatPtrImageCvWrapper = floatPtrImageCvWrapper*(1/256.f) - 0.5f;\n                    // OP_PROFILE_END(timeNormalize2, 1e6, REPS);\n                    // OP_PROFILE_INIT(REPS);\n                    // AVX code\n                    const auto volume = width*height*channels;\n                    int pixel;\n                    const __m256 mmRatio = _mm256_set1_ps(1.f/256.f);\n                    const __m256 mmBias = _mm256_set1_ps(-0.5f);\n                    for (pixel = 0 ; pixel < volume-7 ; pixel += 8)\n                    {\n                        const __m256 input = _mm256_load_ps(&floatPtrImage[pixel]);\n                        // const __m256 input = _mm256_loadu_ps(&floatPtrImage[pixel]); // If non-aligned pointer\n                        const __m256 output = _mm256_fmadd_ps(input, mmRatio, mmBias);\n                        _mm256_store_ps(&floatPtrImage[pixel], output);\n                        // _mm256_storeu_ps(&floatPtrImage[pixel], output); // If non-aligned pointer\n                    }\n                    const auto ratio = 1.f/256.f;\n                    for (; pixel < volume ; ++pixel)\n                        floatPtrImage[pixel] = floatPtrImage[pixel]*ratio - 0.5f;\n                    // OP_PROFILE_END(timeNormalize3, 1e6, REPS);\n                    // std::cout\n                    //     << \"TN1: \" << timeNormalize0 << \" us\\n\"\n                    //     << \"TN1: \" << timeNormalize1 << \" us\\n\"\n                    //     << \"TN2: \" << timeNormalize2 << \" us\\n\"\n                    //     << \"TN3: \" << timeNormalize3 << \" us\\n\"\n                    //     << std::endl;\n                    // std::cout\n                    //     << \"Norm: \" << cv::norm(floatPtrImageCvWrapper-floatPtrImageCvWrapperTest) << \"\\n\"\n                    //     << std::endl;\n                // Non optimized code\n                #else\n                    // floatPtrImage wrapped as cv::Mat\n                        // Empirically tested - OpenCV is more efficient normalizing a whole matrix/image (it uses AVX and\n                        // other optimized instruction sets).\n                        // In addition, the following if statement does not copy the pointer to a cv::Mat, just wraps it.\n                    cv::Mat floatPtrImageCvWrapper(height*width*3, 1, CV_32FC1, floatPtrImage); // CV_32FC3 warns about https://github.com/opencv/opencv/issues/16739\n                    floatPtrImageCvWrapper = floatPtrImageCvWrapper*(1/256.f) - 0.5f;\n                #endif\n            }\n            // // ResNet\n            // else if (normalize == 2)\n            // {\n            //     const int imageArea = width * height;\n            //     const std::array<float,3> means{102.9801, 115.9465, 122.7717};\n            //     for (auto i = 0 ; i < 3 ; i++)\n            //     {\n            //         cv::Mat floatPtrImageCvWrapper(height, width, CV_32FC1, floatPtrImage + i*imageArea);\n            //         floatPtrImageCvWrapper = floatPtrImageCvWrapper - means[i];\n            //     }\n            // }\n            // DenseNet\n            else if (normalize == 2)\n            {\n                const auto scaleDenseNet = 0.017;\n                const int imageArea = width * height;\n                const std::array<float,3> means{103.94f, 116.78f, 123.68f};\n                for (auto i = 0 ; i < 3 ; i++)\n                {\n                    cv::Mat floatPtrImageCvWrapper(height, width, CV_32FC1, floatPtrImage + i*imageArea);\n                    floatPtrImageCvWrapper = scaleDenseNet*(floatPtrImageCvWrapper - means[i]);\n                }\n            }\n            // Unknown\n            else if (normalize != 0)\n                error(\"Unknown normalization value (\" + std::to_string(normalize) + \").\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    double resizeGetScaleFactor(const Point<int>& initialSize, const Point<int>& targetSize)\n    {\n        try\n        {\n            const auto ratioWidth = (targetSize.x - 1) / (double)(initialSize.x - 1);\n            const auto ratioHeight = (targetSize.y - 1) / (double)(initialSize.y - 1);\n            return fastMin(ratioWidth, ratioHeight);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0.;\n        }\n    }\n\n    void keepRoiInside(Rectangle<int>& roi, const int imageWidth, const int imageHeight)\n    {\n        try\n        {\n            // x,y < 0\n            if (roi.x < 0)\n            {\n                roi.width += roi.x;\n                roi.x = 0;\n            }\n            if (roi.y < 0)\n            {\n                roi.height += roi.y;\n                roi.y = 0;\n            }\n            // Bigger than image\n            if (roi.width + roi.x >= imageWidth)\n                roi.width = imageWidth - 1 - roi.x;\n            if (roi.height + roi.y >= imageHeight)\n                roi.height = imageHeight - 1 - roi.y;\n            // Width/height negative\n            roi.width = fastMax(0, roi.width);\n            roi.height = fastMax(0, roi.height);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void transpose(Matrix& matrix)\n    {\n        cv::Mat cvMatrix = OP_OP2CVMAT(matrix);\n        Matrix matrixFinal(matrix.cols(), matrix.rows(), matrix.type());\n        cv::Mat cvMatrixFinal = OP_OP2CVMAT(matrixFinal);\n        cv::transpose(cvMatrix, cvMatrixFinal);\n        std::swap(matrix, matrixFinal);\n    }\n\n    void rotateAndFlipFrame(Matrix& frame, const double rotationAngle, const bool flipFrame)\n    {\n        try\n        {\n            // cv::flip() does not moidify the memory location of the cv::Mat, but cv::transpose does\n            if (!frame.empty())\n            {\n                const auto rotationAngleInt = (int)std::round(rotationAngle) % 360;\n                // Transposing\n                if (rotationAngleInt == 90 || rotationAngleInt == 270 || rotationAngleInt == -90 || rotationAngleInt == -270)\n                    transpose(frame);\n                // Mirroring (flipping)\n                cv::Mat cvMatFrame = OP_OP2CVMAT(frame);\n                if (rotationAngleInt == 0 || rotationAngleInt == 360)\n                {\n                    if (flipFrame)\n                        cv::flip(cvMatFrame, cvMatFrame, 1);\n                }\n                else if (rotationAngleInt == 90 || rotationAngleInt == -270)\n                {\n                    if (!flipFrame)\n                        cv::flip(cvMatFrame, cvMatFrame, 0);\n                }\n                else if (rotationAngleInt == 180 || rotationAngleInt == -180)\n                {\n                    if (flipFrame)\n                        cv::flip(cvMatFrame, cvMatFrame, 0);\n                    else\n                        cv::flip(cvMatFrame, cvMatFrame, -1);\n                }\n                else if (rotationAngleInt == 270 || rotationAngleInt == -90)\n                {\n                    if (flipFrame)\n                        cv::flip(cvMatFrame, cvMatFrame, -1);\n                    else\n                        cv::flip(cvMatFrame, cvMatFrame, 1);\n                }\n                else\n                    error(\"Rotation angle = \" + std::to_string(rotationAngleInt)\n                        + \" != {0, 90, 180, 270} degrees.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    int getCvCapPropFrameCount()\n    {\n        try\n        {\n            return CV_CAP_PROP_FRAME_COUNT;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvCapPropFrameFps()\n    {\n        try\n        {\n            return CV_CAP_PROP_FPS;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvCapPropFrameWidth()\n    {\n        try\n        {\n            return CV_CAP_PROP_FRAME_WIDTH;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvCapPropFrameHeight()\n    {\n        try\n        {\n            return CV_CAP_PROP_FRAME_HEIGHT;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvFourcc(const char c1, const char c2, const char c3, const char c4)\n    {\n        try\n        {\n            return CV_FOURCC(c1,c2,c3,c4);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvImwriteJpegQuality()\n    {\n        try\n        {\n            return CV_IMWRITE_JPEG_QUALITY;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvImwritePngCompression()\n    {\n        try\n        {\n            return CV_IMWRITE_PNG_COMPRESSION;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvLoadImageAnydepth()\n    {\n        try\n        {\n            return CV_LOAD_IMAGE_ANYDEPTH;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n\n    int getCvLoadImageGrayScale()\n    {\n        try\n        {\n            return CV_LOAD_IMAGE_GRAYSCALE;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1;\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/openCvPrivate.cpp",
    "content": "#include <openpose_private/utilities/openCvPrivate.hpp>\n#include <openpose/utilities/fastMath.hpp>\n#include <openpose_private/utilities/avx.hpp>\n#include <openpose_private/utilities/openCvMultiversionHeaders.hpp>\n\nnamespace op\n{\n    void putTextOnCvMat(cv::Mat& cvMat, const std::string& textToDisplay, const Point<int>& position,\n                        const cv::Scalar& color, const bool normalizeWidth, const int imageWidth)\n    {\n        try\n        {\n            const auto font = cv::FONT_HERSHEY_SIMPLEX;\n            const auto ratio = imageWidth/1280.;\n            // const auto fontScale = 0.75;\n            const auto fontScale = 0.8 * ratio;\n            const auto fontThickness = std::max(1, positiveIntRound(2*ratio));\n            const auto shadowOffset = std::max(1, positiveIntRound(2*ratio));\n            int baseline = 0;\n            const auto textSize = cv::getTextSize(textToDisplay, font, fontScale, fontThickness, &baseline);\n            const cv::Size finalPosition{position.x - (normalizeWidth ? textSize.width : 0),\n                                         position.y + textSize.height/2};\n            cv::putText(cvMat, textToDisplay,\n                        cv::Size{finalPosition.width + shadowOffset, finalPosition.height + shadowOffset},\n                        font, fontScale, cv::Scalar{0,0,0}, fontThickness);\n            cv::putText(cvMat, textToDisplay, finalPosition, font, fontScale, color, fontThickness);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void resizeFixedAspectRatio(cv::Mat& resizedCvMat, const cv::Mat& cvMat, const double scaleFactor,\n                                const Point<int>& targetSize, const int borderMode, const cv::Scalar& borderValue)\n    {\n        try\n        {\n            const cv::Size cvTargetSize{targetSize.x, targetSize.y};\n            cv::Mat M = cv::Mat::eye(2,3,CV_64F);\n            M.at<double>(0,0) = scaleFactor;\n            M.at<double>(1,1) = scaleFactor;\n            if (scaleFactor != 1. || cvTargetSize != cvMat.size())\n                cv::warpAffine(cvMat, resizedCvMat, M, cvTargetSize,\n                               (scaleFactor > 1. ? cv::INTER_CUBIC : cv::INTER_AREA), borderMode, borderValue);\n            else\n                cvMat.copyTo(resizedCvMat);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/profiler.cpp",
    "content": "#include <openpose/utilities/profiler.hpp>\n#include <map>\n#include <mutex>\n#include <openpose/utilities/errorAndLog.hpp>\n\n// First, I apologize for the ugliness of the code of this function. Nevertheless, it has been made\n// in this way so that it has no computational impact at all if PROFILER_ENABLED is not defined.\n\nnamespace op\n{\n    unsigned long long Profiler::DEFAULT_X = 1000;\n\n    std::chrono::time_point<std::chrono::high_resolution_clock> getTimerInit()\n    {\n        try\n        {\n            return std::chrono::high_resolution_clock::now();\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return std::chrono::high_resolution_clock::now();\n        }\n    }\n\n    double getTimeSeconds(const std::chrono::time_point<std::chrono::high_resolution_clock>& timerInit)\n    {\n        try\n        {\n            const auto now = std::chrono::high_resolution_clock::now();\n            const auto totalTimeSec = double(\n                std::chrono::duration_cast<std::chrono::nanoseconds>(now-timerInit).count() * 1e-9);\n            return totalTimeSec;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return -1.;\n        }\n    }\n\n    void printTime(\n        const std::chrono::time_point<std::chrono::high_resolution_clock>& timerInit, const std::string& firstMessage,\n        const std::string& secondMessage, const Priority priority)\n    {\n        try\n        {\n            const auto message = firstMessage + std::to_string(getTimeSeconds(timerInit)) + secondMessage;\n            op::opLog(message, priority);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    #ifdef PROFILER_ENABLED\n\n        std::map<std::string, std::tuple<double, unsigned long long, std::chrono::high_resolution_clock::time_point>> sProfilerTuple{\n            std::map<std::string, std::tuple<double, unsigned long long, std::chrono::high_resolution_clock::time_point>>()\n        };\n        std::mutex sMutexProfiler{};\n\n        std::string getKey(const int line, const std::string& function, const std::string& file)\n        {\n            return file + function + std::to_string(line) + getThreadId();\n        }\n\n        void printAveragedTimeMsCommon(const double timePast, const unsigned long long timeCounter, const int line,\n                                       const std::string& function, const std::string& file)\n        {\n            const auto stringMessage = std::to_string(   timePast / timeCounter / 1e6   ) + \" msec\";\n            opLog(stringMessage, Priority::Max, line, function, file);\n        }\n    #endif\n\n    void Profiler::setDefaultX(const unsigned long long defaultX)\n    {\n        #ifdef PROFILER_ENABLED\n            DEFAULT_X = defaultX;\n        #else\n            UNUSED(defaultX);\n        #endif\n    }\n\n    const std::string Profiler::timerInit(const int line, const std::string& function, const std::string& file)\n    {\n        #ifdef PROFILER_ENABLED\n            const auto key = getKey(line, function, file);\n            std::unique_lock<std::mutex> lock{sMutexProfiler};\n            if (sProfilerTuple.count(key) > 0)\n                std::get<2>(sProfilerTuple[key]) = std::chrono::high_resolution_clock::now();\n            else\n                sProfilerTuple[key] = {std::make_tuple(0., 0ull, std::chrono::high_resolution_clock::now())};\n            lock.unlock();\n            return key;\n        #else\n            UNUSED(line);\n            UNUSED(function);\n            UNUSED(file);\n            return \"\";\n        #endif\n    }\n\n    void Profiler::timerEnd(const std::string& key)\n    {\n        #ifdef PROFILER_ENABLED\n            const std::lock_guard<std::mutex> lock{sMutexProfiler};\n            if (sProfilerTuple.count(key) > 0)\n            {\n                auto tuple = sProfilerTuple[key];\n                // Time between init & end\n                const auto timeNs = (double)std::chrono::duration_cast<std::chrono::nanoseconds>(\n                    std::chrono::high_resolution_clock::now() - std::get<2>(tuple)\n                ).count();\n                // Accumulate averaged time\n                std::get<0>(tuple) += timeNs;\n                std::get<1>(tuple)++;\n\n                sProfilerTuple[key] = tuple;\n            }\n            else\n                error(\"Profiler::timerEnd called with a non-existing key.\", __LINE__, __FUNCTION__, __FILE__);\n        #else\n            UNUSED(key);\n        #endif\n    }\n\n    void Profiler::printAveragedTimeMsOnIterationX(const std::string& key, const int line, const std::string& function,\n                                                   const std::string& file, const unsigned long long x)\n    {\n        #ifdef PROFILER_ENABLED\n            std::unique_lock<std::mutex> lock{sMutexProfiler};\n            if (sProfilerTuple.count(key) > 0)\n            {\n                const auto tuple = sProfilerTuple[key];\n                lock.unlock();\n                if (std::get<1>(tuple) == x)\n                {\n                    printAveragedTimeMsCommon(std::get<0>(tuple), std::get<1>(tuple), line, function, file);\n                }\n            }\n            else\n                error(\"Profiler::printAveragedTimeMsOnIterationX called with a non-existing key.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        #else\n            UNUSED(key);\n            UNUSED(line);\n            UNUSED(function);\n            UNUSED(file);\n            UNUSED(x);\n        #endif\n    }\n\n    void Profiler::printAveragedTimeMsEveryXIterations(const std::string& key, const int line,\n                                                       const std::string& function, const std::string& file,\n                                                       const unsigned long long x)\n    {\n        #ifdef PROFILER_ENABLED\n            std::unique_lock<std::mutex> lock{sMutexProfiler};\n            if (sProfilerTuple.count(key) > 0)\n            {\n                const auto tupleElement = sProfilerTuple[key];\n                lock.unlock();\n                if (std::get<1>(tupleElement) == x)\n                {\n                    printAveragedTimeMsCommon(std::get<0>(tupleElement), std::get<1>(tupleElement), line, function, file);\n\n                    // Reset\n                    const std::lock_guard<std::mutex> lockGuard{sMutexProfiler};\n                    auto& tuple = sProfilerTuple[key];\n                    std::get<0>(tuple) = 0.;\n                    std::get<1>(tuple) = 0;\n                }\n            }\n            else\n                error(\"Profiler::printAveragedTimeMsEveryXIterations called with a non-existing key.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n        #else\n            UNUSED(key);\n            UNUSED(line);\n            UNUSED(function);\n            UNUSED(file);\n            UNUSED(x);\n        #endif\n    }\n\n    void Profiler::profileGpuMemory(const int line, const std::string& function, const std::string& file)\n    {\n        #ifdef PROFILER_ENABLED\n            // Print line-function-file info\n            opLog(\"GPU usage.\", Priority::Max, line, function, file);\n\n            // GPU info\n            const auto nvidiaCommand = std::system(\"nvidia-smi | grep \\\"Processes:\\\"\")\n                                     | std::system(\"nvidia-smi | grep \\\"Process name\\\"\");\n            if (nvidiaCommand != 0)\n                opLog(\"Error on the nvidia-smi header. Please, inform us of this error.\", Priority::Max);\n            else\n            {\n                // Print GPU usage or empty otherwise\n                const std::string fileName{file};\n                const std::string getGpuMemoryCommand{\"nvidia-smi | grep \\\"\" + file.substr(0, file.size() - 3) + \"\\\"\"};\n                const auto answer = std::system(getGpuMemoryCommand.c_str());\n                if (answer == 256)\n                    opLog(\"Not used at all.\", Priority::Max);\n                else if (answer != 0)\n                    opLog(\"Bash error: \" + std::to_string(answer), Priority::Max);\n            }\n        #else\n            UNUSED(line);\n            UNUSED(function);\n            UNUSED(file);\n        #endif\n    }\n}\n"
  },
  {
    "path": "src/openpose/utilities/string.cpp",
    "content": "#include <openpose/utilities/string.hpp>\n#include <algorithm> // std::transform\n#include <cctype> // std::tolower, std::toupper\n#include <locale> // std::tolower, std::toupper\n\nnamespace op\n{\n    unsigned long long getLastNumber(const std::string& string)\n    {\n        try\n        {\n            const auto stringNumber = string.substr(string.find_last_not_of(\"0123456789\") + 1);\n            return std::stoull(stringNumber);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return 0ull;\n        }\n    }\n\n    template<typename T>\n    std::string toFixedLengthString(const T number, const unsigned long long stringLength)\n    {\n        try\n        {\n            const auto numberAsString = std::to_string(number);\n            if (stringLength > 0)\n            {\n                if (number < 0)\n                    error(\"toFixedLengthString: number cannot be <= 0, in this case it is: \" + numberAsString + \".\", __LINE__, __FUNCTION__, __FILE__);\n\n                const auto zerosToAdd = stringLength - numberAsString.size();\n                if (zerosToAdd < 0)\n                {\n                    const auto errorMessage = \"toFixedLengthString: number greater than maximum number of digits (stringLength): \"\n                                            + numberAsString + \" vs. \" + std::to_string(stringLength) + \".\";\n                    error(errorMessage, __LINE__, __FUNCTION__, __FILE__);\n                }\n\n                return { std::string(zerosToAdd, '0') + numberAsString};\n            }\n            else\n                return numberAsString;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    // Signed\n    template OP_API std::string toFixedLengthString<char>(const char number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<signed char>(const signed char number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<short>(const short number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<int>(const int number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<long>(const long number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<long long>(const long long number, const unsigned long long stringLength);\n    // Unsigned\n    template OP_API std::string toFixedLengthString<unsigned char>(const unsigned char number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<unsigned short>(const unsigned short number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<unsigned int>(const unsigned int number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<unsigned long>(const unsigned long number, const unsigned long long stringLength);\n    template OP_API std::string toFixedLengthString<unsigned long long>(const unsigned long long number, const unsigned long long stringLength);\n\n    std::vector<std::string> splitString(const std::string& stringToSplit, const std::string& delimiter)\n    {\n        try\n        {\n            std::vector<std::string> result;\n            size_t pos = 0;\n            auto stringToSplitAux = stringToSplit;\n            while ((pos = stringToSplitAux.find(delimiter)) != std::string::npos)\n            {\n                result.emplace_back(stringToSplitAux.substr(0, pos));\n                stringToSplitAux.erase(0, pos + delimiter.length());\n            }\n            result.emplace_back(stringToSplitAux);\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return {};\n        }\n    }\n\n    std::string toLower(const std::string& string)\n    {\n        try\n        {\n            std::string result = string;\n            std::transform(string.begin(), string.end(), result.begin(),\n                [](unsigned char c) { return (unsigned char)std::tolower(c); });\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string toUpper(const std::string& string)\n    {\n        try\n        {\n            std::string result = string;\n            std::transform(string.begin(), string.end(), result.begin(),\n                [](unsigned char c) { return (unsigned char)std::toupper(c); });\n            return result;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string remove0sFromString(const std::string& string)\n    {\n        try\n        {\n            std::string stringNo0s;\n            if (string[0] == '0')\n            {\n                // Find first not 0\n                const std::size_t found = string.find_first_not_of(\"0\");\n                if (found == std::string::npos)\n                    error(\"This should not happen.\", __LINE__, __FUNCTION__, __FILE__);\n                // Make sure that 0 is not the only digit\n                if (string.size() > found && std::isdigit(string[found]))\n                    stringNo0s = string.substr(found);\n                else\n                    stringNo0s = string.substr(found-1);\n            }\n            else\n                stringNo0s = string;\n            return stringNo0s;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n\n    std::string getFirstNumberOnString(const std::string& string)\n    {\n        try\n        {\n            const std::size_t found = string.find_first_not_of(\"0123456789\");\n            if (found == std::string::npos)\n                error(\"This should not happen.\", __LINE__, __FUNCTION__, __FILE__);\n            return string.substr(0, found);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n            return \"\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/CMakeLists.txt",
    "content": "set(SOURCES_OP_WRAPPER\n    defineTemplates.cpp\n    wrapperAuxiliary.cpp\n    wrapperStructExtra.cpp\n    wrapperStructFace.cpp\n    wrapperStructGui.cpp\n    wrapperStructHand.cpp\n    wrapperStructInput.cpp\n    wrapperStructOutput.cpp\n    wrapperStructPose.cpp)\n\ninclude(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)\nprepend(SOURCES_OP_WRAPPER_WITH_CP ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCES_OP_WRAPPER})\nset(SOURCES_OP_WRAPPER_WITH_CP ${SOURCES_OP_WRAPPER_WITH_CP} PARENT_SCOPE)\nset(SOURCES_OPENPOSE ${SOURCES_OPENPOSE} ${SOURCES_OP_WRAPPER_WITH_CP} PARENT_SCOPE)\n\nif (UNIX OR APPLE)\n  add_library(openpose_wrapper ${SOURCES_OP_WRAPPER})\n  target_link_libraries(openpose_wrapper openpose_thread openpose_pose openpose_hand\n      openpose_core openpose_face openpose_filestream openpose_gui openpose_producer\n      openpose_utilities)\n\n  install(TARGETS openpose_wrapper\n      EXPORT OpenPose\n      RUNTIME DESTINATION bin\n      LIBRARY DESTINATION lib\n      ARCHIVE DESTINATION lib/openpose)\nendif (UNIX OR APPLE)\n"
  },
  {
    "path": "src/openpose/wrapper/defineTemplates.cpp",
    "content": "#include <openpose/wrapper/headers.hpp>\n\nnamespace op\n{\n    template class OP_API WrapperT<BASE_DATUM>;\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperAuxiliary.cpp",
    "content": "#include <openpose/wrapper/wrapperAuxiliary.hpp>\n#include <openpose/gpu/gpu.hpp>\n#include <openpose/thread/enumClasses.hpp>\n\nnamespace op\n{\n    void wrapperConfigureSanityChecks(\n        WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace,\n        const WrapperStructHand& wrapperStructHand, const WrapperStructExtra& wrapperStructExtra,\n        const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput,\n        const WrapperStructGui& wrapperStructGui, const bool renderOutput,\n        const bool userInputAndPreprocessingWsEmpty, const bool userOutputWsEmpty,\n        const std::shared_ptr<Producer>& producerSharedPtr, const ThreadManagerMode threadManagerMode)\n    {\n        try\n        {\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n\n            // Disable netInputSizeDynamicBehavior if not images and not custom input\n            // (i.e., fixed resolution stream like webcam or video)\n            if (wrapperStructInput.producerType != ProducerType::ImageDirectory\n                && wrapperStructInput.producerType != ProducerType::None)\n            {\n                wrapperStructPose.netInputSizeDynamicBehavior = -1.f;\n            }\n\n            // Check no wrong/contradictory flags enabled\n            if (wrapperStructPose.alphaKeypoint < 0. || wrapperStructPose.alphaKeypoint > 1.\n                || wrapperStructFace.alphaHeatMap < 0. || wrapperStructFace.alphaHeatMap > 1.\n                || wrapperStructHand.alphaHeatMap < 0. || wrapperStructHand.alphaHeatMap > 1.)\n                error(\"Alpha value for blending must be in the range [0,1].\", __LINE__, __FUNCTION__, __FILE__);\n            if (wrapperStructPose.scaleGap <= 0.f && wrapperStructPose.scalesNumber > 1)\n                error(\"The scale gap must be greater than 0 (it has no effect if the number of scales is 1).\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            if (!renderOutput && (!wrapperStructOutput.writeImages.empty()\n                || !wrapperStructOutput.writeVideo.empty()))\n            {\n                const auto message = \"In order to save the rendered frames (`--write_images` or `--write_video`), you\"\n                                     \" cannot disable `--render_pose`.\";\n                opLog(message, Priority::High);\n            }\n            if (!wrapperStructOutput.writeHeatMaps.empty() && wrapperStructPose.heatMapTypes.empty())\n            {\n                const auto message = \"In order to save the heatmaps (`--write_heatmaps`), you need to pick which heat\"\n                                     \" maps you want to save: `--heatmaps_add_X` flags or fill the\"\n                                     \" wrapperStructPose.heatMapTypes.\";\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n            if (!wrapperStructOutput.writeHeatMaps.empty()\n                && (wrapperStructPose.heatMapScaleMode != ScaleMode::UnsignedChar &&\n                        wrapperStructOutput.writeHeatMapsFormat.getStdString() != \"float\"))\n            {\n                const auto message = \"In order to save the heatmaps, you must either set\"\n                                     \" wrapperStructPose.heatMapScaleMode to ScaleMode::UnsignedChar (i.e., range\"\n                                     \" [0, 255]) or `--write_heatmaps_format` to `float` to storage floating numbers\"\n                                     \" in binary mode.\";\n                error(message, __LINE__, __FUNCTION__, __FILE__);\n            }\n            if (userOutputWsEmpty && threadManagerMode != ThreadManagerMode::Asynchronous\n                && threadManagerMode != ThreadManagerMode::AsynchronousOut)\n            {\n                const std::string additionalMessage{\n                    \" You could also set mThreadManagerMode = mThreadManagerMode::Asynchronous(Out) and/or add your\"\n                    \" own output worker class before calling this function.\"\n                };\n                const auto savingSomething = (\n                    !wrapperStructOutput.writeImages.empty() || !wrapperStructOutput.writeVideo.empty()\n                        || !wrapperStructOutput.writeKeypoint.empty() || !wrapperStructOutput.writeJson.empty()\n                        || !wrapperStructOutput.writeCocoJson.empty() || !wrapperStructOutput.writeHeatMaps.empty()\n                );\n                const auto savingCvOutput = (\n                    !wrapperStructOutput.writeImages.empty() || !wrapperStructOutput.writeVideo.empty()\n                );\n                const bool guiEnabled = (wrapperStructGui.displayMode != DisplayMode::NoDisplay);\n                if (!guiEnabled && !savingCvOutput && renderOutput)\n                {\n                    const auto message = \"GUI is not enabled and you are not saving the output frames. You should then\"\n                                         \" disable rendering for a faster code. I.e., add `--render_pose 0`.\"\n                                         + additionalMessage;\n                    error(message, __LINE__, __FUNCTION__, __FILE__);\n                }\n                if (!guiEnabled && !savingSomething)\n                {\n                    const auto message = \"No output is selected (`--display 0`) and no results are generated (no\"\n                                         \" `--write_X` flags enabled). Thus, no output would be generated.\"\n                                         + additionalMessage;\n                    error(message, __LINE__, __FUNCTION__, __FILE__);\n                }\n                if (wrapperStructInput.framesRepeat && savingSomething)\n                {\n                    const auto message = \"Frames repetition (`--frames_repeat`) is enabled as well as some writing\"\n                                         \" function (`--write_X`). This program would never stop recording the same\"\n                                         \" frames over and over. Please, disable repetition or remove writing.\";\n                    error(message, __LINE__, __FUNCTION__, __FILE__);\n                }\n                // Warnings\n                if (guiEnabled && wrapperStructGui.guiVerbose && !renderOutput)\n                {\n                    const auto message = \"No render is enabled (e.g., `--render_pose 0`), so you might also want to\"\n                                         \" remove the display (set `--display 0` or `--no_gui_verbose`). If you\"\n                                         \" simply want to use OpenPose to record video/images without keypoints, you\"\n                                         \" only need to set `--num_gpu 0`.\" + additionalMessage;\n                    opLog(message, Priority::High);\n                }\n                if (wrapperStructInput.realTimeProcessing && savingSomething)\n                {\n                    const auto message = \"Real time processing is enabled as well as some writing function. Thus, some\"\n                                         \" frames might be skipped. Consider disabling real time processing if you\"\n                                         \" intend to save any results.\";\n                    opLog(message, Priority::High);\n                }\n            }\n            if (!wrapperStructOutput.writeVideo.empty() && producerSharedPtr == nullptr)\n                error(\"Writing video (`--write_video`) is only available if the OpenPose producer is used (i.e.\"\n                      \" producerSharedPtr cannot be a nullptr). Otherwise, OpenPose would not know the frame rate\"\n                      \" of that output video nor whether all the images maintain the same resolution. You might\"\n                      \" use `--write_images` instead.\", __LINE__, __FUNCTION__, __FILE__);\n            if (wrapperStructPose.poseMode == PoseMode::Disabled && !wrapperStructFace.enable\n                && !wrapperStructHand.enable)\n                error(\"Body, face, and hand keypoint detectors are disabled. You must enable at least one (i.e,\"\n                      \" unselect `--body 0`, select `--face`, or select `--hand`.\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            const auto ownDetectorProvided = (wrapperStructFace.detector == Detector::Provided\n                                              || wrapperStructHand.detector == Detector::Provided);\n            if (ownDetectorProvided && userInputAndPreprocessingWsEmpty\n                && threadManagerMode != ThreadManagerMode::Asynchronous\n                && threadManagerMode != ThreadManagerMode::AsynchronousIn)\n                error(\"You have selected to provide your own face and/or hand rectangle detections (`face_detector 2`\"\n                      \" and/or `hand_detector 2`), thus OpenPose will not detect face and/or hand keypoints based on\"\n                      \" the body keypoints. However, you are not providing any information about the location of the\"\n                      \" faces and/or hands. Either provide the location of the face and/or hands (e.g., see the\"\n                      \" `examples/tutorial_api_cpp/` examples, or change the value of `--face_detector` and/or\"\n                      \" `--hand_detector`.\", __LINE__, __FUNCTION__, __FILE__);\n            // Warning\n            if (ownDetectorProvided && wrapperStructPose.poseMode != PoseMode::Disabled)\n                opLog(\"Warning: Body keypoint estimation is enabled while you have also selected to provide your own\"\n                    \" face and/or hand rectangle detections (`face_detector 2` and/or `hand_detector 2`). Therefore,\"\n                    \" OpenPose will not detect face and/or hand keypoints based on the body keypoints. Are you sure\"\n                    \" you want to keep enabled the body keypoint detector? (disable it with `--body 0`).\",\n                    Priority::High);\n            // If 3-D module, 1 person is the maximum\n            if (wrapperStructExtra.reconstruct3d && wrapperStructPose.numberPeopleMax != 1)\n            {\n                error(\"Set `--number_people_max 1` when using `--3d`. The 3-D reconstruction demo assumes there is\"\n                      \" at most 1 person on each image.\", __LINE__, __FUNCTION__, __FILE__);\n            }\n            // If CPU mode, #GPU cannot be > 0\n            if (getGpuMode() == GpuMode::NoGpu)\n                if (wrapperStructPose.gpuNumber > 0)\n                    error(\"GPU number must be negative or 0 if CPU_ONLY is enabled.\",\n                          __LINE__, __FUNCTION__, __FILE__);\n            // If num_gpu 0 --> output_resolution has no effect\n            if (wrapperStructPose.gpuNumber == 0 &&\n                (wrapperStructPose.outputSize.x > 0 || wrapperStructPose.outputSize.y > 0))\n                error(\"If `--num_gpu 0`, then `--output_resolution` has no effect, so either disable it or use\"\n                      \" `--output_resolution -1x-1`. Current output size: (\"\n                      + std::to_string(wrapperStructPose.outputSize.x) + \"x\"\n                      + std::to_string(wrapperStructPose.outputSize.y) + \").\",\n                      __LINE__, __FUNCTION__, __FILE__);\n            #ifdef USE_CPU_ONLY\n                if (wrapperStructPose.scalesNumber > 1)\n                    error(\"Temporarily, the number of scales (`--scale_number`) cannot be greater than 1 for\"\n                          \" `CPU_ONLY` version.\", __LINE__, __FUNCTION__, __FILE__);\n            #endif\n            // Net input resolution cannot be reshaped for Caffe OpenCL and MKL versions, only for CUDA version\n            #if defined USE_MKL || defined USE_OPENCL\n                // If image_dir and netInputSize == -1 --> error\n                if ((producerSharedPtr == nullptr\n                     || producerSharedPtr->getType() == ProducerType::ImageDirectory)\n                    // If netInputSize is -1\n                    && (wrapperStructPose.netInputSize.x == -1 || wrapperStructPose.netInputSize.y == -1))\n                {\n                    wrapperStructPose.netInputSize.x = 656;\n                    wrapperStructPose.netInputSize.y = 368;\n                    opLog(\"The default dynamic `--net_resolution` is not supported in MKL (MKL CPU Caffe) and OpenCL\"\n                        \" Caffe versions. Please, use a static `net_resolution` (recommended\"\n                        \" `--net_resolution 656x368`) or use the Caffe CUDA master branch when processing images\"\n                        \" and/or when using your custom image reader. OpenPose has automatically set the resolution\"\n                        \" to 656x368.\", Priority::High);\n                }\n            #endif\n            #ifndef USE_CUDA\n                opLog(\"---------------------------------- WARNING ----------------------------------\\n\"\n                    \"We have introduced an additional boost in accuracy in the CUDA version of about 0.2% with\"\n                    \" respect to the CPU/OpenCL versions. We will not port this to CPU given the considerable slow\"\n                    \" down in speed it would add to it. Nevertheless, this accuracy boost is almost insignificant so\"\n                    \" the CPU/OpenCL versions can be safely used.\"\n                    \"\\n-------------------------------- END WARNING --------------------------------\",\n                    Priority::High);\n            #endif\n\n            opLog(\"\", Priority::Low, __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n\n    void threadIdPP(unsigned long long& threadId, const bool multiThreadEnabled)\n    {\n        try\n        {\n            if (multiThreadEnabled)\n                threadId++;\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructExtra.cpp",
    "content": "#include <openpose/wrapper/wrapperStructExtra.hpp>\n\nnamespace op\n{\n    WrapperStructExtra::WrapperStructExtra(\n        const bool reconstruct3d_, const int minViews3d_, const bool identification_, const int tracking_,\n        const int ikThreads_) :\n        reconstruct3d{reconstruct3d_},\n        minViews3d{minViews3d_},\n        identification{identification_},\n        tracking{tracking_},\n        ikThreads{ikThreads_}\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructFace.cpp",
    "content": "#include <openpose/wrapper/wrapperStructFace.hpp>\n\nnamespace op\n{\n    WrapperStructFace::WrapperStructFace(\n        const bool enable_, const Detector detector_, const Point<int>& netInputSize_, const RenderMode renderMode_,\n        const float alphaKeypoint_, const float alphaHeatMap_, const float renderThreshold_) :\n        enable{enable_},\n        detector{detector_},\n        netInputSize{netInputSize_},\n        renderMode{renderMode_},\n        alphaKeypoint{alphaKeypoint_},\n        alphaHeatMap{alphaHeatMap_},\n        renderThreshold{renderThreshold_}\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructGui.cpp",
    "content": "#include <openpose/wrapper/wrapperStructGui.hpp>\n\nnamespace op\n{\n    WrapperStructGui::WrapperStructGui(\n        const DisplayMode displayMode_, const bool guiVerbose_, const bool fullScreen_) :\n        displayMode{displayMode_},\n        guiVerbose{guiVerbose_},\n        fullScreen{fullScreen_}\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructHand.cpp",
    "content": "#include <openpose/wrapper/wrapperStructHand.hpp>\n\nnamespace op\n{\n    WrapperStructHand::WrapperStructHand(\n        const bool enable_, const Detector detector_, const Point<int>& netInputSize_, const int scalesNumber_,\n        const float scaleRange_, const RenderMode renderMode_, const float alphaKeypoint_, const float alphaHeatMap_,\n        const float renderThreshold_) :\n        enable{enable_},\n        detector{detector_},\n        netInputSize{netInputSize_},\n        scalesNumber{scalesNumber_},\n        scaleRange{scaleRange_},\n        renderMode{renderMode_},\n        alphaKeypoint{alphaKeypoint_},\n        alphaHeatMap{alphaHeatMap_},\n        renderThreshold{renderThreshold_}\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructInput.cpp",
    "content": "#include <openpose/wrapper/wrapperStructInput.hpp>\n\nnamespace op\n{\n    WrapperStructInput::WrapperStructInput(\n        const ProducerType producerType_, const String& producerString_, const unsigned long long frameFirst_,\n        const unsigned long long frameStep_, const unsigned long long frameLast_, const bool realTimeProcessing_,\n        const bool frameFlip_, const int frameRotate_, const bool framesRepeat_, const Point<int>& cameraResolution_,\n        const String& cameraParameterPath_, const bool undistortImage_, const int numberViews_) :\n        producerType{producerType_},\n        producerString{producerString_},\n        frameFirst{frameFirst_},\n        frameStep{frameStep_},\n        frameLast{frameLast_},\n        realTimeProcessing{realTimeProcessing_},\n        frameFlip{frameFlip_},\n        frameRotate{frameRotate_},\n        framesRepeat{framesRepeat_},\n        cameraResolution{cameraResolution_},\n        cameraParameterPath{cameraParameterPath_},\n        undistortImage{undistortImage_},\n        numberViews{numberViews_}\n    {\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructOutput.cpp",
    "content": "#include <openpose/wrapper/wrapperStructOutput.hpp>\n\nnamespace op\n{\n    WrapperStructOutput::WrapperStructOutput(\n        const double verbose_, const String& writeKeypoint_, const DataFormat writeKeypointFormat_,\n        const String& writeJson_, const String& writeCocoJson_, const int writeCocoJsonVariants_,\n        const int writeCocoJsonVariant_, const String& writeImages_, const String& writeImagesFormat_,\n        const String& writeVideo_, const double writeVideoFps_, const bool writeVideoWithAudio_,\n        const String& writeHeatMaps_, const String& writeHeatMapsFormat_, const String& writeVideo3D_,\n        const String& writeVideoAdam_, const String& writeBvh_, const String& udpHost_,\n        const String& udpPort_) :\n        verbose{verbose_},\n        writeKeypoint{writeKeypoint_},\n        writeKeypointFormat{writeKeypointFormat_},\n        writeJson{writeJson_},\n        writeCocoJson{writeCocoJson_},\n        writeCocoJsonVariants{writeCocoJsonVariants_},\n        writeCocoJsonVariant{writeCocoJsonVariant_},\n        writeImages{writeImages_},\n        writeImagesFormat{writeImagesFormat_},\n        writeVideo{writeVideo_},\n        writeVideoFps{writeVideoFps_},\n        writeVideoWithAudio{writeVideoWithAudio_},\n        writeHeatMaps{writeHeatMaps_},\n        writeHeatMapsFormat{writeHeatMapsFormat_},\n        writeVideo3D{writeVideo3D_},\n        writeVideoAdam{writeVideoAdam_},\n        writeBvh{writeBvh_},\n        udpHost{udpHost_},\n        udpPort{udpPort_}\n    {\n        try\n        {\n            if (!writeBvh.empty())\n                error(\"BVH writing is experimental and not available yet (flag `--write_bvh`). Please, disable this\"\n                      \" flag and do not open a GitHub issue asking for it.\", __LINE__, __FUNCTION__, __FILE__);\n        }\n        catch (const std::exception& e)\n        {\n            error(e.what(), __LINE__, __FUNCTION__, __FILE__);\n        }\n    }\n}\n"
  },
  {
    "path": "src/openpose/wrapper/wrapperStructPose.cpp",
    "content": "#include <openpose/wrapper/wrapperStructPose.hpp>\n\nnamespace op\n{\n    WrapperStructPose::WrapperStructPose(\n        const PoseMode poseMode_, const Point<int>& netInputSize_, const double netInputSizeDynamicBehavior_,\n        const Point<int>& outputSize_, const ScaleMode keypointScaleMode_, const int gpuNumber_,\n        const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const RenderMode renderMode_,\n        const PoseModel poseModel_, const bool blendOriginalFrame_, const float alphaKeypoint_,\n        const float alphaHeatMap_, const int defaultPartToRender_, const String& modelFolder_,\n        const std::vector<HeatMapType>& heatMapTypes_, const ScaleMode heatMapScaleMode_,\n        const bool addPartCandidates_, const float renderThreshold_, const int numberPeopleMax_,\n        const bool maximizePositives_, const double fpsMax_, const String& protoTxtPath_,\n        const String& caffeModelPath_, const float upsamplingRatio_, const bool enableGoogleLogging_) :\n        poseMode{poseMode_},\n        netInputSize{netInputSize_},\n        netInputSizeDynamicBehavior{netInputSizeDynamicBehavior_},\n        outputSize{outputSize_},\n        keypointScaleMode{keypointScaleMode_},\n        gpuNumber{gpuNumber_},\n        gpuNumberStart{gpuNumberStart_},\n        scalesNumber{scalesNumber_},\n        scaleGap{scaleGap_},\n        renderMode{renderMode_},\n        poseModel{poseModel_},\n        blendOriginalFrame{blendOriginalFrame_},\n        alphaKeypoint{alphaKeypoint_},\n        alphaHeatMap{alphaHeatMap_},\n        defaultPartToRender{defaultPartToRender_},\n        modelFolder{modelFolder_},\n        heatMapTypes{heatMapTypes_},\n        heatMapScaleMode{heatMapScaleMode_},\n        addPartCandidates{addPartCandidates_},\n        renderThreshold{renderThreshold_},\n        numberPeopleMax{numberPeopleMax_},\n        maximizePositives{maximizePositives_},\n        fpsMax{fpsMax_},\n        protoTxtPath{protoTxtPath_},\n        caffeModelPath{caffeModelPath_},\n        upsamplingRatio{upsamplingRatio_},\n        enableGoogleLogging{enableGoogleLogging_}\n    {\n    }\n}\n"
  }
]