diff --git a/src/scaffoldmaker/annotation/cecum_terms.py b/src/scaffoldmaker/annotation/cecum_terms.py index 15df6025..96c0f852 100644 --- a/src/scaffoldmaker/annotation/cecum_terms.py +++ b/src/scaffoldmaker/annotation/cecum_terms.py @@ -4,7 +4,13 @@ # convention: preferred name, preferred id, followed by any other ids and alternative names cecum_terms = [ - ("caecum", "UBERON:0001153", "FMA:14541", "ILX:0732270") + ("caecum", "UBERON:0001153", "FMA:14541", "ILX:0732270"), + ("cecum mucosa", "UBERON:0000314", "FMA:14998", "ILX:0723957"), + ("circular muscle layer of cecum", "ILX:0774843"), + ("ileum part of cecum", "None"), + ("longitudinal muscle layer of cecum", "ILX:0776047"), + ("serosa of cecum", "ILX:0773223"), + ("submucosa of cecum", "UBERON:0004927", "FMA:14999", "ILX:0725500") ] diff --git a/src/scaffoldmaker/annotation/smallintestine_terms.py b/src/scaffoldmaker/annotation/smallintestine_terms.py index abc3a0df..ea591783 100644 --- a/src/scaffoldmaker/annotation/smallintestine_terms.py +++ b/src/scaffoldmaker/annotation/smallintestine_terms.py @@ -5,16 +5,22 @@ # convention: preferred name, preferred id, followed by any other ids and alternative names smallintestine_terms = [ ("circular-longitudinal muscle interface of first segment of the duodenum along the gastric-omentum attachment", "ILX:0793090"), + ("circular muscle layer of ileum", "ILX:0776561"), ("circular muscle layer of small intestine", "ILX:0772669"), ("duodenum", "UBERON:0002114", "FMA:7206", "ILX:0726125"), + ("ileocecal junction", "UBERON:0001073", "FMA:11338", "ILX:0730012"), ("ileum", "UBERON:0002116", "FMA:7208", "ILX:0728151"), ("jejunum", "UBERON:0002115", "FMA:7207", "ILX:0724224"), + ("longitudinal muscle layer of ileum", "ILX:0770304"), ("longitudinal muscle layer of small intestine", "ILX:0772125"), ("luminal surface of duodenum", "ILX:0793121"), + ("mucosa of ileum", "ILX:0770578"), ("mucosa of small intestine", "UBERON:0001204", "FMA:14933", "ILX:0770578"), ("serosa of duodenum", "UBERON:0003336", "FMA:14948", "ILX:0732373"), + ("serosa of ileum", "ILX:0774472"), ("serosa of small intestine", "UBERON:0001206", "FMA:14938", "ILX:0727465"), ("small intestine", "UBERON:0002108", "FMA:7200", "ILX:0726770"), + ("submucosa of ileum", "UBERON:0004946", "FMA:14957", "ILX:0734297"), ("submucosa of small intestine", "UBERON:0001205", "FMA:14934", "ILX:0735609") ] diff --git a/src/scaffoldmaker/annotation/stomach_terms.py b/src/scaffoldmaker/annotation/stomach_terms.py index 394dc062..bf04962d 100644 --- a/src/scaffoldmaker/annotation/stomach_terms.py +++ b/src/scaffoldmaker/annotation/stomach_terms.py @@ -23,6 +23,7 @@ ("distal point of lower esophageal sphincter serosa on the greater curvature of stomach", "ILX:0793179"), ("distal point of lower esophageal sphincter serosa on the lesser curvature of stomach", "ILX:0793180"), ("dorsal stomach", "ILX:0793086"), + ("duodenum part of stomach", "None"), ("esophagogastric junction", "UBERON:0007650", "FMA: 9434", "ILX:0733910"), ("esophagogastric junction along the greater curvature on circular-longitudinal muscle interface", "ILX:0793098"), ("esophagogastric junction along the greater curvature on luminal surface", "ILX:0793099"), @@ -30,6 +31,7 @@ ("esophagogastric junction along the lesser curvature on circular-longitudinal muscle interface", "ILX:0793101"), ("esophagogastric junction along the lesser curvature on luminal surface", "ILX:0793102"), ("esophagogastric junction along the lesser curvature on serosa", "ILX:0793103"), + ("esophagus part of stomach", "None"), ("forestomach-glandular stomach junction", "UBERON:0012270", "ILX:0729974"), ("fundus of stomach", "UBERON:0001160", " FMA:14559", "ILX:0724443"), ("fundus-body junction along the greater curvature on circular-longitudinal muscle interface", "ILX:0793104"), diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_bladder1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_bladder1.py index 1bb877d0..a6ec6a92 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_bladder1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_bladder1.py @@ -573,7 +573,7 @@ def generateBaseMesh(cls, region, options): bladderCoordinatesFieldName, elementsCountAround, elementsCountAlongBladder, elementsCountThroughWall, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True) + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True)[0:3] bladderCoordinates = fm.findFieldByName(bladderCoordinatesFieldName) @@ -1335,7 +1335,7 @@ def getBladderCoordinates(elementsCountAlongDome, elementsCountAlongNeck, elemen xList, d1List, d2List, d3List, curvatureList = \ tubemesh.extrudeSurfaceCoordinates(xInner, d1Inner, d2Inner, d3Inner, wallThicknessList, relativeThicknessList, elementsCountAround, elementsCountAlongBladder, elementsCountThroughWall, - transitElementList, outward=False) + transitElementList, outward=False)[0:5] # Deal with multiple nodes at the start point for closed proximal end n = elementsCountAround * (elementsCountThroughWall + 1) diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py index c8e1fd69..ef04477a 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py @@ -884,14 +884,12 @@ def generateBaseMesh(cls, region, options): transitElementList = [0] * elementsCountAround relativeThicknessList = [] - xList, d1List, d2List, d3List, curvatureList = tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, - d2WarpedList, d3WarpedUnitList, - wallThicknessList, - relativeThicknessList, - elementsCountAround, - elementsCountAlong, - elementsCountThroughWall, - transitElementList, outward=True) + xList, d1List, d2List, d3List, curvatureList = \ + tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList, + wallThicknessList, relativeThicknessList, elementsCountAround, + elementsCountAlong, elementsCountThroughWall, transitElementList, + outward=True)[0:5] + # Call the derivatives from the transition list to be replaced in the d2List idx = elementsCountAlongBladder * elementsCountAround for n2 in range(elementsCountThroughWall + 1): @@ -1045,7 +1043,7 @@ def generateBaseMesh(cls, region, options): elementsCountAround, elementsCountAlong, elementsCountThroughWall, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True) + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True)[0:3] if includeUreter: annotationGroups.append(ureterGroup) diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_cecum1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_cecum1.py index ce65ae39..58db44f4 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_cecum1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_cecum1.py @@ -7,14 +7,17 @@ import copy import math +from cmlibs.utils.zinc.field import findOrCreateFieldCoordinates +from cmlibs.zinc.element import Element from cmlibs.zinc.field import Field from cmlibs.zinc.node import Node -from scaffoldmaker.annotation.annotationgroup import AnnotationGroup +from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, mergeAnnotationGroups from scaffoldmaker.annotation.cecum_terms import get_cecum_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 -from scaffoldmaker.meshtypes.meshtype_3d_colonsegment1 import ColonSegmentTubeMeshInnerPoints, \ +from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 +from scaffoldmaker.meshtypes.meshtype_3d_colonsegment1 import ColonSegmentTubeMeshOuterPoints, \ getFullProfileFromHalfHaustrum, getTeniaColi, createNodesAndElementsTeniaColi -from scaffoldmaker.meshtypes.meshtype_3d_ostium1 import MeshType_3d_ostium1, generateOstiumMesh +from scaffoldmaker.meshtypes.meshtype_3d_ostium2 import generateOstiumMesh from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.scaffoldpackage import ScaffoldPackage from scaffoldmaker.utils import interpolation as interp @@ -22,70 +25,164 @@ from scaffoldmaker.utils import tubemesh from scaffoldmaker.utils import vector from scaffoldmaker.utils.annulusmesh import createAnnulusMesh3d -from scaffoldmaker.utils.tracksurface import TrackSurface, TrackSurfacePosition +from scaffoldmaker.utils.eftfactory_bicubichermitelinear import eftfactory_bicubichermitelinear +from scaffoldmaker.utils.eftfactory_tricubichermite import eftfactory_tricubichermite +from scaffoldmaker.utils.eft_utils import setEftScaleFactorIds, remapEftNodeValueLabel +from scaffoldmaker.utils.tracksurface import TrackSurface from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ - mesh_destroy_elements_and_nodes_by_identifiers, get_nodeset_path_field_parameters + mesh_destroy_elements_and_nodes_by_identifiers, get_nodeset_path_ordered_field_parameters -class MeshType_3d_cecum1(Scaffold_base): - ''' - Generates a 3-D cecum mesh with variable numbers - of elements around, along the central line, and through wall. - The cecum is created by a function that generates a cecum - segment and uses tubemesh to map the segment along a central - line profile. The proximal end of the cecum is closed up with - an apex plate. An ostium is included to generate the - ileo-cecal junction. - ''' - centralPathDefaultScaffoldPackages = { - 'Pig 1': ScaffoldPackage(MeshType_1d_path1, { +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3.2, 4-3-5" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[7.50,-20.00,0.00], [0.00,8.28,0.00], [-2.50,0.00,0.00], [0.00,0.00,0.00], [0.00,-0.00,2.50], [0.00,0.00,0.00]]), + (2, [[7.50,-10.86,0.00], [0.00,10.00,0.00], [-4.50,0.00,0.00], [0.00,0.00,0.00], [0.00,-0.00,4.50], [0.00,0.00,0.00]]), + (3, [[7.50,0.00,0.00], [[8.44,0.00,0.04],[0.00,11.72,0.00]], [[0.00,11.60,0.00],[-4.50,0.00,0.00]], [[1.02,6.79,0.00],[0.00,0.00,0.00]], [[0.00,0.00,11.60],[0.00,-0.00,4.50]], [[0.00,0.00,5.77],[0.00,0.00,0.00]]]), + (4, [[-1.88,0.00,-0.08], [10.32,0.00,0.12], [0.00,11.60,0.00], [0.00,0.00,0.00], [0.00,0.00,11.60], [0.00,0.00,0.00]]), + (5, [[15.00,0.00,0.00], [6.56,0.00,-0.04], [0.00,11.60,0.00], [0.00,0.00,0.00], [0.00,0.00,11.60], [0.00,0.00,0.00]]) + ]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-4', + 'name': get_cecum_term('caecum')[0], + 'ontId': get_cecum_term('caecum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_cecum_term('ileum part of cecum')[0], + 'ontId': get_cecum_term('ileum part of cecum')[1] + }] + }) + elif "Human 2" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'Length': 120.0, - 'Number of elements': 3 + "Structure": "1-2-3.2, 4-3-5" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2], [ - (1, [[0.0, 0.0, 0.0], [0.0, 0.0, 60.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]), - (2, [[0.0, 0.0, 60.0], [0.0, 0.0, 60.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]), - (3, [[0.0, 0.0, 120.0], [0.0, 0.0, 60.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]), - (4, [[0.0, 0.0, 180.0], [0.0, 0.0, 60.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]]) - ]) - } ) - } - - ostiumDefaultScaffoldPackages = { - 'Pig 1': ScaffoldPackage(MeshType_3d_ostium1, { + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[-60.630,-80.530,895.250], [-6.170,-10.100,-5.870], [2.660,0.730,-4.050], [2.380,0.990,-1.140], [3.310,-2.970,1.640], [2.380,0.990,-1.140]]), + (2, [[-68.640,-93.290,888.060], [-9.850,-15.420,-8.510], [3.880,1.200,-6.660], [2.380,0.990,-1.140], [2.820,-2.460,1.200], [2.380,0.990,-1.140]]), + (3, [[-80.390,-111.370,878.290], [[-7.790,-0.980,12.360],[-13.650,-20.740,-11.030]], [[20.720,-4.040,12.540],[5.590,1.310,-9.380]], [[2.380,0.990,-1.140],[2.380,0.990,-1.140]], [[2.470,23.830,3.610],[1.510,-1.370,0.710]], [[2.380,0.990,-1.140],[2.380,0.990,-1.140]]]), + (4, [[-71.690,-109.000,866.040], [-9.550,-3.730,12.060], [17.410,-4.850,11.460], [3.730,0.680,4.200], [0.820,19.940,7.200], [3.740,0.690,4.200]]), + (5, [[-87.210,-111.060,890.540], [-4.750,0.410,12.390], [23.270,-3.130,7.880], [2.460,-0.390,-2.950], [3.090,24.460,0.450], [1.830,0.460,-4.310]]) + ]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-4', + 'name': get_cecum_term('caecum')[0], + 'ontId': get_cecum_term('caecum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_cecum_term('ileum part of cecum')[0], + 'ontId': get_cecum_term('ileum part of cecum')[1] + }] + }) + elif "Pig 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, + "Structure": "1-2-3.2, 4-5-6-3-7" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[164.00,29.75,51.53], [0.00,-9.63,-16.67], [-6.00,0.00,0.00], [0.00,0.00,0.00], [0.00,5.20,-3.00], [0.00,0.00,0.00]]), + (2, [[164.00,17.50,30.31], [0.00,-14.87,-25.77], [-10.00,0.00,0.00], [0.00,0.00,0.00], [0.00,8.66,-5.00], [0.00,0.00,0.00]]), + (3, [[164.00,0.00,0.00], [[30.00,0.00,0.00],[0.00,-20.13,-34.85]], [[0.00,37.00,0.00],[-10.00,0.00,0.00]], [[0.00,0.00,0.00],[0.00,0.00,0.00]], [[0.00,0.00,37.00],[0.00,8.66,-5.00]], [[0.00,0.00,0.00],[0.00,0.00,0.00]]]), + (4, [[0.00,0.00,0.00], [60.00,0.00,0.00], [0.00,37.00,0.00], [0.00,0.00,0.00], [0.00,0.00,37.00], [0.00,0.00,0.00]]), + (5, [[60.00,0.00,0.00], [60.00,0.00,0.00], [0.00,37.00,0.00], [0.00,0.00,0.00], [0.00,0.00,37.00], [0.00,0.00,0.00]]), + (6, [[120.00,0.00,0.00], [52.00,0.00,0.00], [0.00,37.00,0.00], [0.00,0.00,0.00], [0.00,0.00,37.00], [0.00,0.00,0.00]]), + (7, [[180.00,0.00,0.00], [2.00,0.00,0.00], [0.00,37.00,0.00], [0.00,0.00,0.00], [0.00,0.00,37.00], [0.00,0.00,0.00]]) + ]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-6', + 'name': get_cecum_term('caecum')[0], + 'ontId': get_cecum_term('caecum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_cecum_term('ileum part of cecum')[0], + 'ontId': get_cecum_term('ileum part of cecum')[1] + }] + }) + +def getDefaultOstiumSettings(): + """ + Generate list of default options for ostium. + """ + options = { 'Number of elements around ostium': 8, 'Number of elements along': 2, - 'Number of elements through wall': 1, # not implemented for > 1 + 'Number of elements through wall': 1, 'Unit scale': 1.0, 'Outlet': False, - 'Ostium diameter': 20.0, - 'Ostium length': 10.0, - 'Ostium wall thickness': 2.0, - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, + 'Ostium wall thickness': 1.6, + 'Ostium wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 10.0, - 'Vessel wall thickness': 2.0, - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, + 'Vessel wall thickness': 1.6, + 'Vessel wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], 'Use linear through vessel wall': True, 'Use cross derivatives': False, 'Refine': False, 'Refine number of elements around': 4, 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }) - } + 'Refine number of elements through wall': 1} + + return options + +def updateOstiumOptions(options, ostiumOptions): + """ + Update ostium sub-scaffold options which depend on parent options. + """ + ostiumOptions['Ostium wall thickness'] = options['Wall thickness'] + ostiumOptions['Vessel wall thickness'] = options['Ileum wall thickness'] + elementsCountThroughWall = options['Number of elements through wall'] + ostiumOptions['Number of elements through wall'] = elementsCountThroughWall + ostiumOptions['Use linear through ostium wall'] = options['Use linear through wall'] + ostiumOptions['Use linear through vessel wall'] = options['Use linear through wall'] + if elementsCountThroughWall == 1: + ostiumOptions['Ostium wall relative thicknesses'] = [1.0] + ostiumOptions['Vessel wall relative thicknesses'] = [1.0] + else: + mucosaRelThickness = options['Mucosa relative thickness'] + submucosaRelThickness = options['Submucosa relative thickness'] + circularRelThickness = options['Circular muscle layer relative thickness'] + longRelThickness = options['Longitudinal muscle layer relative thickness'] + relThicknesses = [mucosaRelThickness, submucosaRelThickness, circularRelThickness, longRelThickness] + ostiumOptions['Ostium wall relative thicknesses'] = relThicknesses + ostiumOptions['Vessel wall relative thicknesses'] = relThicknesses + + return ostiumOptions + + +class MeshType_3d_cecum1(Scaffold_base): + ''' + Generates a 3-D cecum mesh with variable numbers of elements around, along the central line, and through wall. The + cecum is created by a function that generates a cecum segment and uses tubemesh to map the segment along a network + layout. The proximal end of the cecum is closed up with an apex plate. An ostium is included to generate the + ileo-cecal junction. + ''' @staticmethod def getName(): @@ -95,38 +192,35 @@ def getName(): def getParameterSetNames(): return [ 'Default', + 'Human 1', + 'Human 2', 'Pig 1'] @classmethod def getDefaultOptions(cls, parameterSetName='Default'): - centralPathOption = cls.centralPathDefaultScaffoldPackages['Pig 1'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Pig 1'] - options = { - 'Central path': copy.deepcopy(centralPathOption), - 'Number of segments': 5, + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), + 'Number of segments': 1, 'Number of elements around tenia coli': 2, 'Number of elements around haustrum': 8, 'Number of elements along segment': 8, 'Number of elements through wall': 1, - 'Start inner radius': 35.0, - 'Start inner radius derivative': 3.0, - 'End inner radius': 38.0, - 'End inner radius derivative': 3.0, - 'Corner inner radius factor': 0.5, - 'Haustrum inner radius factor': 0.25, - 'Segment length end derivative factor': 1.0, - 'Segment length mid derivative factor': 4.0, + 'Corner outer radius factor': 0.536, + 'Haustrum outer radius factor': 0.464, + 'Segment length end derivative factor': 0.5, + 'Segment length mid derivative factor': 1.0, 'Number of tenia coli': 3, - 'Start tenia coli width': 5.0, - 'Start tenia coli width derivative': 0.0, - 'End tenia coli width': 5.0, - 'End tenia coli width derivative': 0.0, + 'Start tenia coli width': 2.0, + 'Start tenia coli width derivative': 3.3, + 'End tenia coli width': 5.3, + 'End tenia coli width derivative': 3.3, 'Tenia coli thickness': 0.5, - 'Wall thickness': 2.0, - 'Ileocecal junction': copy.deepcopy(ostiumOption), - 'Ileocecal junction angular position degrees': 60.0, - 'Ileocecal junction position along factor': 0.5, + 'Wall thickness': 1.6, + 'Ileum wall thickness': 1.6, + 'Mucosa relative thickness': 0.55, + 'Submucosa relative thickness': 0.15, + 'Circular muscle layer relative thickness': 0.25, + 'Longitudinal muscle layer relative thickness': 0.05, 'Use cross derivatives': False, 'Use linear through wall': True, 'Refine': False, @@ -134,24 +228,43 @@ def getDefaultOptions(cls, parameterSetName='Default'): 'Refine number of elements along': 1, 'Refine number of elements through wall': 1 } - cls.updateSubScaffoldOptions(options) + + if 'Human 2' in parameterSetName: + options['Number of elements along segment'] = 12 + options['Segment length mid derivative factor'] = 3.0 + options['Start tenia coli width'] = 10.0 + options['Start tenia coli width derivative'] = 0.0 + options['End tenia coli width'] = 10.0 + options['End tenia coli width derivative'] = 0.0 + options[ 'Tenia coli thickness'] = 1.6 + + elif 'Pig 1' in parameterSetName: + options['Number of segments'] = 5 + options['Number of elements around haustrum'] = 12 + options['Haustrum outer radius factor'] = 0.25 + options['Segment length end derivative factor'] = 0.5 + options['Segment length mid derivative factor'] = 4.0 + options['Start tenia coli width'] = 5.0 + options['Start tenia coli width derivative'] = 0.0 + options['End tenia coli width'] = 5.0 + options['End tenia coli width derivative'] = 0.0 + options['Wall thickness'] = 2.0 + options['Ileum wall thickness'] = 2.0 + + options['Base parameter set'] = parameterSetName return options @staticmethod def getOrderedOptionNames(): return [ - 'Central path', + 'Network layout', 'Number of segments', 'Number of elements around tenia coli', 'Number of elements around haustrum', 'Number of elements along segment', 'Number of elements through wall', - 'Start inner radius', - 'Start inner radius derivative', - 'End inner radius', - 'End inner radius derivative', - 'Corner inner radius factor', - 'Haustrum inner radius factor', + 'Corner outer radius factor', + 'Haustrum outer radius factor', 'Segment length end derivative factor', 'Segment length mid derivative factor', 'Number of tenia coli', @@ -161,9 +274,11 @@ def getOrderedOptionNames(): 'End tenia coli width derivative', 'Tenia coli thickness', 'Wall thickness', - 'Ileocecal junction', - 'Ileocecal junction angular position degrees', - 'Ileocecal junction position along factor', + 'Ileum wall thickness', + 'Mucosa relative thickness', + 'Submucosa relative thickness', + 'Circular muscle layer relative thickness', + 'Longitudinal muscle layer relative thickness', 'Use cross derivatives', 'Use linear through wall', 'Refine', @@ -173,18 +288,14 @@ def getOrderedOptionNames(): @classmethod def getOptionValidScaffoldTypes(cls, optionName): - if optionName == 'Central path': - return [ MeshType_1d_path1 ] - if optionName == 'Ileocecal junction': - return [ MeshType_3d_ostium1 ] + if optionName == 'Network layout': + return [ MeshType_1d_network_layout1 ] return [] @classmethod def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): - if optionName == 'Central path': - return list(cls.centralPathDefaultScaffoldPackages.keys()) - if optionName == 'Ileocecal junction': - return list(cls.ostiumDefaultScaffoldPackages.keys()) + if optionName == 'Network layout': + return cls.getParameterSetNames() assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() return scaffoldType.getParameterSetNames() @@ -198,22 +309,16 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non if parameterSetName: assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() - if optionName == 'Central path': + if optionName == 'Network layout': if not parameterSetName: - parameterSetName = list(cls.centralPathDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.centralPathDefaultScaffoldPackages[parameterSetName]) - if optionName == 'Ileocecal junction': - if not parameterSetName: - parameterSetName = list(cls.ostiumDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.ostiumDefaultScaffoldPackages[parameterSetName]) + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' @classmethod def checkOptions(cls, options): - if not options['Central path'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Central path'): - options['Central path'] = cls.getOptionScaffoldPackage('Central path', MeshType_1d_path1) - if not options['Ileocecal junction'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Ileocecal junction'): - options['Ileocecal junction'] = cls.getOptionScaffoldPackage('Ileocecal junction', MeshType_3d_ostium1) + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) for key in [ 'Number of segments', 'Refine number of elements around', @@ -224,13 +329,8 @@ def checkOptions(cls, options): for key in [ 'Number of elements around tenia coli', 'Number of elements around haustrum', - 'Number of elements along segment', - 'Start inner radius', - 'Start inner radius derivative', - 'End inner radius', - 'End inner radius derivative', - 'Corner inner radius factor', - 'Haustrum inner radius factor', + 'Corner outer radius factor', + 'Haustrum outer radius factor', 'Segment length end derivative factor', 'Segment length mid derivative factor', 'Number of tenia coli', @@ -238,25 +338,16 @@ def checkOptions(cls, options): 'Start tenia coli width derivative', 'End tenia coli width', 'End tenia coli width derivative', - 'Ileocecal junction angular position degrees', - 'Ileocecal junction position along factor', 'Tenia coli thickness', 'Wall thickness']: if options[key] < 0.0: options[key] = 0.0 - if options['Number of elements through wall'] != 1: - options['Number of elements through wall'] = 1 - cls.updateSubScaffoldOptions(options) - - @classmethod - def updateSubScaffoldOptions(cls, options): - ''' - Update ostium sub-scaffold options which depend on parent options. - ''' - wallThickness = options['Wall thickness'] - ostiumOptions = options['Ileocecal junction'] - ostiumSettings = ostiumOptions.getScaffoldSettings() - ostiumSettings['Ostium wall thickness'] = wallThickness + if options['Number of elements along segment'] < 8: + options['Number of elements along segment'] = 8 + if options['Number of elements along segment'] % 4 > 0: + options['Number of elements along segment'] = options['Number of elements along segment'] // 4 * 4 + if options['Number of elements through wall'] != (1 or 4): + options['Number of elements through wall'] = 4 @classmethod def generateBaseMesh(cls, region, options): @@ -266,445 +357,15 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ - cls.updateSubScaffoldOptions(options) - centralPath = options['Central path'] - segmentCount = options['Number of segments'] - startPhase = 0.0 - elementsCountAroundTC = options['Number of elements around tenia coli'] - elementsCountAroundHaustrum = options['Number of elements around haustrum'] - elementsCountAlongSegment = options['Number of elements along segment'] - elementsCountThroughWall = options['Number of elements through wall'] - startInnerRadius = options['Start inner radius'] - startInnerRadiusDerivative = options['Start inner radius derivative'] - endInnerRadius = options['End inner radius'] - endInnerRadiusDerivative = options['End inner radius derivative'] - cornerInnerRadiusFactor = options['Corner inner radius factor'] - haustrumInnerRadiusFactor = options['Haustrum inner radius factor'] - segmentLengthEndDerivativeFactor = options['Segment length end derivative factor'] - segmentLengthMidDerivativeFactor = options['Segment length mid derivative factor'] - tcCount = options['Number of tenia coli'] - startTCWidth = options['Start tenia coli width'] - startTCWidthDerivative = options['Start tenia coli width derivative'] - endTCWidth = options['End tenia coli width'] - endTCWidthDerivative = options['End tenia coli width derivative'] - tcThickness = options['Tenia coli thickness'] - wallThickness = options['Wall thickness'] - useCrossDerivatives = options['Use cross derivatives'] - useCubicHermiteThroughWall = not(options['Use linear through wall']) - elementsCountAlong = int(elementsCountAlongSegment*segmentCount) - elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum)*tcCount - # Angle between the middle of first tenia coli to ostium location - ostiumPositionAngleAround = math.radians(options['Ileocecal junction angular position degrees']) - # Factor when scaled with segmentLength will give distance between the - # junction and distal end of the cecum - ostiumPositionAlongFactor = options['Ileocecal junction position along factor'] - - ostiumOptions = options['Ileocecal junction'] - ostiumSettings = ostiumOptions.getScaffoldSettings() - ostiumDiameter = ostiumSettings['Ostium diameter'] - - firstNodeIdentifier = 1 - firstElementIdentifier = 1 - - # Central path - tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) - tmpFieldmodule = tmpRegion.getFieldmodule() - cx, cd1, cd2, cd12 = get_nodeset_path_field_parameters( - tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES), - tmpFieldmodule.findFieldByName('coordinates'), - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2]) - del tmpFieldmodule - del tmpRegion - - # find arclength of cecum - cecumLength = 0.0 - elementsCountIn = len(cx) - 1 - sd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, fixAllDirections=True, - magnitudeScalingMode=interp.DerivativeScalingMode.HARMONIC_MEAN) - for e in range(elementsCountIn): - arcLength = interp.getCubicHermiteArcLength(cx[e], sd1[e], cx[e + 1], sd1[e + 1]) - # print(e+1, arcLength) - cecumLength += arcLength - - # Sample central path - smoothd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, - magnitudeScalingMode = interp.DerivativeScalingMode.HARMONIC_MEAN) - sxCecum, sd1Cecum, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, smoothd1, elementsCountAlong) - sd2Cecum, sd12Cecum = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) - - # Calculate segment length - segmentLength = cecumLength / segmentCount - - # Generate variation of radius & tc width along length - innerRadiusAlongCecum = [] - dInnerRadiusAlongCecum = [] - tcWidthAlongCecum = [] - - closedProximalEnd = True - - for n2 in range(elementsCountAlongSegment*segmentCount + 1): - xi = 1/(elementsCountAlongSegment*segmentCount) * n2 - - radius = interp.interpolateCubicHermite([startInnerRadius], [startInnerRadiusDerivative], - [endInnerRadius], [endInnerRadiusDerivative], xi)[0] - innerRadiusAlongCecum.append(radius) - dRadius = interp.interpolateCubicHermiteDerivative([startInnerRadius], [startInnerRadiusDerivative], - [endInnerRadius], [endInnerRadiusDerivative], xi)[0] - dInnerRadiusAlongCecum.append(dRadius) - tcWidth = interp.interpolateCubicHermite([startTCWidth], [startTCWidthDerivative], - [endTCWidth], [endTCWidthDerivative], xi)[0] - tcWidthAlongCecum.append(tcWidth) - - haustrumInnerRadiusFactorAlongCecum = [haustrumInnerRadiusFactor] * (elementsCountAlong + 1) - - xToSample = [] - d1ToSample = [] - d2ToSample = [] - - elementsCountAroundHalfHaustrum = int((elementsCountAroundTC + elementsCountAroundHaustrum)*0.5) - - # Create object - colonSegmentTubeMeshInnerPoints = ColonSegmentTubeMeshInnerPoints( - region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, - tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, - segmentLength, wallThickness, cornerInnerRadiusFactor, haustrumInnerRadiusFactorAlongCecum, - innerRadiusAlongCecum, dInnerRadiusAlongCecum, tcWidthAlongCecum, startPhase) - - # Create annotation - cecumGroup = AnnotationGroup(region, get_cecum_term("caecum")) - annotationGroupsAlong = [] - for i in range(elementsCountAlong): - annotationGroupsAlong.append([cecumGroup]) - - annotationGroupsThroughWall = [] - for i in range(elementsCountThroughWall): - annotationGroupsThroughWall.append([ ]) - - for nSegment in range(segmentCount): - # Make regular segments - xInner, d1Inner, d2Inner, transitElementList, segmentAxis, annotationGroupsAround \ - = colonSegmentTubeMeshInnerPoints.getColonSegmentTubeMeshInnerPoints(nSegment) - - # Replace first half of first segment with apex and sample along apex and second half of segment - if nSegment == 0: - xFirstSegmentSampled, d1FirstSegmentSampled, d2FirstSegmentSampled, d1FirstDirectionVector = \ - getApexSegmentForCecum(xInner, d1Inner, d2Inner, elementsCountAroundHalfHaustrum, - elementsCountAroundTC, elementsCountAround, elementsCountAlongSegment, - tcCount) - - xToSample += xFirstSegmentSampled - d1ToSample += d1FirstSegmentSampled - d2ToSample += d2FirstSegmentSampled - else: - xInnerExtrude = [] - for n in range(len(xInner)): - xInnerExtrude.append([xInner[n][0], xInner[n][1], xInner[n][2] + segmentLength*nSegment]) - xToSample += xInnerExtrude[elementsCountAround:] - d1ToSample += d1Inner[elementsCountAround:] - d2ToSample += d2Inner[elementsCountAround:] - - # Sample along length - xToWarp, d1ToWarp, d2ToWarp = sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVector, - elementsCountAroundHalfHaustrum, elementsCountAroundTC, - elementsCountAround, elementsCountAlong, tcCount) - - # Ensure cecum starts at z = 0.0 - minZ = xToWarp[0][2] - for n2 in range(elementsCountAlong + 1): - zFirstNodeAlong = xToWarp[n2 * elementsCountAround][2] - if zFirstNodeAlong < minZ: - minZ = zFirstNodeAlong - - for n in range(len(xToWarp)): - xToWarp[n][2] = xToWarp[n][2] - minZ - - # Project reference point for warping onto central path - sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ - tubemesh.getPlaneProjectionOnCentralPath(xToWarp, elementsCountAround, elementsCountAlong, - cecumLength, sxCecum, sd1Cecum, sd2Cecum, sd12Cecum) - - # Warp points - xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = \ - tubemesh.warpSegmentPoints(xToWarp, d1ToWarp, d2ToWarp, segmentAxis, sxRefList, sd1RefList, - sd2ProjectedListRef, elementsCountAround, elementsCountAlong, - zRefList) - - # Create coordinates and derivatives - wallThicknessList = [wallThickness] * (elementsCountAlong + 1) - - relativeThicknessList = [] - xList, d1List, d2List, d3List, curvatureList = tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, - d2WarpedList, d3WarpedUnitList, wallThicknessList, relativeThicknessList, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, transitElementList, outward=True) - - # Deal with multiple nodes at end point for closed proximal end - xApexInner = xList[0] - # arclength between apex point and corresponding point on next face - mag = interp.getCubicHermiteArcLength(xList[0], d2List[0], xList[elementsCountAround*2], - d2List[elementsCountAround*2]) - d2ApexInner = vector.setMagnitude(sd2Cecum[0], mag) - d1ApexInner = vector.crossproduct3(sd1Cecum[0], d2ApexInner) - d1ApexInner = vector.setMagnitude(d1ApexInner, mag) - d3ApexUnit = vector.normalise(vector.crossproduct3(vector.normalise(d1ApexInner), - vector.normalise(d2ApexInner))) - d3ApexInner = [d3ApexUnit[c] * wallThickness/elementsCountThroughWall for c in range(3)] - - xCecum = [] - d1Cecum = [] - d2Cecum = [] - d3Cecum = [] - for n3 in range(elementsCountThroughWall + 1): - xApex = [xApexInner[c] + d3ApexUnit[c] * wallThickness/elementsCountThroughWall * n3 for c in range(3)] - xCecum.append(xApex) - d1Cecum.append(d1ApexInner) - d2Cecum.append(d2ApexInner) - d3Cecum.append(d3ApexInner) - - xCecum += xList[(elementsCountThroughWall+1)*elementsCountAround:] - d1Cecum += d1List[(elementsCountThroughWall + 1) * elementsCountAround:] - d2Cecum += d2List[(elementsCountThroughWall + 1) * elementsCountAround:] - d3Cecum += d3List[(elementsCountThroughWall + 1) * elementsCountAround:] - - xFlat = d1Flat = d2Flat = [] - xOrgan = d1Organ = d2Organ = [] - - # Create nodes and elements - if tcThickness > 0: - tubeTCWidthList = colonSegmentTubeMeshInnerPoints.getTubeTCWidthList() - xCecum, d1Cecum, d2Cecum, d3Cecum, annotationGroupsAround = getTeniaColi( - region, xCecum, d1Cecum, d2Cecum, d3Cecum, curvatureList, tcCount, elementsCountAroundTC, - elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, - tubeTCWidthList, tcThickness, sxRefList, annotationGroupsAround, closedProximalEnd) - - nextNodeIdentifier, nextElementIdentifier, annotationGroups = createNodesAndElementsTeniaColi( - region, xCecum, d1Cecum, d2Cecum, d3Cecum, xFlat, d1Flat, d2Flat, xOrgan, d1Organ, d2Organ, None, - elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, - tcCount, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, - closedProximalEnd) - - else: - nextNodeIdentifier, nextElementIdentifier, annotationGroups = tubemesh.createNodesAndElements( - region, xCecum, d1Cecum, d2Cecum, d3Cecum, xFlat, d1Flat, d2Flat, xOrgan, d1Organ, d2Organ, None, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, - annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, - closedProximalEnd) - - # Add ostium on track surface between two tenia on the last segment - elementsAroundTrackSurface = elementsCountAroundHaustrum - elementsAlongTrackSurface = elementsCountAlongSegment - - # Find region where ostium sits - sectorIdx = ostiumPositionAngleAround // (2*math.pi/tcCount) - startIdxElementsAround = int((elementsCountAroundHaustrum + elementsCountAroundTC)*sectorIdx + - elementsCountAroundTC*0.5) - baseNodesIdx = (elementsCountThroughWall + 1) + \ - + (elementsCountAround * (elementsCountThroughWall + 1) + - ((elementsCountAroundTC - 1)*tcCount if tcThickness > 0.0 else 0)) * \ - (elementsCountAlongSegment * (segmentCount - 1) - 1) + elementsCountAround - xTrackSurface = [] - d1TrackSurface = [] - d2TrackSurface = [] - for n2 in range(elementsCountAlongSegment + 1): - for n1 in range(elementsCountAroundHaustrum + 1): - idx = baseNodesIdx + \ - (elementsCountAround * (elementsCountThroughWall + 1) + - ((elementsCountAroundTC - 1)*tcCount if tcThickness > 0.0 else 0)) * n2 + \ - startIdxElementsAround + n1 - xTrackSurface.append(xCecum[idx]) - d1TrackSurface.append(d1Cecum[idx]) - d2TrackSurface.append(d2Cecum[idx]) - - trackSurfaceOstium = TrackSurface(elementsAroundTrackSurface, elementsAlongTrackSurface, - xTrackSurface, d1TrackSurface, d2TrackSurface) - # Find centre position - v1 = xList[0] - v2 = xList[int(elementsCountAroundTC*0.5)] - d1 = d1List[0] - d2 = d1List[int(elementsCountAroundTC*0.5)] - arcLengthTC = interp.getCubicHermiteArcLength(v1, d1, v2, d2) - angleToTCEdge = arcLengthTC / startInnerRadius - angleOstium = ostiumDiameter / startInnerRadius - dAngle = (2 * math.pi / tcCount - 2 * angleToTCEdge) / elementsCountAroundHaustrum - angleAroundInSector = ostiumPositionAngleAround % (2 * math.pi / tcCount) - assert angleAroundInSector > angleToTCEdge + angleOstium * 0.5 and \ - angleAroundInSector < (2*math.pi/tcCount) - angleToTCEdge - angleOstium*0.5,\ - 'Ileocecal junction cannot sit on tenia coli' - - ei1Centre = int((angleAroundInSector - angleToTCEdge) // dAngle) - xi1 = ((angleAroundInSector - angleToTCEdge) - dAngle * ei1Centre) / dAngle - - ostiumDistanceFromCecumDistal = segmentLength * ostiumPositionAlongFactor - - arcLength = interp.getCubicHermiteArcLength(sxRefList[-1], sd1RefList[-1], - sxRefList[-2], sd1RefList[-2]) - distance = arcLength - - for e in range(len(sxRefList)-2, 0, -1): - if ostiumDistanceFromCecumDistal > distance: - arcLength = interp.getCubicHermiteArcLength(sxRefList[e - 1], sd1RefList[e - 1], - sxRefList[e], sd1RefList[e]) - distance += arcLength - else: - ei2Centre = e - elementsCountAlongSegment*(segmentCount-1) - xi2 = (distance - ostiumDistanceFromCecumDistal) / arcLength - break - - centrePosition = TrackSurfacePosition(ei1Centre, ei2Centre, xi1, xi2) - xCentre, d1Centre, d2Centre = trackSurfaceOstium.evaluateCoordinates(centrePosition, derivatives=True) - axis1 = d1Centre - - # Find boundary of ostium on tracksurface - ei1Left, ei1Right, ei2Bottom, ei2Top = getElementIdxOfOstiumBoundary(centrePosition, trackSurfaceOstium, - ostiumDiameter) - - # Extend boundary - ei1Left -= 1 - ei1Right += 1 - ei2Bottom -= 1 - ei2Top += 1 - - assert (ei1Left >= 0 and ei1Right < elementsAroundTrackSurface and - ei2Bottom >= 0 and ei2Top < elementsAlongTrackSurface), \ - 'cecum1.py: Insufficient elements around ostium on tracksurface to make annulus mesh.' - - nodeStart = int(baseNodesIdx + ei2Bottom * (elementsCountAround * (elementsCountThroughWall + 1) + \ - ((elementsCountAroundTC - 1)*tcCount if tcThickness > 0.0 else 0)) + ei1Centre + \ - sectorIdx*(elementsCountAroundHaustrum + elementsCountAroundTC) + elementsCountAroundTC*0.5) - \ - elementsCountAround + 1 # only for 1 layer through wall - - # Store elements and nodes to be deleted later from tracked surface - deleteElementsCountAcross = ei1Right - ei1Left + 1 - deleteElementsCountAlong = ei2Top - ei2Bottom + 1 - deleteElementIdxStart = int((elementsCountAround * elementsCountThroughWall + - (elementsCountAroundTC * tcCount if tcThickness > 0.0 else 0.0)) * - (elementsCountAlong - elementsCountAlongSegment + ei2Bottom) + - elementsCountAroundTC * 0.5 + - (elementsCountAroundTC + elementsCountAroundHaustrum) * sectorIdx + ei1Left + 1) - - deleteElementIdentifier = [] - for n2 in range(deleteElementsCountAlong): - for n1 in range(deleteElementsCountAcross): - elementIdx = deleteElementIdxStart + n1 + n2 * (elementsCountAround + - (int(elementsCountAroundTC * tcCount) - if tcThickness > 0.0 else 0)) - deleteElementIdentifier.append(elementIdx) - - deleteNodeIdxStart = nodeStart - int(deleteElementsCountAcross * 0.5) - deleteNodeIdentifier = [] - for n2 in range(deleteElementsCountAlong + 1): - for n3 in range(elementsCountThroughWall + 1): - for n1 in range(deleteElementsCountAcross + 1): - nodeIdx = deleteNodeIdxStart + n1 + elementsCountAround * n3 + \ - n2 * (elementsCountAround * (elementsCountThroughWall + 1) + - ((elementsCountAroundTC - 1) * tcCount if tcThickness > 0.0 else 0)) - deleteNodeIdentifier.append(nodeIdx) - - innerEndPoints_Id = [] - endProportions = [] - for n1 in range(ei1Centre - ei1Left + 1): - idx = nodeStart - n1 - innerEndPoints_Id.append(idx) - endProportions.append([(ei1Centre - n1)/elementsAroundTrackSurface, ei2Bottom/elementsAlongTrackSurface]) - for n2 in range(ei2Top - ei2Bottom + 1): - idx = idx + 2 * elementsCountAround + ((elementsCountAroundTC - 1) * tcCount if tcThickness > 0.0 else 0) - innerEndPoints_Id.append(idx) - endProportions.append([ei1Left/elementsAroundTrackSurface, (ei2Bottom + n2 + 1)/elementsAlongTrackSurface]) - for n1 in range(1, ei1Right - ei1Left + 2): - idx = idx + 1 - innerEndPoints_Id.append(idx) - endProportions.append([(ei1Left + n1) / elementsAroundTrackSurface, (ei2Top+1) / elementsAlongTrackSurface]) - for n2 in range(ei2Top - ei2Bottom + 1): - idx = idx - 2 * elementsCountAround - ((elementsCountAroundTC - 1) * tcCount if tcThickness > 0.0 else 0) - innerEndPoints_Id.append(idx) - endProportions.append( - [(ei1Right+1) / elementsAroundTrackSurface, (ei2Top - n2) / elementsAlongTrackSurface]) - for n1 in range(ei1Right - ei1Centre): - idx = idx - 1 - innerEndPoints_Id.append(idx) - endProportions.append([(ei1Right - n1) / elementsAroundTrackSurface, ei2Bottom / elementsAlongTrackSurface]) - - innerEndPoints_x = [] - innerEndPoints_d1 = [] - innerEndPoints_d2 = [] - - outerEndPoints_Id = [] - outerEndPoints_x = [] - outerEndPoints_d1 = [] - outerEndPoints_d2 = [] - - for i in range(len(innerEndPoints_Id)): - innerNode = innerEndPoints_Id[i] - innerEndPoints_x.append(xCecum[innerNode-1]) - innerEndPoints_d1.append(d1Cecum[innerNode - 1]) - innerEndPoints_d2.append(d2Cecum[innerNode - 1]) - - outerNode = innerNode + elementsCountAround - outerEndPoints_Id.append(outerNode) - outerEndPoints_x.append(xCecum[outerNode - 1]) - outerEndPoints_d1.append(d1Cecum[outerNode - 1]) - outerEndPoints_d2.append(d2Cecum[outerNode - 1]) - - endPoints_Id = [innerEndPoints_Id, outerEndPoints_Id] - endPoints_x = [innerEndPoints_x, outerEndPoints_x] - endPoints_d1 = [innerEndPoints_d1, outerEndPoints_d1] - endPoints_d2 = [innerEndPoints_d2, outerEndPoints_d2] - - endDerivativesMap = [[None] * len(innerEndPoints_Id), [None] * len(innerEndPoints_Id)] - count = 0 - for n1 in range(ei1Centre - ei1Left): - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((-1, 0, 0), (0, -1, 0), None) - count += 1 - - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((-1, 0, 0), (-1, -1, 0), None, (0, 1, 0)) - count += 1 - for n2 in range(ei2Top - ei2Bottom): - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((0, 1, 0), (-1, 0, 0), None) - count += 1 - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((0, 1, 0), (-1, 1, 0), None, (1, 0, 0)) - count += 1 - for n1 in range(1, ei1Right - ei1Left + 1): - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((1, 0, 0), (0, 1, 0), None) - count += 1 - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((1, 0, 0), (1, 1, 0), None, (0, -1, 0)) - count += 1 - for n2 in range(1, ei2Top - ei2Bottom + 1): - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((0, -1, 0), (1, 0, 0), None) - count += 1 - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((0, -1, 0), (1, -1, 0), None, (-1, 0, 0)) - count += 1 - for n1 in range(ei1Right - ei1Centre): - endDerivativesMap[0][count] = endDerivativesMap[1][count] = ((-1, 0, 0), (0, -1, 0), None) - count += 1 - - ostiumSettings['Number of elements around ostium'] = len(innerEndPoints_Id) - - fm = region.getFieldmodule() - mesh = fm.findMeshByDimension(3) - nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - - cecumMeshGroup = cecumGroup.getMeshGroup(mesh) - - nextNodeIdentifier, nextElementIdentifier, (o1_x, o1_d1, o1_d2, o1_d3, o1_NodeId, o1_Positions) = \ - generateOstiumMesh(region, ostiumSettings, trackSurfaceOstium, centrePosition, axis1, - nextNodeIdentifier, nextElementIdentifier, ostiumMeshGroups= [cecumMeshGroup] ) - - startProportions = [] - for n in range(len(innerEndPoints_Id)): - startProportions.append(trackSurfaceOstium.getProportion(o1_Positions[n])) - - nextNodeIdentifier, nextElementIdentifier = createAnnulusMesh3d( - nodes, mesh, nextNodeIdentifier, nextElementIdentifier, - o1_x, o1_d1, o1_d2, None, o1_NodeId, None, - endPoints_x, endPoints_d1, endPoints_d2, None, endPoints_Id, endDerivativesMap, - elementsCountRadial = 2, meshGroups = [cecumMeshGroup], tracksurface = trackSurfaceOstium, - startProportions = startProportions, endProportions = endProportions) - - # Delete elements under annulus mesh - mesh_destroy_elements_and_nodes_by_identifiers(mesh, deleteElementIdentifier) + nextNodeIdentifier = 1 + nextElementIdentifier = 1 + geometricNetworkLayout = options['Network layout'] + cecumTermsAlong = ['caecum', 'ileum part of cecum'] + geometricNetworkLayout = CecumNetworkLayout(region, geometricNetworkLayout, cecumTermsAlong) + annotationGroups, nextNodeIdentifier, nextElementIdentifier = \ + createCecumMesh3d(region, options, geometricNetworkLayout, nextNodeIdentifier, + nextElementIdentifier)[0:3] return annotationGroups, None @@ -723,10 +384,10 @@ def refineMesh(cls, meshrefinement, options): refineElementsCountThroughWall) return -def getApexSegmentForCecum(xInner, d1Inner, d2Inner, elementsCountAroundHalfHaustrum, +def getApexSegmentForCecum(xOuter, d1Outer, d2Outer, elementsCountAroundHalfHaustrum, elementsCountAroundTC, elementsCountAround, elementsCountAlongSegment, tcCount): """ - Generates the inner coordinates and derivatives for a cecum segment on the closed end. + Generates the outer coordinates and derivatives for a cecum segment on the closed end. The closed end is a single node and segment is created by sampling curves between the point on closed end with nodes on the length along second half of a colon segment. :param xInner: coordinates of a colon segment. @@ -745,15 +406,15 @@ def getApexSegmentForCecum(xInner, d1Inner, d2Inner, elementsCountAroundHalfHaus xFirstSegment = [[0.0, 0.0, 0.0] for c in range(elementsCountAround)] # Compile nodes and d2 for sampling - xFirstSegment += xInner[elementsCountAround * int(elementsCountAlongSegment * 0.5):] # second half of first regular segment - d1FirstDirectionVector = vector.normalise(d1Inner[elementsCountAround]) # Store direction vector of first d1 intra-haustral for later - d2Vector = xInner[elementsCountAround * int(elementsCountAlongSegment * 0.5): + xFirstSegment += xOuter[elementsCountAround * int(elementsCountAlongSegment * 0.5):] # second half of first regular segment + d1FirstDirectionVector = vector.normalise(d1Outer[elementsCountAround]) # Store direction vector of first d1 intra-haustral for later + d2Vector = xOuter[elementsCountAround * int(elementsCountAlongSegment * 0.5): elementsCountAround * (int(elementsCountAlongSegment * 0.5) + 1)] # half face of segment - apex d2FirstSegment = [] for c in range(elementsCountAround): d2 = [d2Vector[c][0], d2Vector[c][1], 0.0 ] # project onto x-y plane to get d2 pointing vertically d2FirstSegment.append(d2) - d2FirstSegment += d2Inner[elementsCountAround * int(elementsCountAlongSegment*0.5):] + d2FirstSegment += d2Outer[elementsCountAround * int(elementsCountAlongSegment*0.5):] # Sample along first segment xFirstSegmentSampledRaw = [] @@ -825,9 +486,9 @@ def getApexSegmentForCecum(xInner, d1Inner, d2Inner, elementsCountAroundHalfHaus def getD1ForFullProfileFromHalfHaustrum(d1HaustrumHalfSet, tcCount): """ Get full profile from half haustrum - :param d1HaustrumHalfSet: - :param tcCount: - :return: + :param d1HaustrumHalfSet: d1 for first half of haustrum + :param tcCount: Number of tenia coli + :return: d1 for nodes around the entire haustrum """ d1HaustrumHalfSet2 = [] d1Haustra = [] @@ -875,8 +536,8 @@ def sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVe :return: nodes and derivatives for equally spaced points. """ - xInnerRaw = [] - d2InnerRaw = [] + xOuterRaw = [] + d2OuterRaw = [] xSampledAlongLength = [] d1SampledAlongLength = [] d2SampledAlongLength = [] @@ -891,8 +552,8 @@ def sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVe xSampled, d2Sampled, se, sxi, _ = interp.sampleCubicHermiteCurves(xForSamplingAlong, d2ForSamplingAlong, elementsCountAlong, arcLengthDerivatives=True) - xInnerRaw.append(xSampled) - d2InnerRaw.append(d2Sampled) + xOuterRaw.append(xSampled) + d2OuterRaw.append(d2Sampled) # Re-arrange sample order & calculate dx_ds1 and dx_ds3 from dx_ds2 for n2 in range(elementsCountAlong + 1): @@ -900,12 +561,12 @@ def sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVe d2Around = [] for n1 in range(elementsCountAroundHalfHaustrum + 1): - x = xInnerRaw[n1][n2] - d2 = d2InnerRaw[n1][n2] + x = xOuterRaw[n1][n2] + d2 = d2OuterRaw[n1][n2] xAround.append(x) d2Around.append(d2) - d1InnerAroundList = [] + d1OuterAroundList = [] if n2 == 0: d1Corrected = d1ToSample[:elementsCountAroundHalfHaustrum + 1] @@ -917,15 +578,15 @@ def sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVe d2 = [v2[c] - v1[c] for c in range(3)] arcLengthAround = interp.computeCubicHermiteArcLength(v1, d1, v2, d2, True) dx_ds1 = [c * arcLengthAround for c in vector.normalise(d1)] - d1InnerAroundList.append(dx_ds1) + d1OuterAroundList.append(dx_ds1) # Account for d1 of node sitting on half haustrum d1 = vector.normalise([xAround[elementsCountAroundHalfHaustrum][c] - xAround[elementsCountAroundHalfHaustrum - 1][c] for c in range(3)]) dx_ds1 = [c * arcLengthAround for c in d1] - d1InnerAroundList.append(dx_ds1) + d1OuterAroundList.append(dx_ds1) - if d1InnerAroundList: - d1Smoothed = interp.smoothCubicHermiteDerivativesLine(xAround, d1InnerAroundList, fixStartDerivative=True) + if d1OuterAroundList: + d1Smoothed = interp.smoothCubicHermiteDerivativesLine(xAround, d1OuterAroundList, fixStartDerivative=True) d1TCEdge = vector.setMagnitude(d1Smoothed[int(elementsCountAroundTC * 0.5)], vector.magnitude(d1Smoothed[int(elementsCountAroundTC * 0.5 - 1)])) d1Transition = vector.setMagnitude(d1Smoothed[int(elementsCountAroundTC * 0.5 + 1)], @@ -944,105 +605,1666 @@ def sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVe return xSampledAlongLength, d1SampledAlongLength, d2SampledAlongLength -def getElementIdxOfOstiumBoundary(centrePosition, trackSurfaceOstium, ostiumDiameter): +def findDerivativeBetweenPoints(v1, v2): """ - Finds the element indices of the boundaries of elements on tracksurface that surround - the ostium. Indices based on numbering for elements around and along tracksurface. - Boundary lies on xi=0 of elements on left and bottom boundaries and xi = 1 for right and - top boundaries. - :param centrePosition: surface description for centre of ostium. - :param trackSurfaceOstium: surface description for tracksurface. - :param ostiumDiameter: Diameter of ostium. - :return: element indices on the left, right, bottom and top boundaries around tracksurface. + Find vector difference between two points and rescale vector difference using cubic hermite arclength + between the points to derive the derivative between the points. + :param v1: start vector + :param v2: end vector + :return: derivative of between v1 and v2 """ + d = [v2[c] - v1[c] for c in range(3)] + arcLengthAround = interp.computeCubicHermiteArcLength(v1, d, v2, d, True) + d = [c * arcLengthAround for c in vector.normalise(d)] + + return d - elementsAroundTrackSurface = trackSurfaceOstium._elementsCount1 - elementsAlongTrackSurface = trackSurfaceOstium._elementsCount2 - ei1 = centrePosition.e1 - ei2 = centrePosition.e2 - xi1 = centrePosition.xi1 - xi2 = centrePosition.xi2 - xCentre, d1Centre, d2Centre = trackSurfaceOstium.evaluateCoordinates(centrePosition, derivatives=True) - - # Left boundary - leftPositionOfCentreElement = TrackSurfacePosition(ei1, ei2, 0, xi2) - xLeft, d1Left, _ = trackSurfaceOstium.evaluateCoordinates(leftPositionOfCentreElement, derivatives=True) - distxLeftToxCentre = interp.computeCubicHermiteArcLength(xLeft, d1Left, xCentre, d1Centre, False) - remainingLength = ostiumDiameter * 0.5 - distxLeftToxCentre - xCurrent = xLeft - d1Current = d1Left - - for n1 in range(ei1, -1, -1): - if remainingLength > 0.0: - prevPosition = TrackSurfacePosition(n1-1, ei2, 0, xi2) - xPrev, d1Prev, _ = trackSurfaceOstium.evaluateCoordinates(prevPosition, derivatives=True) - distPrevToxCurrent = interp.computeCubicHermiteArcLength(xPrev, d1Prev, xCurrent, d1Current, False) - remainingLength -= distPrevToxCurrent - xCurrent = xPrev - d1Current = d1Prev +def createCecumMesh3d(region, options, networkLayout, nodeIdentifier, elementIdentifier, nodeIdProximalIleum=[], + xProximalIleum=[], d1ProximalIleum=[], d2ProximalIleum=[], d3ProximalIleum=[]): + """ + Generates a cecum scaffold in the region using a network layout and parameter options. + :param region: Region to create elements in. + :param options: Parameter options for scaffold. + :param networkLayout: Network layout through the axis of the cecum scaffold. + :param nodeIdentifier: First node identifier. + :param elementIdentifier: First element identifier. + :param nodeIdProximalIleum: Node identifiers of nodes around starting nodes for ileum. + :param xProximalIleum, d1ProximalIleum, d2ProximalIleum, d3ProximalIleum: coordinates and derivatives of nodes + around starting nodes for ileum. + :return allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier. + """ + parameterSetName = options['Base parameter set'] + isHuman = 'Human' in parameterSetName + + segmentCount = options['Number of segments'] + startPhase = 0.0 + elementsCountAroundTC = options['Number of elements around tenia coli'] + elementsCountAroundHaustrum = options['Number of elements around haustrum'] + elementsCountAlongSegment = options['Number of elements along segment'] + elementsCountThroughWall = options['Number of elements through wall'] + cornerOuterRadiusFactor = options['Corner outer radius factor'] + haustrumOuterRadiusFactor = options['Haustrum outer radius factor'] + segmentLengthEndDerivativeFactor = options['Segment length end derivative factor'] + segmentLengthMidDerivativeFactor = options['Segment length mid derivative factor'] + tcCount = options['Number of tenia coli'] + startTCWidth = options['Start tenia coli width'] + startTCWidthDerivative = options['Start tenia coli width derivative'] + endTCWidth = options['End tenia coli width'] + endTCWidthDerivative = options['End tenia coli width derivative'] + tcThickness = options['Tenia coli thickness'] + wallThickness = options['Wall thickness'] + mucosaRelThickness = options['Mucosa relative thickness'] + submucosaRelThickness = options['Submucosa relative thickness'] + circularRelThickness = options['Circular muscle layer relative thickness'] + longitudinalRelThickness = options['Longitudinal muscle layer relative thickness'] + useCrossDerivatives = options['Use cross derivatives'] + useCubicHermiteThroughWall = not (options['Use linear through wall']) + elementsCountAlong = int(elementsCountAlongSegment * segmentCount) + elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum) * tcCount + + ostiumOptions = getDefaultOstiumSettings() + ostiumSettings = updateOstiumOptions(options, ostiumOptions) + + zero = [0.0, 0.0, 0.0] + firstNodeIdentifier = nodeIdentifier + firstElementIdentifier = elementIdentifier + startNode = nodeIdentifier + startElement = elementIdentifier + + fm = region.getFieldmodule() + coordinates = findOrCreateFieldCoordinates(fm) + cache = fm.createFieldcache() + mesh = fm.findMeshByDimension(3) + + nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + nodetemplate = nodes.createNodetemplate() + nodetemplate.defineField(coordinates) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_VALUE, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS1, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS2, 1) + if useCrossDerivatives: + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS1DS2, 1) + if useCubicHermiteThroughWall: + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS3, 1) + if useCrossDerivatives: + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS1DS3, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D2_DS2DS3, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D3_DS1DS2DS3, 1) + + if elementsCountThroughWall == 1: + relativeThicknessList = [1.0] + annotationGroupsThroughWall = [[]] + else: + relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, + circularRelThickness, longitudinalRelThickness] + longitudinalMuscleGroup = AnnotationGroup(region, get_cecum_term("longitudinal muscle layer of cecum")) + circularMuscleGroup = AnnotationGroup(region, get_cecum_term("circular muscle layer of cecum")) + submucosaGroup = AnnotationGroup(region, get_cecum_term("submucosa of cecum")) + mucosaGroup = AnnotationGroup(region, get_cecum_term("cecum mucosa")) + annotationGroupsThroughWall = [[mucosaGroup], [submucosaGroup], [circularMuscleGroup], + [longitudinalMuscleGroup]] + + # Sample network layout along cecum + # print(len(networkLayout.cxGroups)) + cecumLength = networkLayout.arcLengthOfGroupsAlong[0] + cx = networkLayout.cxGroups[0] + cd1 = networkLayout.cd1Groups[0] + cd2 = networkLayout.cd2Groups[0] + cd12 = networkLayout.cd12Groups[0] + + cxIleum = networkLayout.cxGroups[1] + cd1Ileum = networkLayout.cd1Groups[1] + cd2Ileum = networkLayout.cd2Groups[1] + cd3Ileum = networkLayout.cd3Groups[1] + cd12Ileum = networkLayout.cd12Groups[1] + + d2BranchPt = networkLayout.d2BranchPt + d3BranchPt = networkLayout.d3BranchPt + + sxCecum, sd1Cecum, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlong) + sd2Cecum, sd12Cecum = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) + + # Calculate segment length + segmentLength = cecumLength / segmentCount + + # Generate variation of radius & tc width along length + outerRadiusAlongCecum = [] + dOuterRadiusAlongCecum = [] + tcWidthAlongCecum = [] + + closedProximalEnd = True + outerRadiusListCP = [vector.magnitude(c) for c in cd2] + dOuterRadiusListCP = [] + for n in range(len(outerRadiusListCP) - 1): + dOuterRadiusListCP.append(outerRadiusListCP[n + 1] - outerRadiusListCP[n]) + dOuterRadiusListCP.append(outerRadiusListCP[-1] - outerRadiusListCP[-2]) + outerRadiusAlongElementList, dOuterRadiusAlongElementList = \ + interp.interpolateSampleCubicHermite(outerRadiusListCP, dOuterRadiusListCP, se, sxi, ssf) + + for n2 in range(elementsCountAlongSegment * segmentCount + 1): + xi = 1 / (elementsCountAlongSegment * segmentCount) * n2 + + radius = outerRadiusAlongElementList[n2] + outerRadiusAlongCecum.append(radius) + dRadius = dOuterRadiusAlongElementList[n2] + dOuterRadiusAlongCecum.append(dRadius) + tcWidth = interp.interpolateCubicHermite([startTCWidth], [startTCWidthDerivative], + [endTCWidth], [endTCWidthDerivative], xi)[0] + tcWidthAlongCecum.append(tcWidth) + + haustrumOuterRadiusFactorAlongCecum = [haustrumOuterRadiusFactor] * (elementsCountAlong + 1) + + xToSample = [] + d1ToSample = [] + d2ToSample = [] + + elementsCountAroundHalfHaustrum = int((elementsCountAroundTC + elementsCountAroundHaustrum) * 0.5) + + # Create object + colonSegmentTubeMeshOuterPoints = ColonSegmentTubeMeshOuterPoints( + region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, + tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, + segmentLength, wallThickness, cornerOuterRadiusFactor, haustrumOuterRadiusFactorAlongCecum, + outerRadiusAlongCecum, dOuterRadiusAlongCecum, tcWidthAlongCecum, startPhase) + + # Create annotation + cecumGroup = AnnotationGroup(region, get_cecum_term("caecum")) + annotationGroupsAlong = [] + for i in range(elementsCountAlong): + annotationGroupsAlong.append([cecumGroup]) + + for nSegment in range(segmentCount): + # Make regular segments + xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, annotationGroupsAround \ + = colonSegmentTubeMeshOuterPoints.getColonSegmentTubeMeshOuterPoints(nSegment) + + # Replace first half of first segment with apex and sample along apex and second half of segment + if nSegment == 0: + xFirstSegmentSampled, d1FirstSegmentSampled, d2FirstSegmentSampled, d1FirstDirectionVector = \ + getApexSegmentForCecum(xOuter, d1Outer, d2Outer, elementsCountAroundHalfHaustrum, + elementsCountAroundTC, elementsCountAround, elementsCountAlongSegment, + tcCount) + + xToSample += xFirstSegmentSampled + d1ToSample += d1FirstSegmentSampled + d2ToSample += d2FirstSegmentSampled else: - ei1Left = n1 - break + xOuterExtrude = [] + for n in range(len(xOuter)): + xOuterExtrude.append([xOuter[n][0], xOuter[n][1], xOuter[n][2] + segmentLength * nSegment]) + xToSample += xOuterExtrude[elementsCountAround:] + d1ToSample += d1Outer[elementsCountAround:] + d2ToSample += d2Outer[elementsCountAround:] + + # Sample along length + xToWarp, d1ToWarp, d2ToWarp = sampleCecumAlongLength(xToSample, d1ToSample, d2ToSample, d1FirstDirectionVector, + elementsCountAroundHalfHaustrum, elementsCountAroundTC, + elementsCountAround, elementsCountAlong, tcCount) + + # Ensure cecum starts at z = 0.0 + minZ = xToWarp[0][2] + for n2 in range(elementsCountAlong + 1): + zFirstNodeAlong = xToWarp[n2 * elementsCountAround][2] + if zFirstNodeAlong < minZ: + minZ = zFirstNodeAlong + + for n in range(len(xToWarp)): + xToWarp[n][2] = xToWarp[n][2] - minZ + + # Project reference point for warping onto network layout + sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ + tubemesh.getPlaneProjectionOnCentralPath(xToWarp, elementsCountAround, elementsCountAlong, + cecumLength, sxCecum, sd1Cecum, sd2Cecum, sd12Cecum) + + # Warp points + xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = \ + tubemesh.warpSegmentPoints(xToWarp, d1ToWarp, d2ToWarp, segmentAxis, sxRefList, sd1RefList, + sd2ProjectedListRef, elementsCountAround, elementsCountAlong, zRefList) + + # Create coordinates and derivatives + wallThicknessList = [wallThickness] * (elementsCountAlong + 1) + + xList, d1List, d2List, d3List, curvatureList, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal = \ + tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList,d2WarpedList, d3WarpedUnitList, + wallThicknessList, relativeThicknessList, elementsCountAround, + elementsCountAlong, elementsCountThroughWall, transitElementList, + outward=False) + + # Deal with multiple nodes at end point for closed proximal end + xApexInner = xList[0] + # arclength between apex point and corresponding point on next face + magMin = interp.computeCubicHermiteArcLength(xList[0], d2List[0], + xList[elementsCountAround * (elementsCountThroughWall + 1)], + d2List[elementsCountAround * (elementsCountThroughWall + 1)], + rescaleDerivatives=True) + magMax = interp.computeCubicHermiteArcLength(xList[int(0.5*(elementsCountAroundTC + elementsCountAroundHaustrum))], + d2List[int(0.5*(elementsCountAroundTC + elementsCountAroundHaustrum))], + xList[int(0.5*(elementsCountAroundTC + elementsCountAroundHaustrum)) + + elementsCountAround * (elementsCountThroughWall + 1)], + d2List[int(0.5*(elementsCountAroundTC + elementsCountAroundHaustrum)) + + elementsCountAround * (elementsCountThroughWall + 1)], + rescaleDerivatives=True) + mag = 0.5*(magMin + magMax) + d2ApexInner = vector.setMagnitude(sd2Cecum[0], mag) + d1ApexInner = vector.crossproduct3(sd1Cecum[0], d2ApexInner) + d1ApexInner = vector.setMagnitude(d1ApexInner, mag) + d3ApexUnit = vector.normalise(vector.crossproduct3(vector.normalise(d1ApexInner), + vector.normalise(d2ApexInner))) + d3ApexInner = [d3ApexUnit[c] * wallThickness / elementsCountThroughWall for c in range(3)] + + xCecum = [] + d1Cecum = [] + d2Cecum = [] + d3Cecum = [] + + for n3 in range(elementsCountThroughWall + 1): + xApex = [xApexInner[c] + d3ApexUnit[c] * wallThickness / elementsCountThroughWall * n3 for c in range(3)] + xCecum.append(xApex) + d1Cecum.append(d1ApexInner) + d2Cecum.append(d2ApexInner) + d3Cecum.append(d3ApexInner) + + xCecum += xList[(elementsCountThroughWall + 1) * elementsCountAround:] + d1Cecum += d1List[(elementsCountThroughWall + 1) * elementsCountAround:] + d2Cecum += d2List[(elementsCountThroughWall + 1) * elementsCountAround:] + d3Cecum += d3List[(elementsCountThroughWall + 1) * elementsCountAround:] + + xFlat = d1Flat = d2Flat = [] + xOrgan = d1Organ = d2Organ = [] + + # Create nodes and elements + if tcThickness > 0: + tubeTCWidthList = colonSegmentTubeMeshOuterPoints.getTubeTCWidthList() + xCecum, d1Cecum, d2Cecum, d3Cecum, annotationArrayAround, localIdxDistal, xDistal, d1Distal, d2Distal, \ + d3Distal = \ + getTeniaColi(region, xCecum, d1Cecum, d2Cecum, d3Cecum, curvatureList, tcCount, elementsCountAroundTC, + elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, + tubeTCWidthList, tcThickness, annotationGroupsAround, closedProximalEnd, isHuman) + + nextNodeIdentifier, nextElementIdentifier, allAnnotationGroups, nodesIdDistal = createNodesAndElementsTeniaColi( + region, xCecum, d1Cecum, d2Cecum, d3Cecum, xFlat, d1Flat, d2Flat, xOrgan, d1Organ, d2Organ, None, + elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, + tcCount, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, + firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, + closedProximalEnd, localIdxDistal) + + else: + nextNodeIdentifier, nextElementIdentifier, allAnnotationGroups, nodesIdDistal = tubemesh.createNodesAndElements( + region, xCecum, d1Cecum, d2Cecum, d3Cecum, xFlat, d1Flat, d2Flat, xOrgan, d1Organ, d2Organ, None, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, + firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, + closedProximalEnd) + + # nodeIdentifierCecum = nextNodeIdentifier + # for n2 in range(len(cx)): + # node = nodes.createNode(nextNodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, cx[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, cd1[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, cd2[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, [0.0, 0.0, 0.0]) + # nextNodeIdentifier += 1 + # + # ################# + # # Create elements + # ################# + # + # mesh = fm.findMeshByDimension(1) + # cubicHermiteBasis = fm.createElementbasis(1, Elementbasis.FUNCTION_TYPE_CUBIC_HERMITE) + # eft = mesh.createElementfieldtemplate(cubicHermiteBasis) + # elementtemplate = mesh.createElementtemplate() + # elementtemplate.setElementShapeType(Element.SHAPE_TYPE_LINE) + # result = elementtemplate.defineField(coordinates, -1, eft) + # + # elementIdentifier = nextElementIdentifier + # for e in range(len(cx) - 1): + # element = mesh.createElement(elementIdentifier, elementtemplate) + # element.setNodesByIdentifier(eft, [nodeIdentifierCecum + e, nodeIdentifierCecum + 1 + e]) + # elementIdentifier = elementIdentifier + 1 + # + # cx = networkLayout.cxGroups[1] + # cd1 = networkLayout.cd1Groups[1] + # cd2 = networkLayout.cd2Groups[1] + # + # nodeIdentifierIleum = nextNodeIdentifier + # for n2 in range(len(cx)): + # node = nodes.createNode(nextNodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, cx[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, cd1[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, cd2[n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, [0.0, 0.0, 0.0]) + # nextNodeIdentifier += 1 + # + # for e in range(2): + # element = mesh.createElement(elementIdentifier, elementtemplate) + # element.setNodesByIdentifier(eft, [nodeIdentifierIleum + e, nodeIdentifierIleum + 1 + e]) + # elementIdentifier = elementIdentifier + 1 + + # Add ostium on track surface + elementsAroundTrackSurface = elementsCountAroundHaustrum + elementsAlongTrackSurface = elementsCountAlongSegment + + # Find region where ostium sits + # angle between d2 of branch point and vector between branch point and 1st point on ileum + dV = [cxIleum[0][c] - cxIleum[-1][c] for c in range(3)] + ostiumPositionAngleAround = math.acos(vector.dotproduct(dV, d2BranchPt)/ + (vector.magnitude(dV) * vector.magnitude(d2BranchPt))) + if vector.dotproduct(dV,d3BranchPt) != 0: + sign = vector.dotproduct(dV, d3BranchPt)/abs(vector.dotproduct(dV, d3BranchPt)) + if sign < 0: + ostiumPositionAngleAround = math.pi * 2.0 - ostiumPositionAngleAround + sectorIdx = ostiumPositionAngleAround // (2 * math.pi / tcCount) + sectorStartAngle = sectorIdx * (2 * math.pi / tcCount) + + startIdxElementsAround = int((elementsCountAroundHaustrum + elementsCountAroundTC) * sectorIdx + + elementsCountAroundTC * 0.5) + + segmentIdx = int(networkLayout.arcLengthToBranchPt // segmentLength) + + baseNodesIdx = (elementsCountThroughWall + 1) + \ + + (elementsCountAround * (elementsCountThroughWall + 1) + + ((elementsCountAroundTC - 1) * tcCount if tcThickness > 0.0 else 0)) * \ + (elementsCountAlongSegment * segmentIdx - 1) + elementsCountAround + + # Elements to delete + deleteElementIdentifier = [] + for n2 in range(elementsCountAlongSegment): + for n3 in range(elementsCountThroughWall): + for n1 in range(elementsCountAroundHaustrum): + elementIdx = \ + startIdxElementsAround + int(elementsCountAroundTC * (0.5 if tcThickness > 0.0 else 0)) + n1 + \ + (elementsCountAround * n3) + n2 * (elementsCountAround * elementsCountThroughWall + + elementsCountAroundTC * (tcCount if tcThickness > 0.0 else 0))\ + + startElement - 1 + segmentIdx * (elementsCountAlongSegment * + (elementsCountAround * elementsCountThroughWall + + elementsCountAroundTC * (tcCount if tcThickness > 0.0 else 0))) + deleteElementIdentifier.append(elementIdx) + + xTrackSurface = [] + d1TrackSurface = [] + d2TrackSurface = [] + nodesOnLHS = [] + nodesOnRHS = [] + nodesOnDistal = [] + nodesOnProximal = [] + + for n2 in range(elementsCountAlongSegment + 1): + for n1 in range(elementsCountAroundHaustrum + 1): + if n2 == 0 and segmentIdx == 0: + xTrackSurface.append(xApex) + d1TrackSurface.append(d1ApexInner) + d2TrackSurface.append(d2ApexInner) + else: + idx = baseNodesIdx + \ + (elementsCountAround * (elementsCountThroughWall + 1) + + ((elementsCountAroundTC - 1) * tcCount if tcThickness > 0.0 else 0)) * n2 + \ + startIdxElementsAround + n1 + (elementsCountAround * (elementsCountThroughWall - 1)) + xTrackSurface.append(xCecum[idx]) + d1TrackSurface.append(d1Cecum[idx]) + d2TrackSurface.append(d2Cecum[idx]) + + if n1 == 1: + nodeWall = [] + for n3 in range(elementsCountThroughWall, -1, -1): + nodeWall.append(idx - elementsCountAround * n3) + nodesOnLHS.append(nodeWall) + if n1 == elementsCountAroundHaustrum: + nodeWall = [] + for n3 in range(elementsCountThroughWall, -1, -1): + nodeWall.append(idx + 1 - elementsCountAround * n3) + nodesOnRHS.append(nodeWall) + if segmentIdx and n2 == 0 and n1 > 0 and n1 < elementsCountAroundHaustrum: + nodeWall = [] + for n3 in range(elementsCountThroughWall, -1, -1): + nodeWall.append(idx + 1 - elementsCountAround * n3) + nodesOnProximal.append(nodeWall) + if n2 == elementsCountAlongSegment and n1 > 0 and n1 < elementsCountAroundHaustrum: + nodeWall = [] + for n3 in range(elementsCountThroughWall, -1, -1): + nodeWall.append(idx + 1 - elementsCountAround * n3) + nodesOnDistal.append(nodeWall) + + sideNodes = [] + for n2 in range(elementsCountAlongSegment + 1): + for n3 in range(elementsCountThroughWall + 1): + if n2 == 0 and segmentIdx == 0: + sideNodes.append((n2 + 1) * (n3 + 1)) + elif segmentIdx and n2 == 0: + sideNodes.append(nodesOnLHS[n2][n3]) + for n in range(len(nodesOnProximal)): + sideNodes.append(nodesOnProximal[n][n3]) + sideNodes.append(nodesOnRHS[n2][n3]) + elif n2 == elementsCountAlongSegment: + sideNodes.append(nodesOnLHS[n2 + (0 if segmentIdx else -1)][n3]) + for n in range(len(nodesOnDistal)): + sideNodes.append(nodesOnDistal[n][n3]) + sideNodes.append(nodesOnRHS[n2 + (0 if segmentIdx else -1)][n3]) + else: + for n1 in range(2): + if n1 == 0: + sideNodes.append(nodesOnLHS[n2 + (0 if segmentIdx else -1)][n3]) + else: + sideNodes.append(nodesOnRHS[n2 + (0 if segmentIdx else -1)][n3]) + + trackSurfaceOstium = TrackSurface(elementsAroundTrackSurface, elementsAlongTrackSurface, + xTrackSurface, d1TrackSurface, d2TrackSurface) + + # # Visualise track surface + # nodeIdentifier, elementIdentifier = trackSurfaceOstium.generateMesh(region) + + # Find centre position + # track along ileum path and since cxIleum[1] could be above or below the track surface, we check both side to + # determine direction to track. At each point, find the nearest position and take the diff between nearest point + # to the point in line, keep tracking till diff is close to zero. + + xTol = 1.0E-6 + arcStart = 0.0 + arcEnd = networkLayout.arcLengthOfGroupsAlong[1] + nearestPosition = trackSurfaceOstium.findNearestPosition(cxIleum[0]) + xNearestStart = trackSurfaceOstium.evaluateCoordinates(nearestPosition, derivatives=False) + distStart = vector.magnitude([cxIleum[0][c] - xNearestStart[c] for c in range(3)]) + nearestPosition = trackSurfaceOstium.findNearestPosition(cxIleum[-1]) + xNearestEnd = trackSurfaceOstium.evaluateCoordinates(nearestPosition, derivatives=False) + distEnd = vector.magnitude([cxIleum[-1][c] - xNearestEnd[c] for c in range(3)]) + + for iter in range(100): + arcDistance = (arcStart + arcEnd) * 0.5 + x, d1 = interp.getCubicHermiteCurvesPointAtArcDistance(cxIleum, cd1Ileum, arcDistance)[0:2] + nearestPosition = trackSurfaceOstium.findNearestPosition(x) + xNearest = trackSurfaceOstium.evaluateCoordinates(nearestPosition, derivatives=False) + dist = vector.magnitude([x[c] - xNearest[c] for c in range(3)]) + + if abs(distStart - distEnd) > xTol: + if distStart < distEnd: + arcEnd = arcDistance + distEnd = dist + else: + arcStart = arcDistance + distStart = dist - # Right boundary - rightPositionOfCentreElement = TrackSurfacePosition(ei1, ei2, 1.0, xi2) - xRight, d1Right, _ = trackSurfaceOstium.evaluateCoordinates(rightPositionOfCentreElement, derivatives=True) - distxCentreToxRight = interp.computeCubicHermiteArcLength(xCentre, d1Centre, xRight, d1Right, False) - remainingLength = ostiumDiameter * 0.5 - distxCentreToxRight - xCurrent = xRight - d1Current = d1Right - - for n1 in range(ei1, elementsAroundTrackSurface): - if remainingLength > 0.0: - nextPosition = TrackSurfacePosition(n1+1, ei2, 1.0, xi2) - xNext, d1Next, _ = trackSurfaceOstium.evaluateCoordinates(nextPosition, derivatives=True) - distxCurrentToxNext = interp.computeCubicHermiteArcLength(xCurrent, d1Current, xNext, d1Next, False) - remainingLength -= distxCurrentToxNext - xCurrent = xNext - d1Current = d1Next else: - ei1Right = n1 + xCentre, d1Centre, d2Centre = trackSurfaceOstium.evaluateCoordinates(nearestPosition, derivatives=True) + normAxis = vector.normalise([-d for d in d1]) + eIdx = interp.getNearestPointIndex(cxIleum, xCentre) - 1 + arcLenghtSum = 0.0 + for e in range(eIdx): + arcLenghtSum += interp.getCubicHermiteArcLength(cxIleum[e], cd1Ileum[e], + cxIleum[e + 1], cd1Ileum[e + 1]) + xi = (arcDistance - arcLenghtSum)/\ + interp.getCubicHermiteArcLength(cxIleum[eIdx], cd1Ileum[eIdx], cxIleum[eIdx + 1], cd1Ileum[eIdx + 1]) + d2Centre = interp.interpolateCubicHermite(cd2Ileum[eIdx], cd12Ileum[eIdx], cd2Ileum[eIdx + 1], + cd12Ileum[eIdx + 1], xi) break + if iter > 98: + print('Search for ileum entry centre - Max iters reached:', iter) + + ostiumSettings['Number of elements around ostium'] = elementsCountAlongSegment + elementsCountAroundOstium = ostiumSettings['Number of elements around ostium'] + ostiumSettings['Use linear through ostium wall'] = options['Use linear through wall'] + ostiumSettings['Use linear through vessel wall'] = options['Use linear through wall'] + + ileumGroup = AnnotationGroup(region, get_smallintestine_term("ileum")) + ileumMeshGroup = ileumGroup.getMeshGroup(mesh) + ileocecalJunctionGroup = AnnotationGroup(region, get_smallintestine_term("ileocecal junction")) + ileocecalJunctionMeshGroup = ileocecalJunctionGroup.getMeshGroup(mesh) + smallIntestineGroup = AnnotationGroup(region, get_smallintestine_term("small intestine")) + smallIntestineMeshGroup = smallIntestineGroup.getMeshGroup(mesh) + cecumMeshGroup = cecumGroup.getMeshGroup(mesh) + allAnnotationGroups += [ileumGroup, ileocecalJunctionGroup, smallIntestineGroup] + + ostiumWallAnnotationGroups = [] + if elementsCountThroughWall == 4: + ileumMucosaGroup = AnnotationGroup(region, get_smallintestine_term("mucosa of ileum")) + ileumSubmucosaGroup = AnnotationGroup(region, get_smallintestine_term("submucosa of ileum")) + ileumCircularGroup = AnnotationGroup(region, get_smallintestine_term("circular muscle layer of ileum")) + ileumLongitudinalGroup = AnnotationGroup(region, + get_smallintestine_term("longitudinal muscle layer of ileum")) + + ostiumWallAnnotationGroups = [[ileumMucosaGroup, mucosaGroup], + [ileumSubmucosaGroup, submucosaGroup], + [ileumCircularGroup, circularMuscleGroup], + [ileumLongitudinalGroup, longitudinalMuscleGroup]] + + allAnnotationGroups += [ileumMucosaGroup, ileumSubmucosaGroup, + ileumCircularGroup, ileumLongitudinalGroup] + + # Points from track surface and vessel end + xPath = [cxIleum[0], xCentre] + d1Path = [cd1Ileum[0], [-d for d in normAxis]] + d2Path = [cd2Ileum[0], d2Centre] + d3Path = [cd3Ileum[0], [-d for d in d1Centre]] + d12Path = [cd2Ileum[0], [0.0, 0.0, 0.0]] + d13Path = [cd3Ileum[0], [0.0, 0.0, 0.0]] + + networkLayoutIleum = CustomNetworkLayout(xPath, d1Path, d2Path, d3Path, d12Path, d13Path) + + nextNodeIdentifier, nextElementIdentifier, (o1_x, o1_d1, o1_d2, o1_d3, o1_NodeId, o1_Positions) = \ + generateOstiumMesh(region, ostiumSettings, trackSurfaceOstium, networkLayoutIleum, + startNodeIdentifier=nextNodeIdentifier, startElementIdentifier=nextElementIdentifier, + nodeIdProximal=nodeIdProximalIleum, xProximal=xProximalIleum, d1Proximal=d1ProximalIleum, + d2Proximal=d2ProximalIleum, d3Proximal=d3ProximalIleum, + vesselMeshGroups=[[cecumMeshGroup, smallIntestineMeshGroup, ileumMeshGroup]], + ostiumMeshGroups=[cecumMeshGroup, ileocecalJunctionMeshGroup], + wallAnnotationGroups=ostiumWallAnnotationGroups, coordinates=None) + + ostiumFaceStartNode = nextNodeIdentifier + ostiumFaceStartElement = nextElementIdentifier + + # Create location of annulus + xAnnulusOuter = [[] for x in range(elementsCountAroundOstium)] + xAnnulusOuterPosition = [[] for x in range(elementsCountAroundOstium)] + d1AnnulusNorm = [] + d1AnnulusOuter = [] + e1Left = elementsAroundTrackSurface + e1Right = 0 + e2Top = 0 + e2Bottom = elementsAlongTrackSurface + sf = vector.magnitude(networkLayoutIleum.cd2Path[-1]) * 0.35 + for n1 in range(elementsCountAroundOstium): + normD2 = vector.normalise(o1_d2[-1][n1]) + d1AnnulusNorm.append(normD2) + d1AnnulusOuter.append(vector.setMagnitude(o1_d2[-1][n1], sf)) + x = [o1_x[-1][n1][c] + sf * normD2[c] for c in range(3)] + nearestPosition = trackSurfaceOstium.findNearestPosition(x) + e1 = nearestPosition.e1 + e2 = nearestPosition.e2 + if e1 < e1Left: + e1Left = e1 + if e1 > e1Right: + e1Right = e1 + if e2 > e2Top: + e2Top = e2 + if e2 < e2Bottom: + e2Bottom = e2 + xAnnulusOuterPosition[n1] = nearestPosition + xAnnulusOuter[n1] = trackSurfaceOstium.evaluateCoordinates(nearestPosition) + + d2AnnulusOuter = [] + for n in range(elementsCountAlongSegment): + d = findDerivativeBetweenPoints(xAnnulusOuter[n], xAnnulusOuter[(n + 1) % elementsCountAroundOstium]) + d2AnnulusOuter.append(d) + d2AnnulusOuter = interp.smoothCubicHermiteDerivativesLoop(xAnnulusOuter, d2AnnulusOuter) + d3Annulus = [] + for n in range(elementsCountAroundOstium): + d3 = vector.normalise(vector.crossproduct3(vector.normalise(d2AnnulusOuter[n]), d1AnnulusNorm[n])) + d3Annulus.append(d3) + annulusD2Curvature = interp.getCurvaturesAlongCurve(xAnnulusOuter, d2AnnulusOuter, d3Annulus, loop=True) + + # # Visualise annulus + # for n1 in range(len(xAnnulusOuter)): + # node = nodes.createNode(nextNodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, xAnnulusOuter[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1AnnulusOuter[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2AnnulusOuter[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, [0.0, 0.0, 0.0]) + # nextNodeIdentifier += 1 + + # base row counts with 8 elements around ostium + rowsIncrement = int((elementsCountAlongSegment - 8) / 4) + rowsAbove = 1 + rowsIncrement + rowsOstium = 4 + rowsIncrement * 2 + rowsBelow = 3 + rowsIncrement + + # # rowIdx along segment + startRowIdx = rowsBelow + 1 + endRowIdx = rowsBelow + rowsOstium - 1 + + # sample along the midline of ostium + rotAngle = math.pi + rotFrame = matrix.getRotationMatrixFromAxisAngle(d3ApexUnit, rotAngle) + d1A = [rotFrame[j][0] * d1Cecum[1][0] + rotFrame[j][1] * d1Cecum[1][1] + + rotFrame[j][2] * d1Cecum[1][2] for j in range(3)] + + rotAngle = math.pi + rotFrame = matrix.getRotationMatrixFromAxisAngle(vector.normalise(d3Annulus[0]), rotAngle) + d2B = [rotFrame[j][0] * d1AnnulusOuter[0][0] + rotFrame[j][1] * d1AnnulusOuter[0][1] + + rotFrame[j][2] * d1AnnulusOuter[0][2] for j in range(3)] + + # sample along from apex to annulus start + if segmentIdx == 0: + xStart = xCecum[1] + else: + idx = int(elementsAroundTrackSurface * 0.5) + xStart = xTrackSurface[idx] + + xPositionA = trackSurfaceOstium.findNearestPosition(xStart) + xProportionA = trackSurfaceOstium.getProportion(xPositionA) + derivativeA = trackSurfaceOstium.evaluateCoordinates(xPositionA, derivatives=True)[2] + derivativeA = vector.setMagnitude(derivativeA, vector.magnitude(d2ApexInner)) + derivativeMagnitudeA = vector.magnitude(derivativeA) + + xPositionB = trackSurfaceOstium.findNearestPosition(xAnnulusOuter[0]) + xProportionB = trackSurfaceOstium.getProportion(xPositionB) + + nx, nd1, nd2, nd3, proportions = \ + trackSurfaceOstium.createHermiteCurvePoints( + xProportionA[0], xProportionA[1], xProportionB[0], xProportionB[1], + rowsBelow + 1, derivativeStart=derivativeA, derivativeEnd=None) + + pxAlongMidLine, pd2AlongMidLine, pd1AlongMidLine = \ + trackSurfaceOstium.resampleHermiteCurvePointsSmooth( + nx, nd1, nd2, nd3, proportions, derivativeMagnitudeStart=derivativeMagnitudeA)[0:3] + + annulusD2ZeroMag = vector.magnitude(pd2AlongMidLine[-1]) + + for n in range(len(pd1AlongMidLine)): + pd1AlongMidLine[n] = [-d for d in pd1AlongMidLine[n]] + + xPositionA = trackSurfaceOstium.findNearestPosition(xAnnulusOuter[int(elementsCountAlongSegment * 0.5)]) + xProportionA = trackSurfaceOstium.getProportion(xPositionA) + + xB = xTrackSurface[-elementsCountAroundHalfHaustrum] + xPositionB = trackSurfaceOstium.findNearestPosition(xB) + xProportionB = trackSurfaceOstium.getProportion(xPositionB) + derivativeB = d2TrackSurface[-elementsCountAroundHalfHaustrum] + derivativeMagnitudeB = vector.magnitude(d2TrackSurface[-elementsCountAroundHalfHaustrum]) + + nx, nd1, nd2, nd3, proportions = \ + trackSurfaceOstium.createHermiteCurvePoints( + xProportionA[0], xProportionA[1], xProportionB[0], xProportionB[1], + rowsAbove + 1, derivativeStart=None, derivativeEnd=derivativeB) + + pxAlongMidLineBottom, pd2AlongMidLineBottom, pd1AlongMidLineBottom = \ + trackSurfaceOstium.resampleHermiteCurvePointsSmooth( + nx, nd1, nd2, nd3, proportions, derivativeMagnitudeStart=None, + derivativeMagnitudeEnd=derivativeMagnitudeB)[0:3] + + annulusD2HalfOstiumMag = vector.magnitude(pd2AlongMidLineBottom[0]) + + for n in range(len(pd1AlongMidLineBottom)): + pd1AlongMidLineBottom[n] = [-d for d in pd1AlongMidLineBottom[n]] + + # sample points around colon to ostium + annulusIdx = 1 + xAroundAlong = [] + d1AroundAlong = [] + + sideElements = int(elementsCountAroundHaustrum * 0.5) + for n2 in range(elementsCountAlongSegment): + xAround = [] + d1Around = [] + if n2 == 0 and segmentIdx == 0: + for n1 in range(elementsCountAroundHaustrum + 1): + xAround.append(xApex) + d1Around.append(d1A) + else: + for n in range(2): + # LHS + if n == 0: + xPositionA = trackSurfaceOstium.findNearestPosition( + xTrackSurface[n2 * (elementsCountAroundHaustrum + 1)]) + xProportionA = trackSurfaceOstium.getProportion(xPositionA) + derivativeA = d1TrackSurface[n2 * (elementsCountAroundHaustrum + 1)] + derivativeMagnitudeA = vector.magnitude(derivativeA) + + if n2 < rowsBelow + 1: + xPositionB = trackSurfaceOstium.findNearestPosition(pxAlongMidLine[n2]) + derivativeB = None + derivativeMagnitudeB = None + + elif n2 >= rowsBelow + rowsOstium: + idx = n2 - (rowsBelow + rowsOstium) + 1 + xPositionB = trackSurfaceOstium.findNearestPosition(pxAlongMidLineBottom[idx]) + derivativeB = None + derivativeMagnitudeB = None + + else: + xPositionB = trackSurfaceOstium.findNearestPosition(xAnnulusOuter[annulusIdx]) + derivativeB = None + derivativeMagnitudeB = None + + xProportionB = trackSurfaceOstium.getProportion(xPositionB) + + else: # RHS + if n2 < rowsBelow + 1: + xPositionA = trackSurfaceOstium.findNearestPosition(pxAlongMidLine[n2]) + derivativeA = None + derivativeMagnitudeA = None + + elif n2 >= rowsBelow + rowsOstium: + idx = n2 - (rowsBelow + rowsOstium) + 1 + xPositionA = trackSurfaceOstium.findNearestPosition(pxAlongMidLineBottom[idx]) + derivativeA = None + derivativeMagnitudeA = None + + else: + xPositionA = trackSurfaceOstium.findNearestPosition(xAnnulusOuter[-annulusIdx]) + derivativeA = None + derivativeMagnitudeA = None + + xProportionA = trackSurfaceOstium.getProportion(xPositionA) + xPositionB = trackSurfaceOstium.findNearestPosition( + xTrackSurface[n2 * (elementsCountAroundHaustrum + 1) + elementsCountAroundHaustrum]) + xProportionB = trackSurfaceOstium.getProportion(xPositionB) + derivativeB = d1TrackSurface[n2 * (elementsCountAroundHaustrum + 1) + elementsCountAroundHaustrum] + derivativeMagnitudeB = vector.magnitude(derivativeB) + + nx, nd1, nd2, nd3, proportions = \ + trackSurfaceOstium.createHermiteCurvePoints( + xProportionA[0], xProportionA[1], xProportionB[0], xProportionB[1], + sideElements +(0 if (n2 < rowsBelow + 1 or n2 >= rowsBelow + rowsOstium) else -1), + derivativeStart=derivativeA, derivativeEnd=derivativeB) + + nx, nd1 = \ + trackSurfaceOstium.resampleHermiteCurvePointsSmooth( + nx, nd1, nd2, nd3, proportions, derivativeMagnitudeStart=derivativeMagnitudeA, + derivativeMagnitudeEnd=derivativeMagnitudeB)[0:2] + + if n == 0: + xAround += nx + d1Around += nd1 + else: + xAround += nx[(1 if (n2 < rowsBelow + 1 or n2 >= rowsBelow + rowsOstium) else 0):] + d1Around += nd1[(1 if (n2 < rowsBelow + 1 or n2 >= rowsBelow + rowsOstium) else 0):] + if n2 < rowsBelow + 1 or n2 >= rowsBelow + rowsOstium: + d1Around = interp.smoothCubicHermiteDerivativesLine(xAround, d1Around, fixStartDerivative=True, + fixEndDerivative=True) + if n2 >= rowsBelow + 1 and n2 < rowsBelow + rowsOstium: + annulusIdx += 1 + + xAroundAlong.append(xAround) + d1AroundAlong.append(d1Around) + + xAround = [] + d1Around = [] + for n1 in range(elementsCountAroundHaustrum + 1): + xAround.append(xTrackSurface[n1 + (elementsCountAroundHaustrum + 1) * elementsCountAlongSegment]) + d1Around.append(d1TrackSurface[n1 + (elementsCountAroundHaustrum + 1) * elementsCountAlongSegment]) + xAroundAlong.append(xAround) + d1AroundAlong.append(d1Around) + d1AroundAlongOriginal = copy.deepcopy(d1AroundAlong) + + # Calculate d2 along segment + d2AroundAlong = [] + xAlongAll = [] + d2AlongAll = [] + + for n2 in range(len(xAroundAlong)): + d2Around = [] + for n1 in range(len(xAroundAlong[n2])): + d2Around.append([0.0, 0.0, 0.0]) + d2AroundAlong.append(d2Around) + + for n1 in range(elementsCountAroundHaustrum + 1): + nxAlong = [] + nd2Along = [] + nxTop = [] + nd2Top = [] + annulusIdx = 1 + if n1 < elementsCountAroundHalfHaustrum - 2: + for n2 in range(elementsCountAlongSegment): + nxAlong.append(xAroundAlong[n2][n1]) + nd2Along.append(findDerivativeBetweenPoints(xAroundAlong[n2][n1], xAroundAlong[n2 + 1][n1])) + nxAlong.append(xAroundAlong[n2 + 1][n1]) + nd2Along.append(d2TrackSurface[(elementsCountAroundHaustrum + 1) * elementsCountAlongSegment + n1]) + nd2Along = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True, + fixEndDerivative=True) + + xAlongAll.append(nxAlong) + d2AlongAll.append(nd2Along) + + for n2 in range(len(nd2Along)): + d2AroundAlong[n2][n1] = nd2Along[n2] + + # Deal with annulus + elif n1 == elementsCountAroundHalfHaustrum - 2: + # Smooth from apex to annulus + for n2 in range(startRowIdx + 1): + nxAlong.append(xAroundAlong[n2][n1]) + nd2Along.append(findDerivativeBetweenPoints(xAroundAlong[n2][n1], xAroundAlong[n2 + 1][n1])) + nd2Along = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True) + nd2AlongBottomLHS = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True) + + # Make sure d2 at annulus is length of element below + nd2Along[-1] = vector.setMagnitude(d1AnnulusOuter[1], vector.magnitude(nd2Along[-1])) + + # Make magnitude of annulus d2 between start and end row equivalent to arclength of element on its left + for m in range(endRowIdx - startRowIdx - 1): + nxAlong.append(xAnnulusOuter[2 + m]) + n2Idx = m + startRowIdx + 1 + nd2Along.append(vector.setMagnitude(d1AnnulusOuter[2+m], vector.magnitude(d1AroundAlong[n2Idx][n1]))) + + # Smooth from annulus to end of cecum + for n2 in range(endRowIdx, elementsCountAlongSegment): + nxTop.append(xAroundAlong[n2][n1]) + nd2Top.append(findDerivativeBetweenPoints(xAroundAlong[n2][n1], xAroundAlong[n2 + 1][n1])) + nxTop.append(xAroundAlong[elementsCountAlongSegment][n1]) + nd2Top.append(d2TrackSurface[(elementsCountAroundHaustrum + 1) * elementsCountAlongSegment + n1]) + nd2Top = interp.smoothCubicHermiteDerivativesLine(nxTop, nd2Top, fixEndDerivative=True) + nd2AlongTopLHS = interp.smoothCubicHermiteDerivativesLine(nxTop, nd2Top, fixEndDerivative=True) + + # Make sure d2 at annulus is length of element above + nd2Top[0] = vector.setMagnitude(d1AnnulusOuter[int(elementsCountAroundOstium * 0.5) - 1], + vector.magnitude(nd2Top[0])) + + nxAlong += nxTop + nd2Along += nd2Top + + xAlongAll.append(nxAlong) + d2AlongAll.append(nd2Along) + + for n2 in range(len(nd2Along)): + d2AroundAlong[n2][n1] = nd2Along[n2] + if n1 == elementsCountAroundHalfHaustrum - 2 and startRowIdx -1 < n2 < endRowIdx + 1: + d1AroundAlong[n2][n1] = d2AnnulusOuter[annulusIdx] + annulusIdx += 1 + + elif n1 == elementsCountAroundHalfHaustrum - 1: + for n2 in range(len(pxAlongMidLine)): + d2AroundAlong[n2][n1] = pd2AlongMidLine[n2] + for n in range(1, len(pxAlongMidLineBottom)): + d2AroundAlong[n + endRowIdx][n1] = pd2AlongMidLineBottom[n] + nxAlong = pxAlongMidLine + pxAlongMidLineBottom + xAlongAll.append(nxAlong) + d2AlongAll.append(pd2AlongMidLine + pd2AlongMidLineBottom) + + elif n1 == elementsCountAroundHalfHaustrum: + # Smooth from apex to annulus + for n2 in range(startRowIdx + 1): + nxAlong.append(xAroundAlong[n2][n1 + (0 if n2 < startRowIdx else -1)]) + nd2Along.append(findDerivativeBetweenPoints(xAroundAlong[n2][n1], xAroundAlong[n2 + 1][n1])) + nd2Along = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True) + nd2AlongBottomRHS = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True) + + # Make sure d2 at annulus is length of element below + nd2Along[-1] = vector.setMagnitude(d1AnnulusOuter[-1], vector.magnitude(nd2Along[-1])) + + # Make magnitude of annulus d2 between start and end row equivalent to arclength of element on its right + for m in range(endRowIdx - startRowIdx - 1): + nxAlong.append(xAnnulusOuter[-(2 + m)]) + n2Idx = m + startRowIdx + 1 + nd2Along.append(vector.setMagnitude(d1AnnulusOuter[-(2 + m)], + vector.magnitude(d1AroundAlong[n2Idx][n1 - 1]))) + + # Smooth from annulus to end of cecum + for n2 in range(endRowIdx, elementsCountAlongSegment): + nxTop.append(xAroundAlong[n2][n1 + (0 if n2 > endRowIdx else -1)]) + if n2 > endRowIdx - 1: + nxAlongNext = xAroundAlong[n2 + 1][n1] + else: + nxAlongNext = xAroundAlong[n2 + 1][n1 - 1] + nd2Top.append(findDerivativeBetweenPoints(xAroundAlong[n2][n1 + (0 if n2 > endRowIdx else -1)], + nxAlongNext)) + nxTop.append(xAroundAlong[elementsCountAlongSegment][n1]) + nd2Top.append(d2TrackSurface[(elementsCountAroundHaustrum + 1) * elementsCountAlongSegment + n1]) + nd2Top = interp.smoothCubicHermiteDerivativesLine(nxTop, nd2Top, fixEndDerivative=True) + nd2AlongTopRHS = interp.smoothCubicHermiteDerivativesLine(nxTop, nd2Top, fixEndDerivative=True) + + # Make sure d2 at annulus is length of element above + nd2Top[0] = vector.setMagnitude(d1AnnulusOuter[int(elementsCountAroundOstium * 0.5) + 1], + vector.magnitude(nd2Top[0])) + + nxAlong += nxTop + nd2Along += nd2Top + + xAlongAll.append(nxAlong) + d2AlongAll.append(nd2Along) + + for n2 in range(len(nd2Along)): + if n2 < startRowIdx or n2 > endRowIdx: + n1Idx = n1 + else: + n1Idx = n1 - 1 + if n1 == elementsCountAroundHalfHaustrum: + d1AroundAlong[n2][n1Idx] = d2AnnulusOuter[-annulusIdx] + annulusIdx += 1 + d2AroundAlong[n2][n1Idx] = nd2Along[n2] - # Bottom boundary - bottomPositionOfCentreElement = TrackSurfacePosition(ei1, ei2, xi1, 0) - xBottom, _, d2Bottom = trackSurfaceOstium.evaluateCoordinates(bottomPositionOfCentreElement, derivatives=True) - distxBottomToxCentre = interp.computeCubicHermiteArcLength(xBottom, d2Bottom, xCentre, d2Centre, False) - remainingLength = ostiumDiameter * 0.5 - distxBottomToxCentre - xCurrent = xBottom - d2Current = d2Bottom - - for n2 in range(ei2, -1, -1): - if remainingLength > 0.0: - prevPosition = TrackSurfacePosition(ei1, n2 - 1, xi1, 0) - xPrev, _, d2Prev = trackSurfaceOstium.evaluateCoordinates(prevPosition, derivatives=True) - distPrevToxCurrent = interp.computeCubicHermiteArcLength(xPrev, d2Prev, xCurrent, d2Current, False) - remainingLength -= distPrevToxCurrent - xCurrent = xPrev - d2Current = d2Prev else: - ei2Bottom = n2 - break + for n2 in range(elementsCountAlongSegment): + nxAlong.append(xAroundAlong[n2][n1 + (0 if (n2 < startRowIdx or n2 > endRowIdx) else -1)]) + if n2 < startRowIdx - 1 or n2 > endRowIdx -1: + nxAlongNext = xAroundAlong[n2 + 1][n1] + else: + nxAlongNext = xAroundAlong[n2 + 1][n1 - 1] + nd2Along.append(findDerivativeBetweenPoints( + xAroundAlong[n2][n1 + (0 if (n2 < startRowIdx or n2 > endRowIdx) else -1)], nxAlongNext)) + + nxAlong.append(xAroundAlong[n2 + 1][n1]) + nd2Along.append(d2TrackSurface[(elementsCountAroundHaustrum + 1) * elementsCountAlongSegment + n1]) + nd2Along = interp.smoothCubicHermiteDerivativesLine(nxAlong, nd2Along, fixStartDerivative=True, + fixEndDirection=True) + + xAlongAll.append(nxAlong) + d2AlongAll.append(nd2Along) + + for n2 in range(len(nd2Along)): + if n2 < startRowIdx or n2 > endRowIdx: + n1Idx = n1 + else: + n1Idx = n1 - 1 + d2AroundAlong[n2][n1Idx] = nd2Along[n2] + + # Calculate d3 + d3UnitAroundAlong = [] + for n2 in range(len(xAroundAlong)): + d3Around = [] + for n1 in range(len(xAroundAlong[n2])): + d3Around.append(vector.normalise( + vector.crossproduct3(vector.normalise(d1AroundAlong[n2][n1]), vector.normalise(d2AroundAlong[n2][n1])))) + d3UnitAroundAlong.append(d3Around) + + # Calculate curvatures + # Curvatures around + d1Curvature = [] + if segmentIdx == 0: + d1Curvature.append([0.0]) + + for n2 in range(1 if segmentIdx == 0 else 0, elementsCountAlongSegment + 1): + if n2 < startRowIdx or n2 > endRowIdx: #== elementsCountAlongSegment: + d1Curvature.append(interp.getCurvaturesAlongCurve(xAroundAlong[n2], d1AroundAlongOriginal[n2], + d3UnitAroundAlong[n2])) + else: + d1CurvatureLeft = interp.getCurvaturesAlongCurve(xAroundAlong[n2][:int(0.5 * len(xAroundAlong[n2]))], + d1AroundAlongOriginal[n2][:int(0.5 * len(xAroundAlong[n2]))], + d3UnitAroundAlong[n2][:int(0.5 * len(xAroundAlong[n2]))]) + + d1CurvatureRight = interp.getCurvaturesAlongCurve(xAroundAlong[n2][int(0.5 * len(xAroundAlong[n2])):], + d1AroundAlongOriginal[n2][int(0.5 * len(xAroundAlong[n2])):], + d3UnitAroundAlong[n2][int(0.5 * len(xAroundAlong[n2])):]) + d1Curvature.append(d1CurvatureLeft + d1CurvatureRight) + + # Curvatures along + d2Curvature = [] + for n2 in range(len(xAroundAlong)): + d2CurvatureAround = [] + for n1 in range(len(xAroundAlong[n2])): + d2CurvatureAround.append(0.0) + d2Curvature.append(d2CurvatureAround) + + for n1 in range(elementsCountAroundHaustrum + 1): + xAlong = xAlongAll[n1] + d2Along = d2AlongAll[n1] + d3UnitAlong = [] + annulusIdx = 1 + + if n1 < elementsCountAroundHalfHaustrum - 2: + for n2 in range(elementsCountAlongSegment): + d3UnitAlong.append(d3UnitAroundAlong[n2][n1]) + d3UnitAlong.append(d3UnitAroundAlong[n2 + 1][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(xAlong, d2Along, d3UnitAlong) + for n2 in range(len(d2CurvatureAlong)): + d2Curvature[n2][n1] = d2CurvatureAlong[n2] + + elif n1 == elementsCountAroundHalfHaustrum - 2: + # From apex to annulus + for n2 in range(elementsCountAlongSegment): + d3UnitAlong.append(d3UnitAroundAlong[n2][n1]) + d3UnitAlong.append(d3UnitAroundAlong[n2 + 1][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(xAlong[:startRowIdx + 1], nd2AlongBottomLHS, + d3UnitAlong[:startRowIdx + 1]) + + # Curvature of nodes along LHS annulus + for m in range(endRowIdx - startRowIdx - 1): + d2CurvatureAlong.append(d1Curvature[m + startRowIdx + 1][n1]) + + # From annulus to distal end + d2CurvatureAlong += interp.getCurvaturesAlongCurve(xAlong[endRowIdx:], nd2AlongTopLHS, + d3UnitAlong[endRowIdx:]) + + for n2 in range(len(d2CurvatureAlong)): + d2Curvature[n2][n1] = d2CurvatureAlong[n2] + + for n2 in range(startRowIdx, endRowIdx + 1): + d1Curvature[n2][n1] = annulusD2Curvature[annulusIdx] + annulusIdx += 1 + + elif n1 == elementsCountAroundHalfHaustrum - 1: + # From apex to annulus + for n2 in range(len(pxAlongMidLine)): + d3UnitAlong.append(d3UnitAroundAlong[n2][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(pxAlongMidLine, pd2AlongMidLine, d3UnitAlong) + d2CurvatureAnnulusZero = d2CurvatureAlong[-1] + for n2 in range(len(d2CurvatureAlong) - 1): + d2Curvature[n2][n1] = d2CurvatureAlong[n2] + + d3UnitAlong = [] + for n in range(len(pxAlongMidLineBottom)): + d3UnitAlong.append(d3UnitAroundAlong[n + endRowIdx][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(pxAlongMidLineBottom, pd2AlongMidLineBottom, d3UnitAlong) + d2CurvatureAlongHalfOstium = d2CurvatureAlong[0] + for n in range(1, len(pd2AlongMidLineBottom)): + nIdx = n + endRowIdx + d2Curvature[nIdx][n1] = d2CurvatureAlong[n] + + elif n1 == elementsCountAroundHalfHaustrum: + # From apex to annulus + for n2 in range(elementsCountAlongSegment): + d3UnitAlong.append(d3UnitAroundAlong[n2][n1 + (0 if (n2 < startRowIdx or n2 > endRowIdx) else -1)]) + d3UnitAlong.append(d3UnitAroundAlong[n2 + 1][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(xAlong[:startRowIdx + 1], nd2AlongBottomRHS, + d3UnitAlong[:startRowIdx + 1]) + + # Curvature of nodes along LHS annulus + for m in range(endRowIdx - startRowIdx - 1): + d2CurvatureAlong.append(d1Curvature[m + startRowIdx + 1][n1 - 1]) + + # From annulus to distal end + d2CurvatureAlong += interp.getCurvaturesAlongCurve(xAlong[endRowIdx:], nd2AlongTopRHS, + d3UnitAlong[endRowIdx:]) + + for n2 in range(len(d2CurvatureAlong)): + if n2 < startRowIdx or n2 > endRowIdx: + n1Idx = n1 + else: + n1Idx = n1 - 1 + d2Curvature[n2][n1Idx] = d2CurvatureAlong[n2] + + for n2 in range(startRowIdx, endRowIdx + 1): + d1Curvature[n2][n1] = annulusD2Curvature[-annulusIdx] + annulusIdx += 1 - # Top boundary - topPositionOfCentreElement = TrackSurfacePosition(ei1, ei2, xi1, 1.0) - xTop, _, d2Top = trackSurfaceOstium.evaluateCoordinates(topPositionOfCentreElement, derivatives=True) - distxCentreToxTop = interp.computeCubicHermiteArcLength(xCentre, d2Centre, xTop, d2Top, False) - remainingLength = ostiumDiameter * 0.5 - distxCentreToxTop - xCurrent = xTop - d2Current = d2Top - - for n2 in range(ei2, elementsAlongTrackSurface): - if remainingLength > 0.0: - nextPosition = TrackSurfacePosition(ei1, n2+1, xi1, 1.0) - xNext, _, d2Next = trackSurfaceOstium.evaluateCoordinates(nextPosition, derivatives=True) - distxCurrentToxNext = interp.computeCubicHermiteArcLength(xCurrent, d2Current, xNext, d2Next, False) - remainingLength -= distxCurrentToxNext - xCurrent = xNext - d2Current = d2Next else: - ei2Top = n2 - break + for n2 in range(elementsCountAlongSegment): + d3UnitAlong.append(d3UnitAroundAlong[n2][n1 + (0 if (n2 < startRowIdx or n2 > endRowIdx) else -1)]) + d3UnitAlong.append(d3UnitAroundAlong[n2 + 1][n1]) + d2CurvatureAlong = interp.getCurvaturesAlongCurve(xAlong, d2Along, d3UnitAlong) + + # Adjust for corners + if n1 == elementsCountAroundHalfHaustrum: + d2CurvatureAlong[endRowIdx] = annulusD2Curvature[int(elementsCountAlongSegment * 0.5) + 1] + + for n2 in range(len(d2CurvatureAlong)): + if n2 < startRowIdx or n2 > endRowIdx: + n1Idx = n1 + else: + n1Idx = n1 - 1 + d2Curvature[n2][n1Idx] = d2CurvatureAlong[n2] + + # Adjust annulus points + xAroundAlong[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), xAnnulusOuter[0]) + d1AroundAlong[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d2AnnulusOuter[0]) + d2AroundAlong[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), vector.setMagnitude(d1AnnulusOuter[0], + annulusD2ZeroMag)) + d3UnitAroundAlong[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d3Annulus[0]) + d1Curvature[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), annulusD2Curvature[0]) + d2Curvature[startRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d2CurvatureAnnulusZero) + + idx = int(elementsCountAlongSegment * 0.5) + xAroundAlong[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), xAnnulusOuter[idx]) + d1AroundAlong[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d2AnnulusOuter[idx]) + d2AroundAlong[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), vector.setMagnitude(d1AnnulusOuter[idx], + annulusD2HalfOstiumMag)) + d3UnitAroundAlong[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d3Annulus[idx]) + d1Curvature[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), annulusD2Curvature[idx]) + d2Curvature[endRowIdx].insert(int(elementsCountAroundHaustrum * 0.5), d2CurvatureAlongHalfOstium) + + # Create inner nodes + sideNodesToDelete = [] + xList = [] + d1List = [] + d2List = [] + d3List = [] + nodeIdx = ostiumFaceStartNode + idxMat = [] + + if elementsCountThroughWall > 1: + thicknessProportionsUI = [0.0, mucosaRelThickness, submucosaRelThickness, circularRelThickness, + longitudinalRelThickness, longitudinalRelThickness] + thicknessProportions = [thicknessProportion / sum(thicknessProportionsUI[:-1]) + for thicknessProportion in thicknessProportionsUI] + + xi3List = [] + xi3 = 0.0 + for i in range(len(thicknessProportions) - 1): + xi3 += thicknessProportions[i] + xi3List.append(xi3) + + count = 0 + for n2 in range(len(xAroundAlong)): + idxThroughWall = [] + for n3 in range(elementsCountThroughWall + 1): + xi3 = xi3List[n3] if elementsCountThroughWall > 1 else 1.0 / elementsCountThroughWall * n3 + idxAround = [] + + for n1 in range(1 if (n2 == 0 and segmentIdx == 0) else len(xAroundAlong[n2])): + if n1 == 0 or n1 == len(xAroundAlong[n2]) - 1: + sideNodesToDelete.append(nodeIdx) + newNodeIdx = sideNodes[count] + startNode - 1 + count += 1 + + elif n2 == 0 and segmentIdx and n1 > 0 and n1 < len(xAroundAlong[n2]) - 1: + sideNodesToDelete.append(nodeIdx) + newNodeIdx = sideNodes[count] + startNode - 1 + count += 1 + + elif n2 == len(xAroundAlong) - 1 and n1 > 0 and n1 < len(xAroundAlong[n2]) - 1: + sideNodesToDelete.append(nodeIdx) + newNodeIdx = sideNodes[count] + startNode - 1 + count += 1 + + else: + newNodeIdx = nodeIdx + + # Coordinates + norm = d3UnitAroundAlong[n2][n1] + xOut = xAroundAlong[n2][n1] + xIn = [xOut[i] - norm[i] * wallThickness for i in range(3)] + dWall = [wallThickness * c for c in norm] + x = interp.interpolateCubicHermite(xIn, dWall, xOut, dWall, xi3) + xList.append(x) + + # d1 + factor = 1.0 + wallThickness * (1.0 - xi3) * d1Curvature[n2][n1] + d1 = [factor * c for c in d1AroundAlong[n2][n1]] + d1List.append(d1) + + # d2 + factor = 1.0 + wallThickness * (1.0 - xi3) * d2Curvature[n2][n1] + d2 = [factor * c for c in d2AroundAlong[n2][n1]] + d2List.append(d2) + + # d3 + d3 = [c * wallThickness * (thicknessProportions[n3 + 1] if elementsCountThroughWall > 1 else 1.0) + for c in norm] + d3List.append(d3) + + idxAround.append(newNodeIdx) + nodeIdx += 1 + idxThroughWall.append(idxAround) + idxMat.append(idxThroughWall) + + for n in range(len(xList)): + if nextNodeIdentifier in sideNodesToDelete: + nextNodeIdentifier += 1 + continue + else: + node = nodes.createNode(nextNodeIdentifier, nodetemplate) + cache.setNode(node) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, xList[n]) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1List[n]) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2List[n]) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, d3List[n]) + if useCrossDerivatives: + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS2, 1, zero) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS3, 1, zero) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS2DS3, 1, zero) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D3_DS1DS2DS3, 1, zero) + nextNodeIdentifier += 1 + + # Create elements + elementIdxMat = [] + + if useCubicHermiteThroughWall: + eftfactory = eftfactory_tricubichermite(mesh, useCrossDerivatives) + else: + eftfactory = eftfactory_bicubichermitelinear(mesh, useCrossDerivatives) + eftStandard = eftfactory.createEftBasic() + + elementtemplateStandard = mesh.createElementtemplate() + elementtemplateStandard.setElementShapeType(Element.SHAPE_TYPE_CUBE) + elementtemplateStandard.defineField(coordinates, -1, eftStandard) + + elementtemplateX = mesh.createElementtemplate() + elementtemplateX.setElementShapeType(Element.SHAPE_TYPE_CUBE) + + radiansPerElementAround = math.pi * 2.0 / elementsCountAround + elementIdentifier = ostiumFaceStartElement + + for e2 in range(elementsCountAlongSegment): + elementIdxThroughWall = [] + if segmentIdx == 0 and e2 == 0: # pole + for e3 in range(elementsCountThroughWall): + elementIdxAround = [] + for e1 in range(elementsCountAroundHaustrum): + va = e1 + startIdxElementsAround + vb = (e1 + startIdxElementsAround + 1) + eft1 = eftfactory.createEftShellPoleBottom(va * 100, vb * 100) + elementtemplateX.defineField(coordinates, -1, eft1) + element = mesh.createElement(elementIdentifier, elementtemplateX) + bni1 = e3 + 1 + startNode - 1 + bni2 = idxMat[e2 + 1][e3][e1] + bni3 = idxMat[e2 + 1][e3][e1 + 1] + bni4 = bni1 + 1 + bni5 = idxMat[e2 + 1][e3 + 1][e1] + bni6 = idxMat[e2 + 1][e3 + 1][e1 + 1] + nodeIdentifiers = [bni1, bni2, bni3, bni4, bni5, bni6] + element.setNodesByIdentifier(eft1, nodeIdentifiers) + # set general linear map coefficients + radiansAround = (e1 + 1) * radiansPerElementAround + sectorStartAngle + radiansAroundNext = (e1 + 2) * radiansPerElementAround + sectorStartAngle + scalefactors = [ + -1.0, + math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, + math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround, + math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, + math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround] + element.setScaleFactors(eft1, scalefactors) + elementIdxAround.append(elementIdentifier) + elementIdentifier += 1 + annotationGroups = annotationGroupsAlong[e2] + annotationGroupsThroughWall[e3] + if annotationGroups: + allAnnotationGroups = mergeAnnotationGroups(allAnnotationGroups, annotationGroups) + for annotationGroup in annotationGroups: + meshGroup = annotationGroup.getMeshGroup(mesh) + meshGroup.addElement(element) + elementIdxThroughWall.append(elementIdxAround) + elementIdxMat.append(elementIdxThroughWall) + else: + for e3 in range(elementsCountThroughWall): + elementIdxAround = [] + for e1 in range(len(xAroundAlong[e2]) - 1): + offset = 0 + if endRowIdx - startRowIdx > 1: + if e2 == startRowIdx and e1 > int(0.5 * len(xAroundAlong[e2])): + offset = -1 + elif e2 == endRowIdx - 1 and e1 >= int(0.5 * len(xAroundAlong[e2])): + offset = 1 + + if (startRowIdx <= e2 <= endRowIdx - 1) and 0.5 * len(xAroundAlong[e2]) - 2 < e1 < 0.5 * len( + xAroundAlong[e2]): + continue + else: + eft1 = eftStandard + scaleFactors = [] + elementtemplate1 = elementtemplateStandard + bni111 = idxMat[e2][e3][e1] + bni211 = idxMat[e2][e3][e1 + 1] + bni121 = idxMat[e2 + 1][e3][e1 + offset] + bni221 = idxMat[e2 + 1][e3][e1 + 1 + offset] + bni112 = idxMat[e2][e3 + 1][e1] + bni212 = idxMat[e2][e3 + 1][e1 + 1] + bni122 = idxMat[e2 + 1][e3 + 1][e1 + offset] + bni222 = idxMat[e2 + 1][e3 + 1][e1 + 1 + offset] + nodeIdentifiers = [bni111, bni211, bni121, bni221, + bni112, bni212, bni122, bni222] + + if e2 == startRowIdx - 1: + if e1 == elementsCountAroundHalfHaustrum - 3: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 331 + + elif e1 == elementsCountAroundHalfHaustrum - 2: # LHS bottom + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + # print(elementIdentifier) # 332 + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + + elif e1 == elementsCountAroundHalfHaustrum - 1: # RHS bottom + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1])]) + # print(elementIdentifier) # 333 + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + + elif e1 == elementsCountAroundHalfHaustrum: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS2, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) #334 + + elif e2 == startRowIdx: + if e1 == elementsCountAroundHalfHaustrum - 3: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 339 + + elif e1 == elementsCountAroundHalfHaustrum: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, [1]), (Node.VALUE_LABEL_D_DS2, [])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 340 + + elif int(elementsCountAroundOstium*0.25) - 2 > 0 and \ + startRowIdx + 1 <= e2 < startRowIdx + 1 + \ + 2.0 * (int(elementsCountAroundOstium*0.25) - 2): + if e1 == elementsCountAroundHalfHaustrum - 3: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 183, 201 + + elif e1 == elementsCountAroundHalfHaustrum - 1: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 184, 202 + + elif e2 == endRowIdx - 1: + if e1 == elementsCountAroundHalfHaustrum - 3: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS2, [1])]) + remapEftNodeValueLabel(eft1, [4, 8], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 345 + + elif e1 == elementsCountAroundHalfHaustrum - 1: + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS2, [])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS2, + [(Node.VALUE_LABEL_D_DS1, [1])]) + remapEftNodeValueLabel(eft1, [3, 7], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS2, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) # 346 + + elif e2 == endRowIdx: + if e1 == elementsCountAroundHalfHaustrum - 3: # end LHS -1 + scaleFactors = [-1.0] + eft1 = eftfactory.createEftNoCrossDerivatives() + setEftScaleFactorIds(eft1, [1], []) + remapEftNodeValueLabel(eft1, [2, 6], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS2, [1])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print('1', elementIdentifier) #351 + + elif e1 == elementsCountAroundHalfHaustrum: # end RHS + 1 + eft1 = eftfactory.createEftNoCrossDerivatives() + remapEftNodeValueLabel(eft1, [1, 5], Node.VALUE_LABEL_D_DS1, + [(Node.VALUE_LABEL_D_DS1, []), (Node.VALUE_LABEL_D_DS2, [])]) + elementtemplateX.defineField(coordinates, -1, eft1) + elementtemplate1 = elementtemplateX + # print(elementIdentifier) #354 + + element = mesh.createElement(elementIdentifier, elementtemplate1) + element.setNodesByIdentifier(eft1, nodeIdentifiers) + if scaleFactors: + element.setScaleFactors(eft1, scaleFactors) + elementIdxAround.append(elementIdentifier) + elementIdentifier += 1 + annotationGroups = annotationGroupsAlong[e2] + annotationGroupsThroughWall[e3] + if annotationGroups: + allAnnotationGroups = mergeAnnotationGroups(allAnnotationGroups, annotationGroups) + for annotationGroup in annotationGroups: + meshGroup = annotationGroup.getMeshGroup(mesh) + meshGroup.addElement(element) + elementIdxThroughWall.append(elementIdxAround) + elementIdxMat.append(elementIdxThroughWall) + + # Annulus + # Assemble endPoints for annulus + endPoints_x = [[None] * elementsCountAroundOstium for n3 in range(elementsCountThroughWall + 1)] + endPoints_d1 = [[None] * elementsCountAroundOstium for n3 in range(elementsCountThroughWall + 1)] + endPoints_d2 = [[None] * elementsCountAroundOstium for n3 in range(elementsCountThroughWall + 1)] + endNode_Id = [[None] * elementsCountAroundOstium for n3 in range(elementsCountThroughWall + 1)] + endDerivativesMap = [[None] * elementsCountAroundOstium for n3 in range(elementsCountThroughWall + 1)] + endProportions = [] + + for n3 in range(elementsCountThroughWall + 1): + n1 = 0 + for nAround in range(elementsCountAroundOstium): + if nAround == 0: + idx = idxMat[startRowIdx][n3][elementsCountAroundHalfHaustrum - 1] + elif 0 < nAround < (elementsCountAroundOstium * 0.5): + idx = idxMat[startRowIdx + n1][n3][elementsCountAroundHalfHaustrum - 2] + n1 += 1 + elif nAround == int(elementsCountAroundOstium * 0.5): + n1 -= 1 + idx = idxMat[startRowIdx + n1][n3][elementsCountAroundHalfHaustrum - 1] + else: + idx = idxMat[startRowIdx + n1][n3][ + elementsCountAroundHalfHaustrum - 1 + ( + 1 if (n1 == int(elementsCountAroundOstium * 0.5) - 2 or n1 == 0) else 0)] + n1 -= 1 + + endPoints_x[n3][nAround] = xList[idx - ostiumFaceStartNode] + endPoints_d1[n3][nAround] = d1List[idx - ostiumFaceStartNode] + endPoints_d2[n3][nAround] = d2List[idx - ostiumFaceStartNode] + endNode_Id[n3][nAround] = idx + + if n3 == elementsCountThroughWall: # outer layer + endPosition = trackSurfaceOstium.findNearestPosition(endPoints_x[n3][nAround]) + endProportions.append(trackSurfaceOstium.getProportion(endPosition)) + + for n3 in range(elementsCountThroughWall + 1): + for nAround in range(elementsCountAroundOstium): + endDerivativesMap[n3][nAround] = (None, None, None) + + startProportions = [] + for n in range(elementsCountAroundOstium): + startProportions.append(trackSurfaceOstium.getProportion(o1_Positions[n])) + + cecumWallAnnotationGroups = [] + if elementsCountThroughWall == 4: + cecumWallAnnotationGroups = [[mucosaGroup], [submucosaGroup], [circularMuscleGroup], + [longitudinalMuscleGroup]] + + nextNodeIdentifier, nextElementIdentifier = createAnnulusMesh3d( + nodes, mesh, nextNodeIdentifier, elementIdentifier, + o1_x, o1_d1, o1_d2, None, o1_NodeId, None, + endPoints_x, endPoints_d1, endPoints_d2, None, endNode_Id, endDerivativesMap, + elementsCountRadial=1, meshGroups=[cecumMeshGroup], + wallAnnotationGroups=cecumWallAnnotationGroups, + tracksurface=trackSurfaceOstium, + startProportions=startProportions, endProportions=endProportions, + rescaleStartDerivatives=True, rescaleEndDerivatives=True, sampleBlend=0.0, fixMinimumStart=True, + coordinates=coordinates) + + # Delete elements in new haustrum + mesh_destroy_elements_and_nodes_by_identifiers(mesh, deleteElementIdentifier) + + return allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier, nodesIdDistal, xDistal, d1Distal, \ + d2Distal, d3Distal + + +class CecumNetworkLayout: + """ + Generates sampled network layout for cecum scaffold. + """ + def __init__(self, region, networkLayout, termsAlong=[None], ileumSegmentIdx=0, cecumSegmentIdx=[1,2]): + """ + :param region: Zinc region to define model in. + :param networkLayout: Network layout subscaffold from meshtype_1d_networklayout1 + :param termsAlong: Annotation terms along length of network layout + :param ileumSegmentIdx: Segment index of ileum branch. + :param cecumSegmentIdx: Segment index of body of cecum. + """ - return ei1Left, ei1Right, ei2Bottom, ei2Top + # Extract length of each group along cecum from network layout + arcLengthOfGroupsAlong = [] + cxGroups = [] + cd1Groups = [] + cd2Groups = [] + cd3Groups = [] + cd12Groups = [] + cd13Groups = [] + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + pathNetworkMesh = networkLayout.getConstructionObject() + tmpFieldmodule = tmpRegion.getFieldmodule() + tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + networkSegments = pathNetworkMesh.getNetworkSegments() + + cxGroup = [] + cd1Group = [] + cd2Group = [] + cd3Group = [] + cd12Group = [] + cd13Group = [] + cecumNodes = [] + lowerCecumNodes = [] + lowerCecumVersions = [] + ileumNodes = [] + ileumVersions = [] + + for termName in termsAlong: + tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None + tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes + + if termName == "caecum": + nodeiterator = tmpNodeset.createNodeiterator() + node = nodeiterator.next() + while node.isValid(): + cecumNodes.append(node.getIdentifier()) + node = nodeiterator.next() + + for i in range(len(networkSegments[cecumSegmentIdx[1]].getNodeIdentifiers())): + if networkSegments[cecumSegmentIdx[1]].getNodeIdentifiers()[i] in cecumNodes: + lowerCecumNodes.append(networkSegments[cecumSegmentIdx[1]].getNodeIdentifiers()[i]) + lowerCecumVersions.append(networkSegments[cecumSegmentIdx[1]].getNodeVersions()[i]) + + for i in range(2): + cx, cd1, cd2, cd3, cd12, cd13 = get_nodeset_path_ordered_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3], + (lowerCecumNodes if i else networkSegments[cecumSegmentIdx[0]].getNodeIdentifiers()), + (lowerCecumVersions if i else networkSegments[cecumSegmentIdx[0]].getNodeVersions())) + + cxGroup += cx[(1 if i else 0):] + cd1Group += cd1[(1 if i else 0):] + cd2Group += cd2[(1 if i else 0):] + cd3Group += cd3[(1 if i else 0):] + cd12Group += cd12[(1 if i else 0):] + cd13Group += cd13[(1 if i else 0):] + + if i == 0: + xbranchpt = cx[-1] + d2branchpt = cd2[-1] + d3branchpt = cd3[-1] + arcLengthToBranchPt = 0.0 + for n in range(len(cx) - 1): + arcLengthToBranchPt += interp.getCubicHermiteArcLength(cx[n], cd1[n], cx[n + 1], cd1[n + 1]) + + elif termName == "ileum part of cecum": + for i in range(len(networkSegments[ileumSegmentIdx].getNodeIdentifiers())): + if networkSegments[ileumSegmentIdx].getNodeIdentifiers()[i] in cecumNodes: + ileumNodes.append(networkSegments[ileumSegmentIdx].getNodeIdentifiers()[i]) + ileumVersions.append(networkSegments[ileumSegmentIdx].getNodeVersions()[i]) + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = \ + get_nodeset_path_ordered_field_parameters(tmpNodes, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3], + ileumNodes, ileumVersions) + + arcLength = 0.0 + for e in range(len(cxGroup) - 1): + arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], + cxGroup[e + 1], cd1Group[e + 1]) + arcLengthOfGroupsAlong.append(arcLength) + cxGroups.append(cxGroup) + cd1Groups.append(cd1Group) + cd2Groups.append(cd2Group) + cd3Groups.append(cd3Group) + cd12Groups.append(cd12Group) + cd13Groups.append(cd13Group) + + del tmpNodeset + del tmpGroup + + del tmpCoordinates + del tmpNodes + del tmpFieldmodule + del tmpRegion + + self.arcLengthOfGroupsAlong = arcLengthOfGroupsAlong + self.cxGroups = cxGroups + self.cd1Groups = cd1Groups + self.cd2Groups = cd2Groups + self.cd3Groups = cd3Groups + self.cd12Groups = cd12Groups + self.cd13Groups = cd13Groups + self.xBranchPt = xbranchpt + self.d2BranchPt = d2branchpt + self.d3BranchPt = d3branchpt + self.arcLengthToBranchPt = arcLengthToBranchPt + +class CustomNetworkLayout: + """ + Generates sampled network layout for part of network layout. + """ + def __init__(self, cx, cd1, cd2, cd3, cd12, cd13): + self.cxPath = cx + self.cd1Path = cd1 + self.cd2Path = cd2 + self.cd3Path = cd3 + self.cd12Path = cd12 + self.cd13Path = cd13 diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_colon1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_colon1.py index c48033cc..944116cb 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_colon1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_colon1.py @@ -12,9 +12,9 @@ from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, findOrCreateAnnotationGroupForTerm, \ getAnnotationGroupForTerm from scaffoldmaker.annotation.colon_terms import get_colon_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 from scaffoldmaker.meshtypes.meshtype_3d_colonsegment1 import MeshType_3d_colonsegment1, \ - ColonSegmentTubeMeshInnerPoints, getTeniaColi, createFlatCoordinatesTeniaColi, createColonCoordinatesTeniaColi, \ + ColonSegmentTubeMeshOuterPoints, getTeniaColi, createFlatCoordinatesTeniaColi, createColonCoordinatesTeniaColi, \ createNodesAndElementsTeniaColi from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.scaffoldpackage import ScaffoldPackage @@ -24,300 +24,312 @@ from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ get_nodeset_path_field_parameters - -class MeshType_3d_colon1(Scaffold_base): - ''' - Generates a 3-D colon mesh with variable numbers - of elements around, along the central line, and through wall. - The colon is created by a function that generates a colon - segment and uses tubemesh to map the segment along a central - line profile. - ''' - - centralPathDefaultScaffoldPackages = { - 'Cattle 1': ScaffoldPackage(MeshType_1d_path1, { +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 52 - }, - 'meshEdits': exnode_string_from_nodeset_field_parameters( - [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ - (1, [ [ -245.30, 444.60, -49.10 ], [ -267.70, -53.10, -20.20 ], [ 0.00, 0.00, 35.00 ], [ 0.00, 0.00, -4.41 ], [ -6.81, 34.33, 0.00 ], [ 0.00, 0.00, -4.41] ] ), - (2, [ [ -380.30, 484.80, -45.00 ], [ 24.50, 102.70, 15.70 ], [ 0.00, 0.00, 31.47 ], [ 0.00, 0.00, -2.65 ], [ 30.61, -7.30, 0.00 ], [ 0.00, 0.00, -2.65] ] ), - (3, [ [ -298.10, 510.40, -36.80 ], [ 73.60, 9.90, -16.40 ], [ 0.00, 0.00, 29.34 ], [ -12.52, -3.10, -14.34 ], [ 3.91, -29.08, 0.00 ], [ -12.52, -3.10, -14.34] ] ), - (4, [ [ -213.10, 527.90, -22.50 ], [ -1.00, -10.80, 125.60 ], [ -26.23, -6.50, 1.62 ], [ -4.10, -6.11, -25.37 ], [ 6.36, -26.22, -2.20 ], [ -4.10, -6.11, -25.37] ] ), - (5, [ [ -315.50, 570.20, 18.90 ], [ -107.90, 9.30, 21.90 ], [ -2.62, -12.12, -20.82 ], [ 14.35, 4.82, -10.40 ], [ 0.65, -20.97, 12.13 ], [ 14.35, 4.82, -10.40] ] ), - (6, [ [ -417.40, 555.00, 14.60 ], [ -83.00, -41.30, -0.80 ], [ 4.22, 1.17, -21.45 ], [ 0.54, 4.88, 0.73 ], [ 9.74, -19.59, 0.85 ], [ 0.54, 4.88, 0.73] ] ), - (7, [ [ -497.30, 488.90, 13.60 ], [ -44.60, -81.60, 10.00 ], [ -1.56, -2.39, -19.34 ], [ -2.12, -0.60, 2.13 ], [ 17.14, -9.40, -0.22 ], [ -2.12, -0.60, 2.13] ] ), - (8, [ [ -527.00, 392.50, 2.70 ], [ 47.40, -82.00, -7.90 ], [ 0.00, 0.00, -17.20 ], [ 0.68, 1.04, 1.96 ], [ 14.89, 8.61, 0.00 ], [ 0.68, 1.04, 1.96] ] ), - (9, [ [ -461.20, 345.90, -0.80 ], [ 56.90, -44.50, 2.40 ], [ 0.00, 0.00, -15.38 ], [ 0.00, 0.00, 1.09 ], [ 9.47, 12.11, 0.00 ], [ 0.00, 0.00, 1.09] ] ), - (10, [ [ -415.60, 293.80, 3.90 ], [ 93.20, -62.60, 3.10 ], [ 0.00, 0.00, -14.91 ], [ 0.00, 0.00, 0.43 ], [ 8.31, 12.38, 0.00 ], [ 0.00, 0.00, 0.43] ] ), - (11, [ [ -232.20, 264.90, 0.20 ], [ 140.10, 58.20, -1.00 ], [ 0.00, 0.00, -14.58 ], [ 0.00, 0.00, 0.25 ], [ -5.59, 13.46, 0.00 ], [ 0.00, 0.00, 0.25] ] ), - (12, [ [ -168.40, 357.20, 1.30 ], [ 10.10, 78.60, -3.20 ], [ 0.00, 0.00, -14.38 ], [ 0.00, 0.00, 0.15 ], [ -14.26, 1.83, 0.00 ], [ 0.00, 0.00, 0.15] ] ), - (13, [ [ -185.30, 419.10, -0.70 ], [ -45.10, 57.10, -0.90 ], [ 0.00, 0.00, -14.27 ], [ 0.00, 0.00, 0.13 ], [ -11.20, -8.84, 0.00 ], [ 0.00, 0.00, 0.13] ] ), - (14, [ [ -253.20, 466.70, -0.30 ], [ -63.40, 24.70, 0.20 ], [ 0.00, 0.00, -14.13 ], [ 0.00, 0.00, 0.13 ], [ -5.13, -13.17, 0.00 ], [ 0.00, 0.00, 0.13] ] ), - (15, [ [ -323.80, 482.50, 0.10 ], [ -68.20, 2.90, -1.20 ], [ 0.00, 0.00, -14.00 ], [ 0.00, 0.00, 0.12 ], [ -0.59, -13.99, 0.00 ], [ 0.00, 0.00, 0.12] ] ), - (16, [ [ -387.50, 485.40, -0.20 ], [ -44.20, -17.10, -1.00 ], [ 0.00, 0.00, -13.89 ], [ 0.00, 0.00, 0.12 ], [ 5.01, -12.95, 0.00 ], [ 0.00, 0.00, 0.12] ] ), - (17, [ [ -435.60, 433.50, 3.30 ], [ 3.40, -109.50, 1.40 ], [ 0.00, 0.00, -13.76 ], [ 0.00, 0.00, 0.14 ], [ 13.75, 0.43, 0.00 ], [ 0.00, 0.00, 0.14] ] ), - (18, [ [ -370.60, 376.30, -1.10 ], [ 66.90, -29.20, -0.90 ], [ 0.00, 0.00, -13.60 ], [ 0.00, 0.00, 0.12 ], [ 5.44, 12.46, 0.00 ], [ 0.00, 0.00, 0.12] ] ), - (19, [ [ -313.00, 357.90, -0.10 ], [ 40.00, -33.50, 9.60 ], [ 0.00, 0.00, -13.50 ], [ 0.00, 0.00, 0.10 ], [ 8.67, 10.35, 0.00 ], [ 0.00, 0.00, 0.10] ] ), - (20, [ [ -259.20, 340.70, 2.10 ], [ 48.90, 6.40, 1.40 ], [ 0.00, 0.00, -13.40 ], [ 0.00, 0.00, 0.09 ], [ -1.74, 13.29, 0.00 ], [ 0.00, 0.00, 0.09] ] ), - (21, [ [ -246.50, 380.30, -0.80 ], [ -29.70, 33.60, -0.70 ], [ 0.00, 0.00, -13.31 ], [ 0.00, 0.00, 0.09 ], [ -9.97, -8.82, 0.00 ], [ 0.00, 0.00, 0.09] ] ), - (22, [ [ -297.30, 387.10, 0.60 ], [ -59.70, 12.60, -0.00 ], [ 0.00, 0.00, -13.22 ], [ 0.00, 0.00, 0.09 ], [ -2.73, -12.94, 0.00 ], [ 0.00, 0.00, 0.09] ] ), - (23, [ [ -340.20, 415.60, -1.00 ], [ -86.20, 28.90, -2.90 ], [ 0.00, 0.00, -13.13 ], [ 0.00, 0.00, 0.10 ], [ -4.17, -12.45, 0.00 ], [ 0.00, 0.00, 0.10] ] ), - (24, [ [ -398.30, 443.10, -0.10 ], [ 10.60, 82.10, -2.60 ], [ 0.00, 0.00, -13.01 ], [ 0.00, 0.00, 0.12 ], [ -12.90, 1.67, 0.00 ], [ 0.00, 0.00, 0.12] ] ), - (25, [ [ -329.80, 449.10, -2.10 ], [ 53.20, 14.00, -0.50 ], [ 0.00, 0.00, -12.88 ], [ 0.00, 0.00, 0.14 ], [ -3.28, 12.46, 0.00 ], [ 0.00, 0.00, 0.14] ] ), - (26, [ [ -251.30, 425.90, -0.30 ], [ 43.90, -19.30, 0.00 ], [ 0.00, 0.00, -12.74 ], [ 0.00, 0.00, 0.11 ], [ 5.13, 11.66, 0.00 ], [ 0.00, 0.00, 0.11] ] ), - (27, [ [ -209.10, 390.60, 0.00 ], [ 26.00, -38.80, 0.90 ], [ 0.00, 0.00, -12.65 ], [ 0.00, 0.00, 0.08 ], [ 10.51, 7.04, 0.00 ], [ 0.00, 0.00, 0.08] ] ), - (28, [ [ -207.80, 350.80, 1.40 ], [ -9.40, -43.60, 1.80 ], [ 0.00, 0.00, -12.57 ], [ 0.00, 0.00, 0.09 ], [ 12.29, -2.65, 0.00 ], [ 0.00, 0.00, 0.09] ] ), - (29, [ [ -245.80, 299.40, 7.60 ], [ -70.30, -36.00, 1.40 ], [ 0.00, 0.00, -12.46 ], [ 0.00, 0.00, 0.14 ], [ 5.68, -11.09, 0.00 ], [ 0.00, 0.00, 0.14] ] ), - (30, [ [ -345.30, 304.10, 3.10 ], [ -100.20, 27.90, -1.90 ], [ 0.00, 0.00, -12.29 ], [ 0.00, 0.00, 0.17 ], [ -3.30, -11.84, 0.00 ], [ 0.00, 0.00, 0.17] ] ), - (31, [ [ -418.40, 361.10, -0.20 ], [ -57.80, 55.80, -1.70 ], [ 0.00, 0.00, -12.13 ], [ 0.00, 0.00, 0.15 ], [ -8.42, -8.73, 0.00 ], [ 0.00, 0.00, 0.15] ] ), - (32, [ [ -479.20, 415.60, 2.20 ], [ -8.80, 73.10, -1.60 ], [ 0.00, 0.00, -11.98 ], [ 0.00, 0.00, 0.15 ], [ -11.89, -1.43, 0.00 ], [ 0.00, 0.00, 0.15] ] ), - (33, [ [ -439.60, 495.70, -2.10 ], [ 61.10, 57.10, -1.30 ], [ 0.00, 0.00, -11.82 ], [ 0.00, 0.00, 0.15 ], [ -8.07, 8.64, 0.00 ], [ 0.00, 0.00, 0.15] ] ), - (34, [ [ -361.60, 522.60, -3.00 ], [ 78.60, 9.90, 0.20 ], [ 0.00, 0.00, -11.68 ], [ 0.00, 0.00, 0.15 ], [ -1.46, 11.59, 0.00 ], [ 0.00, 0.00, 0.15] ] ), - (35, [ [ -270.10, 506.50, -3.80 ], [ 103.60, -33.30, 1.00 ], [ 0.00, 0.00, -11.52 ], [ 0.00, 0.00, 0.19 ], [ 3.53, 10.97, 0.00 ], [ 0.00, 0.00, 0.19] ] ), - (36, [ [ -148.90, 441.40, -2.10 ], [ 79.70, -91.50, 2.80 ], [ 0.00, 0.00, -11.28 ], [ 0.00, 0.00, 0.23 ], [ 8.51, 7.41, 0.00 ], [ 0.00, 0.00, 0.23] ] ), - (37, [ [ -130.90, 313.30, 4.00 ], [ -4.00, -107.20, 3.10 ], [ 0.00, 0.00, -11.05 ], [ 0.00, 0.00, 0.18 ], [ 11.04, -0.41, 0.00 ], [ 0.00, 0.00, 0.18] ] ), - (38, [ [ -183.90, 251.00, 3.80 ], [ -65.50, -60.20, 3.60 ], [ 0.00, 0.00, -10.90 ], [ 0.00, 0.00, 0.16 ], [ 7.38, -8.03, 0.00 ], [ 0.00, 0.00, 0.16] ] ), - (39, [ [ -280.30, 213.00, 3.40 ], [ -165.10, -18.60, 0.10 ], [ 0.00, 0.00, -10.72 ], [ 0.00, 0.00, 0.20 ], [ 1.20, -10.65, 0.00 ], [ 0.00, 0.00, 0.20] ] ), - (40, [ [ -400.80, 247.50, 6.80 ], [ -127.10, 36.80, 1.30 ], [ 0.00, 0.00, -10.51 ], [ 0.00, 0.00, 0.23 ], [ -2.92, -10.10, 0.00 ], [ 0.00, 0.00, 0.23] ] ), - (41, [ [ -530.50, 290.70, 5.20 ], [ -89.00, 86.50, 0.30 ], [ 0.00, 0.00, -10.27 ], [ 0.00, 0.00, 0.21 ], [ -7.16, -7.36, 0.00 ], [ 0.00, 0.00, 0.21] ] ), - (42, [ [ -568.80, 392.30, 6.90 ], [ -77.40, 67.70, -5.50 ], [ 0.00, 0.00, -10.08 ], [ 0.00, 0.00, 0.23 ], [ -6.64, -7.59, 0.00 ], [ 0.00, 0.00, 0.23] ] ), - (43, [ [ -511.20, 535.10, 2.50 ], [ 86.20, 111.40, -1.00 ], [ 0.00, 0.00, -9.80 ], [ 0.00, 0.00, 0.25 ], [ -7.75, 6.00, 0.00 ], [ 0.00, 0.00, 0.25] ] ), - (44, [ [ -405.00, 601.70, 6.40 ], [ 143.60, 52.20, 2.60 ], [ 0.00, 0.00, -9.58 ], [ 1.49, -1.44, 0.82 ], [ -3.27, 9.00, 0.00 ], [ 1.49, -1.44, 0.82] ] ), - (45, [ [ -238.80, 615.90, 16.60 ], [ 63.30, -9.10, 19.10 ], [ 3.45, -3.33, -7.95 ], [ -5.13, 0.21, 1.79 ], [ 2.06, 8.63, -2.72 ], [ -5.13, 0.21, 1.79] ] ), - (46, [ [ -146.20, 605.90, 36.50 ], [ 49.30, -9.90, -50.60 ], [ -6.72, -1.05, -6.07 ], [ -3.12, 3.94, 7.67 ], [ 0.10, 8.96, -1.66 ], [ -3.12, 3.94, 7.67] ] ), - (47, [ [ -218.40, 585.30, -2.00 ], [ -124.00, 0.40, -37.50 ], [ -3.04, 4.50, 7.19 ], [ 2.76, 2.30, 8.98 ], [ 1.33, 7.80, -4.32 ], [ 2.76, 2.30, 8.98] ] ), - (48, [ [ -376.30, 579.60, -40.80 ], [ -189.20, -50.70, -8.80 ], [ -1.85, 1.22, 8.78 ], [ 4.16, 0.49, -2.60 ], [ -2.23, 8.62, -1.67 ], [ 4.16, 0.49, -2.60] ] ), - (49, [ [ -557.90, 493.90, -24.90 ], [ -30.30, 24.10, 152.80 ], [ 6.19, 6.65, 0.69 ], [ 1.49, -2.48, -8.73 ], [ -6.35, 6.14, -2.23 ], [ 1.49, -2.48, -8.73] ] ), - (50, [ [ -484.80, 594.40, 0.70 ], [ 132.70, 97.00, 3.50 ], [ 3.25, -1.18, -8.47 ], [ -2.78, -5.06, -5.12 ], [ -5.07, 7.03, -2.92 ], [ -2.78, -5.06, -5.12] ] ), - (51, [ [ -318.10, 641.90, -8.50 ], [ 166.70, 17.60, 5.50 ], [ 0.67, -2.88, -8.72 ], [ -2.15, -0.82, -0.11 ], [ -0.82, 8.69, -2.93 ], [ -2.15, -0.82, -0.11] ] ), - (52, [ [ -158.30, 634.70, -1.90 ], [ 176.50, -14.00, 10.80 ], [ -1.08, -2.89, -8.71 ], [ -0.81, 0.27, -0.12 ], [ 0.87, 8.70, -2.99 ], [ -0.81, 0.27, -0.12] ] ), - (53, [ [ 32.70, 611.70, 13.60 ], [ 205.50, -32.20, 20.00 ], [ -0.76, -2.28, -8.98 ], [ 1.46, 0.96, -0.42 ], [ 1.62, 8.84, -2.38 ], [ 1.46, 0.96, -0.42] ] ) ] ), - - 'userAnnotationGroups': [ + "Structure": "1-2-3-4-5-6-7-8-9" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.00,0.00,0.00], [-50.70,178.20,0.00], [-40.03,-10.00,-20.01], [-6.86,-11.39,-2.36], [-19.62,-4.20,41.24], [-14.00,-1.00,-12.00]]), + (2, [[-47.40,188.60,0.00], [-19.30,177.10,0.00], [-37.98,-6.91,-13.80], [11.23,17.36,14.31], [-13.43,-4.23,38.50], [-4.00,19.00,22.00]]), + (3, [[-4.40,396.50,0.00], [206.00,40.10,0.00], [-14.88,29.77,11.90], [13.54,-1.87,21.51], [-6.48,-13.39,32.07], [-6.00,0.00,51.00]]), + (4, [[130.00,384.10,0.00], [130.80,-40.50,0.00], [-5.75,4.60,33.36], [5.83,-8.41,8.86], [-16.41,-29.84,2.70], [0.00,1.00,24.00]]), + (5, [[279.40,383.00,0.00], [118.00,48.70,0.00], [-2.70,13.54,29.79], [9.30,9.73,-10.83], [13.82,-26.53,13.55], [5.00,25.00,-20.00]]), + (6, [[443.90,390.80,0.00], [111.30,-97.00,0.00], [15.21,25.87,9.13], [12.36,-3.74,-23.50], [-10.16,-3.25,29.50], [1.00,-6.00,-35.00]]), + (7, [[475.20,168.00,0.00], [-0.80,-112.40,0.00], [22.45,0.00,-22.45], [-2.41,-19.32,-15.36], [22.45,-0.00,22.45], [15.00,-1.00,-10.00]]), + (8, [[432.60,-32.30,0.00], [-90.50,-59.00,0.00], [10.89,-16.33,-25.41], [-9.58,-7.07,-2.37], [14.04,-21.18,19.63], [8.00,-11.00,-13.00]]), + (9, [[272.40,7.50,0.00], [-79.00,47.40,0.00], [1.53,-16.88,-27.61], [-7.76,6.05,-1.75], [-5.63,-28.82,13.68], [4.00,-12.00,-12.00]]) + ]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-8', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-8', - 'name': get_colon_term('right colon')[0], - 'ontId': get_colon_term('right colon')[1] + 'identifierRanges': '1-2', + 'name': get_colon_term('ascending colon')[0], + 'ontId': get_colon_term('ascending colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '9-46', + 'identifierRanges': '3-5', 'name': get_colon_term('transverse colon')[0], 'ontId': get_colon_term('transverse colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '47-52', - 'name': get_colon_term('left colon')[0], - 'ontId': get_colon_term('left colon')[1] + 'identifierRanges': '6-8', + 'name': get_colon_term('descending colon')[0], + 'ontId': get_colon_term('descending colon')[1] }] - }), - 'Human 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif "Human 2" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 8 - }, - 'meshEdits': exnode_string_from_nodeset_field_parameters( - [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ 0.00, 0.00, 0.00 ], [ -50.70, 178.20, 0.00 ], [ -37.97, -9.49, -18.98 ], [ -6.86, -11.39, -2.36 ], [ -18.61, -3.98, 39.12 ], [ -14.00, -1.00, -12.00] ] ), - (2, [ [ -47.40, 188.60, 0.00 ], [ -19.30, 177.10, 0.00 ], [ -35.79, -6.51, -13.01 ], [ 11.23, 17.36, 14.31 ], [ -12.66, -3.99, 36.28 ], [ -4.00, 19.00, 22.00] ] ), - (3, [ [ -4.40, 396.50, 0.00 ], [ 206.00, 40.10, 0.00 ], [ -13.89, 27.78, 11.11 ], [ 13.54, -1.87, 21.51 ], [ -6.05, -12.50, 29.93 ], [ -6.00, 0.00, 51.00] ] ), - (4, [ [ 130.00, 384.10, 0.00 ], [ 130.80, -40.50, 0.00 ], [ -5.35, 4.28, 31.06 ], [ 5.83, -8.41, 8.86 ], [ -15.28, -27.78, 2.51 ], [ 0.00, 1.00, 24.00] ] ), - (5, [ [ 279.40, 383.00, 0.00 ], [ 118.00, 48.70, 0.00 ], [ -2.51, 12.57, 27.65 ], [ 9.30, 9.73, -10.83 ], [ 12.83, -24.62, 12.58 ], [ 5.00, 25.00, -20.00] ] ), - (6, [ [ 443.90, 390.80, 0.00 ], [ 111.30, -97.00, 0.00 ], [ 14.07, 23.92, 8.44 ], [ 12.36, -3.74, -23.50 ], [ -9.40, -3.01, 27.28 ], [ 1.00, -6.00, -35.00] ] ), - (7, [ [ 475.20, 168.00, 0.00 ], [ -0.80, -112.40, 0.00 ], [ 20.78, 0.00, -20.78 ], [ -2.41, -19.32, -15.36 ], [ 20.78, -0.00, 20.78 ], [ 15.00, -1.00, -10.00] ] ), - (8, [ [ 432.60, -32.30, 0.00 ], [ -90.50, -59.00, 0.00 ], [ 10.09, -15.13, -23.54 ], [ -9.58, -7.07, -2.37 ], [ 13.01, -19.62, 18.19 ], [ 8.00, -11.00, -13.00] ] ), - (9, [ [ 272.40, 7.50, 0.00 ], [ -79.00, 47.40, 0.00 ], [ 1.42, -15.65, -25.60 ], [ -7.76, 6.05, -1.75 ], [ -5.22, -26.72, 12.68 ], [ 4.00, -12.00, -12.00] ] ) ] ), - - 'userAnnotationGroups': [ - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '1-2', - 'name': get_colon_term('ascending colon')[0], - 'ontId': get_colon_term('ascending colon')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '3-5', - 'name': get_colon_term('transverse colon')[0], - 'ontId': get_colon_term('transverse colon')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '6-8', - 'name': get_colon_term('descending colon')[0], - 'ontId': get_colon_term('descending colon')[1] - }] - }), - 'Human 2': ScaffoldPackage(MeshType_1d_path1, { + "Structure": "1-2-3-4-5-6-7-8-9" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.00,0.00,0.00], [-56.81,105.14,-38.05], [-40.03,-10.00,-20.01], [-3.67,-11.77,-1.56], [-22.35,6.24,39.56], [-14.00,-1.00,-12.00]]), + (2, [[-34.50,114.00,-18.10], [-9.51,117.91,3.65], [-35.93,-6.53,-13.07], [12.13,18.49,14.99], [-13.40,-4.92,36.05], [-4.00,19.00,22.00]]), + (3, [[-19.10,218.50,5.50], [79.23,66.40,77.49], [-14.71,29.43,11.78], [14.61,7.18,21.72], [-24.58,-18.69,16.37], [-6.00,0.00,51.00]]), + (4, [[82.50,189.10,94.20], [140.70,-1.06,48.14], [-5.74,4.59,33.25], [5.75,-8.29,9.07], [12.40,-27.90,15.07], [0.00,1.00,24.00]]), + (5, [[226.60,218.70,85.70], [164.08,101.90,-75.52], [-2.72,13.61,29.95], [8.00,9.47,-9.25], [20.99,-22.00,12.86], [5.00,25.00,-20.00]]), + (6, [[325.50,381.70,-57.90], [187.36,-116.61,-173.53], [15.21,25.87,9.13], [12.05,-5.07,-23.99], [5.96,-11.86,28.42], [1.00,-6.00,-35.00]]), + (7, [[354.00,105.30,-24.40], [-20.59,-269.54,30.48], [22.54,0.00,-22.54], [-2.92,-19.10,-14.61], [22.47,6.25,21.72], [15.00,-1.00,-10.00]]), + (8, [[296.50,-121.20,-0.60], [-170.98,-102.19,-18.39], [10.95,-16.42,-25.54], [-9.48,-6.06,-2.33], [14.12,-21.29,19.73], [8.00,-11.00,-13.00]]), + (9, [[169.80,-73.40,-33.50], [-42.47,101.91,-24.43], [1.54,-16.94,-27.72], [-7.96,5.07,-1.75], [-18.03,-23.55,13.36], [4.00,-12.00,-12.00]]) + ] ), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-8', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_colon_term('ascending colon')[0], + 'ontId': get_colon_term('ascending colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-5', + 'name': get_colon_term('transverse colon')[0], + 'ontId': get_colon_term('transverse colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '6-8', + 'name': get_colon_term('descending colon')[0], + 'ontId': get_colon_term('descending colon')[1] + }] + }) + elif "Human 3" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 8 + "Structure": "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-48-49" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( - [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ 0.00, 0.00, 0.00 ], [ -56.81, 105.14, -38.05 ], [ -37.97, -9.49, -18.98 ], [ -3.67, -11.77, -1.56 ], [ -21.20, 5.92, 37.52 ], [ -14.00, -1.00, -12.00 ] ] ), - (2, [ [ -34.50, 114.00, -18.10 ], [ -9.51, 117.91, 3.65 ], [ -33.74, -6.13, -12.27 ], [ 12.13, 18.49, 14.99 ], [ -12.58, -4.62, 33.86 ], [ -4.00, 19.00, 22.00 ] ] ), - (3, [ [ -19.10, 218.50, 5.50 ], [ 79.23, 66.40, 77.49 ], [ -13.72, 27.44, 10.98 ], [ 14.61, 7.18, 21.72 ], [ -22.92, -17.43, 15.26 ], [ -6.00, 0.00, 51.00 ] ] ), - (4, [ [ 82.50, 189.10, 94.20 ], [ 140.70, -1.06, 48.14 ], [ -5.34, 4.27, 30.95 ], [ 5.75, -8.29, 9.07 ], [ 11.54, -25.97, 14.03 ], [ 0.00, 1.00, 24.00 ] ] ), - (5, [ [ 226.60, 218.70, 85.70 ], [ 164.08, 101.90, -75.52 ], [ -2.53, 12.64, 27.81 ], [ 8.00, 9.47, -9.25 ], [ 19.49, -20.43, 11.94 ], [ 5.00, 25.00, -20.00 ] ] ), - (6, [ [ 325.50, 381.70, -57.90 ], [ 187.36, -116.61, -173.53 ], [ 14.07, 23.92, 8.44 ], [ 12.05, -5.07, -23.99 ], [ 5.51, -10.97, 26.28 ], [ 1.00, -6.00, -35.00 ] ] ), - (7, [ [ 354.00, 105.30, -24.40 ], [ -20.59, -269.54, 30.48 ], [ 20.87, 0.00, -20.87 ], [ -2.92, -19.10, -14.61 ], [ 20.81, 5.79, 20.11 ], [ 15.00, -1.00, -10.00 ] ] ), - (8, [ [ 296.50, -121.20, -0.60 ], [ -170.98, -102.19, -18.39 ], [ 10.15, -15.22, -23.67 ], [ -9.48, -6.06, -2.33 ], [ 13.09, -19.73, 18.29 ], [ 8.00, -11.00, -13.00 ] ] ), - (9, [ [ 169.80, -73.40, -33.50 ], [ -42.47, 101.91, -24.43 ], [ 1.43, -15.71, -25.71 ], [ -7.96, 5.07, -1.75 ], [ -16.72, -21.84, 12.39 ], [ 4.00, -12.00, -12.00 ] ] ) ] ), + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[-87.210,-111.060,890.540], [-4.750,0.410,12.390], [23.270,-3.130,7.880], [2.460,-0.390,-2.950], [3.090,24.460,0.450], [1.830,0.460,-4.310]]), + (2, [[-89.990,-110.570,902.650], [-2.050,0.530,12.720], [24.710,-3.280,4.130], [0.070,0.140,-2.810], [3.420,25.000,-0.640], [0.430,0.100,-3.970]]), + (3, [[-91.250,-110.010,915.920], [-0.550,0.530,13.390], [23.610,-2.820,1.080], [-1.460,0.550,-1.920], [2.850,23.610,-0.910], [-1.420,0.540,-2.130]]), + (4, [[-91.080,-109.520,929.390], [0.130,0.650,13.470], [21.830,-2.100,-0.100], [-0.530,0.220,-1.060], [2.080,21.810,-1.180], [-0.530,0.210,-1.170]]), + (5, [[-91.000,-108.720,942.850], [0.830,0.670,13.370], [22.560,-2.350,-1.280], [-0.880,0.270,-1.850], [2.290,22.560,-1.420], [-0.920,0.270,-2.030]]), + (6, [[-89.430,-108.180,956.080], [2.810,0.320,13.110], [20.050,-1.510,-4.270], [-1.960,0.620,-1.350], [1.380,20.440,-0.860], [-2.000,0.620,-1.490]]), + (7, [[-85.390,-108.090,968.920], [3.100,0.440,13.080], [18.600,-0.990,-4.380], [-0.760,0.320,0.660], [0.820,19.040,-0.910], [-0.730,0.310,0.710]]), + (8, [[-83.240,-107.300,982.140], [2.050,0.850,13.230], [18.550,-0.800,-2.820], [-0.240,0.090,0.570], [0.620,18.710,-1.440], [-0.210,0.080,0.630]]), + (9, [[-81.290,-106.400,995.370], [2.320,1.340,13.290], [18.150,-0.790,-3.100], [0.140,0.240,-0.110], [0.470,18.290,-2.130], [0.050,0.310,-0.570]]), + (10, [[-78.600,-104.620,1008.650], [2.140,-1.500,13.270], [18.840,-0.250,-3.070], [-0.910,1.850,-0.220], [0.840,18.750,3.430], [-0.950,1.980,-0.150]]), + (11, [[-77.170,-109.180,1020.820], [4.070,-9.070,9.680], [16.310,3.440,-3.630], [-2.150,4.060,0.800], [-0.010,12.030,12.600], [-1.970,3.890,1.430]]), + (12, [[-71.190,-121.030,1025.580], [7.480,-11.420,0.490], [14.200,9.260,-1.140], [-1.270,2.690,3.170], [0.000,1.980,17.640], [-1.270,2.720,3.230]]), + (13, [[-63.350,-130.560,1022.180], [7.990,-9.440,-3.400], [13.310,9.970,3.600], [-0.810,0.700,2.420], [0.000,-5.470,16.790], [-0.910,0.850,2.430]]), + (14, [[-55.270,-139.840,1018.800], [8.880,-8.590,-3.550], [12.320,10.870,4.490], [-1.070,0.870,0.810], [0.000,-6.180,16.540], [-1.090,0.870,0.810]]), + (15, [[-45.660,-147.660,1015.100], [9.900,-7.390,-3.360], [10.810,11.990,5.470], [-1.630,1.380,0.030], [-0.010,-6.690,16.290], [-1.620,1.360,0.020]]), + (16, [[-35.520,-154.600,1012.080], [11.080,-6.080,-1.980], [8.540,14.060,4.580], [-1.990,1.150,0.250], [-0.010,-5.000,17.000], [-1.970,1.130,0.240]]), + (17, [[-23.710,-159.680,1011.200], [11.970,-4.320,-1.790], [6.200,14.650,6.070], [-1.740,-0.440,2.510], [0.010,-6.170,16.490], [-1.790,-0.440,2.520]]), + (18, [[-11.720,-163.200,1008.530], [12.260,-2.580,-2.060], [4.480,13.030,10.390], [-2.160,-0.110,1.440], [-0.010,-10.220,14.200], [-2.140,-0.120,1.430]]), + (19, [[0.670,-164.820,1007.100], [12.710,-0.730,-0.480], [1.180,14.350,9.430], [-2.670,0.760,-0.810], [-0.010,-8.950,15.090], [-2.580,0.750,-0.810]]), + (20, [[13.556,-164.739,1007.051], [12.750,0.980,0.850], [-1.700,14.800,8.530], [-1.750,0.420,-1.040], [-0.320,-8.140,15.580], [-1.710,0.430,-1.040]]), + (21, [[26.116,-162.906,1008.217], [12.630,1.810,1.230], [-2.890,15.320,7.020], [-2.260,-0.160,-1.140], [-0.450,-6.810,16.270], [-2.230,-0.140,-1.140]]), + (22, [[38.730,-161.010,1010.040], [11.760,4.530,2.770], [-6.960,14.450,5.880], [-3.080,-0.420,-3.340], [-0.980,-6.490,16.380], [-3.120,-0.440,-3.350]]), + (23, [[50.563,-154.087,1013.645], [9.860,7.100,4.160], [-9.105,10.240,0.863], [-1.930,-0.520,-2.090], [-4.770,-2.540,17.360], [-1.970,-0.530,-2.090]]), + (24, [[58.745,-146.870,1017.469], [9.340,7.750,4.350], [-9.097,10.778,0.486], [-1.820,-1.100,1.290], [-3.670,-4.330,17.260], [-1.800,-1.060,1.300]]), + (25, [[67.501,-138.309,1022.249], [7.990,8.770,4.670], [-10.568,9.341,0.117], [-2.500,-1.970,-0.340], [-2.610,-6.250,17.940], [-2.590,-2.160,-0.410]]), + (26, [[74.433,-129.298,1027.145], [5.080,9.970,3.830], [-13.880,7.949,-1.165], [0.030,-2.060,0.330], [-2.126,-4.930,16.625], [-1.530,-1.170,0.490]]), + (27, [[77.560,-119.250,1030.430], [5.040,10.780,-0.510], [-14.630,6.980,2.780], [0.100,1.230,-1.770], [4.280,1.140,20.240], [0.400,1.970,-2.970]]), + (28, [[83.860,-109.530,1026.210], [6.930,6.510,-9.450], [-16.870,11.640,-4.350], [-2.810,1.300,-3.770], [7.220,14.780,13.520], [-1.240,0.300,-4.600]]), + (29, [[89.550,-108.420,1013.560], [3.910,0.860,-13.160], [-20.290,9.170,-5.430], [-1.850,-1.680,0.870], [8.380,20.860,4.280], [-2.140,-1.950,1.170]]), + (30, [[91.640,-107.830,1000.370], [1.780,0.550,-13.270], [-20.930,7.770,-2.480], [-0.800,-1.120,1.760], [7.590,21.030,2.070], [-0.860,-1.120,1.920]]), + (31, [[93.100,-107.330,987.040], [1.010,0.300,-13.420], [-22.050,6.680,-1.510], [-0.560,-0.650,1.350], [6.630,22.100,1.090], [-0.580,-0.660,1.490]]), + (32, [[93.660,-107.240,973.550], [-0.020,1.050,-13.410], [-22.120,6.280,0.520], [0.930,-2.250,1.330], [6.310,22.050,1.910], [0.920,-2.270,1.470]]), + (33, [[93.060,-105.250,960.320], [-0.770,2.250,-13.200], [-20.310,1.700,1.470], [0.920,-2.340,0.150], [1.920,20.030,3.650], [0.930,-2.360,0.170]]), + (34, [[92.120,-102.740,947.160], [-0.420,2.820,-13.160], [-20.350,1.100,0.880], [0.740,-0.110,-0.850], [1.250,19.860,4.690], [0.730,-0.090,-0.940]]), + (35, [[92.230,-99.620,934.040], [0.470,1.780,-13.240], [-18.820,1.460,-0.470], [1.010,0.010,-1.140], [1.390,18.640,2.850], [1.030,0.020,-1.270]]), + (36, [[93.040,-99.170,920.860], [1.210,-0.740,-13.330], [-18.310,1.150,-1.730], [0.280,-0.610,0.540], [1.230,18.350,-1.000], [0.280,-0.690,-0.020]]), + (37, [[94.650,-101.120,907.560], [-0.610,-1.620,-13.470], [-18.270,0.060,0.820], [-0.210,-1.550,3.280], [-0.050,18.160,-2.300], [-0.490,-1.710,2.070]]), + (38, [[91.840,-102.350,894.350], [-3.470,-1.640,-11.950], [-18.620,-2.390,5.740], [0.910,-2.200,3.650], [-3.000,19.300,-1.810], [-0.730,-2.580,3.870]]), + (39, [[87.880,-104.310,883.750], [-5.210,-2.130,-10.320], [-16.280,-4.940,9.250], [2.730,-2.870,2.500], [-6.690,20.720,-1.110], [0.460,-3.190,4.530]]), + (40, [[81.450,-106.590,873.900], [-6.990,-2.140,-9.270], [-12.430,-8.970,11.450], [0.330,-3.150,2.690], [-6.303,19.245,1.555], [2.230,-2.670,3.370]]), + (41, [[73.980,-108.570,865.270], [-8.310,-0.220,-8.520], [-12.268,-8.435,13.125], [-1.280,-1.760,1.510], [-6.633,18.953,4.087], [3.180,-1.460,2.050]]), + (42, [[65.060,-106.920,857.150], [-8.970,1.810,-7.690], [-14.794,-6.343,11.919], [1.280,0.430,-0.090], [-4.396,19.311,7.084], [2.480,0.160,0.520]]), + (43, [[56.070,-104.970,849.910], [-10.000,1.920,-6.880], [-14.078,-6.138,12.772], [2.490,5.000,1.790], [0.172,16.517,6.181], [2.280,4.690,1.100]]), + (44, [[45.110,-103.120,843.530], [-11.000,4.810,-5.260], [-9.460,-1.100,18.780], [2.560,4.660,2.880], [6.930,18.410,4.840], [2.420,4.350,0.870]]), + (45, [[34.860,-95.590,839.810], [-9.590,8.680,-2.670], [-6.610,-0.760,21.270], [0.940,-0.410,0.560], [12.620,13.250,3.920], [0.000,0.160,-0.540]]), + (46, [[26.140,-85.990,838.230], [-8.260,10.160,-2.000], [-7.290,-2.000,20.040], [-0.320,-0.120,-0.850], [14.710,10.710,6.320], [-1.050,-0.470,0.410]]), + (47, [[18.390,-75.310,835.820], [-8.420,10.080,-2.660], [-7.370,-0.990,19.530], [-0.560,0.610,0.800], [16.030,10.170,6.780], [-0.360,-0.280,1.590]]), + (48, [[9.350,-65.880,832.920], [-11.900,13.240,-4.280], [-8.470,-0.620,21.630], [-0.850,0.480,1.280], [17.760,11.500,7.330], [-1.390,-0.780,1.040]]), + (49, [[-5.120,-48.680,827.110], [-17.030,21.160,-7.340], [-8.980,0.200,21.430], [-0.080,1.010,-1.640], [17.760,11.500,7.330], [-1.390,-0.780,1.040]]) + ] ), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-2', + 'identifierRanges': '1-48', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-10', 'name': get_colon_term('ascending colon')[0], 'ontId': get_colon_term('ascending colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '3-5', + 'identifierRanges': '11-26', 'name': get_colon_term('transverse colon')[0], 'ontId': get_colon_term('transverse colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '6-8', + 'identifierRanges': '27-48', 'name': get_colon_term('descending colon')[0], 'ontId': get_colon_term('descending colon')[1] }] - }), - 'Human 3': ScaffoldPackage(MeshType_1d_path1, { + }) + + elif 'Cattle 1' in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 48 + "Structure": "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-48-49-50-51-52-53" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ -87.21, -111.06, 890.54 ], [ -4.75, 0.41, 12.39 ], [ 21.05, -2.83, 7.13 ], [ 2.46, -0.39, -2.95 ], [ 2.79, 22.12, 0.41 ], [ 1.83, 0.46, -4.31 ] ] ), - (2, [ [ -89.99, -110.57, 902.65 ], [ -2.05, 0.53, 12.72 ], [ 22.40, -2.97, 3.74 ], [ 0.07, 0.14, -2.81 ], [ 3.10, 22.66, -0.58 ], [ 0.43, 0.10, -3.97 ] ] ), - (3, [ [ -91.25, -110.01, 915.92 ], [ -0.55, 0.53, 13.39 ], [ 21.27, -2.54, 0.97 ], [ -1.46, 0.55, -1.92 ], [ 2.57, 21.27, -0.82 ], [ -1.42, 0.54, -2.13 ] ] ), - (4, [ [ -91.08, -109.52, 929.39 ], [ 0.13, 0.65, 13.47 ], [ 19.48, -1.87, -0.09 ], [ -0.53, 0.22, -1.06 ], [ 1.86, 19.46, -1.05 ], [ -0.53, 0.21, -1.17 ] ] ), - (5, [ [ -91.00, -108.72, 942.85 ], [ 0.83, 0.67, 13.37 ], [ 20.22, -2.11, -1.15 ], [ -0.88, 0.27, -1.85 ], [ 2.05, 20.22, -1.27 ], [ -0.92, 0.27, -2.03 ] ] ), - (6, [ [ -89.43, -108.18, 956.08 ], [ 2.81, 0.32, 13.11 ], [ 17.75, -1.34, -3.78 ], [ -1.96, 0.62, -1.35 ], [ 1.22, 18.09, -0.76 ], [ -2.00, 0.62, -1.49 ] ] ), - (7, [ [ -85.39, -108.09, 968.92 ], [ 3.10, 0.44, 13.08 ], [ 16.31, -0.87, -3.84 ], [ -0.76, 0.32, 0.66 ], [ 0.72, 16.68, -0.80 ], [ -0.73, 0.31, 0.71 ] ] ), - (8, [ [ -83.24, -107.30, 982.14 ], [ 2.05, 0.85, 13.23 ], [ 16.22, -0.70, -2.47 ], [ -0.24, 0.09, 0.57 ], [ 0.54, 16.36, -1.26 ], [ -0.21, 0.08, 0.63 ] ] ), - (9, [ [ -81.29, -106.40, 995.37 ], [ 2.32, 1.34, 13.29 ], [ 15.83, -0.69, -2.70 ], [ 0.14, 0.24, -0.11 ], [ 0.41, 15.95, -1.86 ], [ 0.05, 0.31, -0.57 ] ] ), - (10, [ [ -78.60, -104.62, 1008.65 ], [ 2.14, -1.50, 13.27 ], [ 16.51, -0.22, -2.69 ], [ -0.91, 1.85, -0.22 ], [ 0.74, 16.43, 3.01 ], [ -0.95, 1.98, -0.15 ] ] ), - (11, [ [ -77.17, -109.18, 1020.82 ], [ 4.07, -9.07, 9.68 ], [ 14.05, 2.96, -3.13 ], [ -2.15, 4.06, 0.80 ], [ -0.01, 10.40, 10.89 ], [ -1.97, 3.89, 1.43 ] ] ), - (12, [ [ -71.19, -121.03, 1025.58 ], [ 7.48, -11.42, 0.49 ], [ 12.23, 7.97, -0.98 ], [ -1.27, 2.69, 3.17 ], [ 0.00, 1.72, 15.29 ], [ -1.27, 2.72, 3.23 ] ] ), - (13, [ [ -63.35, -130.56, 1022.18 ], [ 7.99, -9.44, -3.40 ], [ 11.46, 8.59, 3.10 ], [ -0.81, 0.70, 2.42 ], [ 0.00, -4.74, 14.55 ], [ -0.91, 0.85, 2.43 ] ] ), - (14, [ [ -55.27, -139.84, 1018.80 ], [ 8.88, -8.59, -3.55 ], [ 10.61, 9.36, 3.87 ], [ -1.07, 0.87, 0.81 ], [ 0.00, -5.35, 14.33 ], [ -1.09, 0.87, 0.81 ] ] ), - (15, [ [ -45.66, -147.66, 1015.10 ], [ 9.90, -7.39, -3.36 ], [ 9.31, 10.33, 4.71 ], [ -1.63, 1.38, 0.03 ], [ -0.01, -5.79, 14.11 ], [ -1.62, 1.36, 0.02 ] ] ), - (16, [ [ -35.52, -154.60, 1012.08 ], [ 11.08, -6.08, -1.98 ], [ 7.36, 12.12, 3.95 ], [ -1.99, 1.15, 0.25 ], [ -0.01, -4.33, 14.74 ], [ -1.97, 1.13, 0.24 ] ] ), - (17, [ [ -23.71, -159.68, 1011.20 ], [ 11.97, -4.32, -1.79 ], [ 5.34, 12.62, 5.23 ], [ -1.74, -0.44, 2.51 ], [ 0.01, -5.34, 14.28 ], [ -1.79, -0.44, 2.52 ] ] ), - (18, [ [ -11.72, -163.20, 1008.53 ], [ 12.26, -2.58, -2.06 ], [ 3.87, 11.25, 8.97 ], [ -2.16, -0.11, 1.44 ], [ -0.01, -8.84, 12.28 ], [ -2.14, -0.12, 1.43 ] ] ), - (19, [ [ 0.67, -164.82, 1007.10 ], [ 12.71, -0.73, -0.48 ], [ 1.02, 12.38, 8.14 ], [ -2.67, 0.76, -0.81 ], [ -0.01, -7.75, 13.06 ], [ -2.58, 0.75, -0.81 ] ] ), - (20, [ [ 13.53, -164.63, 1007.59 ], [ 12.75, 0.98, 0.85 ], [ -1.47, 12.77, 7.36 ], [ -1.75, 0.42, -1.04 ], [ -0.28, -7.05, 13.49 ], [ -1.71, 0.43, -1.04 ] ] ), - (21, [ [ 26.09, -162.88, 1008.79 ], [ 12.63, 1.81, 1.23 ], [ -2.49, 13.21, 6.05 ], [ -2.26, -0.16, -1.14 ], [ -0.39, -5.90, 14.09 ], [ -2.23, -0.14, -1.14 ] ] ), - (22, [ [ 38.73, -161.01, 1010.04 ], [ 11.76, 4.53, 2.77 ], [ -6.00, 12.45, 5.07 ], [ -3.08, -0.42, -3.34 ], [ -0.85, -5.62, 14.19 ], [ -3.12, -0.44, -3.35 ] ] ), - (23, [ [ 48.79, -154.12, 1014.15 ], [ 9.86, 7.10, 4.16 ], [ -8.65, 12.37, -0.62 ], [ -1.93, -0.52, -2.09 ], [ -4.15, -2.21, 15.11 ], [ -1.97, -0.53, -2.09 ] ] ), - (24, [ [ 58.41, -146.84, 1018.34 ], [ 9.34, 7.75, 4.35 ], [ -9.86, 11.41, 0.85 ], [ -1.82, -1.10, 1.29 ], [ -3.19, -3.77, 15.02 ], [ -1.80, -1.06, 1.30 ] ] ), - (25, [ [ 67.43, -138.64, 1022.84 ], [ 7.99, 8.77, 4.67 ], [ -12.30, 10.17, 1.95 ], [ -2.50, -1.97, -0.34 ], [ -2.29, -5.48, 15.73 ], [ -2.59, -2.16, -0.41 ] ] ), - (26, [ [ 74.34, -129.42, 1027.61 ], [ 5.08, 9.97, 3.83 ], [ -14.87, 7.50, 0.22 ], [ 0.03, -2.06, 0.33 ], [ -2.33, -5.10, 16.50 ], [ -1.53, -1.17, 0.49 ] ] ), - (27, [ [ 77.56, -119.25, 1030.43 ], [ 5.04, 10.78, -0.51 ], [ -12.53, 5.98, 2.38 ], [ 0.10, 1.23, -1.77 ], [ 3.79, 1.01, 17.93 ], [ 0.40, 1.97, -2.97 ] ] ), - (28, [ [ 83.86, -109.53, 1026.21 ], [ 6.93, 6.51, -9.45 ], [ -14.97, 10.33, -3.86 ], [ -2.81, 1.30, -3.77 ], [ 6.42, 13.14, 12.02 ], [ -1.24, 0.30, -4.60 ] ] ), - (29, [ [ 89.55, -108.42, 1013.56 ], [ 3.91, 0.86, -13.16 ], [ -18.20, 8.23, -4.87 ], [ -1.85, -1.68, 0.87 ], [ 7.52, 18.71, 3.84 ], [ -2.14, -1.95, 1.17 ] ] ), - (30, [ [ 91.64, -107.83, 1000.37 ], [ 1.78, 0.55, -13.27 ], [ -18.73, 6.95, -2.22 ], [ -0.80, -1.12, 1.76 ], [ 6.79, 18.82, 1.85 ], [ -0.86, -1.12, 1.92 ] ] ), - (31, [ [ 93.10, -107.33, 987.04 ], [ 1.01, 0.30, -13.42 ], [ -19.80, 6.00, -1.36 ], [ -0.56, -0.65, 1.35 ], [ 5.95, 19.84, 0.98 ], [ -0.58, -0.66, 1.49 ] ] ), - (32, [ [ 93.66, -107.24, 973.55 ], [ -0.02, 1.05, -13.41 ], [ -19.85, 5.64, 0.47 ], [ 0.93, -2.25, 1.33 ], [ 5.66, 19.79, 1.71 ], [ 0.92, -2.27, 1.47 ] ] ), - (33, [ [ 93.06, -105.25, 960.32 ], [ -0.77, 2.25, -13.20 ], [ -17.96, 1.50, 1.30 ], [ 0.92, -2.34, 0.15 ], [ 1.70, 17.72, 3.23 ], [ 0.93, -2.36, 0.17 ] ] ), - (34, [ [ 92.12, -102.74, 947.16 ], [ -0.42, 2.82, -13.16 ], [ -18.00, 0.97, 0.78 ], [ 0.74, -0.11, -0.85 ], [ 1.11, 17.57, 4.15 ], [ 0.73, -0.09, -0.94 ] ] ), - (35, [ [ 92.23, -99.62, 934.04 ], [ 0.47, 1.78, -13.24 ], [ -16.47, 1.28, -0.41 ], [ 1.01, 0.01, -1.14 ], [ 1.22, 16.31, 2.49 ], [ 1.03, 0.02, -1.27 ] ] ), - (36, [ [ 93.04, -99.17, 920.86 ], [ 1.21, -0.74, -13.33 ], [ -15.97, 1.00, -1.51 ], [ 0.28, -0.61, 0.54 ], [ 1.07, 16.00, -0.87 ], [ 0.28, -0.69, -0.02 ] ] ), - (37, [ [ 94.65, -101.12, 907.56 ], [ -0.61, -1.62, -13.47 ], [ -15.91, 0.05, 0.71 ], [ -0.21, -1.55, 3.28 ], [ -0.04, 15.82, -2.00 ], [ -0.49, -1.71, 2.07 ] ] ), - (38, [ [ 91.84, -102.35, 894.35 ], [ -3.47, -1.64, -11.95 ], [ -16.38, -2.10, 5.05 ], [ 0.91, -2.20, 3.65 ], [ -2.64, 16.98, -1.59 ], [ -0.73, -2.58, 3.87 ] ] ), - (39, [ [ 87.88, -104.31, 883.75 ], [ -5.21, -2.13, -10.32 ], [ -14.30, -4.34, 8.12 ], [ 2.73, -2.87, 2.50 ], [ -5.97, 18.48, -0.99 ], [ 0.46, -3.19, 4.53 ] ] ), - (40, [ [ 81.45, -106.59, 873.90 ], [ -6.99, -2.14, -9.27 ], [ -10.90, -7.86, 10.04 ], [ 0.33, -3.15, 2.69 ], [ -9.26, 19.09, 1.96 ], [ 2.23, -2.67, 3.37 ] ] ), - (41, [ [ 73.98, -108.57, 865.27 ], [ -8.31, -0.22, -8.52 ], [ -13.53, -10.65, 13.47 ], [ -1.28, -1.76, 1.51 ], [ -8.01, 18.53, 7.34 ], [ 3.18, -1.46, 2.05 ] ] ), - (42, [ [ 65.06, -106.92, 857.15 ], [ -8.97, 1.81, -7.69 ], [ -13.39, -11.32, 12.96 ], [ 1.28, 0.43, -0.09 ], [ -4.01, 17.55, 11.89 ], [ 2.48, 0.16, 0.52 ] ] ), - (43, [ [ 56.07, -104.97, 849.91 ], [ -10.00, 1.92, -6.88 ], [ -11.02, -9.85, 13.27 ], [ 2.49, 5.00, 1.79 ], [ -2.03, 16.12, 10.97 ], [ 2.28, 4.69, 1.10 ] ] ), - (44, [ [ 45.11, -103.12, 843.53 ], [ -11.00, 4.81, -5.26 ], [ -8.40, -0.98, 16.68 ], [ 2.56, 4.66, 2.88 ], [ 6.12, 16.27, 4.28 ], [ 2.42, 4.35, 0.87 ] ] ), - (45, [ [ 34.86, -95.59, 839.81 ], [ -9.59, 8.68, -2.67 ], [ -5.91, -0.68, 19.02 ], [ 0.94, -0.41, 0.56 ], [ 11.03, 11.58, 3.43 ], [ 0.00, 0.16, -0.54 ] ] ), - (46, [ [ 26.14, -85.99, 838.23 ], [ -8.26, 10.16, -2.00 ], [ -6.49, -1.78, 17.83 ], [ -0.32, -0.12, -0.85 ], [ 12.91, 9.40, 5.55 ], [ -1.05, -0.47, 0.41 ] ] ), - (47, [ [ 18.39, -75.31, 835.82 ], [ -8.42, 10.08, -2.66 ], [ -6.54, -0.88, 17.32 ], [ -0.56, 0.61, 0.80 ], [ 14.15, 8.98, 5.99 ], [ -0.36, -0.28, 1.59 ] ] ), - (48, [ [ 9.35, -65.88, 832.92 ], [ -11.90, 13.24, -4.28 ], [ -7.61, -0.56, 19.43 ], [ -0.85, 0.48, 1.28 ], [ 15.89, 10.29, 6.56 ], [ -1.39, -0.78, 1.04 ] ] ), - (49, [ [ -5.12, -48.68, 827.11 ], [ -17.03, 21.16, -7.34 ], [ -8.07, 0.18, 19.25 ], [ -0.08, 1.01, -1.64 ], [ 15.89, 10.29, 6.56 ], [ -1.39, -0.78, 1.04 ] ] ) ] ), + [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ + (1, [[-245.30,444.60,-49.10], [-267.70,-53.10,-20.20], [0.00,0.00,38.02], [0.00,0.00,-4.41], [-7.40,37.29,0.00], [0.00,0.00,-4.41]]), + (2, [[-380.30,484.80,-45.00], [24.50,102.70,15.70], [0.00,0.00,34.49], [0.00,0.00,-2.65], [33.55,-8.00,0.00], [0.00,0.00,-2.65]]), + (3, [[-298.10,510.40,-36.80], [73.60,9.90,-16.40], [0.00,0.00,32.36], [-12.52,-3.10,-14.34], [4.31,-32.07,0.00], [-12.52,-3.10,-14.34]]), + (4, [[-213.10,527.90,-22.50], [-1.00,-10.80,125.60], [-29.16,-7.23,1.80], [-4.10,-6.11,-25.37], [7.07,-29.15,-2.45], [-4.10,-6.11,-25.37]]), + (5, [[-315.50,570.20,18.90], [-107.90,9.30,21.90], [-2.95,-13.63,-23.41], [14.35,4.82,-10.40], [0.73,-23.58,13.64], [14.35,4.82,-10.40]]), + (6, [[-417.40,555.00,14.60], [-83.00,-41.30,-0.80], [4.80,1.33,-24.41], [0.54,4.88,0.73], [11.08,-22.29,0.97], [0.54,4.88,0.73]]), + (7, [[-497.30,488.90,13.60], [-44.60,-81.60,10.00], [-1.80,-2.76,-22.33], [-2.12,-0.60,2.13], [19.79,-10.85,-0.25], [-2.12,-0.60,2.13]]), + (8, [[-527.00,392.50,2.70], [47.40,-82.00,-7.90], [0.00,0.00,-20.22], [0.68,1.04,1.96], [17.50,10.12,0.00], [0.68,1.04,1.96]]), + (9, [[-461.20,345.90,-0.80], [56.90,-44.50,2.40], [0.00,0.00,-18.40], [0.00,0.00,1.09], [11.33,14.49,0.00], [0.00,0.00,1.09]]), + (10, [[-415.60,293.80,3.90], [93.20,-62.60,3.10], [0.00,0.00,-17.93], [0.00,0.00,0.43], [9.99,14.89,0.00], [0.00,0.00,0.43]]), + (11, [[-232.20,264.90,0.20], [140.10,58.20,-1.00], [0.00,0.00,-17.60], [0.00,0.00,0.25], [-6.75,16.25,0.00], [0.00,0.00,0.25]]), + (12, [[-168.40,357.20,1.30], [10.10,78.60,-3.20], [0.00,0.00,-17.40], [0.00,0.00,0.15], [-17.26,2.21,0.00], [0.00,0.00,0.15]]), + (13, [[-185.30,419.10,-0.70], [-45.10,57.10,-0.90], [0.00,0.00,-17.29], [0.00,0.00,0.13], [-13.57,-10.71,0.00], [0.00,0.00,0.13]]), + (14, [[-253.20,466.70,-0.30], [-63.40,24.70,0.20], [0.00,0.00,-17.15], [0.00,0.00,0.13], [-6.23,-15.98,0.00], [0.00,0.00,0.13]]), + (15, [[-323.80,482.50,0.10], [-68.20,2.90,-1.20], [0.00,0.00,-17.02], [0.00,0.00,0.12], [-0.72,-17.01,0.00], [0.00,0.00,0.12]]), + (16, [[-387.50,485.40,-0.20], [-44.20,-17.10,-1.00], [0.00,0.00,-16.91], [0.00,0.00,0.12], [6.10,-15.77,0.00], [0.00,0.00,0.12]]), + (17, [[-435.60,433.50,3.30], [3.40,-109.50,1.40], [0.00,0.00,-16.78], [0.00,0.00,0.14], [16.77,0.52,0.00], [0.00,0.00,0.14]]), + (18, [[-370.60,376.30,-1.10], [66.90,-29.20,-0.90], [0.00,0.00,-16.62], [0.00,0.00,0.12], [6.65,15.23,0.00], [0.00,0.00,0.12]]), + (19, [[-313.00,357.90,-0.10], [40.00,-33.50,9.60], [0.00,0.00,-16.52], [0.00,0.00,0.10], [10.61,12.67,0.00], [0.00,0.00,0.10]]), + (20, [[-259.20,340.70,2.10], [48.90,6.40,1.40], [0.00,0.00,-16.42], [0.00,0.00,0.09], [-2.13,16.28,0.00], [0.00,0.00,0.09]]), + (21, [[-246.50,380.30,-0.80], [-29.70,33.60,-0.70], [0.00,0.00,-16.33], [0.00,0.00,0.09], [-12.23,-10.82,0.00], [0.00,0.00,0.09]]), + (22, [[-297.30,387.10,0.60], [-59.70,12.60,-0.00], [0.00,0.00,-16.24], [0.00,0.00,0.09], [-3.35,-15.89,0.00], [0.00,0.00,0.09]]), + (23, [[-340.20,415.60,-1.00], [-86.20,28.90,-2.90], [0.00,0.00,-16.15], [0.00,0.00,0.10], [-5.13,-15.31,0.00], [0.00,0.00,0.10]]), + (24, [[-398.30,443.10,-0.10], [10.60,82.10,-2.60], [0.00,0.00,-16.03], [0.00,0.00,0.12], [-15.90,2.06,0.00], [0.00,0.00,0.12]]), + (25, [[-329.80,449.10,-2.10], [53.20,14.00,-0.50], [0.00,0.00,-15.90], [0.00,0.00,0.14], [-4.05,15.38,0.00], [0.00,0.00,0.14]]), + (26, [[-251.30,425.90,-0.30], [43.90,-19.30,0.00], [0.00,0.00,-15.76], [0.00,0.00,0.11], [6.35,14.42,0.00], [0.00,0.00,0.11]]), + (27, [[-209.10,390.60,0.00], [26.00,-38.80,0.90], [0.00,0.00,-15.67], [0.00,0.00,0.08], [13.02,8.72,0.00], [0.00,0.00,0.08]]), + (28, [[-207.80,350.80,1.40], [-9.40,-43.60,1.80], [0.00,0.00,-15.59], [0.00,0.00,0.09], [15.24,-3.29,0.00], [0.00,0.00,0.09]]), + (29, [[-245.80,299.40,7.60], [-70.30,-36.00,1.40], [0.00,0.00,-15.48], [0.00,0.00,0.14], [7.06,-13.78,0.00], [0.00,0.00,0.14]]), + (30, [[-345.30,304.10,3.10], [-100.20,27.90,-1.90], [0.00,0.00,-15.31], [0.00,0.00,0.17], [-4.11,-14.75,0.00], [0.00,0.00,0.17]]), + (31, [[-418.40,361.10,-0.20], [-57.80,55.80,-1.70], [0.00,0.00,-15.15], [0.00,0.00,0.15], [-10.52,-10.90,0.00], [0.00,0.00,0.15]]), + (32, [[-479.20,415.60,2.20], [-8.80,73.10,-1.60], [0.00,0.00,-15.00], [0.00,0.00,0.15], [-14.89,-1.79,0.00], [0.00,0.00,0.15]]), + (33, [[-439.60,495.70,-2.10], [61.10,57.10,-1.30], [0.00,0.00,-14.84], [0.00,0.00,0.15], [-10.13,10.85,0.00], [0.00,0.00,0.15]]), + (34, [[-361.60,522.60,-3.00], [78.60,9.90,0.20], [0.00,0.00,-14.70], [0.00,0.00,0.15], [-1.84,14.59,0.00], [0.00,0.00,0.15]]), + (35, [[-270.10,506.50,-3.80], [103.60,-33.30,1.00], [0.00,0.00,-14.54], [0.00,0.00,0.19], [4.46,13.84,0.00], [0.00,0.00,0.19]]), + (36, [[-148.90,441.40,-2.10], [79.70,-91.50,2.80], [0.00,0.00,-14.30], [0.00,0.00,0.23], [10.79,9.39,0.00], [0.00,0.00,0.23]]), + (37, [[-130.90,313.30,4.00], [-4.00,-107.20,3.10], [0.00,0.00,-14.07], [0.00,0.00,0.18], [14.06,-0.52,0.00], [0.00,0.00,0.18]]), + (38, [[-183.90,251.00,3.80], [-65.50,-60.20,3.60], [0.00,0.00,-13.92], [0.00,0.00,0.16], [9.42,-10.25,0.00], [0.00,0.00,0.16]]), + (39, [[-280.30,213.00,3.40], [-165.10,-18.60,0.10], [0.00,0.00,-13.74], [0.00,0.00,0.20], [1.54,-13.65,0.00], [0.00,0.00,0.20]]), + (40, [[-400.80,247.50,6.80], [-127.10,36.80,1.30], [0.00,0.00,-13.53], [0.00,0.00,0.23], [-3.76,-13.00,0.00], [0.00,0.00,0.23]]), + (41, [[-530.50,290.70,5.20], [-89.00,86.50,0.30], [0.00,0.00,-13.29], [0.00,0.00,0.21], [-9.27,-9.52,0.00], [0.00,0.00,0.21]]), + (42, [[-568.80,392.30,6.90], [-77.40,67.70,-5.50], [0.00,0.00,-13.10], [0.00,0.00,0.23], [-8.63,-9.86,0.00], [0.00,0.00,0.23]]), + (43, [[-511.20,535.10,2.50], [86.20,111.40,-1.00], [0.00,0.00,-12.82], [0.00,0.00,0.25], [-10.14,7.85,0.00], [0.00,0.00,0.25]]), + (44, [[-405.00,601.70,6.40], [143.60,52.20,2.60], [0.00,0.00,-12.60], [1.49,-1.44,0.82], [-4.30,11.84,0.00], [1.49,-1.44,0.82]]), + (45, [[-238.80,615.90,16.60], [63.30,-9.10,19.10], [4.57,-4.41,-10.54], [-5.13,0.21,1.79], [2.73,11.44,-3.61], [-5.13,0.21,1.79]]), + (46, [[-146.20,605.90,36.50], [49.30,-9.90,-50.60], [-8.95,-1.40,-8.08], [-3.12,3.94,7.67], [0.13,11.93,-2.21], [-3.12,3.94,7.67]]), + (47, [[-218.40,585.30,-2.00], [-124.00,0.40,-37.50], [-4.06,6.01,9.60], [2.76,2.30,8.98], [1.78,10.41,-5.77], [2.76,2.30,8.98]]), + (48, [[-376.30,579.60,-40.80], [-189.20,-50.70,-8.80], [-2.47,1.63,11.71], [4.16,0.49,-2.60], [-2.97,11.49,-2.23], [4.16,0.49,-2.60]]), + (49, [[-557.90,493.90,-24.90], [-30.30,24.10,152.80], [8.24,8.85,0.92], [1.49,-2.48,-8.73], [-8.46,8.18,-2.97], [1.49,-2.48,-8.73]]), + (50, [[-484.80,594.40,0.70], [132.70,97.00,3.50], [4.32,-1.57,-11.27], [-2.78,-5.06,-5.12], [-6.74,9.35,-3.88], [-2.78,-5.06,-5.12]]), + (51, [[-318.10,641.90,-8.50], [166.70,17.60,5.50], [0.89,-3.82,-11.58], [-2.15,-0.82,-0.11], [-1.09,11.54,-3.89], [-2.15,-0.82,-0.11]]), + (52, [[-158.30,634.70,-1.90], [176.50,-14.00,10.80], [-1.43,-3.83,-11.56], [-0.81,0.27,-0.12], [1.15,11.54,-3.97], [-0.81,0.27,-0.12]]), + (53, [[32.70,611.70,13.60], [205.50,-32.20,20.00], [-1.01,-3.02,-11.90], [1.46,0.96,-0.42], [2.15,11.71,-3.15], [1.46,0.96,-0.42]]) + ] ), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-48', + 'identifierRanges': '1-52', 'name': get_colon_term('colon')[0], 'ontId': get_colon_term('colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-10', - 'name': get_colon_term('ascending colon')[0], - 'ontId': get_colon_term('ascending colon')[1] + 'identifierRanges': '1-8', + 'name': get_colon_term('right colon')[0], + 'ontId': get_colon_term('right colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '11-26', + 'identifierRanges': '9-46', 'name': get_colon_term('transverse colon')[0], 'ontId': get_colon_term('transverse colon')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '27-48', - 'name': get_colon_term('descending colon')[0], - 'ontId': get_colon_term('descending colon')[1] + 'identifierRanges': '47-52', + 'name': get_colon_term('left colon')[0], + 'ontId': get_colon_term('left colon')[1] }] - }), - 'Mouse 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif 'Mouse 1' in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 7 + "Structure": "1-2-3-4-5-6-7-8" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ 0.00, 0.00, 0.00 ], [ 6.00, 12.00, -2.00 ], [ 0.67, 0.33, 0.67 ], [ -0.03, 0.95, -0.68 ], [ 0.86, 0.04, -0.51 ], [ 6.00, 0.00, 3.00 ] ] ), - (2, [ [ -2.00, 11.00, -3.00 ], [ -8.00, 4.00, 9.00 ], [ 0.64, 0.64, 0.32 ], [ -0.03, -0.34, -0.02 ], [ -0.37, 0.66, -0.58 ], [ 0.00, 1.00, 2.00 ] ] ), - (3, [ [ -3.00, 2.00, 3.00 ], [ -4.00, -8.00, 0.00 ], [ 0.61, -0.30, 0.61 ], [ -0.15, -0.65, 0.01 ], [ -0.55, 0.27, 0.68 ], [ 1.00, 0.00, 2.00 ] ] ), - (4, [ [ -11.00, -3.00, -4.00 ], [ -8.00, -3.00, -7.00 ], [ 0.33, -0.67, 0.33 ], [ -0.18, -0.18, -0.31 ], [ -0.32, 0.10, 0.75 ], [ 0.00, 0.00, 0.50 ] ] ), - (5, [ [ -16.00, -4.00, 0.00 ], [ 4.00, -3.00, 14.00 ], [ 0.23, -0.70, 0.00 ], [ -0.16, -0.02, -0.19 ], [ 0.71, 0.18, 0.05 ], [ 0.00, 0.00, 0.50 ] ] ), - (6, [ [ -7.00, -8.00, 0.00 ], [ 5.00, -1.00, -14.00 ], [ 0.00, -0.70, 0.00 ], [ 0.03, 0.04, -0.12 ], [ -0.64, -0.00, -0.28 ], [ 0.00, 0.00, 0.50 ] ] ), - (7, [ [ -1.00, -6.00, -1.00 ], [ 2.00, -2.00, 9.00 ], [ 0.21, -0.63, -0.21 ], [ 0.12, 0.11, -0.23 ], [ 0.64, 0.25, -0.11 ], [ 0.00, 0.00, 0.50 ] ] ), - (8, [ [ -2.00, -14.00, 5.00 ], [ -2.00, -4.00, 2.00 ], [ 0.23, -0.47, -0.47 ], [ -0.08, 0.22, -0.28 ], [ 0.53, -0.17, 0.42 ], [ 0.00, 0.00, 0.50 ] ] ) ] ), + (1, [[0.00,0.00,0.00], [6.00,12.00,-2.00], [1.04,0.51,1.04], [-0.03,0.95,-0.68], [1.33,0.06,-0.79], [6.00,0.00,3.00]]), + (2, [[-2.00,11.00,-3.00], [-8.00,4.00,9.00], [1.01,1.01,0.50], [-0.03,-0.34,-0.02], [-0.58,1.04,-0.91], [0.00,1.00,2.00]]), + (3, [[-3.00,2.00,3.00], [-4.00,-8.00,0.00], [0.98,-0.48,0.98], [-0.15,-0.65,0.01], [-0.88,0.43,1.09], [1.00,0.00,2.00]]), + (4, [[-11.00,-3.00,-4.00], [-8.00,-3.00,-7.00], [0.55,-1.12,0.55], [-0.18,-0.18,-0.31], [-0.53,0.17,1.25], [0.00,0.00,0.50]]), + (5, [[-16.00,-4.00,0.00], [4.00,-3.00,14.00], [0.40,-1.22,0.00], [-0.16,-0.02,-0.19], [1.24,0.31,0.09], [0.00,0.00,0.50]]), + (6, [[-7.00,-8.00,0.00], [5.00,-1.00,-14.00], [0.00,-1.25,0.00], [0.03,0.04,-0.12], [-1.14,-0.00,-0.50], [0.00,0.00,0.50]]), + (7, [[-1.00,-6.00,-1.00], [2.00,-2.00,9.00], [0.38,-1.13,-0.38], [0.12,0.11,-0.23], [1.15,0.45,-0.20], [0.00,0.00,0.50]]), + (8, [[-2.00,-14.00,5.00], [-2.00,-4.00,2.00], [0.41,-0.84,-0.84], [-0.08,0.22,-0.28], [0.95,-0.30,0.75], [0.00,0.00,0.50]]) + ] ), 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-7', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -339,24 +351,29 @@ class MeshType_3d_colon1(Scaffold_base): 'name': get_colon_term('left colon')[0], 'ontId': get_colon_term('left colon')[1] }] - }), - 'Mouse 2': ScaffoldPackage(MeshType_1d_path1, { + }) + elif 'Mouse 2' in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 4 + "Structure": "1-2-3-4-5" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ 0.00, 0.00, 0.00 ], [ 0.00, 0.00, 13.00 ], [ 0.00, -1.00, 0.00 ], [ 0.00, 0.03, 0.00 ], [ 1.00, -0.00, 0.00 ], [ 0.00, 0.00, 0.50 ] ] ), - (2, [ [ 0.00, 0.00, 13.00 ], [ 0.00, 2.00, 28.00 ], [ 0.00, -0.96, 0.00 ], [ 0.00, 0.05, 0.00 ], [ 0.95, -0.00, -0.07 ], [ 0.00, 0.00, 0.50 ] ] ), - (3, [ [ -14.00, -2.00, 13.00 ], [ 0.00, -3.00, -19.00 ], [ 0.00, -0.88, 0.00 ], [ 0.00, 0.13, 0.00 ], [ -0.87, -0.02, -0.14 ], [ 0.00, 0.00, 0.50 ] ] ), - (4, [ [ -14.00, -1.00, -10.00 ], [ 1.00, 1.00, -17.00 ], [ 0.00, -0.70, 0.00 ], [ 0.00, 0.08, 0.00 ], [ -0.70, -0.00, -0.00 ], [ 0.00, 0.00, 0.50 ] ] ), - (5, [ [ -14.00, 0.00, -28.00 ], [ 0.00, 0.00, -11.00 ], [ 0.00, -0.70, 0.00 ], [ 0.00, -0.08, 0.00 ], [ -0.70, -0.00, 0.00 ], [ 0.00, 0.00, 0.50 ] ] ) ] ), - + (1, [[0.00,0.00,0.00], [0.00,0.00,13.00], [0.00,-1.55,0.00], [0.00,0.03,0.00], [1.55,-0.00,0.00], [0.00,0.00,0.50]]), + (2, [[0.00,0.00,13.00], [0.00,2.00,28.00], [0.00,-1.51,0.00], [0.00,0.05,0.00], [1.50,-0.00,-0.11], [0.00,0.00,0.50]]), + (3, [[-14.00,-2.00,13.00], [0.00,-3.00,-19.00], [0.00,-1.43,0.00], [0.00,0.13,0.00], [-1.41,-0.03,-0.23], [0.00,0.00,0.50]]), + (4, [[-14.00,-1.00,-10.00], [1.00,1.00,-17.00], [0.00,-1.25,0.00], [0.00,0.08,0.00], [-1.25,-0.00,-0.00], [0.00,0.00,0.50]]), + (5, [[-14.00,0.00,-28.00], [0.00,0.00,-11.00], [0.00,-1.25,0.00], [0.00,-0.08,0.00], [-1.25,-0.00,0.00], [0.00,0.00,0.50]]) + ] ), + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-4', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -378,59 +395,65 @@ class MeshType_3d_colon1(Scaffold_base): 'name': get_colon_term('left colon')[0], 'ontId': get_colon_term('left colon')[1] }] - }), - 'Pig 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif 'Pig 1' in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 39 + "Structure": "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" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ -7.20, 83.30, -20.70 ], [ -65.20, -8.10, 7.60 ], [ 0.00, 0.00, 36.00 ], [ 0.00, 0.00, -0.50 ], [ -8.49, 34.98, 0.48 ], [ 0.00, 0.00, -0.50 ] ] ), - (2, [ [ -68.50, 52.80, -9.60 ], [ -40.10, -36.10, 10.70 ], [ 0.00, 0.00, 35.44 ], [ 0.00, 0.00, -0.63 ], [ -28.28, 21.31, 1.34 ], [ 0.00, 0.00, -0.63 ] ] ), - (3, [ [ -97.40, -26.30, 5.70 ], [ 18.00, -93.20, 13.70 ], [ 0.00, 0.00, 34.73 ], [ 0.00, 0.00, -0.67 ], [ -32.82, -11.34, 0.71 ], [ 0.00, 0.00, -0.67 ] ] ), - (4, [ [ -56.80, -90.50, 14.10 ], [ 65.50, -41.40, 7.30 ], [ 0.00, 0.00, 34.10 ], [ 0.00, 0.00, -0.74 ], [ -15.44, -30.39, 0.30 ], [ 0.00, 0.00, -0.74 ] ] ), - (5, [ [ 48.90, -100.80, 24.00 ], [ 112.20, 40.10, 19.00 ], [ 0.00, 0.00, 33.22 ], [ 0.00, 0.00, -0.91 ], [ 15.90, -29.15, 0.82 ], [ 0.00, 0.00, -0.91 ] ] ), - (6, [ [ 114.80, -12.60, 38.70 ], [ 8.20, 96.10, 14.20 ], [ 0.00, 0.00, 32.28 ], [ 0.00, 0.00, -0.93 ], [ 32.22, 1.92, 0.68 ], [ 0.00, 0.00, -0.93 ] ] ), - (7, [ [ 60.30, 83.50, 43.70 ], [ -108.70, 54.10, 22.40 ], [ 0.00, 0.00, 31.35 ], [ 0.00, 0.00, -0.89 ], [ 8.73, 30.09, 1.03 ], [ 0.00, 0.00, -0.89 ] ] ), - (8, [ [ -41.20, 90.70, 56.30 ], [ -89.00, -32.40, 14.40 ], [ 0.00, 0.00, 30.50 ], [ 0.00, 0.00, -0.93 ], [ -14.57, 26.79, 0.69 ], [ 0.00, 0.00, -0.93 ] ] ), - (9, [ [ -107.90, -9.70, 76.60 ], [ 11.10, -94.40, 11.30 ], [ 0.00, 0.00, 29.47 ], [ 0.00, 0.00, -0.91 ], [ -28.66, -6.85, 0.41 ], [ 0.00, 0.00, -0.91 ] ] ), - (10, [ [ -57.30, -91.90, 81.30 ], [ 71.20, -31.20, 5.70 ], [ 0.00, 0.00, 28.65 ], [ 0.00, 0.00, -0.86 ], [ -9.56, -27.01, 0.15 ], [ 0.00, 0.00, -0.86 ] ] ), - (11, [ [ 51.20, -89.40, 97.20 ], [ 99.10, 55.40, 12.90 ], [ 0.00, 0.00, 27.75 ], [ 0.00, 0.00, -0.90 ], [ 16.17, -22.55, 0.35 ], [ 0.00, 0.00, -0.90 ] ] ), - (12, [ [ 91.60, 9.30, 103.60 ], [ 4.70, 51.20, 3.40 ], [ 0.00, 0.00, 26.86 ], [ 0.00, 0.00, -0.90 ], [ 26.85, -0.69, 0.12 ], [ 0.00, 0.00, -0.90 ] ] ), - (13, [ [ 61.60, 111.80, 109.60 ], [ -85.20, 46.10, 2.60 ], [ 0.00, 0.00, 25.95 ], [ 0.00, 0.00, -0.95 ], [ 11.73, 23.14, 0.02 ], [ 0.00, 0.00, -0.95 ] ] ), - (14, [ [ -54.60, 91.90, 129.40 ], [ -92.70, -55.00, 14.50 ], [ 0.00, 0.00, 24.95 ], [ 0.00, 0.00, -0.94 ], [ -15.45, 19.58, 0.44 ], [ 0.00, 0.00, -0.94 ] ] ), - (15, [ [ -109.00, 5.60, 156.90 ], [ 23.60, -108.20, 27.70 ], [ 0.00, 0.00, 24.05 ], [ 0.00, 0.00, -0.80 ], [ -21.59, -10.51, 1.42 ], [ 0.00, 0.00, -0.80 ] ] ), - (16, [ [ -59.10, -62.50, 170.80 ], [ 74.00, -20.10, 14.40 ], [ 0.00, 0.00, 23.34 ], [ 0.00, 0.00, -0.70 ], [ -1.93, -23.24, 0.79 ], [ 0.00, 0.00, -0.70 ] ] ), - (17, [ [ 23.50, -53.20, 179.70 ], [ 84.60, 47.00, 6.90 ], [ 0.00, 0.00, 22.65 ], [ 0.00, 0.00, -0.73 ], [ 12.38, -18.97, 0.11 ], [ 0.00, 0.00, -0.73 ] ] ), - (18, [ [ 62.30, 30.10, 187.50 ], [ -12.80, 58.00, 0.80 ], [ 0.00, 0.00, 21.88 ], [ 0.00, 0.00, -0.55 ], [ 21.30, 5.00, 0.00 ], [ 0.00, 0.00, -0.55 ] ] ), - (19, [ [ 22.40, 45.20, 181.10 ], [ -23.60, -34.50, -7.40 ], [ 0.00, 0.00, 21.44 ], [ 0.00, 0.00, -0.41 ], [ -15.35, 14.96, 0.65 ], [ 0.00, 0.00, -0.41 ] ] ), - (20, [ [ -1.90, 4.90, 180.50 ], [ -41.30, -30.90, 7.50 ], [ 0.00, 0.00, 21.06 ], [ 0.00, 0.00, -0.39 ], [ -14.89, 14.89, 0.44 ], [ 0.00, 0.00, -0.39 ] ] ), - (21, [ [ -45.10, -12.60, 194.40 ], [ -40.50, -4.60, 6.90 ], [ 0.00, 0.00, 20.67 ], [ 0.00, 0.00, -0.30 ], [ -5.68, 19.87, 0.58 ], [ 0.00, 0.00, -0.30 ] ] ), - (22, [ [ -71.70, -2.20, 197.20 ], [ -25.20, 35.80, -6.80 ], [ 0.00, 0.00, 20.42 ], [ 0.00, 0.00, -0.30 ], [ 18.28, 9.08, 0.48 ], [ 0.00, 0.00, -0.30 ] ] ), - (23, [ [ -65.80, 42.10, 182.30 ], [ 26.60, 37.60, -15.60 ], [ 0.00, 0.00, 20.03 ], [ 0.00, 0.00, -0.46 ], [ 11.97, -15.92, 2.06 ], [ 0.00, 0.00, -0.46 ] ] ), - (24, [ [ -14.10, 81.20, 163.50 ], [ 41.00, 10.30, -9.50 ], [ 0.00, 0.00, 19.48 ], [ 0.00, 0.00, -0.59 ], [ 0.59, -19.44, 0.94 ], [ 0.00, 0.00, -0.59 ] ] ), - (25, [ [ 61.70, 86.10, 156.40 ], [ 77.90, -40.70, 8.90 ], [ 0.00, 0.00, 18.85 ], [ 0.00, 0.00, -0.62 ], [ -7.01, -17.50, 0.19 ], [ 0.00, 0.00, -0.62 ] ] ), - (26, [ [ 92.90, 20.50, 150.30 ], [ 0.00, -73.30, -5.20 ], [ 0.00, 0.00, 18.23 ], [ 0.00, 0.00, -0.69 ], [ -18.19, 1.29, 0.09 ], [ 0.00, 0.00, -0.69 ] ] ), - (27, [ [ 48.90, -65.00, 142.80 ], [ -82.80, -80.00, -1.90 ], [ 0.00, 0.00, 17.44 ], [ 0.00, 0.00, -0.84 ], [ -11.91, 12.74, 0.00 ], [ 0.00, 0.00, -0.84 ] ] ), - (28, [ [ -54.30, -90.80, 134.00 ], [ -60.10, 26.40, -8.20 ], [ 0.00, 0.00, 16.54 ], [ 0.00, 0.00, -0.92 ], [ 8.46, 14.21, 0.25 ], [ 0.00, 0.00, -0.92 ] ] ), - (29, [ [ -89.90, 11.20, 115.00 ], [ 34.90, 125.10, -27.90 ], [ 0.00, 0.00, 15.59 ], [ 0.00, 0.00, -0.88 ], [ 13.83, -7.18, 0.69 ], [ 0.00, 0.00, -0.88 ] ] ), - (30, [ [ -17.40, 74.20, 91.10 ], [ 78.80, 19.10, -15.40 ], [ 0.00, 0.00, 14.77 ], [ 0.00, 0.00, -0.67 ], [ 0.79, -14.74, 0.51 ], [ 0.00, 0.00, -0.67 ] ] ), - (31, [ [ 43.40, 50.20, 73.30 ], [ 30.20, -36.00, -9.90 ], [ 0.00, 0.00, 14.20 ], [ 0.00, 0.00, -0.52 ], [ -12.48, -6.73, 0.60 ], [ 0.00, 0.00, -0.52 ] ] ), - (32, [ [ 62.40, -5.10, 63.50 ], [ 10.90, -54.20, -2.70 ], [ 0.00, 0.00, 13.72 ], [ 0.00, 0.00, -0.48 ], [ -13.56, -2.05, 0.03 ], [ 0.00, 0.00, -0.48 ] ] ), - (33, [ [ 32.70, -51.70, 56.10 ], [ -38.60, -29.80, -8.10 ], [ 0.00, 0.00, 13.24 ], [ 1.37, 2.33, -1.30 ], [ -6.29, 11.65, 0.36 ], [ 1.59, 2.70, -1.41 ] ] ), - (34, [ [ -38.10, -28.60, 46.80 ], [ -62.50, 82.60, -19.20 ], [ 3.28, 5.57, 10.81 ], [ 1.59, -2.89, -2.75 ], [ 9.22, 6.17, -5.96 ], [ 1.85, -3.40, -3.08 ] ] ), - (35, [ [ 5.70, 40.40, 22.40 ], [ 144.80, 18.60, -20.50 ], [ 2.68, -8.27, 7.65 ], [ -4.75, -6.37, -4.66 ], [ 0.33, -7.82, -8.54 ], [ -5.62, -7.55, -5.37 ] ] ), - (36, [ [ 53.00, -14.70, -4.10 ], [ -6.00, -25.70, -46.70 ], [ -5.67, -8.15, 1.68 ], [ -3.78, 1.55, -1.86 ], [ -8.24, 3.65, -4.49 ], [ -4.60, 1.69, -2.12 ] ] ), - (37, [ [ 24.80, -0.40, -48.80 ], [ -13.40, 23.90, -30.60 ], [ -6.57, -5.70, 2.41 ], [ 4.46, 2.06, 2.31 ], [ -1.87, 3.95, 7.90 ], [ 5.41, 2.39, 2.88 ] ] ), - (38, [ [ -20.90, 15.30, -77.90 ], [ -51.20, -30.60, 21.10 ], [ 3.74, -4.06, 6.43 ], [ -1.12, 2.71, -1.85 ], [ -2.63, 5.93, 5.46 ], [ -1.44, 3.31, -2.27 ] ] ), - (39, [ [ -47.60, 33.90, -112.20 ], [ 32.60, 30.70, -27.80 ], [ -8.36, -0.32, -1.04 ], [ -7.25, 2.76, -6.03 ], [ -3.75, 2.25, 7.20 ], [ -8.97, 3.42, -7.45 ] ] ), - (40, [ [ 19.60, 96.00, -167.50 ], [ 19.90, 19.10, -18.40 ], [ -6.99, 0.72, -4.50 ], [ 9.97, -0.68, -0.89 ], [ -2.97, 5.84, 5.17 ], [ 12.30, -0.82, -1.11 ] ] ) ] ), - + (1, [[-7.20,83.30,-20.70], [-65.20,-8.10,7.60], [0.00,0.00,38.25], [0.00,0.00,-0.50], [-9.02,37.17,0.51], [0.00,0.00,-0.50]]), + (2, [[-68.50,52.80,-9.60], [-40.10,-36.10,10.70], [0.00,0.00,37.69], [0.00,0.00,-0.63], [-30.08,22.66,1.43], [0.00,0.00,-0.63]]), + (3, [[-97.40,-26.30,5.70], [18.00,-93.20,13.70], [0.00,0.00,36.98], [0.00,0.00,-0.67], [-34.95,-12.07,0.76], [0.00,0.00,-0.67]]), + (4, [[-56.80,-90.50,14.10], [65.50,-41.40,7.30], [0.00,0.00,36.35], [0.00,0.00,-0.74], [-16.46,-32.40,0.32], [0.00,0.00,-0.74]]), + (5, [[48.90,-100.80,24.00], [112.20,40.10,19.00], [0.00,0.00,35.47], [0.00,0.00,-0.91], [16.98,-31.12,0.88], [0.00,0.00,-0.91]]), + (6, [[114.80,-12.60,38.70], [8.20,96.10,14.20], [0.00,0.00,34.53], [0.00,0.00,-0.93], [34.47,2.05,0.73], [0.00,0.00,-0.93]]), + (7, [[60.30,83.50,43.70], [-108.70,54.10,22.40], [0.00,0.00,33.60], [0.00,0.00,-0.89], [9.36,32.25,1.10], [0.00,0.00,-0.89]]), + (8, [[-41.20,90.70,56.30], [-89.00,-32.40,14.40], [0.00,0.00,32.75], [0.00,0.00,-0.93], [-15.64,28.77,0.74], [0.00,0.00,-0.93]]), + (9, [[-107.90,-9.70,76.60], [11.10,-94.40,11.30], [0.00,0.00,31.72], [0.00,0.00,-0.91], [-30.85,-7.37,0.44], [0.00,0.00,-0.91]]), + (10, [[-57.30,-91.90,81.30], [71.20,-31.20,5.70], [0.00,0.00,30.90], [0.00,0.00,-0.86], [-10.31,-29.13,0.16], [0.00,0.00,-0.86]]), + (11, [[51.20,-89.40,97.20], [99.10,55.40,12.90], [0.00,0.00,30.00], [0.00,0.00,-0.90], [17.48,-24.38,0.38], [0.00,0.00,-0.90]]), + (12, [[91.60,9.30,103.60], [4.70,51.20,3.40], [0.00,0.00,29.11], [0.00,0.00,-0.90], [29.10,-0.75,0.13], [0.00,0.00,-0.90]]), + (13, [[61.60,111.80,109.60], [-85.20,46.10,2.60], [0.00,0.00,28.20], [0.00,0.00,-0.95], [12.75,25.15,0.02], [0.00,0.00,-0.95]]), + (14, [[-54.60,91.90,129.40], [-92.70,-55.00,14.50], [0.00,0.00,27.20], [0.00,0.00,-0.94], [-16.84,21.35,0.48], [0.00,0.00,-0.94]]), + (15, [[-109.00,5.60,156.90], [23.60,-108.20,27.70], [0.00,0.00,26.30], [0.00,0.00,-0.80], [-23.61,-11.49,1.55], [0.00,0.00,-0.80]]), + (16, [[-59.10,-62.50,170.80], [74.00,-20.10,14.40], [0.00,0.00,25.59], [0.00,0.00,-0.70], [-2.12,-25.48,0.87], [0.00,0.00,-0.70]]), + (17, [[23.50,-53.20,179.70], [84.60,47.00,6.90], [0.00,0.00,24.90], [0.00,0.00,-0.73], [13.61,-20.85,0.12], [0.00,0.00,-0.73]]), + (18, [[62.30,30.10,187.50], [-12.80,58.00,0.80], [0.00,0.00,24.13], [0.00,0.00,-0.55], [23.49,5.51,0.00], [0.00,0.00,-0.55]]), + (19, [[22.40,45.20,181.10], [-23.60,-34.50,-7.40], [0.00,0.00,23.69], [0.00,0.00,-0.41], [-16.96,16.53,0.72], [0.00,0.00,-0.41]]), + (20, [[-1.90,4.90,180.50], [-41.30,-30.90,7.50], [0.00,0.00,23.31], [0.00,0.00,-0.39], [-16.48,16.48,0.49], [0.00,0.00,-0.39]]), + (21, [[-45.10,-12.60,194.40], [-40.50,-4.60,6.90], [0.00,0.00,22.92], [0.00,0.00,-0.30], [-6.30,22.03,0.64], [0.00,0.00,-0.30]]), + (22, [[-71.70,-2.20,197.20], [-25.20,35.80,-6.80], [0.00,0.00,22.67], [0.00,0.00,-0.30], [20.29,10.08,0.53], [0.00,0.00,-0.30]]), + (23, [[-65.80,42.10,182.30], [26.60,37.60,-15.60], [0.00,0.00,22.28], [0.00,0.00,-0.46], [13.31,-17.71,2.29], [0.00,0.00,-0.46]]), + (24, [[-14.10,81.20,163.50], [41.00,10.30,-9.50], [0.00,0.00,21.73], [0.00,0.00,-0.59], [0.66,-21.69,1.05], [0.00,0.00,-0.59]]), + (25, [[61.70,86.10,156.40], [77.90,-40.70,8.90], [0.00,0.00,21.10], [0.00,0.00,-0.62], [-7.85,-19.59,0.21], [0.00,0.00,-0.62]]), + (26, [[92.90,20.50,150.30], [0.00,-73.30,-5.20], [0.00,0.00,20.48], [0.00,0.00,-0.69], [-20.43,1.45,0.10], [0.00,0.00,-0.69]]), + (27, [[48.90,-65.00,142.80], [-82.80,-80.00,-1.90], [0.00,0.00,19.69], [0.00,0.00,-0.84], [-13.45,14.38,0.00], [0.00,0.00,-0.84]]), + (28, [[-54.30,-90.80,134.00], [-60.10,26.40,-8.20], [0.00,0.00,18.79], [0.00,0.00,-0.92], [9.61,16.14,0.28], [0.00,0.00,-0.92]]), + (29, [[-89.90,11.20,115.00], [34.90,125.10,-27.90], [0.00,0.00,17.84], [0.00,0.00,-0.88], [15.82,-8.22,0.79], [0.00,0.00,-0.88]]), + (30, [[-17.40,74.20,91.10], [78.80,19.10,-15.40], [0.00,0.00,17.02], [0.00,0.00,-0.67], [0.91,-16.99,0.59], [0.00,0.00,-0.67]]), + (31, [[43.40,50.20,73.30], [30.20,-36.00,-9.90], [0.00,0.00,16.45], [0.00,0.00,-0.52], [-14.46,-7.80,0.70], [0.00,0.00,-0.52]]), + (32, [[62.40,-5.10,63.50], [10.90,-54.20,-2.70], [0.00,0.00,15.97], [0.00,0.00,-0.48], [-15.78,-2.39,0.03], [0.00,0.00,-0.48]]), + (33, [[32.70,-51.70,56.10], [-38.60,-29.80,-8.10], [0.00,0.00,15.49], [1.37,2.33,-1.30], [-7.36,13.63,0.42], [1.59,2.70,-1.41]]), + (34, [[-38.10,-28.60,46.80], [-62.50,82.60,-19.20], [3.87,6.57,12.74], [1.59,-2.89,-2.75], [10.87,7.27,-7.02], [1.85,-3.40,-3.08]]), + (35, [[5.70,40.40,22.40], [144.80,18.60,-20.50], [3.20,-9.88,9.14], [-4.75,-6.37,-4.66], [0.39,-9.34,-10.20], [-5.62,-7.55,-5.37]]), + (36, [[53.00,-14.70,-4.10], [-6.00,-25.70,-46.70], [-6.94,-9.97,2.06], [-3.78,1.55,-1.86], [-10.08,4.47,-5.49], [-4.60,1.69,-2.12]]), + (37, [[24.80,-0.40,-48.80], [-13.40,23.90,-30.60], [-8.21,-7.12,3.01], [4.46,2.06,2.31], [-2.34,4.93,9.87], [5.41,2.39,2.88]]), + (38, [[-20.90,15.30,-77.90], [-51.20,-30.60,21.10], [4.73,-5.14,8.14], [-1.12,2.71,-1.85], [-3.33,7.50,6.91], [-1.44,3.31,-2.27]]), + (39, [[-47.60,33.90,-112.20], [32.60,30.70,-27.80], [-10.59,-0.41,-1.32], [-7.25,2.76,-6.03], [-4.75,2.85,9.12], [-8.97,3.42,-7.45]]), + (40, [[19.60,96.00,-167.50], [19.90,19.10,-18.40], [-8.87,0.91,-5.71], [9.97,-0.68,-0.89], [-3.77,7.41,6.56], [12.30,-0.82,-1.11]]) + ] ), + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-39', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -452,8 +475,17 @@ class MeshType_3d_colon1(Scaffold_base): 'name': get_colon_term('descending colon')[0], 'ontId': get_colon_term('descending colon')[1] }] - }), - } + }) + + +class MeshType_3d_colon1(Scaffold_base): + ''' + Generates a 3-D colon mesh with variable numbers + of elements around, along the central line, and through wall. + The colon is created by a function that generates a colon + segment and uses tubemesh to map the segment along a central + line profile. + ''' @staticmethod def getName(): @@ -473,21 +505,6 @@ def getParameterSetNames(): @classmethod def getDefaultOptions(cls, parameterSetName='Default'): - if 'Human 2' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 2'] - elif 'Human 3' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 3'] - elif 'Cattle 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Cattle 1'] - elif 'Mouse 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Mouse 1'] - elif 'Mouse 2' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Mouse 2'] - elif 'Pig 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Pig 1'] - else: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 1'] - if 'Human 3' in parameterSetName: segmentProfileOption = ScaffoldPackage(MeshType_3d_colonsegment1, defaultParameterSetName='Human 2') elif 'Cattle' in parameterSetName: @@ -499,7 +516,8 @@ def getDefaultOptions(cls, parameterSetName='Default'): else: segmentProfileOption = ScaffoldPackage(MeshType_3d_colonsegment1, defaultParameterSetName='Human 1') options = { - 'Central path': copy.deepcopy(centralPathOption), + 'Base parameter set': parameterSetName, + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), 'Segment profile': segmentProfileOption, 'Number of segments': 30, 'Start phase': 0.0, @@ -507,6 +525,7 @@ def getDefaultOptions(cls, parameterSetName='Default'): 'Proximal-transverse tenia coli width': 10.0, 'Transverse-distal tenia coli width': 10.0, 'Distal tenia coli width': 10.0, + 'Use linear through wall': True, 'Refine': False, 'Refine number of elements around': 1, 'Refine number of elements along': 1, @@ -522,22 +541,23 @@ def getDefaultOptions(cls, parameterSetName='Default'): options['Number of segments'] = 33 elif 'Mouse' in parameterSetName: options['Number of segments'] = 10 - options['Proximal tenia coli width'] = 0.5 - options['Proximal-transverse tenia coli width'] = 0.5 - options['Transverse-distal tenia coli width'] = 0.5 - options['Distal tenia coli width'] = 0.5 + options['Proximal tenia coli width'] = 0.77 + options['Proximal-transverse tenia coli width'] = 0.8 + options['Transverse-distal tenia coli width'] = 0.9 + options['Distal tenia coli width'] = 0.9 elif 'Pig 1' in parameterSetName: options['Number of segments'] = 120 options['Proximal tenia coli width'] = 5.0 options['Proximal-transverse tenia coli width'] = 4.0 options['Transverse-distal tenia coli width'] = 3.0 options['Distal tenia coli width'] = 1.5 + return options @staticmethod def getOrderedOptionNames(): return [ - 'Central path', + 'Network layout', 'Segment profile', 'Number of segments', 'Start phase', @@ -545,6 +565,7 @@ def getOrderedOptionNames(): 'Proximal-transverse tenia coli width', 'Transverse-distal tenia coli width', 'Distal tenia coli width', + 'Use linear through wall', 'Refine', 'Refine number of elements around', 'Refine number of elements along', @@ -552,16 +573,16 @@ def getOrderedOptionNames(): @classmethod def getOptionValidScaffoldTypes(cls, optionName): - if optionName == 'Central path': - return [MeshType_1d_path1] + if optionName == 'Network layout': + return [MeshType_1d_network_layout1] if optionName == 'Segment profile': return [MeshType_3d_colonsegment1] return [] @classmethod def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): - if optionName == 'Central path': - return list(cls.centralPathDefaultScaffoldPackages.keys()) + if optionName == 'Network layout': + return cls.getParameterSetNames() assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() @@ -577,10 +598,10 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() - if optionName == 'Central path': + if optionName == 'Network layout': if not parameterSetName: - parameterSetName = list(cls.centralPathDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.centralPathDefaultScaffoldPackages[parameterSetName]) + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) if optionName == 'Segment profile': if not parameterSetName: parameterSetName = scaffoldType.getParameterSetNames()[0] @@ -589,8 +610,8 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non @classmethod def checkOptions(cls, options): - if not options['Central path'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Central path'): - options['Central path'] = cls.getOptionScaffoldPackage('Central path', MeshType_1d_path1) + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) if not options['Segment profile'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Segment profile'): options['Segment profile'] = cls.getOptionScaffoldPackage('Segment profile', MeshType_3d_colonsegment1) for key in [ @@ -616,314 +637,26 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ - centralPath = options['Central path'] + nextNodeIdentifier = 1 + nextElementIdentifier = 1 + segmentProfile = options['Segment profile'] - segmentCount = options['Number of segments'] - startPhase = options['Start phase'] % 360.0 - proximalTCWidth = options['Proximal tenia coli width'] - proximalTransverseTCWidth = options['Proximal-transverse tenia coli width'] - transverseDistalTCWidth = options['Transverse-distal tenia coli width'] - distalTCWidth = options['Distal tenia coli width'] segmentSettings = segmentProfile.getScaffoldSettings() - - elementsCountAroundTC = segmentSettings['Number of elements around tenia coli'] - elementsCountAroundHaustrum = segmentSettings['Number of elements around haustrum'] - cornerInnerRadiusFactor = segmentSettings['Corner inner radius factor'] - haustrumInnerRadiusFactor = segmentSettings['Haustrum inner radius factor'] - segmentLengthEndDerivativeFactor = segmentSettings['Segment length end derivative factor'] - segmentLengthMidDerivativeFactor = segmentSettings['Segment length mid derivative factor'] tcCount = segmentSettings['Number of tenia coli'] - tcThickness = segmentSettings['Tenia coli thickness'] - elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum) * tcCount - - elementsCountAlongSegment = segmentSettings['Number of elements along segment'] - elementsCountThroughWall = segmentSettings['Number of elements through wall'] - wallThickness = segmentSettings['Wall thickness'] - mucosaRelThickness = segmentSettings['Mucosa relative thickness'] - submucosaRelThickness = segmentSettings['Submucosa relative thickness'] - circularRelThickness = segmentSettings['Circular muscle layer relative thickness'] - longitudinalRelThickness = segmentSettings['Longitudinal muscle layer relative thickness'] - useCrossDerivatives = segmentSettings['Use cross derivatives'] - useCubicHermiteThroughWall = not (segmentSettings['Use linear through wall']) - elementsCountAlong = int(elementsCountAlongSegment * segmentCount) - - # Colon coordinates - lengthToDiameterRatio = 24 - wallThicknessToDiameterRatio = 0.1 - teniaColiThicknessToDiameterRatio = 0.25 * wallThicknessToDiameterRatio - relativeThicknessListColonCoordinates = [1.0 / elementsCountThroughWall for n3 in range(elementsCountThroughWall)] - - firstNodeIdentifier = 1 - firstElementIdentifier = 1 - - # Central path - if tcCount == 1: - colonTermsAlong = [None, 'right colon', 'transverse colon', 'left colon'] - elif tcCount == 2: - colonTermsAlong = [None, 'spiral colon', 'transverse colon', 'descending colon'] - elif tcCount == 3: - colonTermsAlong = [None, 'ascending colon', 'transverse colon', 'descending colon'] - - tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) - tmpFieldmodule = tmpRegion.getFieldmodule() - tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') - arcLengthOfGroupsAlong = [] - - for termName in colonTermsAlong: - tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None - tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes - - cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( - tmpNodeset, tmpCoordinates, - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, - Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, - Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) - arcLength = 0.0 - for e in range(len(cxGroup) - 1): - arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], - cxGroup[e + 1], cd1Group[e + 1]) - arcLengthOfGroupsAlong.append(arcLength) - - if not termName: - cx = cxGroup - cd1 = cd1Group - cd2 = cd2Group - cd3 = cd3Group - cd12 = cd12Group - cd13 = cd13Group - - del tmpNodeset - del tmpGroup - - del tmpCoordinates - del tmpNodes - del tmpFieldmodule - del tmpRegion - - # find arclength of colon - length = 0.0 - elementsCountIn = len(cx) - 1 - sd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, fixAllDirections=True, - magnitudeScalingMode=interp.DerivativeScalingMode.HARMONIC_MEAN) - for e in range(elementsCountIn): - arcLength = interp.getCubicHermiteArcLength(cx[e], sd1[e], cx[e + 1], sd1[e + 1]) - # print(e+1, arcLength) - length += arcLength - segmentLength = length / segmentCount - - # Sample central path - sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlong) - sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) - - centralPathLength = arcLengthOfGroupsAlong[0] - elementAlongLength = centralPathLength / elementsCountAlong - - elementsCountAlongGroups = [] - groupLength = 0.0 - e = 0 - elementsCount = 1 - length = elementAlongLength - for i in range(1, len(colonTermsAlong)): - groupLength += arcLengthOfGroupsAlong[i] - if e == elementsCountAlong - 2: - elementsCount += 1 - elementsCountAlongGroups.append(elementsCount) - else: - while length < groupLength: - elementsCount += 1 - e += 1 - length += elementAlongLength - - # check which end is grouplength closer to - distToUpperEnd = abs(length - groupLength) - distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) - if distToLowerEnd < distToUpperEnd: - elementsCount -= 1 - elementsCountAlongGroups.append(elementsCount) - e -= 1 - length -= elementAlongLength - else: - elementsCountAlongGroups.append(elementsCount) - elementsCount = 0 - - # Generate variation of radius & tc width along length - lengthList = [0.0, arcLengthOfGroupsAlong[1], arcLengthOfGroupsAlong[1] + arcLengthOfGroupsAlong[2], - arcLengthOfGroupsAlong[0]] - - innerRadiusListCP = [vector.magnitude(c) for c in cd2] - dInnerRadiusListCP = [] - for n in range(len(innerRadiusListCP) - 1): - dInnerRadiusListCP.append(innerRadiusListCP[n + 1] - innerRadiusListCP[n]) - dInnerRadiusListCP.append(innerRadiusListCP[-1] - innerRadiusListCP[-2]) - innerRadiusAlongElementList, dInnerRadiusAlongElementList = interp.interpolateSampleCubicHermite( - innerRadiusListCP, dInnerRadiusListCP, se, sxi, ssf) - - tcWidthList = [proximalTCWidth, proximalTransverseTCWidth, transverseDistalTCWidth, distalTCWidth] - tcWidthAlongElementList, dTCWidthAlongElementList = interp.sampleParameterAlongLine(lengthList, - tcWidthList, - elementsCountAlong) - - # Account for reduced haustrum appearance in transverse and distal pig colon - if tcCount == 2: - haustrumInnerRadiusFactorList = [haustrumInnerRadiusFactor, haustrumInnerRadiusFactor * 0.75, - haustrumInnerRadiusFactor * 0.5, haustrumInnerRadiusFactor * 0.2] - haustrumInnerRadiusFactorAlongElementList = \ - interp.sampleParameterAlongLine(lengthList, haustrumInnerRadiusFactorList, elementsCountAlong)[0] - else: - haustrumInnerRadiusFactorAlongElementList = [haustrumInnerRadiusFactor] * (elementsCountAlong + 1) - - # Create annotation groups for colon sections - colonGroup = AnnotationGroup(region, get_colon_term("colon")) + geometricNetworkLayout = options['Network layout'] if tcCount == 1: - proximalGroup = AnnotationGroup(region, get_colon_term("right colon")) - transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) - distalGroup = AnnotationGroup(region, get_colon_term("left colon")) - annotationGroupAlong = [[colonGroup, proximalGroup], - [colonGroup, transverseGroup], - [colonGroup, distalGroup]] - + colonTermsAlong = ['colon', 'right colon', 'transverse colon', 'left colon'] elif tcCount == 2: - spiralGroup = AnnotationGroup(region, get_colon_term("spiral colon")) - transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) - distalGroup = AnnotationGroup(region, get_colon_term("descending colon")) - annotationGroupAlong = [[colonGroup, spiralGroup], - [colonGroup, transverseGroup], - [colonGroup, distalGroup]] - + colonTermsAlong = ['colon', 'spiral colon', 'transverse colon', 'descending colon'] elif tcCount == 3: - ascendingGroup = AnnotationGroup(region, get_colon_term("ascending colon")) - transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) - descendingGroup = AnnotationGroup(region, get_colon_term("descending colon")) - annotationGroupAlong = [[colonGroup, ascendingGroup], - [colonGroup, transverseGroup], - [colonGroup, descendingGroup]] - - annotationGroupsAlong = [] - for i in range(len(elementsCountAlongGroups)): - elementsCount = elementsCountAlongGroups[i] - for n in range(elementsCount): - annotationGroupsAlong.append(annotationGroupAlong[i]) - - xExtrude = [] - d1Extrude = [] - d2Extrude = [] - d3UnitExtrude = [] - sxRefExtrudeList = [] - - if elementsCountThroughWall == 1: - relativeThicknessList = [1.0] - annotationGroupsThroughWall = [[]] - else: - relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, - circularRelThickness, longitudinalRelThickness] - mucosaGroup = AnnotationGroup(region, get_colon_term("colonic mucosa")) - submucosaGroup = AnnotationGroup(region, get_colon_term("submucosa of colon")) - circularMuscleGroup = AnnotationGroup(region, get_colon_term("circular muscle layer of colon")) - longitudinalMuscleGroup = AnnotationGroup(region, get_colon_term("longitudinal muscle layer of colon")) - annotationGroupsThroughWall = [[mucosaGroup], [submucosaGroup], - [circularMuscleGroup], [longitudinalMuscleGroup]] - - # Create object - colonSegmentTubeMeshInnerPoints = ColonSegmentTubeMeshInnerPoints( - region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, - tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, - segmentLength, wallThickness, cornerInnerRadiusFactor, haustrumInnerRadiusFactorAlongElementList, - innerRadiusAlongElementList, dInnerRadiusAlongElementList, tcWidthAlongElementList, - startPhase) - - for nSegment in range(segmentCount): - # Create inner points - xInner, d1Inner, d2Inner, transitElementList, segmentAxis, annotationGroupsAround \ - = colonSegmentTubeMeshInnerPoints.getColonSegmentTubeMeshInnerPoints(nSegment) - - # Project reference point for warping onto central path - start = nSegment * elementsCountAlongSegment - end = (nSegment + 1) * elementsCountAlongSegment + 1 - sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ - tubemesh.getPlaneProjectionOnCentralPath(xInner, elementsCountAround, elementsCountAlongSegment, - segmentLength, sx[start:end], sd1[start:end], sd2[start:end], - sd12[start:end]) - - # Warp segment points - xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = tubemesh.warpSegmentPoints( - xInner, d1Inner, d2Inner, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, - elementsCountAround, elementsCountAlongSegment, zRefList) - - # Store points along length - xExtrude += xWarpedList if nSegment == 0 else xWarpedList[elementsCountAround:] - d1Extrude += d1WarpedList if nSegment == 0 else d1WarpedList[elementsCountAround:] - d2Extrude += d2WarpedList if nSegment == 0 else d2WarpedList[elementsCountAround:] - d3UnitExtrude += d3WarpedUnitList if nSegment == 0 else d3WarpedUnitList[elementsCountAround:] - sxRefExtrudeList += sxRefList if nSegment == 0 else sxRefList[elementsCountAround:] - - contractedWallThicknessList = colonSegmentTubeMeshInnerPoints.getContractedWallThicknessList() - - # Create coordinates and derivatives - xList, d1List, d2List, d3List, curvatureList = tubemesh.extrudeSurfaceCoordinates(xExtrude, d1Extrude, - d2Extrude, d3UnitExtrude, contractedWallThicknessList, relativeThicknessList, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, transitElementList, - outward=True) - - relaxedLengthList, xiList = colonSegmentTubeMeshInnerPoints.getRelaxedLengthAndXiList() - - closedProximalEnd = False - - if tcThickness > 0: - tubeTCWidthList = colonSegmentTubeMeshInnerPoints.getTubeTCWidthList() - xList, d1List, d2List, d3List, annotationArrayAround = getTeniaColi( - region, xList, d1List, d2List, d3List, curvatureList, tcCount, elementsCountAroundTC, - elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, - tubeTCWidthList, tcThickness, sxRefExtrudeList, annotationGroupsAround, - closedProximalEnd) - - # Create flat coordinates - xFlat, d1Flat, d2Flat = createFlatCoordinatesTeniaColi( - xiList, relaxedLengthList, length, wallThickness, relativeThicknessList, tcCount, tcThickness, - elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, - elementsCountThroughWall, transitElementList, closedProximalEnd) + colonTermsAlong = ['colon', 'ascending colon', 'transverse colon', 'descending colon'] - # Create colon coordinates - xColon, d1Colon, d2Colon = createColonCoordinatesTeniaColi(xiList, relativeThicknessListColonCoordinates, - lengthToDiameterRatio, - wallThicknessToDiameterRatio, - teniaColiThicknessToDiameterRatio, tcCount, - elementsCountAroundTC, - elementsCountAroundHaustrum, - elementsCountAlong, elementsCountThroughWall, - transitElementList, closedProximalEnd) - - # Create nodes and elements - nextNodeIdentifier, nextElementIdentifier, annotationGroups = createNodesAndElementsTeniaColi( - region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, xColon, d1Colon, d2Colon, - "colon coordinates", elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, - elementsCountThroughWall, tcCount, annotationGroupsAround, annotationGroupsAlong, - annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, - useCrossDerivatives, closedProximalEnd) + geometricNetworkLayout = ColonNetworkLayout(region, geometricNetworkLayout, colonTermsAlong) - else: - # Create flat coordinates - xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates( - xiList, relaxedLengthList, length, wallThickness, relativeThicknessList, elementsCountAround, - elementsCountAlong, elementsCountThroughWall, transitElementList) - - # Create colon coordinates - xColon, d1Colon, d2Colon = tubemesh.createOrganCoordinates(xiList, relativeThicknessListColonCoordinates, - lengthToDiameterRatio, - wallThicknessToDiameterRatio, - elementsCountAround, - elementsCountAlong, elementsCountThroughWall, - transitElementList) - - # Create nodes and elements - nextNodeIdentifier, nextElementIdentifier, annotationGroups = tubemesh.createNodesAndElements( - region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, xColon, d1Colon, d2Colon, - "colon coordinates", elementsCountAround, elementsCountAlong, elementsCountThroughWall, - annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, - closedProximalEnd) + annotationGroups, nextNodeIdentifier, nextElementIdentifier = \ + createColonMesh3d(region, options, geometricNetworkLayout, nextNodeIdentifier, + nextElementIdentifier, flatCoordinates=True, materialCoordinates=True)[0:3] return annotationGroups, None @@ -968,3 +701,371 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): mucosaInnerSurface = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_colon_term("luminal surface of the colonic mucosa")) mucosaInnerSurface.getMeshGroup(mesh2d).addElementsConditional(is_mucosaInnerSurface) + +def createColonMesh3d(region, options, networkLayout, nextNodeIdentifier, nextElementIdentifier, + flatCoordinates=False, materialCoordinates=False, + nodeIdProximal=[], xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[]): + """ + Generates a colon scaffold in the region using a network layout and parameter options. + :param region: Region to create elements in. + :param options: Parameter options for creating scaffold. + :param networkLayout: Network layout through the path of the colon. + :param nextNodeIdentifier: Next node identifier to use. + :param nextElementIdentifier: Next element identifier to use. + :param flatCoordinates: Generate flat coordinates if True. + :param materialCoordinates: Create material coordinates if True. + :param nodeIdProximal, xProximal, d1Proximal, d2Proximal, d3Proximal: Node identifier, coordinates and derivatives + of nodes to use at proximal end of scaffold. + :return annotationGroups, nextNodeIdentifier, nextElementIdentifier, nodesIdDistal, xDistal, d1Distal, d2Distal, + d3Distal + """ + parameterSetName = options['Base parameter set'] + isHuman = 'Human' in parameterSetName + segmentProfile = options['Segment profile'] + segmentCount = options['Number of segments'] + startPhase = options['Start phase'] % 360.0 + proximalTCWidth = options['Proximal tenia coli width'] + proximalTransverseTCWidth = options['Proximal-transverse tenia coli width'] + transverseDistalTCWidth = options['Transverse-distal tenia coli width'] + distalTCWidth = options['Distal tenia coli width'] + useCubicHermiteThroughWall = not (options['Use linear through wall']) + segmentSettings = segmentProfile.getScaffoldSettings() + + elementsCountAroundTC = segmentSettings['Number of elements around tenia coli'] + elementsCountAroundHaustrum = segmentSettings['Number of elements around haustrum'] + cornerOuterRadiusFactor = segmentSettings['Corner outer radius factor'] + haustrumOuterRadiusFactor = segmentSettings['Haustrum outer radius factor'] + segmentLengthEndDerivativeFactor = segmentSettings['Segment length end derivative factor'] + segmentLengthMidDerivativeFactor = segmentSettings['Segment length mid derivative factor'] + tcCount = segmentSettings['Number of tenia coli'] + tcThickness = segmentSettings['Tenia coli thickness'] + elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum) * tcCount + + elementsCountAlongSegment = segmentSettings['Number of elements along segment'] + elementsCountThroughWall = segmentSettings['Number of elements through wall'] + wallThickness = segmentSettings['Wall thickness'] + mucosaRelThickness = segmentSettings['Mucosa relative thickness'] + submucosaRelThickness = segmentSettings['Submucosa relative thickness'] + circularRelThickness = segmentSettings['Circular muscle layer relative thickness'] + longitudinalRelThickness = segmentSettings['Longitudinal muscle layer relative thickness'] + useCrossDerivatives = segmentSettings['Use cross derivatives'] + + elementsCountAlong = int(elementsCountAlongSegment * segmentCount) + + # Colon coordinates + lengthToDiameterRatio = 24 + wallThicknessToDiameterRatio = 0.1 + teniaColiThicknessToDiameterRatio = 0.25 * wallThicknessToDiameterRatio + relativeThicknessListColonCoordinates = [1.0 / elementsCountThroughWall for n3 in range(elementsCountThroughWall)] + + # Network layout + if tcCount == 1: + colonTermsAlong = ['colon', 'right colon', 'transverse colon', 'left colon'] + elif tcCount == 2: + colonTermsAlong = ['colon', 'spiral colon', 'transverse colon', 'descending colon'] + elif tcCount == 3: + colonTermsAlong = ['colon', 'ascending colon', 'transverse colon', 'descending colon'] + + networkLayoutLength = networkLayout.arcLengthOfGroupsAlong[0] + cx = networkLayout.cxGroups[0] + cd1 = networkLayout.cd1Groups[0] + cd2 = networkLayout.cd2Groups[0] + cd12 = networkLayout.cd12Groups[0] + arcLengthOfGroupsAlong = networkLayout.arcLengthOfGroupsAlong + + # find arclength of colon + length = 0.0 + elementsCountIn = len(cx) - 1 + sd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, fixAllDirections=True, + magnitudeScalingMode=interp.DerivativeScalingMode.HARMONIC_MEAN) + for e in range(elementsCountIn): + arcLength = interp.getCubicHermiteArcLength(cx[e], sd1[e], cx[e + 1], sd1[e + 1]) + # print(e+1, arcLength) + length += arcLength + segmentLength = length / segmentCount + + # Sample network layout + sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlong) + sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) + + elementAlongLength = networkLayoutLength / elementsCountAlong + + elementsCountAlongGroups = [] + groupLength = 0.0 + e = 0 + elementsCount = 1 + length = elementAlongLength + for i in range(1, len(colonTermsAlong)): + groupLength += arcLengthOfGroupsAlong[i] + if e == elementsCountAlong - 2: + elementsCount += 1 + elementsCountAlongGroups.append(elementsCount) + else: + while length < groupLength: + elementsCount += 1 + e += 1 + length += elementAlongLength + + # check which end is grouplength closer to + distToUpperEnd = abs(length - groupLength) + distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) + if distToLowerEnd < distToUpperEnd: + elementsCount -= 1 + elementsCountAlongGroups.append(elementsCount) + e -= 1 + length -= elementAlongLength + else: + elementsCountAlongGroups.append(elementsCount) + elementsCount = 0 + + # Generate variation of radius & tc width along length + lengthList = [0.0, arcLengthOfGroupsAlong[1], + arcLengthOfGroupsAlong[1] + arcLengthOfGroupsAlong[2], + arcLengthOfGroupsAlong[0]] + + outerRadiusListCP = [vector.magnitude(c) for c in cd2] + dOuterRadiusListCP = [] + for n in range(len(outerRadiusListCP) - 1): + dOuterRadiusListCP.append(outerRadiusListCP[n + 1] - outerRadiusListCP[n]) + dOuterRadiusListCP.append(outerRadiusListCP[-1] - outerRadiusListCP[-2]) + outerRadiusAlongElementList, dOuterRadiusAlongElementList = interp.interpolateSampleCubicHermite( + outerRadiusListCP, dOuterRadiusListCP, se, sxi, ssf) + + tcWidthList = [proximalTCWidth, proximalTransverseTCWidth, transverseDistalTCWidth, distalTCWidth] + tcWidthAlongElementList, dTCWidthAlongElementList = interp.sampleParameterAlongLine(lengthList, + tcWidthList, + elementsCountAlong) + + # Account for reduced haustrum appearance in transverse and distal pig colon + if tcCount == 2: + haustrumOuterRadiusFactorList = [haustrumOuterRadiusFactor, haustrumOuterRadiusFactor * 0.75, + haustrumOuterRadiusFactor * 0.5, haustrumOuterRadiusFactor * 0.2] + haustrumOuterRadiusFactorAlongElementList = \ + interp.sampleParameterAlongLine(lengthList, haustrumOuterRadiusFactorList, elementsCountAlong)[0] + else: + haustrumOuterRadiusFactorAlongElementList = [haustrumOuterRadiusFactor] * (elementsCountAlong + 1) + + # Create annotation groups for colon sections + colonGroup = AnnotationGroup(region, get_colon_term("colon")) + + if tcCount == 1: + proximalGroup = AnnotationGroup(region, get_colon_term("right colon")) + transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) + distalGroup = AnnotationGroup(region, get_colon_term("left colon")) + annotationGroupAlong = [[colonGroup, proximalGroup], + [colonGroup, transverseGroup], + [colonGroup, distalGroup]] + + elif tcCount == 2: + spiralGroup = AnnotationGroup(region, get_colon_term("spiral colon")) + transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) + distalGroup = AnnotationGroup(region, get_colon_term("descending colon")) + annotationGroupAlong = [[colonGroup, spiralGroup], + [colonGroup, transverseGroup], + [colonGroup, distalGroup]] + + elif tcCount == 3: + ascendingGroup = AnnotationGroup(region, get_colon_term("ascending colon")) + transverseGroup = AnnotationGroup(region, get_colon_term("transverse colon")) + descendingGroup = AnnotationGroup(region, get_colon_term("descending colon")) + annotationGroupAlong = [[colonGroup, ascendingGroup], + [colonGroup, transverseGroup], + [colonGroup, descendingGroup]] + + annotationGroupsAlong = [] + for i in range(len(elementsCountAlongGroups)): + elementsCount = elementsCountAlongGroups[i] + for n in range(elementsCount): + annotationGroupsAlong.append(annotationGroupAlong[i]) + + xExtrude = [] + d1Extrude = [] + d2Extrude = [] + d3UnitExtrude = [] + sxRefExtrudeList = [] + + if elementsCountThroughWall == 1: + relativeThicknessList = [1.0] + annotationGroupsThroughWall = [[]] + else: + relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, + circularRelThickness, longitudinalRelThickness] + mucosaGroup = AnnotationGroup(region, get_colon_term("colonic mucosa")) + submucosaGroup = AnnotationGroup(region, get_colon_term("submucosa of colon")) + circularMuscleGroup = AnnotationGroup(region, get_colon_term("circular muscle layer of colon")) + longitudinalMuscleGroup = AnnotationGroup(region, get_colon_term("longitudinal muscle layer of colon")) + annotationGroupsThroughWall = [[mucosaGroup], [submucosaGroup], + [circularMuscleGroup], [longitudinalMuscleGroup]] + + # Create object + colonSegmentTubeMeshOuterPoints = ColonSegmentTubeMeshOuterPoints( + region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, + tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, + segmentLength, wallThickness, cornerOuterRadiusFactor, haustrumOuterRadiusFactorAlongElementList, + outerRadiusAlongElementList, dOuterRadiusAlongElementList, tcWidthAlongElementList, + startPhase) + + for nSegment in range(segmentCount): + # Create inner points + xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, annotationGroupsAround \ + = colonSegmentTubeMeshOuterPoints.getColonSegmentTubeMeshOuterPoints(nSegment) + + # Project reference point for warping onto network layout + start = nSegment * elementsCountAlongSegment + end = (nSegment + 1) * elementsCountAlongSegment + 1 + sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ + tubemesh.getPlaneProjectionOnCentralPath(xOuter, elementsCountAround, elementsCountAlongSegment, + segmentLength, sx[start:end], sd1[start:end], sd2[start:end], + sd12[start:end]) + + # Warp segment points + xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = tubemesh.warpSegmentPoints( + xOuter, d1Outer, d2Outer, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, + elementsCountAround, elementsCountAlongSegment, zRefList) + + # Store points along length + xExtrude += xWarpedList if nSegment == 0 else xWarpedList[elementsCountAround:] + d1Extrude += d1WarpedList if nSegment == 0 else d1WarpedList[elementsCountAround:] + d2Extrude += d2WarpedList if nSegment == 0 else d2WarpedList[elementsCountAround:] + d3UnitExtrude += d3WarpedUnitList if nSegment == 0 else d3WarpedUnitList[elementsCountAround:] + sxRefExtrudeList += sxRefList if nSegment == 0 else sxRefList[elementsCountAround:] + + contractedWallThicknessList = colonSegmentTubeMeshOuterPoints.getContractedWallThicknessList() + + # Create coordinates and derivatives + xList, d1List, d2List, d3List, curvatureList, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal = \ + tubemesh.extrudeSurfaceCoordinates(xExtrude, d1Extrude, d2Extrude, d3UnitExtrude, + contractedWallThicknessList, relativeThicknessList, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + transitElementList, outward=False, xProximal=xProximal, + d1Proximal=d1Proximal, d2Proximal=d2Proximal, d3Proximal=d3Proximal) + + relaxedLengthList, xiList = colonSegmentTubeMeshOuterPoints.getRelaxedLengthAndXiList() + + closedProximalEnd = False + + if tcThickness > 0: + tubeTCWidthList = colonSegmentTubeMeshOuterPoints.getTubeTCWidthList() + xList, d1List, d2List, d3List, annotationArrayAround, localIdxDistal, xDistal, d1Distal, d2Distal, \ + d3Distal = \ + getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, tcCount, elementsCountAroundTC, + elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, + tubeTCWidthList, tcThickness, annotationGroupsAround, closedProximalEnd, + isHuman, xProximal=xProximal, d1Proximal=d1Proximal, d2Proximal=d2Proximal, + d3Proximal=d3Proximal) + + # Create flat coordinates + if flatCoordinates: + xFlat, d1Flat, d2Flat = createFlatCoordinatesTeniaColi( + xiList, relaxedLengthList, length, wallThickness, relativeThicknessList, tcCount, tcThickness, + elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, + elementsCountThroughWall, transitElementList, closedProximalEnd) + else: + xFlat = d1Flat = d2Flat = [] + + # Create colon coordinates + if materialCoordinates: + xColon, d1Colon, d2Colon = \ + createColonCoordinatesTeniaColi(xiList, relativeThicknessListColonCoordinates, lengthToDiameterRatio, + wallThicknessToDiameterRatio, teniaColiThicknessToDiameterRatio, + tcCount, elementsCountAroundTC, elementsCountAroundHaustrum, + elementsCountAlong, elementsCountThroughWall, transitElementList, + closedProximalEnd) + else: + xColon = d1Colon = d2Colon = [] + + # Create nodes and elements + nextNodeIdentifier, nextElementIdentifier, annotationGroups, nodesIdDistal = createNodesAndElementsTeniaColi( + region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, xColon, d1Colon, d2Colon, + "colon coordinates", elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, + elementsCountThroughWall, tcCount, annotationGroupsAround, annotationGroupsAlong, + annotationGroupsThroughWall, nextNodeIdentifier, nextElementIdentifier, useCubicHermiteThroughWall, + useCrossDerivatives, closedProximalEnd, localIdxDistal=localIdxDistal, nodeIdProximal=nodeIdProximal) + + else: + # Create flat coordinates + xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates( + xiList, relaxedLengthList, length, wallThickness, relativeThicknessList, elementsCountAround, + elementsCountAlong, elementsCountThroughWall, transitElementList) + + # Create colon coordinates + xColon, d1Colon, d2Colon = tubemesh.createOrganCoordinates(xiList, relativeThicknessListColonCoordinates, + lengthToDiameterRatio, + wallThicknessToDiameterRatio, + elementsCountAround, + elementsCountAlong, elementsCountThroughWall, + transitElementList) + + # Create nodes and elements + nextNodeIdentifier, nextElementIdentifier, annotationGroups, nodesIdDistal = tubemesh.createNodesAndElements( + region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, xColon, d1Colon, d2Colon, + "colon coordinates", elementsCountAround, elementsCountAlong, elementsCountThroughWall, + annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, + nextNodeIdentifier, nextElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, + closedProximalEnd, localIdxDistal=localIdxDistal, nodeIdProximal=nodeIdProximal) + + return annotationGroups, nextNodeIdentifier, nextElementIdentifier, nodesIdDistal, xDistal, d1Distal, d2Distal, \ + d3Distal + +class ColonNetworkLayout: + + def __init__(self, region, networkLayout, termsAlong=[None]): + """ + :param region: Zinc region to define model in. + :param networkLayout: Network layout subscaffold from meshtype_1d_network_layout1 + :param termsAlong: Annotation terms along length of colon + """ + # Extract length of each group along colon from network layout + cxGroups = [] + cd1Groups = [] + cd2Groups = [] + cd3Groups = [] + cd12Groups = [] + cd13Groups = [] + + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + tmpFieldmodule = tmpRegion.getFieldmodule() + tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + arcLengthOfGroupsAlong = [] + + for termName in termsAlong: + tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None + tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) + + arcLength = 0.0 + for e in range(len(cxGroup) - 1): + arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], + cxGroup[e + 1], cd1Group[e + 1]) + arcLengthOfGroupsAlong.append(arcLength) + + if termName == "colon": + cxGroups.append(cxGroup) + cd1Groups.append(cd1Group) + cd2Groups.append(cd2Group) + cd3Groups.append(cd3Group) + cd12Groups.append(cd12Group) + cd13Groups.append(cd13Group) + + del tmpNodeset + del tmpGroup + + del tmpCoordinates + del tmpNodes + del tmpFieldmodule + del tmpRegion + + self.arcLengthOfGroupsAlong = arcLengthOfGroupsAlong + self.cxGroups = cxGroups + self.cd1Groups = cd1Groups + self.cd2Groups = cd2Groups + self.cd3Groups = cd3Groups + self.cd12Groups = cd12Groups + self.cd13Groups = cd13Groups diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_colonsegment1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_colonsegment1.py index 9f6b4dfa..24688dd4 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_colonsegment1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_colonsegment1.py @@ -15,6 +15,7 @@ from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, mergeAnnotationGroups, \ findOrCreateAnnotationGroupForTerm, findAnnotationGroupByName, getAnnotationGroupForTerm from scaffoldmaker.annotation.colon_terms import get_colon_term +from scaffoldmaker.annotation.cecum_terms import get_cecum_term from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.utils import interpolation as interp from scaffoldmaker.utils import matrix @@ -56,25 +57,26 @@ def getParameterSetNames(): @staticmethod def getDefaultOptions(parameterSetName='Default'): options = { + 'Base parameter set': parameterSetName, 'Number of elements around tenia coli': 2, 'Number of elements around haustrum': 8, 'Number of elements along segment': 4, 'Number of elements through wall': 4, 'Start phase': 0.0, - 'Start inner radius': 43.5, - 'Start inner radius derivative': 0.0, - 'End inner radius': 33.0, - 'End inner radius derivative': 0.0, - 'Corner inner radius factor': 0.5, - 'Haustrum inner radius factor': 0.5, + 'Start outer radius': 45.4, + 'Start outer radius derivative': 0.0, + 'End outer radius': 35.3, + 'End outer radius derivative': 0.0, + 'Corner outer radius factor': 0.536, + 'Haustrum outer radius factor': 0.464, 'Segment length end derivative factor': 0.5, 'Segment length mid derivative factor': 3.0, 'Segment length': 50.0, 'Number of tenia coli': 3, - 'Start tenia coli width': 10.0, - 'Start tenia coli width derivative': 0.0, - 'End tenia coli width': 10.0, - 'End tenia coli width derivative': 0.0, + 'Start tenia coli width': 11.1, + 'Start tenia coli width derivative': 0.4, + 'End tenia coli width': 11.5, + 'End tenia coli width derivative': 0.4, 'Tenia coli thickness': 0.6, 'Wall thickness': 1.6, 'Mucosa relative thickness': 0.18, @@ -89,30 +91,31 @@ def getDefaultOptions(parameterSetName='Default'): 'Refine number of elements through wall': 1 } if 'Cattle' in parameterSetName: - options['Start inner radius'] = 10.5 - options['End inner radius'] = 10.5 - options['Corner inner radius factor'] = 0.0 - options['Haustrum inner radius factor'] = 0.0 + options['Start outer radius'] = 13.52 + options['End outer radius'] = 13.52 + options['Corner outer radius factor'] = 0.0 + options['Haustrum outer radius factor'] = 0.0 options['Segment length end derivative factor'] = 0.0 options['Segment length mid derivative factor'] = 0.0 options['Number of tenia coli'] = 1 - options['Start tenia coli width'] = 3.0 - options['End tenia coli width'] = 3.0 + options['Start tenia coli width'] = 3.85 + options['End tenia coli width'] = 3.85 options['Tenia coli thickness'] = 0.0 options['Wall thickness'] = 3.02 elif 'Human 2' in parameterSetName: - options['Haustrum inner radius factor'] = 0.4 + options['Number of elements through wall'] = 1 + options['Haustrum outer radius factor'] = 0.364 options['Tenia coli thickness'] = 1.6 elif 'Mouse' in parameterSetName: - options['Start inner radius'] = 0.94 - options['End inner radius'] = 0.94 - options['Corner inner radius factor'] = 0.0 - options['Haustrum inner radius factor'] = 0.0 + options['Start outer radius'] = 1.49 + options['End outer radius'] = 1.49 + options['Corner outer radius factor'] = 0.0 + options['Haustrum outer radius factor'] = 0.0 options['Segment length end derivative factor'] = 0.0 options['Segment length mid derivative factor'] = 0.0 options['Number of tenia coli'] = 1 - options['Start tenia coli width'] = 0.8 - options['End tenia coli width'] = 0.8 + options['Start tenia coli width'] = 1.29 + options['End tenia coli width'] = 1.29 options['Tenia coli thickness'] = 0.0 options['Wall thickness'] = 0.55 options['Mucosa relative thickness'] = 0.4 @@ -120,16 +123,16 @@ def getDefaultOptions(parameterSetName='Default'): options['Circular muscle layer relative thickness'] = 0.3 options['Longitudinal muscle layer relative thickness'] = 0.2 elif 'Pig' in parameterSetName: - options['Start inner radius'] = 20.0 - options['End inner radius'] = 20.0 - options['Corner inner radius factor'] = 0.0 - options['Haustrum inner radius factor'] = 0.2 + options['Start outer radius'] = 22.23 + options['End outer radius'] = 22.23 + options['Corner outer radius factor'] = 0.0 + options['Haustrum outer radius factor'] = 0.17 options['Segment length end derivative factor'] = 0.8 options['Segment length mid derivative factor'] = 2.0 options['Segment length'] = 25.0 options['Number of tenia coli'] = 2 - options['Start tenia coli width'] = 5.0 - options['End tenia coli width'] = 5.0 + options['Start tenia coli width'] = 5.5 + options['End tenia coli width'] = 5.5 options['Tenia coli thickness'] = 0.5 options['Wall thickness'] = 2.0 options['Mucosa relative thickness'] = 0.34 @@ -147,12 +150,12 @@ def getOrderedOptionNames(): 'Number of elements along segment', 'Number of elements through wall', 'Start phase', - 'Start inner radius', - 'Start inner radius derivative', - 'End inner radius', - 'End inner radius derivative', - 'Corner inner radius factor', - 'Haustrum inner radius factor', + 'Start outer radius', + 'Start outer radius derivative', + 'End outer radius', + 'End outer radius derivative', + 'Corner outer radius factor', + 'Haustrum outer radius factor', 'Segment length end derivative factor', 'Segment length mid derivative factor', 'Segment length', @@ -198,9 +201,9 @@ def checkOptions(options): if options[key] % 2 > 0: options[key] = options[key] + 1 for key in [ - 'Start inner radius', - 'End inner radius', - 'Haustrum inner radius factor', + 'Start outer radius', + 'End outer radius', + 'Haustrum outer radius factor', 'Segment length end derivative factor', 'Segment length mid derivative factor', 'Segment length', @@ -212,10 +215,10 @@ def checkOptions(options): 'Longitudinal muscle layer relative thickness']: if options[key] < 0.0: options[key] = 0.0 - if options['Corner inner radius factor'] < 0.1: - options['Corner inner radius factor'] = 0.1 + if options['Corner outer radius factor'] < 0.1: + options['Corner outer radius factor'] = 0.1 for key in [ - 'Corner inner radius factor', + 'Corner outer radius factor', 'Segment length end derivative factor']: if options[key] > 1.0: options[key] = 1.0 @@ -226,12 +229,12 @@ def checkOptions(options): for key in [ 'Start tenia coli width', 'End tenia coli width']: - if options[key] < 0.2 * min(options['Start inner radius'], options['End inner radius']): - options[key] = round(0.2 * min(options['Start inner radius'], options['End inner radius']), 2) - if options['Start tenia coli width'] > round(math.sqrt(3) * 0.5 * options['Start inner radius'], 2): - options['Start tenia coli width'] = round(math.sqrt(3) * 0.5 * options['Start inner radius'], 2) - if options['End tenia coli width'] > round(math.sqrt(3) * 0.5 * options['End inner radius'], 2): - options['End tenia coli width'] = round(math.sqrt(3) * 0.5 * options['End inner radius'], 2) + if options[key] < 0.2 * min(options['Start outer radius'], options['End outer radius']): + options[key] = round(0.2 * min(options['Start outer radius'], options['End outer radius']), 2) + if options['Start tenia coli width'] > round(math.sqrt(3) * 0.5 * options['Start outer radius'], 2): + options['Start tenia coli width'] = round(math.sqrt(3) * 0.5 * options['Start outer radius'], 2) + if options['End tenia coli width'] > round(math.sqrt(3) * 0.5 * options['End outer radius'], 2): + options['End tenia coli width'] = round(math.sqrt(3) * 0.5 * options['End outer radius'], 2) @classmethod def generateBaseMesh(cls, region, options): @@ -241,17 +244,19 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ + parameterSetName = options['Base parameter set'] + isHuman = 'Human' in parameterSetName elementsCountAroundTC = options['Number of elements around tenia coli'] elementsCountAroundHaustrum = options['Number of elements around haustrum'] elementsCountAlongSegment = options['Number of elements along segment'] elementsCountThroughWall = options['Number of elements through wall'] startPhase = options['Start phase'] % 360.0 - startRadius = options['Start inner radius'] - startRadiusDerivative = options['Start inner radius derivative'] - endRadius = options['End inner radius'] - endRadiusDerivative = options['End inner radius derivative'] - cornerInnerRadiusFactor = options['Corner inner radius factor'] - haustrumInnerRadiusFactor = options['Haustrum inner radius factor'] + startRadius = options['Start outer radius'] + startRadiusDerivative = options['Start outer radius derivative'] + endRadius = options['End outer radius'] + endRadiusDerivative = options['End outer radius derivative'] + cornerOuterRadiusFactor = options['Corner outer radius factor'] + haustrumOuterRadiusFactor = options['Haustrum outer radius factor'] segmentLengthEndDerivativeFactor = options['Segment length end derivative factor'] segmentLengthMidDerivativeFactor = options['Segment length mid derivative factor'] segmentLength = options['Segment length'] @@ -272,13 +277,13 @@ def generateBaseMesh(cls, region, options): firstNodeIdentifier = 1 firstElementIdentifier = 1 - # Central path + # Network layout cx = [[0.0, 0.0, 0.0], [segmentLength, 0.0, 0.0]] cd1 = [[segmentLength, 0.0, 0.0], [segmentLength, 0.0, 0.0]] cd2 = [[0.0, 1.0, 0.0], [0.0, 1.0, 0.0]] cd12 = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] - # Sample central path + # Sample network layout sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlongSegment) sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) @@ -299,12 +304,12 @@ def generateBaseMesh(cls, region, options): [endTCWidth], [endTCWidthDerivative], xi)[0] tcWidthAlongSegment.append(tcWidth) - haustrumInnerRadiusFactorAlongSegment = [haustrumInnerRadiusFactor] * (elementsCountAlongSegment + 1) + haustrumOuterRadiusFactorAlongSegment = [haustrumOuterRadiusFactor] * (elementsCountAlongSegment + 1) - colonSegmentTubeMeshInnerPoints = ColonSegmentTubeMeshInnerPoints( + colonSegmentTubeMeshOuterPoints = ColonSegmentTubeMeshOuterPoints( region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, - segmentLength, wallThickness, cornerInnerRadiusFactor, haustrumInnerRadiusFactorAlongSegment, + segmentLength, wallThickness, cornerOuterRadiusFactor, haustrumOuterRadiusFactorAlongSegment, radiusAlongSegment, dRadiusAlongSegment, tcWidthAlongSegment, startPhase) # Create annotation @@ -313,24 +318,24 @@ def generateBaseMesh(cls, region, options): for i in range(elementsCountAlongSegment): annotationGroupsAlong.append([colonGroup]) - # Create inner points + # Create outer points nSegment = 0 closedProximalEnd = False - xInner, d1Inner, d2Inner, transitElementList, segmentAxis, annotationGroupsAround = \ - colonSegmentTubeMeshInnerPoints.getColonSegmentTubeMeshInnerPoints(nSegment) + xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, annotationGroupsAround = \ + colonSegmentTubeMeshOuterPoints.getColonSegmentTubeMeshOuterPoints(nSegment) - # Project reference point for warping onto central path + # Project reference point for warping onto network layout sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ - tubemesh.getPlaneProjectionOnCentralPath(xInner, elementsCountAround, elementsCountAlongSegment, + tubemesh.getPlaneProjectionOnCentralPath(xOuter, elementsCountAround, elementsCountAlongSegment, segmentLength, sx, sd1, sd2, sd12) # Warp segment points xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = tubemesh.warpSegmentPoints( - xInner, d1Inner, d2Inner, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, + xOuter, d1Outer, d2Outer, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, elementsCountAround, elementsCountAlongSegment, zRefList) - contractedWallThicknessList = colonSegmentTubeMeshInnerPoints.getContractedWallThicknessList() + contractedWallThicknessList = colonSegmentTubeMeshOuterPoints.getContractedWallThicknessList() if elementsCountThroughWall == 1: relativeThicknessList = [1.0] @@ -350,18 +355,18 @@ def generateBaseMesh(cls, region, options): tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList, contractedWallThicknessList, relativeThicknessList, elementsCountAround, elementsCountAlongSegment, elementsCountThroughWall, transitElementList, - outward=True) + outward=False)[0:5] xColonSegment = d1ColonSegment = d2ColonSegment = [] - relaxedLengthList, xiList = colonSegmentTubeMeshInnerPoints.getRelaxedLengthAndXiList() + relaxedLengthList, xiList = colonSegmentTubeMeshOuterPoints.getRelaxedLengthAndXiList() if tcThickness > 0: - tubeTCWidthList = colonSegmentTubeMeshInnerPoints.getTubeTCWidthList() + tubeTCWidthList = colonSegmentTubeMeshOuterPoints.getTubeTCWidthList() xList, d1List, d2List, d3List, annotationGroupsAround = getTeniaColi( region, xList, d1List, d2List, d3List, curvatureList, tcCount, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, elementsCountThroughWall, - tubeTCWidthList, tcThickness, sxRefList, annotationGroupsAround, closedProximalEnd) + tubeTCWidthList, tcThickness, annotationGroupsAround, closedProximalEnd, isHuman)[0:5] # Create flat coordinates xFlat, d1Flat, d2Flat = createFlatCoordinatesTeniaColi( @@ -375,7 +380,7 @@ def generateBaseMesh(cls, region, options): d2ColonSegment, None, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, elementsCountThroughWall, tcCount, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd) + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd)[0:3] else: # Create flat coordinates xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates( @@ -388,7 +393,7 @@ def generateBaseMesh(cls, region, options): d2ColonSegment, None, elementsCountAround, elementsCountAlongSegment, elementsCountThroughWall, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, - closedProximalEnd) + closedProximalEnd)[0:3] return annotationGroups, None @@ -435,16 +440,16 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): mucosaInnerSurface.getMeshGroup(mesh2d).addElementsConditional(is_mucosaInnerSurface) -class ColonSegmentTubeMeshInnerPoints: +class ColonSegmentTubeMeshOuterPoints: """ - Generates inner profile of a colon segment for use by tubemesh. + Generates outer profile of a colon segment for use by tubemesh. """ def __init__(self, region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, segmentLength, wallThickness, - cornerInnerRadiusFactor, haustrumInnerRadiusFactorAlongElementList, innerRadiusAlongElementList, - dInnerRadiusAlongElementList, tcWidthAlongElementList, startPhase): + cornerOuterRadiusFactor, haustrumOuterRadiusFactorAlongElementList, outerRadiusAlongElementList, + dOuterRadiusAlongElementList, tcWidthAlongElementList, startPhase): self._region = region self._elementsCountAroundTC = elementsCountAroundTC self._elementsCountAroundHaustrum = elementsCountAroundHaustrum @@ -454,10 +459,10 @@ def __init__(self, region, elementsCountAroundTC, elementsCountAroundHaustrum, self._segmentLengthMidDerivativeFactor = segmentLengthMidDerivativeFactor self._segmentLength = segmentLength self._wallThickness = wallThickness - self._cornerInnerRadiusFactor = cornerInnerRadiusFactor - self._haustrumInnerRadiusFactorAlongElementList = haustrumInnerRadiusFactorAlongElementList - self._innerRadiusAlongElementList = innerRadiusAlongElementList - self._dInnerRadiusAlongElementList = dInnerRadiusAlongElementList + self._cornerOuterRadiusFactor = cornerOuterRadiusFactor + self._haustrumOuterRadiusFactorAlongElementList = haustrumOuterRadiusFactorAlongElementList + self._outerRadiusAlongElementList = outerRadiusAlongElementList + self._dOuterRadiusAlongElementList = dOuterRadiusAlongElementList self._tcWidthAlongElementList = tcWidthAlongElementList self._tubeTCWidthList = [] self._xiList = [] @@ -465,27 +470,27 @@ def __init__(self, region, elementsCountAroundTC, elementsCountAroundHaustrum, self._contractedWallThicknessList = [] self._startPhase = startPhase - def getColonSegmentTubeMeshInnerPoints(self, nSegment): + def getColonSegmentTubeMeshOuterPoints(self, nSegment): # Unpack parameter variation along elements - radiusSegmentList = self._innerRadiusAlongElementList[nSegment * self._elementsCountAlongSegment: + radiusSegmentList = self._outerRadiusAlongElementList[nSegment * self._elementsCountAlongSegment: (nSegment + 1) * self._elementsCountAlongSegment + 1] - dRadiusSegmentList = self._dInnerRadiusAlongElementList[nSegment * self._elementsCountAlongSegment: + dRadiusSegmentList = self._dOuterRadiusAlongElementList[nSegment * self._elementsCountAlongSegment: (nSegment + 1) * self._elementsCountAlongSegment + 1] tcWidthSegmentList = self._tcWidthAlongElementList[nSegment * self._elementsCountAlongSegment: (nSegment + 1) * self._elementsCountAlongSegment + 1] - haustrumInnerRadiusFactorSegmentList = self._haustrumInnerRadiusFactorAlongElementList[ + haustrumOuterRadiusFactorSegmentList = self._haustrumOuterRadiusFactorAlongElementList[ nSegment * self._elementsCountAlongSegment: (nSegment + 1) * self._elementsCountAlongSegment + 1] - xInner, d1Inner, d2Inner, transitElementList, xiSegment, relaxedLengthSegment, contractedWallThicknessSegment, \ + xOuter, d1Outer, d2Outer, transitElementList, xiSegment, relaxedLengthSegment, contractedWallThicknessSegment, \ segmentAxis, annotationGroupsAround = \ - getColonSegmentInnerPoints(self._region, + getColonSegmentOuterPoints(self._region, self._elementsCountAroundTC, self._elementsCountAroundHaustrum, self._elementsCountAlongSegment, self._tcCount, self._segmentLengthEndDerivativeFactor, self._segmentLengthMidDerivativeFactor, self._segmentLength, self._wallThickness, - self._cornerInnerRadiusFactor, haustrumInnerRadiusFactorSegmentList, + self._cornerOuterRadiusFactor, haustrumOuterRadiusFactorSegmentList, radiusSegmentList, dRadiusSegmentList, tcWidthSegmentList, self._startPhase) @@ -502,7 +507,7 @@ def getColonSegmentTubeMeshInnerPoints(self, nSegment): contractedWallThickness = contractedWallThicknessSegment[startIdx:self._elementsCountAlongSegment + 1] self._contractedWallThicknessList += contractedWallThickness - return xInner, d1Inner, d2Inner, transitElementList, segmentAxis, annotationGroupsAround + return xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, annotationGroupsAround def getTubeTCWidthList(self): return self._tubeTCWidthList @@ -514,14 +519,14 @@ def getContractedWallThicknessList(self): return self._contractedWallThicknessList -def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, +def getColonSegmentOuterPoints(region, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlongSegment, tcCount, segmentLengthEndDerivativeFactor, segmentLengthMidDerivativeFactor, - segmentLength, wallThickness, cornerInnerRadiusFactor, - haustrumInnerRadiusFactorSegmentList, radiusSegmentList, dRadiusSegmentList, + segmentLength, wallThickness, cornerOuterRadiusFactor, + haustrumOuterRadiusFactorSegmentList, radiusSegmentList, dRadiusSegmentList, tcWidthSegmentList, startPhase): """ Generates a 3-D colon segment mesh with variable numbers of tenia coli, - numbers of elements around, along the central path, and through wall. + numbers of elements around, along the network layout, and through wall. Colon segment with one "tenia coli" (mouse) has a circular profile along its length. Colon segment with two tenia coli (pig) has a circular profile at the inter-haustral septa, and a bowtie profile in the intra-haustral @@ -538,22 +543,22 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun length to scale derivative along the mid length of the segment. :param segmentLength: Length of a colon segment. :param wallThickness: Thickness of wall. - :param cornerInnerRadiusFactor: Roundness of triangular corners of - inter-haustral septa. Factor is multiplied by inner radius + :param cornerOuterRadiusFactor: Roundness of triangular corners of + inter-haustral septa. Factor is multiplied by outer radius to get a radius of curvature at the corners. Only applicable for three tenia coli. Set to zero for two tenia coli. - :param haustrumInnerRadiusFactorSegmentList: Factor is multiplied by inner + :param haustrumOuterRadiusFactorSegmentList: Factor is multiplied by inner radius to obtain radius of intersecting circles in the middle cross-section along a haustra segment. :param radiusSegmentList: List of inner radius defined from center of triangular profile to vertex of the triangle at proximal end of the colon segment for each element along. - :param dRadiusSegmentList: List of rate of change of inner radius at proximal end + :param dRadiusSegmentList: List of rate of change of outer radius at proximal end for each element along. :param tcWidthSegmentList: List of tenia coli width at proximal end of the colon segment for each element along. :param startPhase: Phase at start. - :return coordinates, derivatives on inner surface of a colon segment. + :return coordinates, derivatives on outer surface of a colon segment. :return transitElementList: stores true if element around is an element that transits from tenia coli / mesenteric zone to haustrum / non-mesenteric zone. :return xiList: List of xi for each node around. xi refers to node position @@ -579,8 +584,8 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun d2HalfSet = [] d2Raw = [] - xInnerRaw = [] - dx_ds2InnerRaw = [] + xOuterRaw = [] + dx_ds2OuterRaw = [] xFinal = [] d1Final = [] d2Final = [] @@ -599,7 +604,7 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun xHalfSet, d1HalfSet = \ createHalfSetInterHaustralSegment(elementsCountAroundTC, elementsCountAroundHaustrum, tcCount, tcWidth, - radius, cornerInnerRadiusFactor, sampleElementOut) + radius, cornerOuterRadiusFactor, sampleElementOut) for i in range(len(xHalfSet)): d2HalfSet.append([0.0, 0.0, 0.0]) @@ -610,8 +615,7 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun for n1 in range(elementsCountAroundTC + elementsCountAroundHaustrum): xFinal.append([x[n1][0], x[n1][1], z]) xFace.append([x[n1][0], x[n1][1], z]) - xiFace, lengthAroundFace = getXiListFromOuterLengthProfile(xFace, d1, segmentAxis, - wallThickness, transitElementList) + xiFace, lengthAroundFace = getXiListFromOuterLengthProfile(xFace, d1) xiList.append(xiFace) relaxedLengthList.append(lengthAroundFace) contractedWallThicknessList.append(wallThickness) @@ -657,13 +661,13 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun radius = radiusSegmentList[n2] sdRadius = dRadiusSegmentList[n2] tcWidth = tcWidthSegmentList[n2] - haustrumInnerRadiusFactor = haustrumInnerRadiusFactorSegmentList[n2] + haustrumOuterRadiusFactor = haustrumOuterRadiusFactorSegmentList[n2] # Create segment of inner radius # Calculate x and d1 at the start, mid, and end faces xHalfSetStart, d1HalfSetStart = createHalfSetInterHaustralSegment( elementsCountAroundTC, elementsCountAroundHaustrum, tcCount, tcWidth, radius, - cornerInnerRadiusFactor, sampleElementOut) + cornerOuterRadiusFactor, sampleElementOut) if startPhase == 0.0: if n2 == 0: @@ -677,7 +681,7 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun xHalfSetMid, d1HalfSetMid = createHalfSetIntraHaustralSegment( elementsCountAroundTC, elementsCountAroundHaustrum, tcCount, tcWidth, radius, - cornerInnerRadiusFactor, sampleElementOut, haustrumInnerRadiusFactor) + cornerOuterRadiusFactor, sampleElementOut, haustrumOuterRadiusFactor) d1AtStartOfEachMidFace.append(d1HalfSetMid[0]) @@ -759,8 +763,8 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun xResampled, d1Resampled, se, sxi, _ = interp.sampleCubicHermiteCurves(xForSamplingAlong, d1ForSamplingAlong, elementsCountAlongSegment, arcLengthDerivatives=True) - xInnerRaw.append(xResampled) - dx_ds2InnerRaw.append(d1Resampled) + xOuterRaw.append(xResampled) + dx_ds2OuterRaw.append(d1Resampled) # Re-arrange sample order & calculate dx_ds1 and dx_ds3 from dx_ds2 for n2 in range(elementsCountAlongSegment + 1): @@ -770,26 +774,26 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun d2Around = [] for n1 in range(elementsCountAroundHalfHaustrum + 1): - x = xInnerRaw[n1][n2] + x = xOuterRaw[n1][n2] # Bring first face back to origin x = [x[0], x[1], x[2] - lengthToFirstPhase] - dx_ds2 = dx_ds2InnerRaw[n1][n2] + dx_ds2 = dx_ds2OuterRaw[n1][n2] xAround.append(x) d2Around.append(dx_ds2) - dx_ds1InnerAroundList = [] + dx_ds1OuterAroundList = [] if startPhase == 0.0 and n2 == 0: d1Corrected = d1Phase0FirstFace elif startPhase == 0.0 and elementsCountAlongSegment % 2 == 0 and \ n2 == int(elementsCountAlongSegment * 0.5): - dx_ds1InnerAroundList = dx_ds1InnerAroundList + d1Phase0MidFace + dx_ds1OuterAroundList = dx_ds1OuterAroundList + d1Phase0MidFace elif startPhase == 0.0 and n2 > elementsCountAlongSegment - 1: d1Corrected = d1Phase0LastFace elif startPhase == 180.0 and n2 == 0: - dx_ds1InnerAroundList = dx_ds1InnerAroundList + d1180FirstFace + dx_ds1OuterAroundList = dx_ds1OuterAroundList + d1180FirstFace elif startPhase == 180.0 and n2 > elementsCountAlongSegment - 1: - dx_ds1InnerAroundList = dx_ds1InnerAroundList + d1180LastFace + dx_ds1OuterAroundList = dx_ds1OuterAroundList + d1180LastFace elif startPhase == 180.0 and elementsCountAlongSegment % 2 == 0 and \ n2 == int(elementsCountAlongSegment * 0.5): d1Corrected = d1180MidFace @@ -802,15 +806,15 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun d2 = [v2[c] - v1[c] for c in range(3)] arcLengthAround = interp.computeCubicHermiteArcLength(v1, d1, v2, d2, True) dx_ds1 = [c * arcLengthAround for c in vector.normalise(d1)] - dx_ds1InnerAroundList.append(dx_ds1) + dx_ds1OuterAroundList.append(dx_ds1) # Account for d1 of node sitting on half haustrum d1 = vector.normalise([xAround[elementsCountAroundHalfHaustrum][c] - xAround[elementsCountAroundHalfHaustrum - 1][c] for c in range(3)]) dx_ds1 = [c * arcLengthAround for c in d1] - dx_ds1InnerAroundList.append(dx_ds1) + dx_ds1OuterAroundList.append(dx_ds1) - if dx_ds1InnerAroundList: - d1Smoothed = interp.smoothCubicHermiteDerivativesLine(xAround, dx_ds1InnerAroundList, + if dx_ds1OuterAroundList: + d1Smoothed = interp.smoothCubicHermiteDerivativesLine(xAround, dx_ds1OuterAroundList, fixStartDerivative=True) d1TCEdge = vector.setMagnitude(d1Smoothed[int(elementsCountAroundTC * 0.5)], vector.magnitude(d1Smoothed[int(elementsCountAroundTC * 0.5 - 1)])) @@ -829,16 +833,14 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun xHalfSetRelaxed, d1HalfSetRelaxed = \ createHalfSetIntraHaustralSegment(elementsCountAroundTC, elementsCountAroundHaustrum, tcCount, tcWidthSegmentList[n2], radiusSegmentList[n2], - cornerInnerRadiusFactor, sampleElementOut, haustrumInnerRadiusFactor) + cornerOuterRadiusFactor, sampleElementOut, haustrumOuterRadiusFactor) xRelaxed, d1Relaxed, _ = getFullProfileFromHalfHaustrum(xHalfSetRelaxed, d1HalfSetRelaxed, d2Around, tcCount) - xiFace, relaxedLengthAroundFace = getXiListFromOuterLengthProfile(xRelaxed, d1Relaxed, segmentAxis, - wallThickness, transitElementList) + xiFace, relaxedLengthAroundFace = getXiListFromOuterLengthProfile(xRelaxed, d1Relaxed) xiList.append(xiFace) relaxedLengthList.append(relaxedLengthAroundFace) - contractedLengthAroundFace = getXiListFromOuterLengthProfile(xAlongList, d1AlongList, segmentAxis, - wallThickness, transitElementList)[1] + contractedLengthAroundFace = getXiListFromOuterLengthProfile(xAlongList, d1AlongList)[1] contractedWallThickness = relaxedLengthAroundFace * wallThickness / contractedLengthAroundFace contractedWallThicknessList.append(contractedWallThickness) @@ -856,7 +858,7 @@ def getColonSegmentInnerPoints(region, elementsCountAroundTC, elementsCountAroun def createHalfSetInterHaustralSegment(elementsCountAroundTC, elementsCountAroundHaustrum, - tcCount, tcWidth, radius, cornerInnerRadiusFactor, sampleElementOut): + tcCount, tcWidth, radius, cornerOuterRadiusFactor, sampleElementOut): """ Find locations and derivative of nodes in half of an inter-haustral segment. Circular profile for segment @@ -866,10 +868,10 @@ def createHalfSetInterHaustralSegment(elementsCountAroundTC, elementsCountAround :param elementsCountAroundHaustrum: Number of elements around haustrum. :param tcCount: Number of tenia coli. :param tcWidth: Width of tenia coli. - :param radius: Inner radius of circular profile with two tenia coli, + :param radius: Outer radius of circular profile with two tenia coli, radius of circle enclosing triangle for profile with three tenia coli. - :param cornerInnerRadiusFactor: Roundness of triangular corners of - inter-haustral septa. Factor is multiplied by inner radius + :param cornerOuterRadiusFactor: Roundness of triangular corners of + inter-haustral septa. Factor is multiplied by outer radius to get a radius of curvature at the corners. Only applicable for three tenia coli. Set to zero for two tenia coli. :param sampleElementOut: Number of sample points used to set up profile @@ -887,7 +889,7 @@ def createHalfSetInterHaustralSegment(elementsCountAroundTC, elementsCountAround sampleElementOut, startRadians=0.0) else: # tcCount == 3, Triangular profile - cornerRC = cornerInnerRadiusFactor * radius + cornerRC = cornerOuterRadiusFactor * radius radiansRangeRC = [7 * math.pi / 4, 0.0, math.pi / 4] for n1 in range(3): @@ -936,8 +938,8 @@ def createHalfSetInterHaustralSegment(elementsCountAroundTC, elementsCountAround def createHalfSetIntraHaustralSegment(elementsCountAroundTC, elementsCountAroundHaustrum, - tcCount, tcWidth, radius, cornerInnerRadiusFactor, sampleElementOut, - haustrumInnerRadiusFactor): + tcCount, tcWidth, radius, cornerOuterRadiusFactor, sampleElementOut, + haustrumOuterRadiusFactor): """ Find locations and derivative of nodes in half of an intra-haustral segment. Bow-tie profile for segment with two tenia coli and @@ -946,15 +948,15 @@ def createHalfSetIntraHaustralSegment(elementsCountAroundTC, elementsCountAround :param elementsCountAroundHaustrum: Number of elements around haustrum. :param tcCount: Number of tenia coli. :param tcWidth: Width of tenia coli. - :param radius: Inner radius of circular inter-haustral profile with two + :param radius: Outer radius of circular inter-haustral profile with two tenia coli, radius of circle enclosing triangle for inter-haustral profile with three tenia coli. - :param cornerInnerRadiusFactor: Roundness of triangular corners of - inter-haustral septa. Factor is multiplied by inner radius + :param cornerOuterRadiusFactor: Roundness of triangular corners of + inter-haustral septa. Factor is multiplied by outer radius to get a radius of curvature at the corners. Only applicable for three tenia coli. Set to zero for two tenia coli. :param sampleElementOut: Number of sample points used to set up profile - :param haustrumInnerRadiusFactor: Factor is multiplied by inner + :param haustrumOuterRadiusFactor: Factor is multiplied by outer radius to obtain radius of intersecting circles in the middle cross-section along a haustra segment. :return: Node location and derivative on half of a haustrum segment. @@ -966,8 +968,8 @@ def createHalfSetIntraHaustralSegment(elementsCountAroundTC, elementsCountAround d1HalfSetIntraHaustra = [] # Set up profile - cornerRC = cornerInnerRadiusFactor * radius - haustrumRadius = (haustrumInnerRadiusFactor + 1) * radius + cornerRC = cornerOuterRadiusFactor * radius + haustrumRadius = (haustrumOuterRadiusFactor + 1) * radius if tcCount == 2: # Bow-tie profile originRC = (radius * radius - haustrumRadius * haustrumRadius) / (-2.0 * haustrumRadius) RC = haustrumRadius - originRC @@ -1252,13 +1254,12 @@ def getFullProfileFromHalfHaustrum(xHaustrumHalfSet, d1HaustrumHalfSet, return xHaustra, d1Haustra, d2Haustra -def getXiListFromOuterLengthProfile(xInner, d1Inner, segmentAxis, - wallThickness, transitElementList): +def getXiListFromOuterLengthProfile(xOuter, d1Outer): """ Gets a list of xi for flat coordinates calculated from outer arclength of elements around a segment (most relaxed state). - :param xInner: Coordinates of points on inner surface around segment. - :param d1Inner: Derivatives of points on inner surface around segment. + :param xOuter: Coordinates of points on outer surface around segment. + :param d1Outer: Derivatives of points on outer surface around segment. :param segmentAxis: Axis of segment. :param wallThickness: Thickness of wall. :param transitElementList: stores true if element around is an element that @@ -1267,37 +1268,6 @@ def getXiListFromOuterLengthProfile(xInner, d1Inner, segmentAxis, wall thickness from inner points. :return totalArcLengthOuter: Total arclength around outer surface of elements. """ - unitNormList = [] - xOuter = [] - curvatureInner = [] - d1Outer = [] - - for n in range(len(xInner)): - unitNormList.append(vector.normalise(vector.crossproduct3(d1Inner[n], segmentAxis))) - - for n in range(len(xInner)): - norm = unitNormList[n] - # Calculate outer coordinates - x = [xInner[n][i] + norm[i] * wallThickness for i in range(3)] - xOuter.append(x) - # Calculate curvature along elements around - prevIdx = n - 1 if (n != 0) else len(xInner) - 1 - nextIdx = n + 1 if (n < (len(xInner) - 1)) else 0 - kappam = interp.getCubicHermiteCurvatureSimple(xInner[prevIdx], d1Inner[prevIdx], xInner[n], d1Inner[n], 1.0)[0] - kappap = interp.getCubicHermiteCurvatureSimple(xInner[n], d1Inner[n], xInner[nextIdx], d1Inner[nextIdx], 0.0)[0] - curvatureAround = 0.0 - if not transitElementList[n] and not transitElementList[(n - 1) % (len(xInner))]: - curvatureAround = 0.5 * (kappam + kappap) - elif transitElementList[n]: - curvatureAround = kappam - elif transitElementList[(n - 1) % (len(xInner))]: - curvatureAround = kappap - curvatureInner.append(curvatureAround) - - for n in range(len(xOuter)): - factor = 1.0 + wallThickness * curvatureInner[n] - dx_ds1 = [factor * c for c in d1Inner[n]] - d1Outer.append(dx_ds1) arcLengthList = [] for n1 in range(len(xOuter)): @@ -1324,7 +1294,8 @@ def getXiListFromOuterLengthProfile(xInner, d1Inner, segmentAxis, def getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, tcCount, elementsCountAroundTC, elementsCountAroundHaustrum, elementsCountAlong, elementsCountThroughWall, - tubeTCWidthList, tcThickness, sx, annotationGroupsAround, closedProximalEnd): + tubeTCWidthList, tcThickness, annotationGroupsAround, closedProximalEnd, isHuman, + xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[]): """ Create equally spaced points for tenia coli over the outer surface of the colon. Points are sampled from a cubic @@ -1346,11 +1317,13 @@ def getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, :param elementsCountThroughWall: Number of elements through wall. :param tubeTCWidthList: List of tenia coli width along tube length. :param tcThickness: Thickness of tenia coli at its thickest part. - :param sx: Coordinates of central path. :param annotationGroupsAround: annotation groups for elements around tube. :param closedProximalEnd: True when proximal end of tube is closed. - :return: coordinates, derivatives, annotationGroupsAround for colon with tenia - coli. + :param isHuman: True if making scaffold for human. + :param xProximal, d1Proximal, d2Proximal, d3Proximal: Optional for passing coordinates and derivatives of points on + proximal end of colon segment. + :return: coordinates, derivatives, annotationGroupsAround for colon with tenia coli and local index, coordinates and + derivatives for nodes around distal end of colon. """ elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum) * tcCount @@ -1409,11 +1382,10 @@ def getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, d3TCRaw.append(d3) d3List[xTCInnerSet[n]] = d3 - innerIdx = xTCInnerSet[n] - elementsCountThroughWall * elementsCountAround - curvature = curvatureList[innerIdx] - distanceToInnerIdx = vector.magnitude([xTCOuter[i] - xList[innerIdx][i] for i in range(3)]) + curvature = curvatureList[xTCInnerSet[n]] + distanceToInnerIdx = vector.magnitude([xTCOuter[i] - xTCInner[i] for i in range(3)]) factor = 1.0 - curvature * distanceToInnerIdx - d2 = [factor * c for c in d2List[innerIdx]] + d2 = [factor * c for c in d2List[xTCInnerSet[n]]] d2TCRaw.append(d2) xTCArranged = xTCArranged + xTCRaw[int(elementsCountAroundTC * 0.5 - 1):] + \ @@ -1425,17 +1397,19 @@ def getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, d3TCArranged = d3TCArranged + d3TCRaw[int(elementsCountAroundTC * 0.5 - 1):] + \ d3TCRaw[:int(elementsCountAroundTC * 0.5 - 1)] - x, d1, d2, d3 = combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTCArranged, d1TCArranged, - d2TCArranged, d3TCArranged, (elementsCountAroundTC - 1) * tcCount, elementsCountAround, - elementsCountAlong, elementsCountThroughWall, closedProximalEnd) + x, d1, d2, d3, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal = \ + combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTCArranged, d1TCArranged, + d2TCArranged, d3TCArranged, (elementsCountAroundTC - 1) * tcCount, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, closedProximalEnd, + xProximal, d1Proximal, d2Proximal, d3Proximal) # Update annotation groups - if tcCount == 2 or closedProximalEnd: + if tcCount == 2 or not isHuman: tcGroup = AnnotationGroup(region, get_colon_term("taenia coli")) for i in range(elementsCountAroundTC * tcCount): annotationGroupsAround.append([tcGroup]) - elif tcCount == 3: + elif tcCount == 3 and isHuman: tlGroup = AnnotationGroup(region, get_colon_term("taenia libera")) tmGroup = AnnotationGroup(region, get_colon_term("taenia mesocolica")) toGroup = AnnotationGroup(region, get_colon_term("taenia omentalis")) @@ -1448,16 +1422,15 @@ def getTeniaColi(region, xList, d1List, d2List, d3List, curvatureList, for n in range(elementsCount): annotationGroupsAround.append(annotationGroupAround[i]) - return x, d1, d2, d3, annotationGroupsAround + return x, d1, d2, d3, annotationGroupsAround, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal -def combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTC, d1TC, d2TC, - d3TC, nodesCountAroundTC, elementsCountAround, elementsCountAlong, - elementsCountThroughWall, closedProximalEnd): +def combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTC, d1TC, d2TC, d3TC, nodesCountAroundTC, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, closedProximalEnd, + xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[]): """ - Arranges coordinates and derivatives around inner surface to - outer surface, followed by tenia coli points before extending - along length of colon. + Arranges coordinates and derivatives around inner surface to outer surface, followed by tenia coli points before + extending along length of colon. :param xList, d1List, d2List, d3List: coordinates and derivatives of colon. :param xTC, d1TC, d2TC, d3TC: coordinates and derivatives of tenia coli. :param nodesCountAroundTC: Number of nodes around tenia coli. @@ -1465,22 +1438,37 @@ def combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTC, d1TC, d2TC, :param elementsCountAlong: Number of elements along colon. :param elementsCountThroughWall: Number of elements through wall. :param closedProximalEnd: True when proximal end of tube is closed. - : return: reordered coordinates and derivatives + :param xProximal, d1Proximal, d2Proximal, d3Proximal: Optional for passing coordinates and derivatives of points on + proximal end of colon segment. + :return: reordered coordinates and derivatives and local index, coordinates and derivatives of nodes on distal end. """ x = [] d1 = [] d2 = [] d3 = [] + count = 0 + localIdxDistal = [] + xDistal = [] + d1Distal = [] + d2Distal = [] + d3Distal = [] # Add tenia coli points to coordinates list for n2 in range(elementsCountAlong + 1): for n3 in range(elementsCountThroughWall + 1): + xDistalAround = [] + d1DistalAround = [] + d2DistalAround = [] + d3DistalAround = [] + localIdxDistalAround = [] + if closedProximalEnd and n2 == 0: x.append(xList[n3]) d1.append(d1List[n3]) d2.append(d2List[n3]) if d3List: d3.append(d3List[n3]) + count += 1 else: for n1 in range(elementsCountAround): # Append colon wall coordinates from inside to outside wall @@ -1489,23 +1477,61 @@ def combineTeniaColiWithColon(xList, d1List, d2List, d3List, xTC, d1TC, d2TC, n3 * elementsCountAround + n1 if closedProximalEnd \ else n2 * elementsCountAround * (elementsCountThroughWall + 1) + n3 * elementsCountAround + n1 - x.append(xList[n]) - d1.append(d1List[n]) - d2.append(d2List[n]) - if d3List: - d3.append(d3List[n]) + if xProximal and n2 == 0 and not closedProximalEnd: + x.append(xProximal[n3][n1]) + d1.append(d1Proximal[n3][n1]) + d2.append(d2Proximal[n3][n1]) + if d3List: + d3.append(d3Proximal[n3][n1]) + else: + x.append(xList[n]) + d1.append(d1List[n]) + d2.append(d2List[n]) + if d3List: + d3.append(d3List[n]) + + if n2 == elementsCountAlong: + localIdxDistalAround.append(count) + xDistalAround.append(xList[n]) + d1DistalAround.append(d1List[n]) + d2DistalAround.append(d2List[n]) + if d3List: + d3DistalAround.append(d3List[n]) + count += 1 + + if n2 == elementsCountAlong: + xDistal.append(xDistalAround) + d1Distal.append(d1DistalAround) + d2Distal.append(d2DistalAround) + d3Distal.append(d3DistalAround) + localIdxDistal.append(localIdxDistalAround) # Append tenia coli coordinates if not (closedProximalEnd and n2 == 0): for nTC in range(nodesCountAroundTC): - nTCCount = (n2 - 1 if closedProximalEnd else n2) * nodesCountAroundTC + nTC - x.append(xTC[nTCCount]) - d1.append(d1TC[nTCCount]) - d2.append(d2TC[nTCCount]) - if d3TC: - d3.append(d3TC[nTCCount]) - - return x, d1, d2, d3 + if xProximal and n2 == 0: + x.append(xProximal[-1][elementsCountAround + nTC]) + d1.append(d1Proximal[-1][elementsCountAround + nTC]) + d2.append(d2Proximal[-1][elementsCountAround + nTC]) + if d3List: + d3.append(d3Proximal[-1][elementsCountAround + nTC]) + else: + nTCCount = (n2 - 1 if closedProximalEnd else n2) * nodesCountAroundTC + nTC + x.append(xTC[nTCCount]) + d1.append(d1TC[nTCCount]) + d2.append(d2TC[nTCCount]) + if d3TC: + d3.append(d3TC[nTCCount]) + if n2 == elementsCountAlong: + localIdxDistal[-1].append(count) + xDistal[-1].append(xTC[nTCCount]) + d1Distal[-1].append(d1TC[nTCCount]) + d2Distal[-1].append(d2TC[nTCCount]) + if d3TC: + d3Distal[-1].append(d3TC[nTCCount]) + count += 1 + + return x, d1, d2, d3, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal def createFlatCoordinatesTeniaColi(xiList, relaxedLengthList, @@ -1599,11 +1625,11 @@ def createFlatCoordinatesTeniaColi(xiList, relaxedLengthList, d2FlatListTC.append(d2Flat) d2FlatListTC = d2FlatListTC + d2FlatListTC[-((elementsCountAroundTC - 1) * tcCount + 1):] - xFlat, d1Flat, d2Flat, _ = combineTeniaColiWithColon(xFlatColon, d1FlatColon, d2FlatColon, [], + xFlat, d1Flat, d2Flat = combineTeniaColiWithColon(xFlatColon, d1FlatColon, d2FlatColon, [], xFlatListTC, d1FlatListTC, d2FlatListTC, [], (elementsCountAroundTC - 1) * tcCount + 1, elementsCountAround + 1, elementsCountAlong, - elementsCountThroughWall, closedProximalEnd) + elementsCountThroughWall, closedProximalEnd)[0:3] return xFlat, d1Flat, d2Flat @@ -1674,10 +1700,10 @@ def createColonCoordinatesTeniaColi(xiList, relativeThicknessList, lengthToDiame d2TC = [d2 for n in range(len(xTC))] - xColon, d1Colon, d2Colon, _ = combineTeniaColiWithColon(xColon, d1Colon, d2Colon, [], xTC, d1TC, d2TC, [], + xColon, d1Colon, d2Colon = combineTeniaColiWithColon(xColon, d1Colon, d2Colon, [], xTC, d1TC, d2TC, [], (elementsCountAroundTC - 1) * tcCount, elementsCountAround, elementsCountAlong, - elementsCountThroughWall, closedProximalEnd) + elementsCountThroughWall, closedProximalEnd)[0:3] return xColon, d1Colon, d2Colon @@ -1690,7 +1716,8 @@ def createNodesAndElementsTeniaColi(region, elementsCountAlong, elementsCountThroughWall, tcCount, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd): + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd, + localIdxDistal=[], nodeIdProximal=[]): """ Create nodes and elements for the coordinates and flat coordinates fields. Note that flat coordinates not implemented for closedProximalEnd yet. @@ -1712,15 +1739,23 @@ def createNodesAndElementsTeniaColi(region, :param useCubicHermiteThroughWall: use linear when false. :param useCrossDerivatives: use cross derivatives when true. :param closedProximalEnd: True when proximal end of tube is closed. - :return nodeIdentifier, elementIdentifier, allAnnotationGroups + :param localIdxDistal: Local identifiers derived for distal nodes of the tube. + :param nodeIdProximal: Node identifiers to use as proximal end of tube. + :return nodeIdentifier, elementIdentifier, allAnnotationGroups, nodes on distal end of scaffold. """ nodeIdentifier = firstNodeIdentifier elementIdentifier = firstElementIdentifier elementsCountAround = (elementsCountAroundTC + elementsCountAroundHaustrum) * tcCount + startNode = firstNodeIdentifier # Create coordinates field zero = [0.0, 0.0, 0.0] + nodesDistal = [] + + for i in range(len(localIdxDistal)): + nodesDistal.append([firstNodeIdentifier + c for c in localIdxDistal[i]]) + fm = region.getFieldmodule() fm.beginChange() cache = fm.createFieldcache() @@ -1840,7 +1875,22 @@ def createNodesAndElementsTeniaColi(region, organElementtemplate2.defineField(organCoordinates, -1, eftOrgan2) # create nodes for coordinates field - for n in range(len(x)): + if nodeIdProximal: + proximalNodesOffset = 0 + for m in range(len(nodeIdProximal)): + proximalNodesOffset += len(nodeIdProximal[m]) + # proximalNodesOffset = len(nodeIdProximal) * len(nodeIdProximal[0]) + nodeList = [] + newNodeList = [] + + if nodeIdProximal: + for n3 in range(len(nodeIdProximal)): + for n1 in range(len(nodeIdProximal[n3])): + nodeList.append(nodeIdentifier) + newNodeList.append(nodeIdProximal[n3][n1]) + nodeIdentifier = nodeIdentifier + 1 + + for n in range(proximalNodesOffset if nodeIdProximal else 0, len(x)): node = nodes.createNode(nodeIdentifier, nodetemplate) cache.setNode(node) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, x[n]) @@ -1852,7 +1902,6 @@ def createNodesAndElementsTeniaColi(region, coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS1DS3, 1, zero) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D2_DS2DS3, 1, zero) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D3_DS1DS2DS3, 1, zero) - # print('NodeIdentifier = ', nodeIdentifier, x[n], d1[n], d2[n]) nodeIdentifier = nodeIdentifier + 1 # Create nodes for flat coordinates field @@ -1924,10 +1973,13 @@ def createNodesAndElementsTeniaColi(region, allAnnotationGroups = [] for group in annotationGroupsThroughWall: - longitudinalMuscle = findAnnotationGroupByName(group, "longitudinal muscle layer of colon") + longitudinalMuscle = findAnnotationGroupByName(group, ("longitudinal muscle layer of cecum" if closedProximalEnd + else "longitudinal muscle layer of colon")) if longitudinalMuscle: - longitudinalMuscleGroup = AnnotationGroup(region, get_colon_term("longitudinal muscle layer of colon")) + longitudinalMuscleGroup = \ + AnnotationGroup(region, (get_cecum_term("longitudinal muscle layer of cecum") if closedProximalEnd + else get_colon_term("longitudinal muscle layer of colon"))) if closedProximalEnd: elementtemplate3 = mesh.createElementtemplate() @@ -1955,6 +2007,7 @@ def createNodesAndElementsTeniaColi(region, bni2 = elementsCountThroughWall + 1 + elementsCountAround * e3 + e1 + 1 bni3 = elementsCountThroughWall + 1 + elementsCountAround * e3 + (e1 + 1) % elementsCountAround + 1 nodeIdentifiers = [bni1, bni2, bni3, bni1 + 1, bni2 + elementsCountAround, bni3 + elementsCountAround] + nodeIdentifiers = [c + startNode - 1 for c in nodeIdentifiers] element.setNodesByIdentifier(eft3, nodeIdentifiers) # set general linear map coefficients radiansAround = e1 * radiansPerElementAround @@ -1987,7 +2040,7 @@ def createNodesAndElementsTeniaColi(region, math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround] - bni21 = elementsCountThroughWall + 1 + bni21 = elementsCountThroughWall + 1 + startNode - 1 bni22 = bni21 + elementsCountAround * elementsCountThroughWall + 1 + eTC bni23 = bni22 + 1 bni31 = bni22 + elementsCountAround @@ -2028,7 +2081,7 @@ def createNodesAndElementsTeniaColi(region, math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround] - bni21 = elementsCountThroughWall + 1 + bni21 = elementsCountThroughWall + 1 + startNode - 1 bni22 = bni21 + elementsCountAround * elementsCountThroughWall + int(elementsCountAroundTC * 0.5) + \ elementsCountAroundHaustrum + N * (elementsCountAroundTC + elementsCountAroundHaustrum) + \ eTC + 1 @@ -2081,7 +2134,7 @@ def createNodesAndElementsTeniaColi(region, math.sin(radiansAround), math.cos(radiansAround), radiansPerElementAround, math.sin(radiansAroundNext), math.cos(radiansAroundNext), radiansPerElementAround] - bni21 = elementsCountThroughWall + 1 + bni21 = elementsCountThroughWall + 1 + startNode - 1 bni22 = bni21 + elementsCountAround * (elementsCountThroughWall + 1) - \ int(elementsCountAroundTC * 0.5) + eTC + 1 if elementsCountAroundTC > 2: @@ -2143,6 +2196,12 @@ def createNodesAndElementsTeniaColi(region, bni22 = e2 * now + (e3 + 1) * elementsCountAround + (e1 + 1) % elementsCountAround + 1 + tcOffset1 nodeIdentifiers = [bni11, bni12, bni11 + now + tcOffset, bni12 + now + tcOffset, bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset] + nodeIdentifiers = [c + startNode - 1 for c in nodeIdentifiers] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] onOpening = e1 > elementsCountAround - 2 element = mesh.createElement(elementIdentifier, elementtemplate) element.setNodesByIdentifier(eft, nodeIdentifiers) @@ -2182,6 +2241,14 @@ def createNodesAndElementsTeniaColi(region, else: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni31, bni31 + now + tcOffset] + + nodeIdentifiers = [c + startNode - 1 for c in nodeIdentifiers] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] + element = \ mesh.createElement(elementIdentifier, elementtemplate if eTC < int(elementsCountAroundTC * 0.5) - 1 else elementtemplate1) @@ -2211,29 +2278,34 @@ def createNodesAndElementsTeniaColi(region, bni21 = elementsCountThroughWall + 1 + ( e2 - 1) * now + elementsCountThroughWall * elementsCountAround \ + eTC + 1 + tcOffset1 + int(elementsCountAroundTC * 0.5) + \ - (N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + (N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + startNode - 1 bni22 = elementsCountThroughWall + 1 + ( e2 - 1) * now + elementsCountThroughWall * elementsCountAround + \ eTC + 2 + tcOffset1 + int(elementsCountAroundTC * 0.5) + \ - (N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + (N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + startNode - 1 bni31 = elementsCountThroughWall + 1 + e2 * now + eTC + 1 + tcOffset1 + \ - int(elementsCountAroundTC * 0.5) - 1 + N * (elementsCountAroundTC - 1) + int(elementsCountAroundTC * 0.5) - 1 + N * (elementsCountAroundTC - 1) + startNode - 1 bni32 = elementsCountThroughWall + 1 + e2 * now + eTC + 2 + tcOffset1 + \ - int(elementsCountAroundTC * 0.5) - 1 + N * (elementsCountAroundTC - 1) + int(elementsCountAroundTC * 0.5) - 1 + N * (elementsCountAroundTC - 1) + startNode - 1 else: bni21 = e2 * now + elementsCountThroughWall * elementsCountAround + eTC + 1 + tcOffset1 + \ int(elementsCountAroundTC * 0.5) + ( - N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + N + 1) * elementsCountAroundHaustrum + N * elementsCountAroundTC + startNode - 1 bni22 = e2 * now + elementsCountThroughWall * elementsCountAround + eTC + 2 + tcOffset1 + \ int(elementsCountAroundTC * 0.5) + (N + 1) * elementsCountAroundHaustrum + \ - N * elementsCountAroundTC + N * elementsCountAroundTC + startNode - 1 bni31 = (e2 + 1) * now + eTC + 1 + tcOffset1 + int(elementsCountAroundTC * 0.5) - 1 + \ - N * (elementsCountAroundTC - 1) + N * (elementsCountAroundTC - 1) + startNode - 1 bni32 = (e2 + 1) * now + eTC + 2 + tcOffset1 + int(elementsCountAroundTC * 0.5) - 1 + \ - N * (elementsCountAroundTC - 1) + N * (elementsCountAroundTC - 1) + startNode - 1 if eTC == 0: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni32, bni32 + now + tcOffset] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] element = mesh.createElement(elementIdentifier, elementtemplate2) element.setNodesByIdentifier(eft2, nodeIdentifiers) if xFlat: @@ -2245,6 +2317,11 @@ def createNodesAndElementsTeniaColi(region, elif 0 < eTC < elementsCountAroundTC - 1: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni31, bni32, bni31 + now + tcOffset, bni32 + now + tcOffset] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] element = mesh.createElement(elementIdentifier, elementtemplate) element.setNodesByIdentifier(eft, nodeIdentifiers) if xFlat: @@ -2256,6 +2333,11 @@ def createNodesAndElementsTeniaColi(region, else: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni31, bni31 + now + tcOffset] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] element = mesh.createElement(elementIdentifier, elementtemplate1) element.setNodesByIdentifier(eft1, nodeIdentifiers) if xFlat: @@ -2280,30 +2362,37 @@ def createNodesAndElementsTeniaColi(region, bni21 = elementsCountThroughWall + 1 + (e2 - 1) * now + \ elementsCountThroughWall * elementsCountAround + eTC + 1 + tcOffset1 + \ int(elementsCountAroundTC * 0.5) + tcCount * elementsCountAroundHaustrum + \ - (tcCount - 1) * elementsCountAroundTC - bni22 = elementsCountThroughWall + 1 + (e2 - 1) * now + \ + (tcCount - 1) * elementsCountAroundTC + startNode - 1 + bni22 = + startNode - 1 + elementsCountThroughWall + 1 + (e2 - 1) * now + \ elementsCountThroughWall * elementsCountAround + 1 + \ tcOffset1 if eTC == int(elementsCountAroundTC * 0.5 - 1) else bni21 + 1 bni31 = elementsCountThroughWall + 1 + e2 * now + eTC + 1 + tcOffset1 + \ - int(elementsCountAroundTC * 0.5) - 1 + (tcCount - 1) * (elementsCountAroundTC - 1) - bni32 = elementsCountThroughWall + 1 + e2 * now + 1 + tcOffset1 if eTC == int( + int(elementsCountAroundTC * 0.5) - 1 + (tcCount - 1) * (elementsCountAroundTC - 1) + startNode - 1 + bni32 = startNode - 1 + elementsCountThroughWall + 1 + e2 * now + 1 + tcOffset1 if eTC == int( elementsCountAroundTC * 0.5 - 1) \ else bni31 + 1 else: bni21 = e2 * now + elementsCountThroughWall * elementsCountAround + eTC + 1 + tcOffset1 + \ int(elementsCountAroundTC * 0.5) + tcCount * elementsCountAroundHaustrum + \ - (tcCount - 1) * elementsCountAroundTC - bni22 = e2 * now + elementsCountThroughWall * elementsCountAround + 1 + tcOffset1 if eTC == int( + (tcCount - 1) * elementsCountAroundTC + startNode - 1 + bni22 = e2 * now + elementsCountThroughWall * elementsCountAround + 1 + tcOffset1 + startNode - 1 if eTC == int( elementsCountAroundTC * 0.5 - 1) else bni21 + 1 bni31 = (e2 + 1) * now + eTC + 1 + tcOffset1 + int(elementsCountAroundTC * 0.5) - 1 + \ - (tcCount - 1) * (elementsCountAroundTC - 1) - bni32 = (e2 + 1) * now + 1 + tcOffset1 if eTC == int(elementsCountAroundTC * 0.5 - 1) else bni31 + 1 + (tcCount - 1) * (elementsCountAroundTC - 1) + startNode - 1 + bni32 = (e2 + 1) * now + 1 + tcOffset1 + startNode - 1 if eTC == int(elementsCountAroundTC * 0.5 - 1) else bni31 + 1 if eTC > 0: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni31, bni32, bni31 + now + tcOffset, bni32 + now + tcOffset] else: nodeIdentifiers = [bni21, bni22, bni21 + now + tcOffset, bni22 + now + tcOffset, bni32, bni32 + now + tcOffset] + + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] + onOpening = (eTC == int(elementsCountAroundTC * 0.5 - 1)) element = mesh.createElement(elementIdentifier, elementtemplate if eTC > 0 else elementtemplate2) element.setNodesByIdentifier(eft if eTC > 0 else eft2, nodeIdentifiers) @@ -2329,4 +2418,4 @@ def createNodesAndElementsTeniaColi(region, fm.endChange() - return nodeIdentifier, elementIdentifier, allAnnotationGroups + return nodeIdentifier, elementIdentifier, allAnnotationGroups, nodesDistal diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_esophagus1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_esophagus1.py index 8efa4373..d25b3ec6 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_esophagus1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_esophagus1.py @@ -6,6 +6,7 @@ import copy import math + from cmlibs.utils.zinc.field import findOrCreateFieldGroup, findOrCreateFieldStoredString, \ findOrCreateFieldStoredMeshLocation from cmlibs.zinc.element import Element @@ -14,42 +15,41 @@ from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, getAnnotationGroupForTerm, \ findOrCreateAnnotationGroupForTerm from scaffoldmaker.annotation.esophagus_terms import get_esophagus_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.scaffoldpackage import ScaffoldPackage from scaffoldmaker.utils import geometry from scaffoldmaker.utils import interpolation as interp from scaffoldmaker.utils import tubemesh from scaffoldmaker.utils import vector -from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ +from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters,\ get_nodeset_path_field_parameters - -class MeshType_3d_esophagus1(Scaffold_base): - """ - Generates a 3-D esophagus mesh with variable numbers of elements around, along the central line, and through wall. - The esophagus is created by a function that generates an elliptical tube segment and uses tubemesh to map the - segment along a central path profile. - """ - - centralPathDefaultScaffoldPackages = { - 'Human 1': ScaffoldPackage(MeshType_1d_path1, { +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 4 - }, + "Structure": "1-2-3-4-5" + }, 'meshEdits': exnode_string_from_nodeset_field_parameters( - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ -0.42, -100.50, 1401.88 ], [ 0.74, 14.22, -46.12 ], [ 7.85, -0.56, -0.05 ], [ 0.69, 0.03, 0.02 ], [ -0.22, -2.98, -0.92 ], [ 0.19, 1.51, 0.43 ] ] ), - (2, [ [ 0.52, -84.95, 1340.25 ], [ 1.15, 16.87, -77.08 ], [ 7.08, -0.66, -0.04 ], [ -0.25, -0.13, 0.05 ], [ -0.19, -2.04, -0.45 ], [ -0.03, 0.34, 0.51 ] ] ), - (3, [ [ 1.85, -67.80, 1247.93 ], [ -0.05, -4.17, -89.62 ], [ 6.13, -0.92, 0.04 ], [ -0.56, 0.20, 0.44 ], [ -0.38, -2.56, 0.12 ], [ 0.00, 0.08, 0.61 ] ] ), - (4, [ [ 0.55, -90.99, 1166.45 ], [ 6.95, -24.56, -60.26 ], [ 4.15, 1.65, -0.20 ], [ -1.22, 1.08, 1.18 ], [ 0.88, -2.09, 0.95 ], [ -0.02, 0.46, 0.61 ] ] ), - (5, [ [ 9.34, -111.30, 1127.62 ], [ 3.74, -1.54, -6.85 ], [ 1.93, 1.69, 0.67 ], [ -2.29, 1.59, 1.62 ], [ 1.32, -1.98, 1.17 ], [ -0.24, 0.29, 0.57 ] ] )] ), + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, + Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.394, -100.872, 1402.818], [-0.035, 12.367, -48.020], [8.730, -0.526, -0.142], [0.613, -0.153, -0.037], [-0.272, -4.224, -1.088], [-0.169, -1.491, -0.564]]), + (2, [[0.520, -86.043, 1340.066], [0.501, 16.682, -77.602], [9.142, -0.799, -0.113], [0.212, -0.392, 0.096], [-0.465, -5.159, -1.112], [-0.215, -0.377, 0.515]]), + (3, [[1.368, -67.733, 1247.932], [0.235, -3.685, -89.672], [9.061, -1.366, 0.080], [-0.833, -0.231, 0.187], [-0.714, -4.722, 0.192], [-0.167, 0.445, 1.659]]), + (4, [[0.361, -91.057, 1165.531], [-2.499, -24.560, -49.102], [7.540, -1.290, 0.261], [-0.809, 1.514, 2.095], [-0.806, -4.269, 2.176], [0.001, 0.896, 0.910]]), + (5, [[11.750, -111.874, 1127.887], [7.636, -5.715, -7.930], [5.678, 1.265, 4.556], [-8.397, 13.092, 24.878], [-0.708, -3.530, 1.862], [-0.807, -7.995, 7.596]]) + ]), 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-4', + 'name': get_esophagus_term('esophagus')[0], + 'ontId': get_esophagus_term('esophagus')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -71,8 +71,15 @@ class MeshType_3d_esophagus1(Scaffold_base): 'name': get_esophagus_term('abdominal part of esophagus')[0], 'ontId': get_esophagus_term('abdominal part of esophagus')[1] }] - }) - } + }) + + +class MeshType_3d_esophagus1(Scaffold_base): + """ + Generates a 3-D esophagus mesh with variable numbers of elements around, along the central line, and through wall. + The esophagus is created by a function that generates an elliptical tube segment and uses tubemesh to map the + segment along a network layout profile. + """ @staticmethod def getName(): @@ -86,13 +93,12 @@ def getParameterSetNames(): @classmethod def getDefaultOptions(cls, parameterSetName='Default'): - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 1'] options = { - 'Central path': copy.deepcopy(centralPathOption), + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), 'Number of elements around': 8, 'Number of elements along': 20, - 'Number of elements through wall': 4, - 'Wall thickness': 3.2, + 'Number of elements through wall': 1, + 'Wall thickness': 1.2, 'Mucosa relative thickness': 0.35, 'Submucosa relative thickness': 0.15, 'Circular muscle layer relative thickness': 0.25, @@ -109,7 +115,7 @@ def getDefaultOptions(cls, parameterSetName='Default'): @staticmethod def getOrderedOptionNames(): return [ - 'Central path', + 'Network layout', 'Number of elements around', 'Number of elements along', 'Number of elements through wall', @@ -127,14 +133,14 @@ def getOrderedOptionNames(): @classmethod def getOptionValidScaffoldTypes(cls, optionName): - if optionName == 'Central path': - return [MeshType_1d_path1] + if optionName == 'Network layout': + return [MeshType_1d_network_layout1] return [] @classmethod def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): - if optionName == 'Central path': - return list(cls.centralPathDefaultScaffoldPackages.keys()) + if optionName == 'Network layout': + return cls.getParameterSetNames() assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() @@ -150,16 +156,16 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() - if optionName == 'Central path': + if optionName == 'Network layout': if not parameterSetName: - parameterSetName = list(cls.centralPathDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.centralPathDefaultScaffoldPackages[parameterSetName]) + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' @classmethod def checkOptions(cls, options): - if not options['Central path'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Central path'): - options['Central path'] = cls.getOptionScaffoldPackage('Central path', MeshType_1d_path1) + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) if options['Number of elements through wall'] != (1 or 4): options['Number of elements through wall'] = 4 for key in [ @@ -182,323 +188,16 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ - centralPath = options['Central path'] - elementsCountAround = options['Number of elements around'] - elementsCountAlong = options['Number of elements along'] - elementsCountThroughWall = options['Number of elements through wall'] - wallThickness = options['Wall thickness'] - mucosaRelThickness = options['Mucosa relative thickness'] - submucosaRelThickness = options['Submucosa relative thickness'] - circularRelThickness = options['Circular muscle layer relative thickness'] - longitudinalRelThickness = options['Longitudinal muscle layer relative thickness'] - useCrossDerivatives = options['Use cross derivatives'] - useCubicHermiteThroughWall = not(options['Use linear through wall']) - - # Esophagus coordinates - lengthToDiameterRatio = 15 - wallThicknessToDiameterRatio = 0.15 - relativeThicknessListEsoCoordinates = [1.0 / elementsCountThroughWall for n3 in range(elementsCountThroughWall)] - - firstNodeIdentifier = 1 - firstElementIdentifier = 1 - - # Central path - tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) - tmpFieldmodule = tmpRegion.getFieldmodule() - tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') - esophagusTermsAlong =\ - [None, 'cervical part of esophagus', 'thoracic part of esophagus', 'abdominal part of esophagus'] - arcLengthOfGroupsAlong = [] - - for termName in esophagusTermsAlong: - tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None - tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes - - cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( - tmpNodeset, tmpCoordinates, - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, - Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, - Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) - arcLength = 0.0 - for e in range(len(cxGroup) - 1): - arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], - cxGroup[e + 1], cd1Group[e + 1]) - arcLengthOfGroupsAlong.append(arcLength) - - if not termName: - cx = cxGroup - cd1 = cd1Group - cd2 = cd2Group - cd3 = cd3Group - cd12 = cd12Group - cd13 = cd13Group - - del tmpNodeset - del tmpGroup - - del tmpCoordinates - del tmpNodes - del tmpFieldmodule - del tmpRegion + nextNodeIdentifier = 1 + nextElementIdentifier = 1 + esophagusTermsAlong = ['esophagus', 'cervical part of esophagus', 'thoracic part of esophagus', + 'abdominal part of esophagus'] + geometricNetworkLayout = options['Network layout'] + geometricNetworkLayout = EsophagusNetworkLayout(region, geometricNetworkLayout, esophagusTermsAlong) - # Sample central path - sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlong) - sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) - sd3, sd13 = interp.interpolateSampleCubicHermite(cd3, cd13, se, sxi, ssf) - - centralPathLength = arcLengthOfGroupsAlong[0] - elementAlongLength = centralPathLength / elementsCountAlong - - elementsCountAlongGroups = [] - groupLength = 0.0 - e = 0 - elementsCount = 1 - length = elementAlongLength - for i in range(1, len(esophagusTermsAlong)): - groupLength += arcLengthOfGroupsAlong[i] - if e == elementsCountAlong - 2: - elementsCount += 1 - elementsCountAlongGroups.append(elementsCount) - else: - while length < groupLength: - elementsCount += 1 - e += 1 - length += elementAlongLength - - # check which end is grouplength closer to - distToUpperEnd = abs(length - groupLength) - distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) - if distToLowerEnd < distToUpperEnd: - elementsCount -= 1 - elementsCountAlongGroups.append(elementsCount) - e -= 1 - length -= elementAlongLength - else: - elementsCountAlongGroups.append(elementsCount) - elementsCount = 0 - - majorRadiusElementList = sd2 - minorRadiusElementList = sd3 - - # Create annotation groups along esophagus - esophagusGroup = AnnotationGroup(region, get_esophagus_term("esophagus")) - cervicalGroup = AnnotationGroup(region, get_esophagus_term("cervical part of esophagus")) - thoracicGroup = AnnotationGroup(region, get_esophagus_term("thoracic part of esophagus")) - abdominalGroup = AnnotationGroup(region, get_esophagus_term("abdominal part of esophagus")) - - annotationGroupAlong = [[esophagusGroup, cervicalGroup], - [esophagusGroup, thoracicGroup], - [esophagusGroup, abdominalGroup]] - - annotationGroupsAlong = [] - for i in range(len(elementsCountAlongGroups)): - elementsCount = elementsCountAlongGroups[i] - for n in range(elementsCount): - annotationGroupsAlong.append(annotationGroupAlong[i]) - - annotationGroupsAround = [] - for i in range(elementsCountAround): - annotationGroupsAround.append([]) - - # Groups through wall - longitudinalMuscleGroup = AnnotationGroup(region, - get_esophagus_term("esophagus smooth muscle longitudinal layer")) - circularMuscleGroup = AnnotationGroup(region, get_esophagus_term("esophagus smooth muscle circular layer")) - submucosaGroup = AnnotationGroup(region, get_esophagus_term("submucosa of esophagus")) - mucosaGroup = AnnotationGroup(region, get_esophagus_term("esophagus mucosa")) - - if elementsCountThroughWall == 1: - relativeThicknessList = [1.0] - annotationGroupsThroughWall = [[]] - else: - relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, - circularRelThickness, longitudinalRelThickness] - annotationGroupsThroughWall = [[mucosaGroup], - [submucosaGroup], - [circularMuscleGroup], - [longitudinalMuscleGroup]] - - xToSample = [] - d1ToSample = [] - for n2 in range(elementsCountAlong + 1): - # Create inner points - cx = [0.0, 0.0, elementAlongLength * n2] - axis1 = [vector.magnitude(majorRadiusElementList[n2]), 0.0, 0.0] - axis2 = [0.0, vector.magnitude(minorRadiusElementList[n2]), 0.0] - xInner, d1Inner = geometry.createEllipsePoints(cx, 2 * math.pi, axis1, axis2, - elementsCountAround, startRadians=0.0) - xToSample += xInner - d1ToSample += d1Inner - - d2ToSample = [[0.0, 0.0, elementAlongLength]] * (elementsCountAround * (elementsCountAlong+1)) - - # Sample along length - xInnerRaw = [] - d2InnerRaw = [] - xToWarp = [] - d1ToWarp = [] - d2ToWarp = [] - flatWidthList = [] - xiList = [] - - for n1 in range(elementsCountAround): - xForSamplingAlong = [] - d2ForSamplingAlong = [] - for n2 in range(elementsCountAlong + 1): - idx = n2 * elementsCountAround + n1 - xForSamplingAlong.append(xToSample[idx]) - d2ForSamplingAlong.append(d2ToSample[idx]) - xSampled, d2Sampled = interp.sampleCubicHermiteCurves(xForSamplingAlong, d2ForSamplingAlong, - elementsCountAlong, arcLengthDerivatives=True)[0:2] - xInnerRaw.append(xSampled) - d2InnerRaw.append(d2Sampled) - - # Re-arrange sample order & calculate dx_ds1 and dx_ds3 from dx_ds2 - for n2 in range(elementsCountAlong + 1): - xAround = [] - d2Around = [] - - for n1 in range(elementsCountAround): - x = xInnerRaw[n1][n2] - d2 = d2InnerRaw[n1][n2] - xAround.append(x) - d2Around.append(d2) - - d1Around = [] - for n1 in range(elementsCountAround): - v1 = xAround[n1] - v2 = xAround[(n1 + 1) % elementsCountAround] - d1 = d2 = [v2[c] - v1[c] for c in range(3)] - arcLengthAround = interp.computeCubicHermiteArcLength(v1, d1, v2, d2, True) - dx_ds1 = [c * arcLengthAround for c in vector.normalise(d1)] - d1Around.append(dx_ds1) - d1Smoothed = interp.smoothCubicHermiteDerivativesLoop(xAround, d1Around) - - xToWarp += xAround - d1ToWarp += d1Smoothed - d2ToWarp += d2Around - - # Flat width and xi - flatWidth = 0.0 - xiFace = [] - for n1 in range(elementsCountAround): - v1 = xAround[n1] - d1 = d1Smoothed[n1] - v2 = xAround[(n1 + 1) % elementsCountAround] - d2 = d1Smoothed[(n1 + 1) % elementsCountAround] - flatWidth += interp.getCubicHermiteArcLength(v1, d1, v2, d2) - flatWidthList.append(flatWidth) - - for n1 in range(elementsCountAround + 1): - xi = 1.0 / elementsCountAround * n1 - xiFace.append(xi) - xiList.append(xiFace) - - # Project reference point for warping onto central path - sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ - tubemesh.getPlaneProjectionOnCentralPath(xToWarp, elementsCountAround, elementsCountAlong, - centralPathLength, sx, sd1, sd2, sd12) - - # Warp points - segmentAxis = [0.0, 0.0, 1.0] - closedProximalEnd = False - - innerRadiusAlong = [] - for n2 in range(elementsCountAlong + 1): - firstNodeAlong = xToWarp[n2 * elementsCountAround] - midptSegmentAxis = [0.0, 0.0, elementAlongLength * n2] - radius = vector.magnitude(firstNodeAlong[c] - midptSegmentAxis[c] for c in range(3)) - innerRadiusAlong.append(radius) - - xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = \ - tubemesh.warpSegmentPoints(xToWarp, d1ToWarp, d2ToWarp, segmentAxis, sxRefList, sd1RefList, - sd2ProjectedListRef, elementsCountAround, elementsCountAlong, - zRefList) - - # Create coordinates and derivatives - transitElementList = [0]*elementsCountAround - xList, d1List, d2List, d3List, curvatureList = \ - tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList, - [wallThickness]*(elementsCountAlong+1), relativeThicknessList, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, - transitElementList, outward=True) - - # Create flat coordinates - xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates(xiList, flatWidthList, length, wallThickness, - relativeThicknessList, elementsCountAround, - elementsCountAlong, elementsCountThroughWall, - transitElementList) - - # Create colon coordinates - xEso, d1Eso, d2Eso = \ - tubemesh.createOrganCoordinates(xiList, relativeThicknessListEsoCoordinates, lengthToDiameterRatio, - wallThicknessToDiameterRatio, elementsCountAround, elementsCountAlong, - elementsCountThroughWall, transitElementList) - - # Create nodes and elements - nodeIdentifier, elementIdentifier, annotationGroups = \ - tubemesh.createNodesAndElements(region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, - xEso, d1Eso, d2Eso, "esophagus coordinates", elementsCountAround, - elementsCountAlong, elementsCountThroughWall, annotationGroupsAround, - annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd) - - # annotation fiducial points - fm = region.getFieldmodule() - fm.beginChange() - mesh = fm.findMeshByDimension(3) - cache = fm.createFieldcache() - - markerGroup = findOrCreateFieldGroup(fm, "marker") - markerName = findOrCreateFieldStoredString(fm, name="marker_name") - markerLocation = findOrCreateFieldStoredMeshLocation(fm, mesh, name="marker_location") - - nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - markerPoints = markerGroup.getOrCreateNodesetGroup(nodes) - markerTemplateInternal = nodes.createNodetemplate() - markerTemplateInternal.defineField(markerName) - markerTemplateInternal.defineField(markerLocation) - - markerNames = ["proximodorsal midpoint on serosa of upper esophageal sphincter", - "proximoventral midpoint on serosa of upper esophageal sphincter", - "distal point of lower esophageal sphincter serosa on the greater curvature of stomach", - "distal point of lower esophageal sphincter serosa on the lesser curvature of stomach"] - - totalElements = elementIdentifier - radPerElementAround = math.pi * 2.0 / elementsCountAround - elementAroundHalfPi = int(0.25 * elementsCountAround) - xi1HalfPi = (math.pi * 0.5 - radPerElementAround * elementAroundHalfPi)/radPerElementAround - elementAroundPi = int(0.5 * elementsCountAround) - xi1Pi = (math.pi - radPerElementAround * elementAroundPi)/radPerElementAround - - markerElementIdentifiers = [elementsCountAround * elementsCountThroughWall - elementAroundHalfPi, - elementAroundHalfPi + 1 + elementsCountAround * (elementsCountThroughWall - 1), - totalElements - elementsCountAround, - totalElements - elementsCountAround + elementAroundPi] - - markerXis = [[1.0 - xi1HalfPi, 0.0, 1.0], - [xi1HalfPi, 0.0, 1.0], - [0.0, 1.0, 1.0], - [xi1Pi, 1.0, 1.0]] - - for n in range(len(markerNames)): - markerGroup = findOrCreateAnnotationGroupForTerm(annotationGroups, region, - get_esophagus_term(markerNames[n])) - markerElement = mesh.findElementByIdentifier(markerElementIdentifiers[n]) - markerXi = markerXis[n] - cache.setMeshLocation(markerElement, markerXi) - markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal) - nodeIdentifier += 1 - cache.setNode(markerPoint) - markerName.assignString(cache, markerGroup.getName()) - markerLocation.assignMeshLocation(cache, markerElement, markerXi) - for group in [esophagusGroup, markerGroup]: - group.getNodesetGroup(nodes).addNode(markerPoint) - - fm.endChange() + annotationGroups, nextNodeIdentifier, nextElementIdentifier = \ + createEsophagusMesh3d(region, options, geometricNetworkLayout, nextNodeIdentifier, nextElementIdentifier, + flatCoordinates=True, materialCoordinates=True)[:3] return annotationGroups, None @@ -543,3 +242,374 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): mucosaInnerSurface = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_esophagus_term("luminal surface of esophagus")) mucosaInnerSurface.getMeshGroup(mesh2d).addElementsConditional(is_mucosaInnerSurface) + +def createEsophagusMesh3d(region, options, networkLayout, nextNodeIdentifier, nextElementIdentifier, + flatCoordinates=False, materialCoordinates=False): + """ + Generates an esophagus scaffold in the region using a network layout and parameter options. + :param region: Region to create elements in. + :param options: Parameter options for esophagus scaffold. + :param networkLayout: Network layout describing path of the esophagus. + :param nextNodeIdentifier: Next node identifier to use. + :param nextElementIdentifier: Next element identifier to use. + :param flatCoordinates: Create flat coordinates if True. + :param materialCoordinates: Create material coordinates if True. + :return annotationGroups, nodeIdentifier, elementIdentifier, nodeIdDistal, xDistal, d1Distal, d2Distal, d3Distal + """ + elementsCountAround = options['Number of elements around'] + elementsCountAlong = options['Number of elements along'] + elementsCountThroughWall = options['Number of elements through wall'] + wallThickness = options['Wall thickness'] + mucosaRelThickness = options['Mucosa relative thickness'] + submucosaRelThickness = options['Submucosa relative thickness'] + circularRelThickness = options['Circular muscle layer relative thickness'] + longitudinalRelThickness = options['Longitudinal muscle layer relative thickness'] + useCrossDerivatives = options['Use cross derivatives'] + useCubicHermiteThroughWall = not(options['Use linear through wall']) + + # Esophagus coordinates + lengthToDiameterRatio = 15 + wallThicknessToDiameterRatio = 0.15 + relativeThicknessListEsoCoordinates = [1.0 / elementsCountThroughWall for n3 in range(elementsCountThroughWall)] + + esophagusTermsAlong =\ + ['esophagus', 'cervical part of esophagus', 'thoracic part of esophagus', 'abdominal part of esophagus'] + + networkLayoutLength = networkLayout.arcLengthOfGroupsAlong[0] + cx = networkLayout.cxGroups[0] + cd1 = networkLayout.cd1Groups[0] + cd2 = networkLayout.cd2Groups[0] + cd12 = networkLayout.cd12Groups[0] + cd3 = networkLayout.cd3Groups[0] + cd13 = networkLayout.cd13Groups[0] + arcLengthOfGroupsAlong = networkLayout.arcLengthOfGroupsAlong + + # Sample network layout + sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlong) + sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) + sd3, sd13 = interp.interpolateSampleCubicHermite(cd3, cd13, se, sxi, ssf) + + elementAlongLength = networkLayoutLength / elementsCountAlong + + elementsCountAlongGroups = [] + groupLength = 0.0 + e = 0 + elementsCount = 1 + length = elementAlongLength + for i in range(1, len(esophagusTermsAlong)): + groupLength += arcLengthOfGroupsAlong[i] + if e == elementsCountAlong - 2: + elementsCount += 1 + elementsCountAlongGroups.append(elementsCount) + else: + while length < groupLength: + elementsCount += 1 + e += 1 + length += elementAlongLength + + # check which end is grouplength closer to + distToUpperEnd = abs(length - groupLength) + distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) + if distToLowerEnd < distToUpperEnd: + elementsCount -= 1 + elementsCountAlongGroups.append(elementsCount) + e -= 1 + length -= elementAlongLength + else: + elementsCountAlongGroups.append(elementsCount) + elementsCount = 0 + + majorRadiusElementList = sd2 + minorRadiusElementList = sd3 + + # Create annotation groups along esophagus + esophagusGroup = AnnotationGroup(region, get_esophagus_term("esophagus")) + cervicalGroup = AnnotationGroup(region, get_esophagus_term("cervical part of esophagus")) + thoracicGroup = AnnotationGroup(region, get_esophagus_term("thoracic part of esophagus")) + abdominalGroup = AnnotationGroup(region, get_esophagus_term("abdominal part of esophagus")) + + annotationGroupAlong = [[esophagusGroup, cervicalGroup], + [esophagusGroup, thoracicGroup], + [esophagusGroup, abdominalGroup]] + + annotationGroupsAlong = [] + for i in range(len(elementsCountAlongGroups)): + elementsCount = elementsCountAlongGroups[i] + for n in range(elementsCount): + annotationGroupsAlong.append(annotationGroupAlong[i]) + + annotationGroupsAround = [] + for i in range(elementsCountAround): + annotationGroupsAround.append([]) + + # Groups through wall + longitudinalMuscleGroup = AnnotationGroup(region, + get_esophagus_term("esophagus smooth muscle longitudinal layer")) + circularMuscleGroup = AnnotationGroup(region, get_esophagus_term("esophagus smooth muscle circular layer")) + submucosaGroup = AnnotationGroup(region, get_esophagus_term("submucosa of esophagus")) + mucosaGroup = AnnotationGroup(region, get_esophagus_term("esophagus mucosa")) + + if elementsCountThroughWall == 1: + relativeThicknessList = [1.0] + annotationGroupsThroughWall = [[]] + else: + relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, + circularRelThickness, longitudinalRelThickness] + annotationGroupsThroughWall = [[mucosaGroup], + [submucosaGroup], + [circularMuscleGroup], + [longitudinalMuscleGroup]] + + xToSample = [] + d1ToSample = [] + for n2 in range(elementsCountAlong + 1): + # Create inner points + cx = [0.0, 0.0, elementAlongLength * n2] + axis1 = [vector.magnitude(majorRadiusElementList[n2]), 0.0, 0.0] + axis2 = [0.0, vector.magnitude(minorRadiusElementList[n2]), 0.0] + xInner, d1Inner = geometry.createEllipsePoints(cx, 2 * math.pi, axis1, axis2, + elementsCountAround, startRadians=0.0) + xToSample += xInner + d1ToSample += d1Inner + + d2ToSample = [[0.0, 0.0, elementAlongLength]] * (elementsCountAround * (elementsCountAlong+1)) + + # Sample along length + xInnerRaw = [] + d2InnerRaw = [] + xToWarp = [] + d1ToWarp = [] + d2ToWarp = [] + flatWidthList = [] + xiList = [] + + for n1 in range(elementsCountAround): + xForSamplingAlong = [] + d2ForSamplingAlong = [] + for n2 in range(elementsCountAlong + 1): + idx = n2 * elementsCountAround + n1 + xForSamplingAlong.append(xToSample[idx]) + d2ForSamplingAlong.append(d2ToSample[idx]) + xSampled, d2Sampled = interp.sampleCubicHermiteCurves(xForSamplingAlong, d2ForSamplingAlong, + elementsCountAlong, arcLengthDerivatives=True)[0:2] + xInnerRaw.append(xSampled) + d2InnerRaw.append(d2Sampled) + + # Re-arrange sample order & calculate dx_ds1 and dx_ds3 from dx_ds2 + for n2 in range(elementsCountAlong + 1): + xAround = [] + d2Around = [] + + for n1 in range(elementsCountAround): + x = xInnerRaw[n1][n2] + d2 = d2InnerRaw[n1][n2] + xAround.append(x) + d2Around.append(d2) + + d1Around = [] + for n1 in range(elementsCountAround): + v1 = xAround[n1] + v2 = xAround[(n1 + 1) % elementsCountAround] + d1 = d2 = [v2[c] - v1[c] for c in range(3)] + arcLengthAround = interp.computeCubicHermiteArcLength(v1, d1, v2, d2, True) + dx_ds1 = [c * arcLengthAround for c in vector.normalise(d1)] + d1Around.append(dx_ds1) + d1Smoothed = interp.smoothCubicHermiteDerivativesLoop(xAround, d1Around) + + xToWarp += xAround + d1ToWarp += d1Smoothed + d2ToWarp += d2Around + + # Flat width and xi + flatWidth = 0.0 + xiFace = [] + for n1 in range(elementsCountAround): + v1 = xAround[n1] + d1 = d1Smoothed[n1] + v2 = xAround[(n1 + 1) % elementsCountAround] + d2 = d1Smoothed[(n1 + 1) % elementsCountAround] + flatWidth += interp.getCubicHermiteArcLength(v1, d1, v2, d2) + flatWidthList.append(flatWidth) + + for n1 in range(elementsCountAround + 1): + xi = 1.0 / elementsCountAround * n1 + xiFace.append(xi) + xiList.append(xiFace) + + # Project reference point for warping onto network layout + sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ + tubemesh.getPlaneProjectionOnCentralPath(xToWarp, elementsCountAround, elementsCountAlong, + networkLayoutLength, sx, sd1, sd2, sd12) + + # Warp points + segmentAxis = [0.0, 0.0, 1.0] + closedProximalEnd = False + + innerRadiusAlong = [] + for n2 in range(elementsCountAlong + 1): + firstNodeAlong = xToWarp[n2 * elementsCountAround] + midptSegmentAxis = [0.0, 0.0, elementAlongLength * n2] + radius = vector.magnitude(firstNodeAlong[c] - midptSegmentAxis[c] for c in range(3)) + innerRadiusAlong.append(radius) + + xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = \ + tubemesh.warpSegmentPoints(xToWarp, d1ToWarp, d2ToWarp, segmentAxis, sxRefList, sd1RefList, + sd2ProjectedListRef, elementsCountAround, elementsCountAlong, + zRefList) + + # Create coordinates and derivatives + transitElementList = [0]*elementsCountAround + xList, d1List, d2List, d3List, curvatureList, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal = \ + tubemesh.extrudeSurfaceCoordinates(xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList, + [wallThickness]*(elementsCountAlong+1), relativeThicknessList, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + transitElementList, outward=False) + + # Create flat coordinates + if flatCoordinates: + xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates(xiList, flatWidthList, length, wallThickness, + relativeThicknessList, elementsCountAround, + elementsCountAlong, elementsCountThroughWall, + transitElementList) + else: + xFlat = d1Flat = d2Flat = [] + + # Create colon coordinates + if materialCoordinates: + xEso, d1Eso, d2Eso = \ + tubemesh.createOrganCoordinates(xiList, relativeThicknessListEsoCoordinates, lengthToDiameterRatio, + wallThicknessToDiameterRatio, elementsCountAround, elementsCountAlong, + elementsCountThroughWall, transitElementList) + else: + xEso = d1Eso = d2Eso = [] + + # Create nodes and elements + nodeIdentifier, elementIdentifier, annotationGroups, nodeIdDistal = \ + tubemesh.createNodesAndElements(region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, + xEso, d1Eso, d2Eso, "esophagus coordinates", elementsCountAround, + elementsCountAlong, elementsCountThroughWall, annotationGroupsAround, + annotationGroupsAlong, annotationGroupsThroughWall, + nextNodeIdentifier, nextElementIdentifier, + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd, + localIdxDistal) + + # annotation fiducial points + fm = region.getFieldmodule() + fm.beginChange() + mesh = fm.findMeshByDimension(3) + cache = fm.createFieldcache() + + markerGroup = findOrCreateFieldGroup(fm, "marker") + markerName = findOrCreateFieldStoredString(fm, name="marker_name") + markerLocation = findOrCreateFieldStoredMeshLocation(fm, mesh, name="marker_location") + + nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + markerPoints = markerGroup.getOrCreateNodesetGroup(nodes) + markerTemplateInternal = nodes.createNodetemplate() + markerTemplateInternal.defineField(markerName) + markerTemplateInternal.defineField(markerLocation) + + markerNames = ["proximodorsal midpoint on serosa of upper esophageal sphincter", + "proximoventral midpoint on serosa of upper esophageal sphincter", + "distal point of lower esophageal sphincter serosa on the greater curvature of stomach", + "distal point of lower esophageal sphincter serosa on the lesser curvature of stomach"] + + totalElements = elementIdentifier + radPerElementAround = math.pi * 2.0 / elementsCountAround + elementAroundHalfPi = int(0.25 * elementsCountAround) + xi1HalfPi = (math.pi * 0.5 - radPerElementAround * elementAroundHalfPi)/radPerElementAround + elementAroundPi = int(0.5 * elementsCountAround) + xi1Pi = (math.pi - radPerElementAround * elementAroundPi)/radPerElementAround + + markerElementIdentifiers = [elementsCountAround * elementsCountThroughWall - elementAroundHalfPi, + elementAroundHalfPi + 1 + elementsCountAround * (elementsCountThroughWall - 1), + totalElements - elementsCountAround, + totalElements - elementsCountAround + elementAroundPi] + + markerXis = [[1.0 - xi1HalfPi, 0.0, 1.0], + [xi1HalfPi, 0.0, 1.0], + [0.0, 1.0, 1.0], + [xi1Pi, 1.0, 1.0]] + + for n in range(len(markerNames)): + markerGroup = findOrCreateAnnotationGroupForTerm(annotationGroups, region, + get_esophagus_term(markerNames[n])) + markerElement = mesh.findElementByIdentifier(markerElementIdentifiers[n]) + markerXi = markerXis[n] + cache.setMeshLocation(markerElement, markerXi) + markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal) + nodeIdentifier += 1 + cache.setNode(markerPoint) + markerName.assignString(cache, markerGroup.getName()) + markerLocation.assignMeshLocation(cache, markerElement, markerXi) + for group in [esophagusGroup, markerGroup]: + group.getNodesetGroup(nodes).addNode(markerPoint) + + fm.endChange() + + return annotationGroups, nodeIdentifier, elementIdentifier, nodeIdDistal, xDistal, d1Distal, d2Distal, d3Distal + +class EsophagusNetworkLayout: + """ + Generates sampled network layout for esophagus scaffold. + """ + def __init__(self, region, networkLayout, termsAlong=[None]): + """ + :param region: Zinc region to define model in. + :param networkLayout: Network layout subscaffold from meshtype_1d_network_layout1 + :param termsAlong: Annotation terms along length of network layout + """ + # Extract length of each group along esophagus from network layout + cxGroups = [] + cd1Groups = [] + cd2Groups = [] + cd3Groups = [] + cd12Groups = [] + cd13Groups = [] + + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + tmpFieldmodule = tmpRegion.getFieldmodule() + tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + arcLengthOfGroupsAlong = [] + + for termName in termsAlong: + tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None + tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) + + arcLength = 0.0 + for e in range(len(cxGroup) - 1): + arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], + cxGroup[e + 1], cd1Group[e + 1]) + arcLengthOfGroupsAlong.append(arcLength) + + if termName == "esophagus": + cxGroups.append(cxGroup) + cd1Groups.append(cd1Group) + cd2Groups.append(cd2Group) + cd3Groups.append(cd3Group) + cd12Groups.append(cd12Group) + cd13Groups.append(cd13Group) + + del tmpNodeset + del tmpGroup + + del tmpCoordinates + del tmpNodes + del tmpFieldmodule + del tmpRegion + + self.arcLengthOfGroupsAlong = arcLengthOfGroupsAlong + self.cxGroups = cxGroups + self.cd1Groups = cd1Groups + self.cd2Groups = cd2Groups + self.cd3Groups = cd3Groups + self.cd12Groups = cd12Groups + self.cd13Groups = cd13Groups diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_gastrointestinaltract1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_gastrointestinaltract1.py new file mode 100644 index 00000000..7c778235 --- /dev/null +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_gastrointestinaltract1.py @@ -0,0 +1,738 @@ +""" +Generates a 3-D gastrointestinal tract mesh along the central line, +with variable numbers of elements around, along and through +wall, with variable radius and thickness along. +""" + +import copy + +from cmlibs.utils.zinc.field import findOrCreateFieldCoordinates +from cmlibs.zinc.field import Field +from cmlibs.zinc.node import Node +from scaffoldmaker.annotation.annotationgroup import mergeAnnotationGroups, getAnnotationGroupForTerm +from scaffoldmaker.annotation.cecum_terms import get_cecum_term +from scaffoldmaker.annotation.colon_terms import get_colon_term +from scaffoldmaker.annotation.esophagus_terms import get_esophagus_term +from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term +from scaffoldmaker.annotation.stomach_terms import get_stomach_term +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 +from scaffoldmaker.meshtypes.meshtype_3d_cecum1 import MeshType_3d_cecum1, createCecumMesh3d, CecumNetworkLayout +from scaffoldmaker.meshtypes.meshtype_3d_colon1 import MeshType_3d_colon1, createColonMesh3d, ColonNetworkLayout +from scaffoldmaker.meshtypes.meshtype_3d_esophagus1 import MeshType_3d_esophagus1, createEsophagusMesh3d, \ + EsophagusNetworkLayout +from scaffoldmaker.meshtypes.meshtype_3d_smallintestine1 import MeshType_3d_smallintestine1, \ + createSmallIntestineMesh3d, SmallIntestineNetworkLayout +from scaffoldmaker.meshtypes.meshtype_3d_stomach1 import MeshType_3d_stomach1, createStomachMesh3d, StomachNetworkLayout +from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base +from scaffoldmaker.scaffoldpackage import ScaffoldPackage +from scaffoldmaker.utils import interpolation as interp +from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters + + +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3-4-5-6-7.2, 8-9-10-11-7-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-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-76-77-78-79-80-81-82-83-84-85-86-87-88-89-" + "90-91-92-93-94-95-96-97-98-99-100-101-102-103-104-105-106-107-108-109-110-111-112-113-" + "114-115-116-117-118-119-120-121-122-123-124-125-126-127-128-129-130-131-132-133-134-135-" + "136-137-138-139-140-141-142-143-144-145-146-147-148-149-150-151-152-153-154-155-156-157-" + "158-159-160-161-162-163-164-165-166-167-168-169-170-171-172.2, 173-172-174-175-176-177-" + "178-179-180-181-182-183-184-185-186-187-188-189-190-191-192-193-194-195-196-197-198-199-" + "200-201-202-203-204-205-206-207-208-209-210-211-212-213-214-215-216-217-218-219-220-221-" + "222" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.394,-100.872,1402.818], [-0.035,12.367,-48.020], [8.730,-0.526,-0.142], [0.613,-0.153,-0.037], [-0.272,-4.224,-1.088], [-0.169,-1.491,-0.564]]), + (2, [[0.520,-86.043,1340.066], [0.501,16.682,-77.602], [9.142,-0.799,-0.113], [0.212,-0.392,0.096], [-0.465,-5.159,-1.112], [-0.215,-0.377,0.515]]), + (3, [[1.368,-67.733,1247.932], [0.235,-3.685,-89.672], [9.061,-1.366,0.080], [-0.833,-0.231,0.187], [-0.714,-4.722,0.192], [-0.167,0.445,1.659]]), + (4, [[0.361,-91.057,1165.531], [-2.499,-24.560,-49.102], [7.540,-1.290,0.261], [-0.809,1.514,2.095], [-0.806,-4.269,2.176], [0.001,0.896,0.910]]), + (5, [[11.750,-111.874,1127.887], [7.636,-5.715,-7.930], [5.678,1.265,4.556], [-8.397,13.092,24.878], [-0.708,-3.530,1.862], [-0.807,-7.995,7.596]]),# stomach + (6, [[23.789,-117.922,1120.040], [26.354,-6.724,-6.404], [4.223,6.205,10.864], [10.037,1.800,8.968], [-1.192,-11.215,6.869], [-2.926,-13.889,10.204]]), + (7, [[63.704,-120.094,1123.374], [[0.500,-9.138,-13.405],[50.106,1.267,11.056]], [[37.742,-3.477,3.778],[-2.509,7.605,10.499]], [[3.190,-0.590,-0.290],[3.190,-0.590,-0.290]], [[-5.452,-34.121,23.056],[-1.379,-10.790,7.486]], [[-0.100,-1.220,0.550],[-0.100,-1.220,0.550]]]), + (8, [[61.247,-99.931,1152.681], [0.346,-2.728,-3.873], [11.320,-0.365,1.269], [15.701,-3.029,2.832], [-0.653,-5.931,4.119], [-5.756,-22.456,14.946]]), + (9, [[61.743,-103.510,1147.760], [0.413,-3.592,-5.311], [24.159,-2.387,3.493], [10.039,-1.491,0.928], [-2.982,-15.339,10.142], [-2.384,-12.784,8.034]]), + (10, [[62.381,-107.527,1141.785], [0.249,-4.737,-7.073], [30.559,-2.973,3.067], [5.720,-0.448,-0.071], [-3.839,-23.420,15.550], [-0.206,-5.098,2.599]]), + (11, [[62.800,-113.150,1133.665], [0.116,-6.546,-9.651], [35.408,-3.630,2.888], [4.541,-0.488,0.325], [-4.677,-29.659,20.061], [-0.383,-3.012,1.219]]), + (12, [[64.339,-131.197,1107.233], [0.086,-11.682,-16.915], [39.201,-3.705,2.758], [0.490,-2.470,-4.030], [-5.108,-35.712,24.638], [0.260,0.760,0.250]]), + (13, [[62.912,-143.954,1088.811], [-5.216,-12.408,-17.967], [34.623,-8.161,-4.415], [-4.950,-4.940,-8.800], [-4.917,-34.532,25.275], [0.770,0.610,1.050]]), + (14, [[53.361,-155.397,1072.006], [-15.833,-9.775,-15.486], [25.117,-13.916,-16.896], [-14.190,-3.410,-7.580], [-2.355,-30.712,21.794], [2.030,4.350,-1.240]]), + (15, [[32.110,-162.230,1059.680], [-22.173,-3.681,-8.142], [10.067,-16.126,-20.126], [-15.400,0.330,-0.620], [-2.559,-23.629,17.653], [1.200,8.620,-5.080]]), + (16, [[10.560,-162.970,1055.650], [-20.956,2.164,-0.908], [-0.696,-13.976,-17.241], [-8.750,2.830,4.760], [-2.502,-18.048,14.732], [-1.000,7.490,-3.260]]), + (17, [[-8.740,-158.280,1057.630], [-17.269,8.027,2.588], [-6.253,-10.164,-10.200], [-2.630,4.430,6.290], [-3.442,-11.913,13.981], [-1.380,7.080,-2.660]]), + (18, [[-23.260,-147.620,1060.640], [-11.787,11.369,1.720], [-5.807,-5.321,-4.621], [-0.700,3.020,1.710], [-3.207,-4.764,9.515], [-2.080,5.830,-2.460]]), + (19, [[-32.281,-136.261,1061.249], [-6.125,11.114,-0.493], [-5.735,-3.374,-4.823], [-2.070,-0.220,-4.520], [-4.630,-2.238,7.071], [-4.400,2.440,0.570]]),# small intestine + (20, [[-40.674,-122.300,1060.850], [-5.403,7.321,-2.629], [-4.779,-4.249,-5.161], [2.360,-0.320,0.120], [-5.138,-1.668,6.875], [-0.250,2.080,-4.500]]), + (21, [[-48.346,-108.981,1049.574], [-6.840,19.440,-21.940], [-3.459,-4.108,-5.699], [0.900,0.690,1.570], [-7.043,0.777,3.341], [-0.760,2.950,-2.230]]), + (22, [[-43.450,-95.700,1015.590], [40.730,3.220,-44.800], [-5.240,-3.340,-4.990], [-0.380,4.380,-0.330], [-2.270,6.020,-1.640], [4.590,3.490,-0.790]]), + (23, [[26.760,-119.310,992.030], [58.860,-18.680,-8.450], [0.310,3.940,-6.600], [4.150,2.330,1.070], [2.230,5.490,3.380], [3.360,-4.080,2.370]]), + (24, [[63.862,-132.266,992.002], [9.680,-30.910,-18.900], [5.846,1.916,2.960], [-0.330,-6.200,3.780], [5.300,-1.090,4.490], [-3.680,-1.570,1.510]]), + (25, [[46.280,-139.940,982.680], [-22.680,-4.850,-10.940], [1.050,-7.060,0.970], [-0.930,-3.800,3.220], [-3.190,0.420,6.420], [-5.340,-0.640,-2.850]]), + (26, [[28.560,-141.070,974.610], [3.750,-10.520,-21.300], [1.560,-6.210,3.340], [-1.000,0.060,-0.070], [-6.850,-1.870,-0.290], [1.100,-0.530,-6.400]]), + (27, [[52.390,-146.130,971.400], [18.400,-3.700,0.670], [-1.440,-7.110,0.300], [-0.590,-0.290,-0.540], [0.190,-0.340,-7.250], [2.420,0.060,-1.890]]), + (28, [[63.130,-148.180,973.520], [10.490,-1.410,1.470], [-1.070,-7.160,0.770], [2.410,0.380,0.120], [0.880,-0.900,-7.160], [-2.030,-1.100,0.840]]), + (29, [[72.690,-148.910,974.300], [7.650,3.570,-7.080], [3.500,-6.340,0.580], [0.430,0.200,-1.420], [-3.880,-2.630,-5.520], [-3.490,0.080,4.650]]), + (30, [[71.050,-143.650,964.650], [-5.960,4.700,-11.040], [-0.810,-6.830,-2.470], [-2.360,-0.380,-1.140], [-6.400,-0.430,3.270], [0.270,0.950,6.070]]), + (31, [[61.060,-140.780,954.520], [-17.960,3.880,-6.220], [-1.070,-7.120,-1.370], [0.180,-0.250,1.370], [-2.560,-0.940,6.800], [3.840,0.270,2.130]]), + (32, [[37.990,-136.930,957.170], [-18.820,0.880,5.080], [-0.160,-7.340,0.670], [1.900,0.170,0.590], [1.940,0.610,7.070], [2.120,1.030,-0.120]]), + (33, [[24.260,-138.060,963.160], [-17.400,-6.040,8.510], [2.590,-6.900,0.380], [2.420,1.010,0.690], [2.780,1.420,6.690], [-2.180,-0.670,-0.740]]), + (34, [[6.500,-150.310,973.050], [-8.250,-16.440,-13.420], [4.890,-4.750,2.820], [-1.080,-0.490,-0.280], [-4.820,-1.850,5.240], [-4.270,-0.820,-2.180]]), + (35, [[15.970,-149.800,957.690], [-4.350,-1.250,-14.050], [0.990,-7.390,0.350], [-1.040,-0.780,-0.850], [-6.950,-0.830,2.230], [-0.480,0.190,-0.500]]), + (36, [[8.290,-150.980,954.250], [-3.340,-0.730,-8.150], [1.180,-7.370,0.180], [0.180,0.050,0.370], [-6.710,-1.000,2.840], [0.560,-0.430,-3.270]]), + (37, [[10.770,-150.880,946.760], [5.270,-0.050,-7.150], [1.370,-7.280,1.060], [-0.120,-0.030,0.050], [-5.800,-1.710,-4.270], [2.050,0.220,-4.830]]), + (38, [[18.300,-151.090,941.260], [7.790,0.880,-2.390], [0.880,-7.450,0.160], [0.050,-0.010,-0.900], [-2.150,-0.400,-7.160], [4.520,1.490,-0.770]]), + (39, [[24.850,-149.580,941.590], [5.320,0.620,3.020], [1.330,-7.350,-0.840], [-0.350,0.010,-0.650], [3.510,1.370,-6.460], [3.430,0.580,1.190]]), + (40, [[27.850,-149.810,945.920], [3.490,-0.550,3.990], [0.330,-7.390,-1.300], [-0.750,-0.040,-0.150], [5.610,1.090,-4.760], [-0.580,-0.160,-0.310]]), + (41, [[31.640,-150.640,949.370], [5.770,-0.500,1.810], [-0.280,-7.430,-1.160], [0.320,-0.010,0.320], [2.310,1.020,-7.080], [-4.590,-0.600,-0.740]]), + (42, [[38.160,-150.550,948.480], [5.400,1.270,-4.340], [1.280,-7.400,-0.560], [1.280,0.320,-0.530], [-4.630,-0.350,-5.870], [-4.440,-1.610,3.120]]), + (43, [[40.300,-148.530,942.170], [-0.500,2.450,-7.550], [2.420,-6.730,-2.350], [1.390,0.820,-0.980], [-7.020,-2.420,-0.320], [-0.570,-0.950,1.020]]), + (44, [[36.760,-146.190,935.090], [3.270,5.380,-6.440], [4.320,-5.620,-2.500], [0.260,-0.080,1.070], [-5.500,-2.170,-4.600], [3.600,1.240,-3.410]]), + (45, [[44.600,-142.080,934.770], [8.650,3.530,1.100], [2.850,-7.000,0.020], [-1.020,-0.770,1.000], [0.830,0.310,-7.530], [3.410,1.450,-1.300]]), + (46, [[53.340,-139.440,937.210], [8.310,2.340,2.220], [2.150,-7.250,-0.380], [-0.540,-0.170,-0.420], [1.710,0.890,-7.340], [0.070,0.370,0.030]]), + (47, [[61.180,-137.390,939.220], [8.230,1.720,1.430], [1.690,-7.360,-0.860], [-0.380,-0.100,-0.170], [1.060,1.120,-7.440], [-0.840,-0.070,-0.120]]), + (48, [[69.720,-136.030,940.040], [8.420,1.510,0.050], [1.350,-7.460,-0.740], [0.300,0.210,-0.630], [-0.090,0.740,-7.580], [-3.560,-0.970,1.730]]), + (49, [[77.280,-134.500,939.340], [4.490,4.180,-8.530], [2.310,-6.920,-2.180], [-0.290,0.070,-0.480], [-6.410,-0.930,-3.830], [-3.190,-0.950,5.530]]), + (50, [[71.890,-131.270,929.110], [-6.780,1.090,-6.790], [0.090,-7.530,-1.300], [-0.440,-0.260,1.250], [-5.410,-0.970,5.250], [0.240,0.450,2.900]]), + (51, [[66.110,-131.600,925.900], [-4.090,-0.450,-4.440], [0.540,-7.640,0.280], [0.080,0.050,1.400], [-5.560,-0.210,5.140], [-0.150,0.880,-0.160]]), + (52, [[63.930,-132.090,921.070], [-3.930,-1.160,-4.370], [0.320,-7.470,1.700], [0.720,0.300,0.950], [-5.720,0.870,4.920], [0.660,0.510,0.560]]), + (53, [[58.470,-133.890,917.960], [-6.670,-3.360,-3.670], [2.290,-6.970,2.210], [2.280,0.920,-0.110], [-3.960,0.750,6.500], [2.250,0.030,1.310]]), + (54, [[51.020,-139.090,914.020], [-6.630,-6.740,0.390], [5.400,-5.250,1.130], [1.070,0.420,-1.320], [-0.590,1.020,7.590], [3.120,0.370,0.200]]), + (55, [[46.770,-145.490,918.120], [-5.050,-4.370,2.870], [4.810,-5.920,-0.550], [-1.310,-0.890,-0.940], [2.680,1.520,7.030], [1.260,-0.680,-0.120]]), + (56, [[41.950,-147.920,919.780], [-5.030,-2.380,1.940], [2.900,-7.030,-1.100], [-1.320,-0.680,-0.330], [2.770,0.010,7.180], [-0.110,-1.000,0.120]]), + (57, [[36.760,-150.210,922.000], [-5.100,-1.680,1.580], [2.030,-7.330,-1.240], [-0.510,-0.220,0.810], [2.440,-0.560,7.300], [-0.450,0.500,0.130]]), + (58, [[31.890,-151.330,922.990], [-5.710,-1.250,1.560], [1.770,-7.500,0.460], [-0.570,-0.180,0.730], [1.840,0.880,7.450], [-2.050,0.330,0.030]]), + (59, [[25.550,-152.650,925.180], [-6.280,-0.560,-2.170], [0.700,-7.710,-0.030], [-0.690,-0.090,-0.620], [-2.500,-0.250,7.310], [-3.190,-0.780,-0.830]]), + (60, [[22.170,-152.270,920.060], [-4.850,0.300,-4.200], [0.270,-7.700,-0.850], [-0.240,-0.020,0.240], [-5.020,-0.810,5.760], [2.410,0.370,-0.060]]), + (61, [[16.600,-152.110,917.510], [-6.970,0.000,2.680], [0.200,-7.740,0.510], [-0.300,-0.030,0.600], [2.770,0.540,7.210], [5.780,0.370,-0.740]]), + (62, [[13.120,-152.320,924.900], [-3.730,0.410,7.150], [-0.450,-7.750,0.210], [-0.140,-0.020,-0.160], [6.780,-0.300,3.550], [-0.230,-0.180,0.200]]), + (63, [[9.440,-151.370,931.310], [-7.880,0.190,2.810], [-0.130,-7.780,0.170], [0.490,-0.010,0.120], [2.610,0.120,7.310], [-3.700,0.330,2.080]]), + (64, [[1.230,-152.170,928.310], [-8.130,-0.720,-1.080], [0.620,-7.760,0.490], [0.090,-0.010,-0.290], [-1.060,0.400,7.710], [1.430,-0.160,-0.650]]), + (65, [[-5.970,-152.740,928.930], [-5.640,-0.310,4.390], [0.170,-7.800,-0.330], [-0.930,0.040,0.090], [4.760,-0.160,6.120], [3.980,-0.840,-4.110]]), + (66, [[-8.050,-152.700,935.120], [0.840,0.430,7.280], [-1.310,-7.670,0.600], [-1.080,0.170,0.740], [7.520,-1.340,-0.790], [0.790,-0.430,-1.110]]), + (67, [[-4.180,-151.980,940.930], [-5.500,2.850,8.020], [-2.070,-7.440,1.220], [-0.370,0.070,-0.100], [6.170,-0.960,4.570], [-3.010,0.560,4.290]]), + (68, [[-15.920,-150.230,939.850], [-11.530,2.830,0.080], [-1.870,-7.620,-0.020], [0.120,0.150,0.780], [0.040,-0.030,7.840], [0.810,0.000,-1.160]]), + (69, [[-25.870,-146.770,940.970], [-2.690,4.150,9.230], [-1.800,-7.150,2.690], [0.690,0.200,1.480], [7.250,-0.880,2.510], [1.720,-1.410,-6.490]]), + (70, [[-19.430,-146.580,946.990], [7.700,1.830,5.130], [-0.490,-7.140,3.290], [1.240,-0.130,-0.090], [4.500,-2.940,-5.700], [-0.590,-0.040,-3.450]]), + (71, [[-11.610,-143.430,950.540], [5.250,2.520,5.680], [0.830,-7.420,2.520], [0.750,-0.240,-0.870], [5.910,-1.040,-5.000], [0.830,1.410,0.570]]), + (72, [[-9.220,-141.820,956.880], [3.600,1.580,5.200], [1.220,-7.660,1.480], [-0.050,-0.130,-0.420], [6.390,0.150,-4.470], [0.120,0.280,0.100]]), + (73, [[-4.880,-140.390,960.700], [3.780,1.360,4.900], [0.780,-7.720,1.540], [0.070,-0.060,-0.650], [6.230,-0.310,-4.720], [0.530,0.530,1.660]]), + (74, [[-1.980,-139.200,966.470], [0.650,0.130,7.290], [1.420,-7.780,0.010], [0.230,-0.060,-0.880], [7.610,1.390,-0.700], [0.660,0.740,3.140]]), + (75, [[-4.150,-140.360,973.960], [-2.380,-0.650,10.170], [1.190,-7.830,-0.220], [-0.650,-0.070,-0.200], [7.500,1.090,1.830], [-0.210,-0.700,2.000]]), + (76, [[-6.206,-140.381,984.826], [-3.997,1.953,8.625], [-0.240,-7.940,-0.400], [-0.770,0.020,-0.440], [7.090,-0.380,3.280], [-1.820,-1.020,2.460]]), + (77, [[-11.071,-137.239,990.534], [-6.502,2.564,3.616], [-0.730,-7.850,-1.030], [0.040,-0.000,-0.150], [4.330,-1.250,6.510], [-3.510,-0.150,2.180]]), + (78, [[-18.114,-135.562,991.751], [-6.821,0.865,-0.438], [-0.170,-7.940,-0.730], [0.590,-0.040,0.750], [-0.320,-0.720,7.930], [-4.070,0.690,0.160]]), + (79, [[-24.108,-135.469,989.949], [-5.560,-1.043,-2.740], [0.530,-7.940,0.630], [-0.080,0.160,1.480], [-4.270,0.240,6.690], [-3.140,0.950,-2.220]]), + (80, [[-28.764,-137.545,986.518], [-3.033,-3.486,-4.184], [-0.280,-7.620,2.380], [-1.430,0.310,0.610], [-7.020,1.290,3.320], [-0.940,0.180,-5.150]]), + (81, [[-29.636,-141.811,982.334], [1.634,-2.756,-5.189], [-2.170,-7.290,2.440], [-1.160,0.110,-0.290], [-7.100,1.030,-3.250], [0.490,-0.350,-4.870]]), + (82, [[-24.820,-145.190,978.580], [4.650,-2.180,-4.590], [-2.130,-7.580,1.440], [0.290,-0.260,-0.910], [-5.460,0.450,-5.750], [-0.330,0.230,1.000]]), + (83, [[-20.750,-146.910,974.010], [1.230,-0.700,-6.940], [-1.580,-7.840,0.510], [0.080,-0.090,-0.690], [-7.590,1.430,-1.480], [0.460,0.350,5.770]]), + (84, [[-23.390,-146.100,967.330], [-6.320,1.650,-4.010], [-2.030,-7.760,0.010], [-0.160,0.070,0.360], [-4.040,1.070,6.800], [4.830,-0.400,4.280]]), + (85, [[-30.600,-144.330,967.780], [-6.690,2.040,2.190], [-1.930,-7.690,1.270], [0.050,0.000,0.440], [2.650,0.580,7.550], [3.030,-0.350,0.340]]), + (86, [[-36.170,-142.250,971.340], [-6.590,1.940,2.270], [-1.940,-7.730,1.010], [0.040,-0.010,0.090], [2.700,0.310,7.560], [0.370,-0.020,-0.150]]), + (87, [[-43.400,-140.590,972.070], [-6.040,1.970,2.740], [-1.830,-7.710,1.480], [0.020,0.340,1.180], [3.470,0.560,7.230], [2.300,-0.410,-2.270]]), + (88, [[-47.620,-138.630,976.140], [-1.780,2.680,4.620], [-1.870,-7.070,3.390], [0.010,0.350,0.980], [7.300,-0.460,3.080], [1.720,-1.440,-3.710]]), + (89, [[-47.100,-135.980,980.160], [0.980,1.950,4.050], [-1.830,-6.900,3.760], [0.210,-0.140,-0.200], [7.550,-2.370,-0.680], [0.040,-0.760,-2.210]]), + (90, [[-45.780,-134.750,984.020], [1.920,1.940,5.580], [-1.460,-7.340,3.050], [-0.530,0.370,0.090], [7.430,-2.220,-1.790], [-0.240,0.260,1.070]]), + (91, [[-42.419,-130.149,990.122], [-1.920,7.780,7.360], [-3.780,-5.370,4.690], [-2.140,1.260,-0.060], [6.910,-1.720,3.610], [-3.470,2.540,4.150]]), + (92, [[-48.414,-118.983,992.238], [-8.280,6.980,-7.760], [-5.960,-5.080,1.790], [0.610,-1.110,-1.840], [-2.030,4.630,6.340], [-6.540,1.980,-0.430]]), + (93, [[-54.520,-122.570,980.900], [-5.100,0.460,-13.050], [-2.600,-7.660,0.750], [2.850,-1.090,0.850], [-7.020,2.660,2.840], [-2.860,-1.790,-2.310]]), + (94, [[-56.534,-121.929,967.273], [-3.400,-6.950,-12.830], [-2.036,-6.714,3.150], [-1.690,1.750,1.250], [-7.800,0.860,1.600], [1.210,-0.700,-4.510]]), + (95, [[-57.601,-134.069,961.014], [4.440,-11.120,-4.920], [-6.170,-3.970,3.410], [-1.800,0.340,-0.380], [-4.460,1.190,-6.700], [1.720,-0.860,-3.600]]), + (96, [[-53.650,-142.090,958.040], [8.150,-8.950,-3.450], [-4.950,-5.680,3.060], [2.040,-1.620,-0.110], [-3.750,-0.620,-7.230], [-0.920,-0.860,0.970]]), + (97, [[-43.780,-150.900,953.550], [6.860,-6.210,-10.820], [-1.570,-7.380,3.240], [0.100,-0.470,-1.480], [-6.930,-0.360,-4.180], [-0.500,1.880,6.120]]), + (98, [[-42.790,-151.920,940.920], [-10.160,7.350,-12.870], [-4.740,-6.680,-0.070], [-1.780,0.370,-1.940], [-4.810,3.350,5.710], [1.370,1.930,5.900]]), + (99, [[-59.560,-139.320,940.870], [-10.470,7.530,-10.550], [-4.670,-6.770,-0.210], [-0.780,0.740,0.770], [-4.390,2.820,6.370], [-0.630,1.740,-4.220]]), + (100, [[-61.190,-138.430,930.230], [-0.370,-2.040,-12.190], [-5.970,-5.520,1.110], [-0.860,0.960,0.960], [-5.640,5.920,-0.830], [0.650,-0.720,-6.690]]), + (101, [[-60.050,-143.370,918.840], [6.120,-9.410,-3.110], [-6.440,-4.780,1.790], [0.250,-0.370,-0.760], [-2.750,0.780,-7.780], [3.390,-3.100,-3.060]]), + (102, [[-54.810,-148.970,924.540], [7.070,-6.600,2.050], [-5.610,-6.050,-0.170], [0.760,-0.860,-0.330], [1.380,-1.050,-8.130], [-1.610,1.400,1.580]]), + (103, [[-48.000,-154.670,922.570], [3.540,-3.720,-7.480], [-4.830,-6.610,1.000], [1.210,-0.760,-0.140], [-5.850,3.580,-4.550], [-4.060,1.810,3.830]]), + (104, [[-49.390,-154.510,914.460], [0.270,0.350,-10.670], [-3.110,-7.640,-0.330], [1.860,-0.790,-0.480], [-7.540,3.070,-0.100], [1.640,-1.570,-0.540]]), + (105, [[-46.730,-154.010,904.000], [18.990,-1.890,-1.480], [-0.780,-8.190,0.400], [1.310,-0.300,0.500], [-0.670,-0.340,-8.190], [5.190,-2.310,-4.980]]), + (106, [[-31.900,-157.000,923.200], [20.270,-2.840,5.710], [-1.280,-8.040,0.540], [1.630,0.180,0.170], [2.100,-0.860,-7.850], [-3.210,-0.770,1.420]]), + (107, [[-17.040,-158.470,917.330], [10.690,1.600,-10.940], [1.940,-7.840,0.740], [0.870,0.010,-0.110], [-5.440,-1.880,-5.580], [-1.710,0.190,-0.090]]), + (108, [[-12.920,-154.880,905.590], [14.280,1.560,-5.120], [1.010,-8.000,0.370], [-0.980,-0.090,-0.580], [-2.650,-0.690,-7.580], [1.890,1.140,-1.150]]), + (109, [[0.790,-157.220,913.220], [17.050,-0.100,-3.500], [-0.160,-8.010,-0.530], [0.240,0.090,-0.240], [-1.610,0.550,-7.830], [0.100,0.160,0.010]]), + (110, [[11.370,-154.850,899.810], [20.470,4.340,-7.040], [1.620,-7.800,-0.100], [0.670,0.240,-0.620], [-2.500,-0.420,-7.540], [-1.600,0.070,0.920]]), + (111, [[35.280,-149.960,905.730], [15.010,5.710,-13.200], [0.800,-7.500,-2.330], [1.120,0.330,0.340], [-5.360,1.170,-5.590], [-1.050,-1.380,0.950]]), + (112, [[31.510,-148.900,893.070], [11.510,6.020,-14.640], [3.170,-7.130,-0.440], [1.650,0.510,0.450], [-5.440,-2.110,-5.150], [2.200,-0.030,-0.530]]), + (113, [[53.210,-142.180,892.150], [16.130,8.560,4.600], [3.960,-6.330,-2.130], [0.420,0.200,0.800], [0.580,2.810,-7.250], [3.440,1.000,-0.610]]), + (114, [[61.915,-135.512,899.756], [10.425,5.807,7.557], [4.220,-6.470,0.220], [-1.030,-0.530,1.150], [2.810,1.590,-7.040], [-2.200,-1.800,0.660]]), + (115, [[72.652,-131.499,906.138], [13.270,2.580,-11.410], [1.590,-7.520,0.150], [-0.630,-0.250,0.200], [-4.770,-1.120,-5.790], [-4.380,-1.930,4.880]]), + (116, [[70.933,-136.139,889.296], [-12.490,-8.250,-22.650], [3.260,-6.840,0.700], [0.840,0.360,-0.040], [-5.890,-2.380,4.110], [0.640,-0.370,7.040]]), + (117, [[47.820,-142.630,864.930], [-22.720,-8.470,-7.520], [2.750,-7.000,-0.430], [0.030,0.230,-1.270], [-1.940,-1.200,7.190], [5.330,1.350,0.110]]), + (118, [[33.710,-147.840,866.620], [-7.310,-5.020,5.800], [3.020,-6.590,-1.880], [-0.710,0.240,-1.450], [4.500,0.350,5.980], [2.350,2.560,-6.780]]), + (119, [[33.450,-149.550,870.080], [6.660,-2.670,8.620], [1.910,-6.380,-3.460], [-0.810,0.030,-0.860], [5.650,3.480,-3.300], [0.800,2.080,-6.770]]), + (120, [[48.500,-149.860,877.560], [8.440,-1.400,10.880], [1.840,-6.880,-2.310], [-0.550,-0.390,1.170], [5.590,2.820,-3.970], [-1.370,-2.160,5.890]]), + (121, [[49.170,-151.340,885.880], [-14.130,-2.760,6.710], [0.940,-7.250,-1.010], [-0.570,0.330,-0.410], [3.260,-0.510,6.640], [-3.090,-3.470,6.170]]), + (122, [[30.330,-151.820,877.700], [-17.160,1.530,-4.960], [0.920,-5.490,-4.890], [-1.510,-0.140,0.400], [-1.940,-4.930,5.180], [0.640,-0.130,0.130]]), + (123, [[16.360,-149.060,875.570], [-10.970,1.710,5.380], [-1.800,-6.980,-1.460], [-0.540,-0.730,1.970], [2.830,-2.080,6.450], [2.860,1.800,-0.060]]), + (124, [[11.690,-148.720,883.920], [-10.140,1.000,8.830], [-0.940,-7.280,-0.260], [0.660,-0.150,1.090], [4.710,-0.800,5.500], [-0.400,1.320,0.040]]), + (125, [[-3.830,-146.990,890.110], [-14.280,1.090,0.550], [-0.520,-7.220,0.830], [0.360,0.010,-0.260], [0.340,0.810,7.240], [-1.670,-0.060,0.660]]), + (126, [[-14.790,-146.520,886.710], [-10.850,0.220,0.510], [-0.160,-7.240,-0.380], [0.730,0.030,-0.300], [0.330,-0.390,7.230], [2.180,0.020,-0.940]]), + (127, [[-23.910,-146.550,890.530], [-7.400,-0.950,6.580], [0.980,-7.160,0.070], [-0.520,0.100,0.630], [4.680,0.690,5.370], [0.750,0.450,-0.150]]), + (128, [[-28.030,-148.180,898.370], [-13.610,2.900,3.800], [-1.230,-7.020,0.960], [-1.430,0.370,-0.840], [2.040,0.580,6.860], [-3.990,-0.650,0.170]]), + (129, [[-42.020,-140.320,889.270], [-9.930,7.700,-9.680], [-1.440,-6.120,-3.390], [0.840,-0.040,-0.890], [-5.330,-1.240,4.490], [-3.620,0.110,-4.100]]), + (130, [[-47.830,-133.820,880.590], [1.670,2.810,-9.020], [0.190,-6.800,-2.080], [0.020,-0.240,2.820], [-6.870,0.170,-1.220], [2.630,-0.650,-5.170]]), + (131, [[-43.360,-134.640,876.970], [7.370,-1.120,-1.770], [-0.610,-6.830,1.800], [-0.490,-0.090,1.490], [-1.840,-1.590,-6.650], [3.370,-0.420,-3.090]]), + (132, [[-34.800,-135.760,878.370], [7.330,-0.800,-0.160], [-0.760,-7.020,0.280], [-0.510,0.020,-0.710], [-0.180,-0.260,-7.060], [-2.440,1.360,1.660]]), + (133, [[-29.320,-136.240,877.180], [3.390,-0.800,-5.310], [-1.570,-6.870,0.040], [-0.230,0.050,0.030], [-5.670,1.270,-3.820], [-3.220,0.720,3.410]]), + (134, [[-30.610,-136.870,870.770], [-0.250,-0.250,-5.290], [-1.190,-6.910,0.380], [0.280,-0.030,-0.030], [-6.790,1.180,0.270], [0.350,-0.330,-1.210]]), + (135, [[-30.230,-136.860,867.080], [2.790,-0.450,-3.890], [-0.940,-6.950,0.140], [0.330,-0.030,-0.120], [-5.570,0.670,-4.070], [3.300,-0.630,-3.480]]), + (136, [[-25.370,-137.760,865.060], [8.760,-0.500,1.850], [-0.440,-6.980,0.180], [0.240,0.000,-0.170], [1.430,-0.270,-6.840], [3.730,-0.350,-1.770]]), + (137, [[-17.010,-136.930,873.250], [9.540,-0.880,-1.350], [-0.710,-6.910,-0.470], [-0.790,0.170,0.250], [-0.920,0.560,-6.870], [-3.990,0.940,2.860]]), + (138, [[-14.620,-138.100,867.370], [2.470,-1.150,-8.780], [-1.880,-6.660,0.340], [1.250,0.410,-0.040], [-6.320,1.680,-1.990], [-1.180,0.210,1.020]]), + (139, [[-13.210,-138.670,858.260], [15.020,8.840,-1.860], [3.370,-5.940,-1.020], [3.020,0.320,-0.460], [-1.140,0.510,-6.800], [4.300,-0.760,-2.960]]), + (140, [[-2.010,-129.090,875.920], [14.730,5.570,5.540], [2.300,-6.430,0.360], [-3.380,0.090,1.420], [2.260,0.450,-6.450], [-4.260,0.280,1.850]]), + (141, [[5.710,-128.310,873.450], [4.220,-3.800,-6.920], [-2.330,-6.100,1.930], [1.540,1.120,0.790], [-5.490,0.890,-3.830], [-2.900,-1.920,4.890]]), + (142, [[3.860,-133.450,867.510], [-1.780,-5.980,-7.590], [4.850,-4.160,2.140], [1.960,0.650,1.010], [-4.520,-3.360,3.710], [0.300,-2.100,1.250]]), + (143, [[2.440,-139.690,858.800], [7.020,-5.190,-6.230], [0.110,-5.150,4.400], [-1.690,-0.890,0.210], [-5.060,-2.920,-3.280], [2.220,0.250,-4.490]]), + (144, [[11.980,-140.150,859.350], [17.700,2.250,-1.140], [0.950,-6.060,2.790], [1.390,-0.390,-2.080], [-0.040,-2.820,-6.130], [2.190,0.110,-1.390]]), + (145, [[35.300,-132.990,854.910], [8.740,9.550,-15.220], [4.050,-5.230,-0.960], [0.820,0.890,-2.820], [-4.430,-2.650,-4.200], [-1.330,-1.300,4.050]]), + (146, [[29.930,-128.550,843.920], [-12.950,5.120,-19.360], [3.680,-4.210,-3.570], [-1.410,0.000,-0.870], [-4.190,-4.930,1.490], [1.700,-0.300,5.110]]), + (147, [[9.390,-125.790,820.060], [-27.750,1.440,5.840], [-0.470,-6.580,-0.630], [-1.270,-0.920,1.780], [1.320,-0.720,6.460], [4.740,2.190,-0.360]]), + (148, [[4.650,-126.740,840.920], [-6.020,1.180,15.730], [0.130,-6.590,0.550], [-0.730,0.090,0.190], [6.110,0.310,2.320], [-2.110,0.210,1.570]]), + (149, [[0.040,-125.010,849.260], [-9.240,1.850,1.000], [-1.260,-6.450,0.320], [0.680,0.070,-0.540], [0.750,0.180,6.550], [-5.740,-0.820,-0.600]]), + (150, [[-4.440,-124.790,843.150], [-5.020,0.460,-16.660], [1.260,-6.430,-0.560], [1.980,0.080,-0.420], [-6.090,-1.340,1.790], [-4.270,-1.020,-2.570]]), + (151, [[-4.100,-124.240,817.800], [-14.820,-5.980,-12.690], [2.230,-6.130,0.290], [-0.080,-0.020,0.180], [-3.880,-1.170,5.070], [6.330,1.590,-0.020]]), + (152, [[-13.820,-128.400,823.840], [-7.490,-1.580,13.510], [1.550,-6.330,0.120], [-0.550,0.000,0.710], [5.490,1.400,3.200], [4.920,1.220,-2.010]]), + (153, [[-15.540,-126.400,839.810], [-2.260,3.630,12.780], [1.060,-6.110,1.920], [-1.860,0.050,-0.360], [6.210,1.310,0.730], [-0.950,-1.430,1.430]]), + (154, [[-17.860,-122.190,848.910], [-6.970,2.290,6.400], [-1.900,-6.170,0.140], [0.210,-0.110,-0.730], [4.060,-1.150,4.850], [-5.500,-0.820,1.290]]), + (155, [[-24.460,-122.950,849.040], [-11.050,-2.260,-14.690], [1.030,-6.350,0.200], [1.600,-0.050,0.470], [-5.050,-0.700,3.900], [-6.400,0.950,-0.750]]), + (156, [[-23.980,-124.710,821.700], [-13.900,-3.450,-17.210], [-1.090,-5.980,2.080], [-0.110,-0.110,-0.760], [-4.880,2.110,3.530], [5.050,-0.430,0.870]]), + (157, [[-38.600,-127.220,820.180], [-12.580,-0.430,8.780], [-0.020,-6.390,-0.330], [-0.170,-0.020,-0.170], [3.670,-0.290,5.240], [4.860,-1.540,-2.070]]), + (158, [[-42.520,-125.650,832.780], [1.330,2.910,14.250], [-1.250,-6.100,1.370], [-0.030,0.210,1.190], [6.110,-1.310,-0.300], [1.080,-0.260,-3.490]]), + (159, [[-35.800,-121.920,845.730], [4.200,3.780,10.200], [0.010,-5.960,2.200], [-0.160,0.230,0.570], [5.880,-0.780,-2.130], [0.090,0.030,0.690]]), + (160, [[-33.620,-118.720,852.840], [0.500,3.010,6.470], [-0.930,-5.650,2.700], [-0.790,-0.030,-0.570], [6.150,-1.010,0.000], [-0.330,-0.030,2.500]]), + (161, [[-34.440,-116.110,858.280], [-2.640,1.810,5.040], [-1.710,-5.940,1.230], [0.580,-0.290,-1.410], [5.320,-0.890,3.110], [-1.830,0.370,2.710]]), + (162, [[-38.380,-115.330,862.170], [-6.050,-0.340,2.350], [0.220,-6.280,-0.340], [1.370,-0.090,-0.250], [2.280,-0.240,5.850], [-4.210,0.450,0.940]]), + (163, [[-44.500,-116.930,861.580], [-11.590,-3.810,-10.160], [1.110,-6.090,1.020], [0.440,0.120,0.610], [-4.130,0.030,4.700], [-4.540,0.050,-0.790]]), + (164, [[-51.780,-120.720,839.030], [-15.880,-5.450,-10.360], [1.830,-5.970,0.320], [-1.360,0.270,0.870], [-3.220,-0.700,5.310], [4.290,0.490,0.090]]), + (165, [[-64.650,-124.350,841.480], [-11.510,0.420,9.850], [0.150,-6.190,0.440], [-0.550,0.330,1.540], [3.970,0.430,4.630], [4.380,-0.520,-2.900]]), + (166, [[-69.370,-119.950,854.330], [5.110,4.210,16.620], [-1.330,-5.740,1.870], [0.690,0.270,0.730], [5.670,-1.740,-1.310], [0.560,-1.580,-4.180]]), + (167, [[-55.630,-118.570,867.170], [8.190,15.700,8.570], [-2.415,-2.636,3.160], [0.890,1.630,1.440], [4.280,-1.310,-1.700], [0.130,0.200,0.140]]), + (168, [[-52.380,-100.900,869.760], [4.760,24.010,12.610], [-3.169,0.219,3.447], [-0.280,-0.300,-1.610], [4.600,-0.510,-0.770], [-2.290,1.100,4.280]]), + (169, [[-41.730,-76.290,892.900], [-14.020,14.240,19.650], [-3.750,-3.589,-1.622], [3.240,-2.890,0.750], [1.930,-2.620,3.270], [-5.090,5.860,6.610]]), + (170, [[-60.630,-80.530,895.250], [-6.170,-10.100,-5.870], [2.660,0.730,-4.050], [2.380,0.990,-1.140], [3.310,-2.970,1.640], [2.380,0.990,-1.140]]),# cecum + (171, [[-68.640,-93.290,888.060], [-9.850,-15.420,-8.510], [3.880,1.200,-6.660], [2.380,0.990,-1.140], [2.820,-2.460,1.200], [2.380,0.990,-1.140]]), + (172, [[-80.390,-111.370,878.290], [[-7.790,-0.980,12.360],[-13.650,-20.740,-11.030]], [[20.720,-4.040,12.540],[5.590,1.310,-9.380]], [[2.380,0.990,-1.140],[2.380,0.990,-1.140]], [[2.470,23.830,3.610],[1.510,-1.370,0.710]], [[2.380,0.990,-1.140],[2.380,0.990,-1.140]]]), + (173, [[-71.690,-109.000,866.040], [-9.550,-3.730,12.060], [17.410,-4.850,11.460], [3.730,0.680,4.200], [0.820,19.940,7.200], [3.740,0.690,4.200]]), + (174, [[-87.210,-111.060,890.540], [-4.750,0.410,12.390], [23.270,-3.130,7.880], [2.460,-0.390,-2.950], [3.090,24.460,0.450], [1.830,0.460,-4.310]]),# colon + (175, [[-89.990,-110.570,902.650], [-2.050,0.530,12.720], [24.710,-3.280,4.130], [0.070,0.140,-2.810], [3.420,25.000,-0.640], [0.430,0.100,-3.970]]), + (176, [[-91.250,-110.010,915.920], [-0.550,0.530,13.390], [23.610,-2.820,1.080], [-1.460,0.550,-1.920], [2.850,23.610,-0.910], [-1.420,0.540,-2.130]]), + (177, [[-91.080,-109.520,929.390], [0.130,0.650,13.470], [21.830,-2.100,-0.100], [-0.530,0.220,-1.060], [2.080,21.810,-1.180], [-0.530,0.210,-1.170]]), + (178, [[-91.000,-108.720,942.850], [0.830,0.670,13.370], [22.560,-2.350,-1.280], [-0.880,0.270,-1.850], [2.290,22.560,-1.420], [-0.920,0.270,-2.030]]), + (179, [[-89.430,-108.180,956.080], [2.810,0.320,13.110], [20.050,-1.510,-4.270], [-1.960,0.620,-1.350], [1.380,20.440,-0.860], [-2.000,0.620,-1.490]]), + (180, [[-85.390,-108.090,968.920], [3.100,0.440,13.080], [18.600,-0.990,-4.380], [-0.760,0.320,0.660], [0.820,19.040,-0.910], [-0.730,0.310,0.710]]), + (181, [[-83.240,-107.300,982.140], [2.050,0.850,13.230], [18.550,-0.800,-2.820], [-0.240,0.090,0.570], [0.620,18.710,-1.440], [-0.210,0.080,0.630]]), + (182, [[-81.290,-106.400,995.370], [2.320,1.340,13.290], [18.150,-0.790,-3.100], [0.140,0.240,-0.110], [0.470,18.290,-2.130], [0.050,0.310,-0.570]]), + (183, [[-78.600,-104.620,1008.650], [2.140,-1.500,13.270], [18.840,-0.250,-3.070], [-0.910,1.850,-0.220], [0.840,18.750,3.430], [-0.950,1.980,-0.150]]), + (184, [[-77.170,-109.180,1020.820], [4.070,-9.070,9.680], [16.310,3.440,-3.630], [-2.150,4.060,0.800], [-0.010,12.030,12.600], [-1.970,3.890,1.430]]), + (185, [[-71.190,-121.030,1025.580], [7.480,-11.420,0.490], [14.200,9.260,-1.140], [-1.270,2.690,3.170], [0.000,1.980,17.640], [-1.270,2.720,3.230]]), + (186, [[-63.350,-130.560,1022.180], [7.990,-9.440,-3.400], [13.310,9.970,3.600], [-0.810,0.700,2.420], [0.000,-5.470,16.790], [-0.910,0.850,2.430]]), + (187, [[-55.270,-139.840,1018.800], [8.880,-8.590,-3.550], [12.320,10.870,4.490], [-1.070,0.870,0.810], [0.000,-6.180,16.540], [-1.090,0.870,0.810]]), + (188, [[-45.660,-147.660,1015.100], [9.900,-7.390,-3.360], [10.810,11.990,5.470], [-1.630,1.380,0.030], [-0.010,-6.690,16.290], [-1.620,1.360,0.020]]), + (189, [[-35.520,-154.600,1012.080], [11.080,-6.080,-1.980], [8.540,14.060,4.580], [-1.990,1.150,0.250], [-0.010,-5.000,17.000], [-1.970,1.130,0.240]]), + (190, [[-23.710,-159.680,1011.200], [11.970,-4.320,-1.790], [6.200,14.650,6.070], [-1.740,-0.440,2.510], [0.010,-6.170,16.490], [-1.790,-0.440,2.520]]), + (191, [[-11.720,-163.200,1008.530], [12.260,-2.580,-2.060], [4.480,13.030,10.390], [-2.160,-0.110,1.440], [-0.010,-10.220,14.200], [-2.140,-0.120,1.430]]), + (192, [[0.670,-164.820,1007.100], [12.710,-0.730,-0.480], [1.180,14.350,9.430], [-2.670,0.760,-0.810], [-0.010,-8.950,15.090], [-2.580,0.750,-0.810]]), + (193, [[13.556,-164.739,1007.051], [12.750,0.980,0.850], [-1.700,14.800,8.530], [-1.750,0.420,-1.040], [-0.320,-8.140,15.580], [-1.710,0.430,-1.040]]), + (194, [[26.116,-162.906,1008.217], [12.630,1.810,1.230], [-2.890,15.320,7.020], [-2.260,-0.160,-1.140], [-0.450,-6.810,16.270], [-2.230,-0.140,-1.140]]), + (195, [[38.730,-161.010,1010.040], [11.760,4.530,2.770], [-6.960,14.450,5.880], [-3.080,-0.420,-3.340], [-0.980,-6.490,16.380], [-3.120,-0.440,-3.350]]), + (196, [[50.563,-154.087,1013.645], [9.860,7.100,4.160], [-9.105,10.240,0.863], [-1.930,-0.520,-2.090], [-4.770,-2.540,17.360], [-1.970,-0.530,-2.090]]), + (197, [[58.745,-146.870,1017.469], [9.340,7.750,4.350], [-9.097,10.778,0.486], [-1.820,-1.100,1.290], [-3.670,-4.330,17.260], [-1.800,-1.060,1.300]]), + (198, [[67.501,-138.309,1022.249], [7.990,8.770,4.670], [-10.568,9.341,0.117], [-2.500,-1.970,-0.340], [-2.610,-6.250,17.940], [-2.590,-2.160,-0.410]]), + (199, [[74.433,-129.298,1027.145], [5.080,9.970,3.830], [-13.880,7.949,-1.165], [0.030,-2.060,0.330], [-2.126,-4.930,16.625], [-1.530,-1.170,0.490]]), + (200, [[77.560,-119.250,1030.430], [5.040,10.780,-0.510], [-14.630,6.980,2.780], [0.100,1.230,-1.770], [4.280,1.140,20.240], [0.400,1.970,-2.970]]), + (201, [[83.860,-109.530,1026.210], [6.930,6.510,-9.450], [-16.870,11.640,-4.350], [-2.810,1.300,-3.770], [7.220,14.780,13.520], [-1.240,0.300,-4.600]]), + (202, [[89.550,-108.420,1013.560], [3.910,0.860,-13.160], [-20.290,9.170,-5.430], [-1.850,-1.680,0.870], [8.380,20.860,4.280], [-2.140,-1.950,1.170]]), + (203, [[91.640,-107.830,1000.370], [1.780,0.550,-13.270], [-20.930,7.770,-2.480], [-0.800,-1.120,1.760], [7.590,21.030,2.070], [-0.860,-1.120,1.920]]), + (204, [[93.100,-107.330,987.040], [1.010,0.300,-13.420], [-22.050,6.680,-1.510], [-0.560,-0.650,1.350], [6.630,22.100,1.090], [-0.580,-0.660,1.490]]), + (205, [[93.660,-107.240,973.550], [-0.020,1.050,-13.410], [-22.120,6.280,0.520], [0.930,-2.250,1.330], [6.310,22.050,1.910], [0.920,-2.270,1.470]]), + (206, [[93.060,-105.250,960.320], [-0.770,2.250,-13.200], [-20.310,1.700,1.470], [0.920,-2.340,0.150], [1.920,20.030,3.650], [0.930,-2.360,0.170]]), + (207, [[92.120,-102.740,947.160], [-0.420,2.820,-13.160], [-20.350,1.100,0.880], [0.740,-0.110,-0.850], [1.250,19.860,4.690], [0.730,-0.090,-0.940]]), + (208, [[92.230,-99.620,934.040], [0.470,1.780,-13.240], [-18.820,1.460,-0.470], [1.010,0.010,-1.140], [1.390,18.640,2.850], [1.030,0.020,-1.270]]), + (209, [[93.040,-99.170,920.860], [1.210,-0.740,-13.330], [-18.310,1.150,-1.730], [0.280,-0.610,0.540], [1.230,18.350,-1.000], [0.280,-0.690,-0.020]]), + (210, [[94.650,-101.120,907.560], [-0.610,-1.620,-13.470], [-18.270,0.060,0.820], [-0.210,-1.550,3.280], [-0.050,18.160,-2.300], [-0.490,-1.710,2.070]]), + (211, [[91.840,-102.350,894.350], [-3.470,-1.640,-11.950], [-18.620,-2.390,5.740], [0.910,-2.200,3.650], [-3.000,19.300,-1.810], [-0.730,-2.580,3.870]]), + (212, [[87.880,-104.310,883.750], [-5.210,-2.130,-10.320], [-16.280,-4.940,9.250], [2.730,-2.870,2.500], [-6.690,20.720,-1.110], [0.460,-3.190,4.530]]), + (213, [[81.450,-106.590,873.900], [-6.990,-2.140,-9.270], [-12.430,-8.970,11.450], [0.330,-3.150,2.690], [-6.303,19.245,1.555], [2.230,-2.670,3.370]]), + (214, [[73.980,-108.570,865.270], [-8.310,-0.220,-8.520], [-12.268,-8.435,13.125], [-1.280,-1.760,1.510], [-6.633,18.953,4.087], [3.180,-1.460,2.050]]), + (215, [[65.060,-106.920,857.150], [-8.970,1.810,-7.690], [-14.794,-6.343,11.919], [1.280,0.430,-0.090], [-4.396,19.311,7.084], [2.480,0.160,0.520]]), + (216, [[56.070,-104.970,849.910], [-10.000,1.920,-6.880], [-14.078,-6.138,12.772], [2.490,5.000,1.790], [0.172,16.517,6.181], [2.280,4.690,1.100]]), + (217, [[45.110,-103.120,843.530], [-11.000,4.810,-5.260], [-9.460,-1.100,18.780], [2.560,4.660,2.880], [6.930,18.410,4.840], [2.420,4.350,0.870]]), + (218, [[34.860,-95.590,839.810], [-9.590,8.680,-2.670], [-6.610,-0.760,21.270], [0.940,-0.410,0.560], [12.620,13.250,3.920], [0.000,0.160,-0.540]]), + (219, [[26.140,-85.990,838.230], [-8.260,10.160,-2.000], [-7.290,-2.000,20.040], [-0.320,-0.120,-0.850], [14.710,10.710,6.320], [-1.050,-0.470,0.410]]), + (220, [[18.390,-75.310,835.820], [-8.420,10.080,-2.660], [-7.370,-0.990,19.530], [-0.560,0.610,0.800], [16.030,10.170,6.780], [-0.360,-0.280,1.590]]), + (221, [[9.350,-65.880,832.920], [-11.900,13.240,-4.280], [-8.470,-0.620,21.630], [-0.850,0.480,1.280], [17.760,11.500,7.330], [-1.390,-0.780,1.040]]), + (222, [[-5.120,-48.680,827.110], [-17.030,21.160,-7.340], [-8.980,0.200,21.430], [-0.080,1.010,-1.640], [17.760,11.500,7.330], [-1.390,-0.780,1.040]]) + ] ), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-4', + 'name': get_esophagus_term('esophagus')[0], + 'ontId': get_esophagus_term('esophagus')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1', + 'name': get_esophagus_term('cervical part of esophagus')[0], + 'ontId': get_esophagus_term('cervical part of esophagus')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '2-3', + 'name': get_esophagus_term('thoracic part of esophagus')[0], + 'ontId': get_esophagus_term('thoracic part of esophagus')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '4', + 'name': get_esophagus_term('abdominal part of esophagus')[0], + 'ontId': get_esophagus_term('abdominal part of esophagus')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '5-18', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '5-6', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '7-10', + 'name': get_stomach_term('fundus of stomach')[0], + 'ontId': get_stomach_term('fundus of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '11-14', + 'name': get_stomach_term('body of stomach')[0], + 'ontId': get_stomach_term('body of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '15-16', + 'name': get_stomach_term('pyloric antrum')[0], + 'ontId': get_stomach_term('pyloric antrum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '17', + 'name': get_stomach_term('pyloric canal')[0], + 'ontId': get_stomach_term('pyloric canal')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '18', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '19-169', + 'name': get_smallintestine_term('small intestine')[0], + 'ontId': get_smallintestine_term('small intestine')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '19-23', + 'name': get_smallintestine_term('duodenum')[0], + 'ontId': get_smallintestine_term('duodenum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '24-100', + 'name': get_smallintestine_term('jejunum')[0], + 'ontId': get_smallintestine_term('jejunum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '101-169', + 'name': get_smallintestine_term('ileum')[0], + 'ontId': get_smallintestine_term('ileum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '170-173', + 'name': get_cecum_term('caecum')[0], + 'ontId': get_cecum_term('caecum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '170-171', + 'name': get_cecum_term('ileum part of cecum')[0], + 'ontId': get_cecum_term('ileum part of cecum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '174-221', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '174-184', + 'name': get_colon_term('ascending colon')[0], + 'ontId': get_colon_term('ascending colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '185-199', + 'name': get_colon_term('transverse colon')[0], + 'ontId': get_colon_term('transverse colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '200-222', + 'name': get_colon_term('descending colon')[0], + 'ontId': get_colon_term('descending colon')[1] + }] + }) + + +class MeshType_3d_gastrointestinaltract1(Scaffold_base): + ''' + Generates a 3-D gastrointestinal tract mesh with variable numbers of elements around, along the central line, + and through wall. The tract is created by following an annotated network layout and calling scaffold function to + generate the respective segment along the central line profile. + ''' + + @staticmethod + def getName(): + return '3D Gastrointestinal Tract 1' + + @staticmethod + def getParameterSetNames(): + return [ + 'Default', + 'Human 1'] + + @classmethod + def getDefaultOptions(cls, parameterSetName='Default'): + esophagusOption = ScaffoldPackage(MeshType_3d_esophagus1, defaultParameterSetName='Human 1') + stomachOption = ScaffoldPackage(MeshType_3d_stomach1, defaultParameterSetName='Human 2') + smallIntestineOption = ScaffoldPackage(MeshType_3d_smallintestine1, defaultParameterSetName='Human 1') + cecumOption = ScaffoldPackage(MeshType_3d_cecum1, defaultParameterSetName='Human 2') + colonOption = ScaffoldPackage(MeshType_3d_colon1, defaultParameterSetName='Human 3') + options = {'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), + 'Esophagus': esophagusOption, + 'Stomach': stomachOption, + 'Small intestine': smallIntestineOption, + 'Cecum': cecumOption, + 'Colon': colonOption, + 'Use linear through wall': True, + 'Refine': False, + 'Refine number of elements surface': 4, + 'Refine number of elements through wall': 1 + } + + return options + + @staticmethod + def getOrderedOptionNames(): + return [ + 'Network layout', + 'Esophagus', + 'Stomach', + 'Small intestine', + 'Cecum', + 'Colon', + 'Use linear through wall', + 'Refine', + 'Refine number of elements surface', + 'Refine number of elements through wall'] + + @classmethod + def getOptionValidScaffoldTypes(cls, optionName): + if optionName == 'Network layout': + return [MeshType_1d_network_layout1] + if optionName == 'Esophagus': + return [MeshType_3d_esophagus1] + if optionName == 'Stomach': + return [MeshType_3d_stomach1] + if optionName == 'Small intestine': + return [MeshType_3d_smallintestine1] + if optionName == 'Cecum': + return [MeshType_3d_cecum1] + if optionName == 'Colon': + return [MeshType_3d_colon1] + return [] + + @classmethod + def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): + if optionName == 'Network layout': + return cls.getParameterSetNames() + assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ + cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ + 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() + return scaffoldType.getParameterSetNames() + + @classmethod + def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=None): + ''' + :param parameterSetName: Name of valid parameter set for option Scaffold, or None for default. + :return: ScaffoldPackage. + ''' + if parameterSetName: + assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ + 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ + ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() + if optionName == 'Network layout': + if not parameterSetName: + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) + if optionName == 'Esophagus': + if not parameterSetName: + parameterSetName = scaffoldType.getParameterSetNames()[0] + return ScaffoldPackage(scaffoldType, defaultParameterSetName=parameterSetName) + if optionName == 'Stomach': + if not parameterSetName: + parameterSetName = scaffoldType.getParameterSetNames()[0] + return ScaffoldPackage(scaffoldType, defaultParameterSetName=parameterSetName) + if optionName == 'Small intestine': + if not parameterSetName: + parameterSetName = scaffoldType.getParameterSetNames()[0] + return ScaffoldPackage(scaffoldType, defaultParameterSetName=parameterSetName) + if optionName == 'Cecum': + if not parameterSetName: + parameterSetName = scaffoldType.getParameterSetNames()[0] + return ScaffoldPackage(scaffoldType, defaultParameterSetName=parameterSetName) + if optionName == 'Colon': + if not parameterSetName: + parameterSetName = scaffoldType.getParameterSetNames()[0] + return ScaffoldPackage(scaffoldType, defaultParameterSetName=parameterSetName) + assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' + + @classmethod + def checkOptions(cls, options): + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) + if not options['Esophagus'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Esophagus'): + options['Esophagus'] = cls.getOptionScaffoldPackage('Esophagus', MeshType_3d_esophagus1) + if not options['Stomach'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Stomach'): + options['Stomach'] = cls.getOptionScaffoldPackage('Stomach', MeshType_3d_stomach1) + if not options['Small intestine'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Small intestine'): + options['Small intestine'] = cls.getOptionScaffoldPackage('Small intestine', MeshType_3d_smallintestine1) + if not options['Cecum'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Cecum'): + options['Cecum'] = cls.getOptionScaffoldPackage('Cecum', MeshType_3d_cecum1) + if not options['Colon'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Colon'): + options['Colon'] = cls.getOptionScaffoldPackage('Colon', MeshType_3d_colon1) + for key in [ + 'Refine number of elements surface', + 'Refine number of elements through wall']: + if options[key] < 1: + options[key] = 1 + cls.updateSubScaffoldOptions(options) + + + @classmethod + def updateSubScaffoldOptions(cls, options): + ''' + Update sub-scaffold options which depend on parent options. + ''' + esoOptions = options['Esophagus'] + esoSettings = esoOptions.getScaffoldSettings() + esoSettings['Number of elements through wall'] = 1 + stomachOptions = options['Stomach'] + stomachSettings = stomachOptions.getScaffoldSettings() + stomachSettings['Number of elements through wall'] = 1 + smallIntestineOptions = options['Small intestine'] + smallIntestineSettings = smallIntestineOptions.getScaffoldSettings() + smallIntestineSettings['Number of elements through wall'] = 1 + cecumOptions = options['Cecum'] + cecumSettings = cecumOptions.getScaffoldSettings() + cecumSettings['Number of elements through wall'] = 1 + colonOptions = options['Colon'] + colonSettings = colonOptions.getScaffoldSettings() + colonSegmentOptions = colonSettings['Segment profile'] + colonSegmentSettings = colonSegmentOptions.getScaffoldSettings() + colonSegmentSettings['Number of elements through wall'] = 1 + + + @classmethod + def generateBaseMesh(cls, region, options): + """ + Generate the base tricubic Hermite mesh. + :param region: Zinc region to define model in. Must be empty. + :param options: Dict containing options. See getDefaultOptions(). + :return: annotationGroups + """ + cls.updateSubScaffoldOptions(options) + networkLayout = options['Network layout'] + esophagusOptions = options['Esophagus'] + stomachOptions = options['Stomach'] + smallIntestineOptions = options['Small intestine'] + cecumOptions = options['Cecum'] + colonOptions = options['Colon'] + esophagusSettings = esophagusOptions.getScaffoldSettings() + stomachSettings = stomachOptions.getScaffoldSettings() + smallIntestineSettings = smallIntestineOptions.getScaffoldSettings() + cecumSettings = cecumOptions.getScaffoldSettings() + colonSettings = colonOptions.getScaffoldSettings() + + esophagusSettings['Use linear through wall'] = options['Use linear through wall'] + stomachSettings['Use linear through wall'] = options['Use linear through wall'] + smallIntestineSettings['Use linear through wall'] = options['Use linear through wall'] + cecumSettings['Use linear through wall'] = options['Use linear through wall'] + colonSettings['Use linear through wall'] = options['Use linear through wall'] + + nextNodeIdentifier = 1 + nextElementIdentifier = 1 + + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + + # Network layout + gastroTermsAlong = [['esophagus', 'cervical part of esophagus', 'thoracic part of esophagus', + 'abdominal part of esophagus'], + ['stomach', 'fundus of stomach', 'body of stomach', 'pyloric antrum', 'pyloric canal', + 'duodenum part of stomach', 'esophagus part of stomach'], + ['small intestine', 'duodenum', 'jejunum', 'ileum'], + ['caecum', 'ileum part of cecum'], + ['colon', 'ascending colon', 'transverse colon', 'descending colon']] + + for section in range(len(gastroTermsAlong)): + fm = region.getFieldmodule() + coordinates = findOrCreateFieldCoordinates(fm) + allAnnotationGroups = [] + + if gastroTermsAlong[section][0] == 'esophagus': + esoNetworkLayout = EsophagusNetworkLayout(region, networkLayout, gastroTermsAlong[section]) + annotationGroupsEsophagus, nextNodeIdentifier, nextElementIdentifier, nodesIdEsoDistal,\ + xEsoDistal, d1EsoDistal, d2EsoDistal, d3EsoDistal = \ + createEsophagusMesh3d(region, esophagusSettings, esoNetworkLayout, nextNodeIdentifier, + nextElementIdentifier) + + elif gastroTermsAlong[section][0] == 'stomach': + stomachNetworkLayout = StomachNetworkLayout(region, networkLayout, gastroTermsAlong[section], + esoSegmentIdx=0, stomachSegmentIdx=[1,2]) + annotationGroupsStomach, nextNodeIdentifier, nextElementIdentifier, _, nodesIdStomachDistal,\ + xStomachDistal, d1StomachDistal, d2StomachDistal, d3StomachDistal, arclengthCPStomachDistal, xPrev, \ + d2Prev = \ + createStomachMesh3d(region, fm, coordinates, gastroTermsAlong[section], + allAnnotationGroups, stomachNetworkLayout, + options=stomachSettings, nodeIdentifier=nextNodeIdentifier, + elementIdentifier=nextElementIdentifier, + nodeIdProximalEso=nodesIdEsoDistal, xProximalEso=xEsoDistal, + d1ProximalEso=d1EsoDistal, d2ProximalEso=d2EsoDistal, d3ProximalEso=d3EsoDistal) + nearLCGroup = getAnnotationGroupForTerm(annotationGroupsStomach, + ("elements adjacent to lesser curvature", "None")) + annotationGroupsStomach.remove(nearLCGroup) + + elif gastroTermsAlong[section][0] == 'small intestine': + smallIntestineNetworkLayout = SmallIntestineNetworkLayout(region, networkLayout, + gastroTermsAlong[section]) + + annotationGroupsSmallIntestine, nextNodeIdentifier, nextElementIdentifier, \ + nodesIdSmallIntestineDistal, xSmallIntestineDistal, d1SmallIntestineDistal, d2SmallIntestineDistal, \ + d3SmallIntestineDistal, xNext, d2Next = \ + createSmallIntestineMesh3d(region, smallIntestineSettings, smallIntestineNetworkLayout, + nextNodeIdentifier, nextElementIdentifier, + nodeIdProximal=nodesIdStomachDistal, xProximal=xStomachDistal, + d1Proximal=d1StomachDistal, d2Proximal=d2StomachDistal, + d3Proximal=d3StomachDistal, arclengthCPProximal=arclengthCPStomachDistal) + + # Smooth d2 at intersection between stomach and small intestine + cache = fm.createFieldcache() + nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + for n3 in range(len(nodesIdStomachDistal)): + for n in range(len(nodesIdStomachDistal[n3])): + newD2 = interp.smoothCubicHermiteDerivativesLine( + [xPrev[n3][n], xStomachDistal[n3][n], xNext[n3][n]], + [d2Prev[n3][n], d2StomachDistal[n3][n], d2Next[n3][n]], + fixStartDerivative=True, fixEndDerivative=True)[1] + + cache.setNode(nodes.findNodeByIdentifier(nodesIdStomachDistal[n3][n])) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, newD2) + + elif gastroTermsAlong[section][0] == 'caecum': + cecumNetworkLayout = CecumNetworkLayout(region, networkLayout, gastroTermsAlong[section], + ileumSegmentIdx=2, cecumSegmentIdx=[3,4]) + annotationGroupsCecum, nextNodeIdentifier, nextElementIdentifier, nodesIdCecumDistal, \ + xCecumDistal, d1CecumDistal, d2CecumDistal, d3CecumDistal = \ + createCecumMesh3d(region, cecumSettings, cecumNetworkLayout, nextNodeIdentifier, + nextElementIdentifier, nodeIdProximalIleum=nodesIdSmallIntestineDistal, + xProximalIleum=xSmallIntestineDistal, d1ProximalIleum=d1SmallIntestineDistal, + d2ProximalIleum=d2SmallIntestineDistal, d3ProximalIleum=d3SmallIntestineDistal) + + elif gastroTermsAlong[section][0] == 'colon': + colonNetworkLayout = ColonNetworkLayout(region, networkLayout, gastroTermsAlong[section]) + annotationGroupsColon, nextNodeIdentifier, nextElementIdentifier, \ + nodesIdColonDistal, xColonDistal, d1ColonDistal, d2ColonDistal, d3ColonDistal = \ + createColonMesh3d(region, colonSettings, colonNetworkLayout, nextNodeIdentifier, + nextElementIdentifier, nodeIdProximal=nodesIdCecumDistal, + xProximal=xCecumDistal, d1Proximal=d1CecumDistal, d2Proximal=d2CecumDistal, + d3Proximal=d3CecumDistal) + + del tmpRegion + + annotationGroups = mergeAnnotationGroups(annotationGroupsEsophagus, annotationGroupsStomach, + annotationGroupsSmallIntestine, annotationGroupsCecum, + annotationGroupsColon) + + return annotationGroups, None + + @classmethod + def refineMesh(cls, meshrefinement, options): + """ + Refine source mesh into separate region, with change of basis. + :param meshrefinement: MeshRefinement, which knows source and target region. + :param options: Dict containing options. See getDefaultOptions(). + """ + refineElementsCountAround = options['Refine number of elements surface'] + refineElementsCountAlong = options['Refine number of elements surface'] + refineElementsCountThroughWall = options['Refine number of elements through wall'] + + meshrefinement.refineAllElementsCubeStandard3d(refineElementsCountAround, refineElementsCountAlong, + refineElementsCountThroughWall) + return + +class SectionNetworkLayout: + """ + Generates sampled network layout for GI Tract scaffold. + """ + def __init__(self, arcLengthOfGroupsAlong, cxGroups, cd1Groups, cd2Groups,cd3Groups, cd12Groups, cd13Groups): + """ + :param region: Zinc region to define model in. + :param networkLayout: Network layout subscaffold from meshtype_1d_networklayout1 + :param stomachTermsAlong: Annotation terms along length of network layout + """ + self.arcLengthOfGroupsAlong = arcLengthOfGroupsAlong + self.cxGroups = cxGroups + self.cd1Groups = cd1Groups + self.cd2Groups = cd2Groups + self.cd3Groups = cd3Groups + self.cd12Groups = cd12Groups + self.cd13Groups = cd13Groups diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_ostium2.py b/src/scaffoldmaker/meshtypes/meshtype_3d_ostium2.py new file mode 100644 index 00000000..e4871996 --- /dev/null +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_ostium2.py @@ -0,0 +1,1092 @@ +""" +Generates a single or double/common ostium, where one or more vessels enters a chamber. +""" + +from __future__ import division + +import copy +import math + +from cmlibs.utils.zinc.field import findOrCreateFieldCoordinates +from cmlibs.zinc.element import Element, Elementbasis +from cmlibs.zinc.field import Field +from cmlibs.zinc.node import Node +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 +from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base +from scaffoldmaker.scaffoldpackage import ScaffoldPackage +from scaffoldmaker.utils import interpolation as interp +from scaffoldmaker.utils import vector +from scaffoldmaker.utils.annulusmesh import createAnnulusMesh3d +from scaffoldmaker.utils.eftfactory_tricubichermite import eftfactory_tricubichermite +from scaffoldmaker.utils.geometry import sampleEllipsePoints, getApproximateEllipsePerimeter +from scaffoldmaker.utils.meshrefinement import MeshRefinement +from scaffoldmaker.utils.tracksurface import TrackSurface, calculate_surface_axes +from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ + get_nodeset_path_field_parameters + + +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default"): + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, + Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.00, 0.00, 1.00], [0.00, 0.00, -0.50], [0.00, 0.50, 0.00], [0.00, 0.00, 0.00], [1.00, 0.00, 0.00], [0.00, 0.00, 0.00]]), + (2, [[0.00, 0.00, 0.50], [0.00, 0.00, -0.50], [0.00, 1.00, 0.00], [0.00, 0.00, 0.00], [1.00, 0.00, 0.00], [0.00, 0.00, 0.00]]), + (3, [[0.00, 0.00, 0.00], [0.00, 0.00, -0.50], [0.00, 1.00, 0.00], [0.00, 0.00, 0.00], [2.00, 0.00, 0.00], [0.00, 0.00, 0.00]])]) + }) + +class MeshType_3d_ostium2(Scaffold_base): + """ + Generates a 3-D single or double/common ostium inlet or outlet. + """ + + @staticmethod + def getName(): + return '3D Ostium 2' + + @classmethod + def getDefaultOptions(cls, parameterSetName='Default'): + options = { + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), + # 'Number of vessels': 1, + # 'Number of elements across common': 2, + 'Number of elements around ostium': 8, + 'Number of elements along': 2, + 'Number of elements through wall': 1, + 'Unit scale': 1.0, + 'Outlet': False, + 'Ostium wall thickness': 0.08, + 'Ostium wall relative thicknesses': [1.0], + # 'Ostium inter-vessel distance': 0.8, + # 'Ostium inter-vessel height': 0.0, + 'Use linear through ostium wall': False, + 'Vessel wall thickness': 0.04, + 'Vessel wall relative thicknesses': [1.0], + 'Use linear through vessel wall': True, + # 'Use cross derivatives': False, + 'Refine': False, + 'Refine number of elements around': 4, + 'Refine number of elements along': 4, + 'Refine number of elements through wall': 1 + } + + return options + + @staticmethod + def getOrderedOptionNames(): + return [ + 'Network layout', + # 'Number of vessels', + # 'Number of elements across common', + 'Number of elements around ostium', + 'Number of elements along', + 'Number of elements through wall', + 'Unit scale', + 'Outlet', + 'Ostium wall thickness', + 'Ostium wall relative thicknesses', + # 'Ostium inter-vessel distance', + # 'Ostium inter-vessel height', + 'Use linear through ostium wall', + 'Vessel wall thickness', + 'Vessel wall relative thicknesses', + 'Use linear through vessel wall', + # 'Use cross derivatives', # not implemented + 'Refine', + 'Refine number of elements around', + 'Refine number of elements along', + 'Refine number of elements through wall' + ] + + @classmethod + def getOptionValidScaffoldTypes(cls, optionName): + if optionName == 'Network layout': + return [MeshType_1d_network_layout1] + + @classmethod + def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): + if optionName == 'Network layout': + return cls.getParameterSetNames() + assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ + cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ + 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() + return scaffoldType.getParameterSetNames() + + @classmethod + def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=None): + """ + :param parameterSetName: Name of valid parameter set for option Scaffold, or None for default. + :return: ScaffoldPackage. + """ + if parameterSetName: + assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ + 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ + ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() + if optionName == 'Network layout': + if not parameterSetName: + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) + assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' + + @classmethod + def checkOptions(cls, options): + dependentChanges = False + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) + # vesselsCount = options['Number of vessels'] + # if vesselsCount != 1: + # vesselsCount = options['Number of vessels'] = 1 + for key in [ + # 'Number of elements across common', + 'Number of elements along', + 'Number of elements through wall', + 'Refine number of elements around', + 'Refine number of elements along', + 'Refine number of elements through wall']: + if options[key] < 1: + options[key] = 1 + # if options['Number of elements around ostium'] < 2 * vesselsCount: + # options['Number of elements around ostium'] = 2 * vesselsCount + # dependentChanges = True # because can happen by changing number of vessels + # currently must have even number around ostium if multiple vessels: + # if (vesselsCount > 1) and (options['Number of elements around ostium'] % 2): + # options['Number of elements around ostium'] += 1 + # dependentChanges = True # because can happen by changing number of vessels + for key in [ + 'Unit scale', + 'Ostium wall thickness', + # 'Ostium inter-vessel distance', + 'Vessel wall thickness']: + if options[key] < 0.0: + options[key] = 0.0 + elementsThroughWall = options['Number of elements through wall'] + ostiumThicknessProportionsCountKey = 'Ostium wall relative thicknesses' + vesselThicknessProportionsCountKey = 'Vessel wall relative thicknesses' + ostiumWallCount = len(options[ostiumThicknessProportionsCountKey]) + vesselWallCount = len(options[vesselThicknessProportionsCountKey]) + if elementsThroughWall == 1: + options[ostiumThicknessProportionsCountKey] = options[vesselThicknessProportionsCountKey] = [1.0] + if ostiumWallCount < elementsThroughWall: + options[ostiumThicknessProportionsCountKey] += \ + [options[ostiumThicknessProportionsCountKey][-1] for i in range(elementsThroughWall - ostiumWallCount)] + dependentChanges = True + elif ostiumWallCount > elementsThroughWall: + options[ostiumThicknessProportionsCountKey] = \ + options[ostiumThicknessProportionsCountKey][:elementsThroughWall] + dependentChanges = True + if vesselWallCount < elementsThroughWall: + options[vesselThicknessProportionsCountKey] += \ + [options[vesselThicknessProportionsCountKey][-1] for i in range(elementsThroughWall - vesselWallCount)] + dependentChanges = True + elif vesselWallCount > elementsThroughWall: + options[vesselThicknessProportionsCountKey] = \ + options[vesselThicknessProportionsCountKey][:elementsThroughWall] + dependentChanges = True + return dependentChanges + + @classmethod + def generateBaseMesh(cls, region, options): + """ + Generate the base tricubic/bicubic Hermite mesh. + :param region: Zinc region to define model in. Must be empty. + :param options: Dict containing options. See getDefaultOptions(). + :return: [] empty list of AnnotationGroup, None + """ + unitScale = options['Unit scale'] + centralPath = options['Network layout'] + centralPath = CentralPath(region, centralPath, unitScale) + + # interVesselDistance = unitScale * options['Ostium inter-vessel distance'] + ox = centralPath.cxPath[-1] + od2 = centralPath.cd2Path[-1] + od3 = centralPath.cd3Path[-1] + scale = 4.0 * vector.magnitude([od2[c] + od3[c] for c in range(3)]) + + nxOffset = [vector.setMagnitude([-od3[c] - od2[c] for c in range(3)], scale), + vector.setMagnitude([od3[c] - od2[c] for c in range(3)], scale), + vector.setMagnitude([-od3[c] + od2[c] for c in range(3)], scale), + vector.setMagnitude([od3[c] + od2[c] for c in range(3)], scale)] + + nx = [] + for n in range(len(nxOffset)): + nx.append([ox[c] + nxOffset[n][c] for c in range(3)]) + + nd1 = [vector.setMagnitude(od3, 2.0 * scale)] * 4 + nd2 = [vector.setMagnitude(od2, 2.0 * scale)] * 4 + + trackSurface = TrackSurface(1, 1, nx, nd1, nd2) + generateOstiumMesh(region, options, trackSurface, centralPath) + + return [], None + + @classmethod + def refineMesh(cls, meshrefinement, options): + """ + :param meshrefinement: MeshRefinement, which knows source and target region. + :param options: Dict containing options. See getDefaultOptions(). + """ + assert isinstance(meshrefinement, MeshRefinement) + refineElementsCountAround = options['Refine number of elements around'] + refineElementsCountAlong = options['Refine number of elements along'] + refineElementsCountThroughWall = options['Refine number of elements through wall'] + meshrefinement.refineAllElementsCubeStandard3d(refineElementsCountAround, refineElementsCountAlong, + refineElementsCountThroughWall) + + +def getOstiumElementsCountsAroundVessels(elementsCountAroundOstium, elementsCountAcross, vesselsCount): + """ + Determine numbers of elements around each vessel to fit numbers of elements around ostium. + :param elementsCountAroundOstium: Number of elements around outside of ostium. + Minimum of 2 + 2 * vesselsCount. Must be even if more than 1 vessels. + :param elementsCountAcross: Number of elements across ostium between multiple vessels. + Unused if vesselsCount is 1. + :param vesselsCount: Number of vessels from 1 to 3. + :return: List of numbers of elements around each vessel to fit numbers around ostium, + number of elements mid side (non-zero only for 3+ vessels). + """ + assert 1 <= vesselsCount <= 3 + assert elementsCountAroundOstium >= 2 * vesselsCount + assert (1 == vesselsCount) or (elementsCountAroundOstium % 2 == 0) + assert elementsCountAcross > 0 + if vesselsCount == 1: + return [elementsCountAroundOstium], 0 + if vesselsCount == 2: + count = elementsCountAroundOstium // 2 + elementsCountAcross + return [count, count], 0 + # vesselsCount == 3: + # Around oinc Total:Vessels 1 Total:Vessels 2 + # 6 1 8: 3-4-3 10: 4-6-4 + # 8 1 10: 4-4-4 12: 5-6-5 + # 10 1 12: 5-4-5 14: 6-6-6 + # 12 2 14: 5-6-5 16: 6-8-6 + # 14 2 16: 6-6-6 18: 7-8-7 + # 16 2 18: 7-6-7 20: 8-8-8 + elementsCountAroundMid = ((elementsCountAroundOstium + 1) // 6) + countInner = 2 * (elementsCountAroundMid + elementsCountAcross) + countOuter = (elementsCountAroundOstium - 2 * elementsCountAroundMid) // 2 + elementsCountAcross + return [countOuter, countInner, countOuter], elementsCountAroundMid + + +def generateOstiumMesh(region, options, trackSurface, centralPath, startNodeIdentifier=1, startElementIdentifier=1, + nodeIdProximal=[], xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[], + vesselMeshGroups=None, ostiumMeshGroups=None, wallAnnotationGroups=None, coordinates=None): + """ + Generates an ostium mesh in the region using a central path and parameter options. + :param region: Region to create elements in. + :param options: Parameter options for ostium scaffold. + :param trackSurface: Track surface for building ostium scaffold. + :param centralPath: Central path through the axis of the ostium scaffold. + :param startNodeIdentifier: First node identifier to use. + :param startElementIdentifier: First element identifier to use. + :param nodeIdProximal, xProximal, d1Proximal, d2Proximal, d3Proximal: Identifier, coordinates and derivatives of + nodes to use on proximal end of vessel. + :param vesselMeshGroups: List (over number of vessels) of list of mesh groups to add vessel elements to. + :param ostiumMeshGroups: List of mesh groups to add only row of elements at ostium end to. + :param wallAnnotationGroups: list of annotation groups to add to wall elements. + :return: nextNodeIdentifier, nextElementIdentifier, Ostium points tuple + (ox[n3][n1][c], od1[n3][n1][c], od2[n3][n1][c], od3[n3][n1][c], oNodeId[n3][n1], oPositions). + """ + + vesselsCount = 1 #options['Number of vessels'] + elementsCountAroundOstium = options['Number of elements around ostium'] + # elementsCountAcross = options['Number of elements across common'] + elementsCountAroundVessel = elementsCountAroundOstium + # elementsCountsAroundVessels, elementsCountAroundMid = \ + # getOstiumElementsCountsAroundVessels(elementsCountAroundOstium, elementsCountAcross, vesselsCount) + # elementsCountAroundEnd = (elementsCountAroundOstium - 2 * elementsCountAroundMid) // 2 + # print('\nvesselsCount', vesselsCount, 'elementsCountsAroundOstium', elementsCountAroundOstium, + # 'elementsCountAcross', elementsCountAcross) + # print('--> elementsCountsAroundVessels', elementsCountsAroundVessels, + # 'elementsCountAroundMid', elementsCountAroundMid) + elementsCountAlong = options['Number of elements along'] + elementsCountThroughWall = options['Number of elements through wall'] + unitScale = options['Unit scale'] + + isOutlet = options['Outlet'] + ostiumWallThickness = unitScale * options['Ostium wall thickness'] + ostiumWallThicknessProportionsUI = copy.deepcopy(options['Ostium wall relative thicknesses']) + # interVesselHeight = unitScale * options['Ostium inter-vessel height'] + # interVesselDistance = unitScale * options['Ostium inter-vessel distance'] if (vesselsCount > 1) else 0.0 + # halfInterVesselDistance = 0.5 * interVesselDistance + useCubicHermiteThroughOstiumWall = not(options['Use linear through ostium wall']) + vesselWallThickness = unitScale * options['Vessel wall thickness'] + vesselWallThicknessProportionsUI = copy.deepcopy(options['Vessel wall relative thicknesses']) + useCubicHermiteThroughVesselWall = not(options['Use linear through vessel wall']) + useCrossDerivatives = False # options['Use cross derivatives'] # not implemented + # ostiumRadius = vector.magnitude(centralPath.cd2Path[-1]) + + arcLength = 0.0 + for e in range(len(centralPath.cxPath) - 1): + arcLength += interp.getCubicHermiteArcLength(centralPath.cxPath[e], centralPath.cd1Path[e], + centralPath.cxPath[e + 1], centralPath.cd1Path[e + 1]) + + fm = region.getFieldmodule() + fm.beginChange() + cache = fm.createFieldcache() + if not coordinates: + coordinates = findOrCreateFieldCoordinates(fm) + + nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + nodeIdentifier = startNodeIdentifier + + nodetemplate = nodes.createNodetemplate() + nodetemplate.defineField(coordinates) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_VALUE, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS1, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS2, 1) + nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS3, 1) + nodetemplateLinearS3 = nodes.createNodetemplate() + nodetemplateLinearS3.defineField(coordinates) + nodetemplateLinearS3.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_VALUE, 1) + nodetemplateLinearS3.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS1, 1) + nodetemplateLinearS3.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS2, 1) + + mesh = fm.findMeshByDimension(3) + elementIdentifier = startElementIdentifier + + # track points in shape of ostium + # get directions in plane of surface at centre: + centrePosition = trackSurface.findNearestPosition(centralPath.cxPath[-1]) + cx, cd1, cd2 = trackSurface.evaluateCoordinates(centrePosition, True) + trackDirection1, trackDirection2, centreNormal = calculate_surface_axes(cd1, cd2, cd1) + + ellipsePerimeter = getApproximateEllipsePerimeter(vector.magnitude(centralPath.cd2Path[-1]), + vector.magnitude(centralPath.cd3Path[-1])) + # halfCircumference = math.pi * ostiumRadius + # circumference = 2.0 * halfCircumference + distance = 0.0 + # elementLengthAroundOstiumMid = 0.0 + # vesselsSpanAll = interVesselDistance * (vesselsCount - 1) + # vesselsSpanMid = interVesselDistance * (vesselsCount - 2) + + elementLengthAroundOstiumEnd = ellipsePerimeter / elementsCountAroundOstium + + # if vesselsCount == 1: + # elementLengthAroundOstiumEnd = circumference / elementsCountAroundOstium + # vesselOstiumPositions = [centrePosition] + # ocx = [cx] + # ocd1 = [trackDirection1] + # ocd2 = [trackDirection2] + # ocd3 = [centreNormal] + + # else: + # elementLengthAroundOstiumEnd = (circumference + 2.0 * interVesselDistance) / \ + # (elementsCountAroundOstium - 2 * elementsCountAroundMid) + # if elementsCountAroundMid > 0: + # elementLengthAroundOstiumMid = interVesselDistance * (vesselsCount - 2) / elementsCountAroundMid + # vesselOstiumPositions = [] + # ocx = [] + # ocd1 = [] + # ocd2 = [] + # ocd3 = [] + # for v in range(vesselsCount): + # vesselOstiumPositions.append(trackSurface.trackVector(centrePosition, trackDirection1, + # (v / (vesselsCount - 1) - 0.5) * vesselsSpanAll)) + # x, d1, d2 = trackSurface.evaluateCoordinates(vesselOstiumPositions[-1], -1) + # d1, d2, d3 = calculate_surface_axes(d1, d2, trackDirection1) + # ocx .append(x) + # ocd1.append(d1) + # ocd2.append(d2) + # ocd3.append(d3) + + # coordinates around ostium + ox = [[] for n3 in range(elementsCountThroughWall + 1)] + od1 = [[] for n3 in range(elementsCountThroughWall + 1)] + od2 = [[] for n3 in range(elementsCountThroughWall + 1)] + od3 = [[] for n3 in range(elementsCountThroughWall + 1)] + oPositions = [] + ostiumWallThicknessProportions = [ostiumWallThicknessProportion / sum(ostiumWallThicknessProportionsUI) + for ostiumWallThicknessProportion in ostiumWallThicknessProportionsUI] + vesselWallThicknessProportions = [vesselWallThicknessProportion / sum(vesselWallThicknessProportionsUI) + for vesselWallThicknessProportion in vesselWallThicknessProportionsUI] + + ostiumWallThicknessProportions.append(ostiumWallThicknessProportions[-1]) + vesselWallThicknessProportions.append(vesselWallThicknessProportions[-1]) + + xOstiumOuter, d1OstiumOuter = sampleEllipsePoints(centralPath.cxPath[-1], centralPath.cd2Path[-1], + centralPath.cd3Path[-1], 0.0, 2.0*math.pi, + elementsCountAroundOstium) + del xOstiumOuter[-1], d1OstiumOuter[-1] + + for n1 in range(elementsCountAroundOstium): + elementLength = elementLengthAroundOstiumEnd + # if distance <= (vesselsSpanMid + halfInterVesselDistance): + # print('1') + # position = trackSurface.trackVector(centrePosition, trackDirection1, 0.5 * vesselsSpanMid - distance) + # sideDirection = trackDirection2reverse + # if n1 < elementsCountAroundMid: + # elementLength = elementLengthAroundOstiumMid + # elif distance < (vesselsSpanMid + halfInterVesselDistance + halfCircumference): + # position = vesselOstiumPositions[0] + # angleRadians = (distance - (vesselsSpanMid + halfInterVesselDistance)) / ostiumRadius + # w1 = -math.sin(angleRadians) + # w2 = -math.cos(angleRadians) + # print('2', math.degrees(w1), math.degrees(w2)) + # sideDirection = [(w1 * trackDirection1[c] + w2 * trackDirection2[c]) for c in range(3)] + # elif distance < (2.0 * vesselsSpanMid + halfInterVesselDistance + halfCircumference + interVesselDistance): + # position = trackSurface.trackVector(centrePosition, trackDirection1, distance - + # (1.5 * vesselsSpanMid + interVesselDistance + halfCircumference)) + # sideDirection = trackDirection2 + # if 0 <= (n1 - elementsCountAroundEnd - elementsCountAroundMid) < elementsCountAroundMid: + # elementLength = elementLengthAroundOstiumMid + # print('3') + # elif distance < (2.0 * vesselsSpanMid + halfInterVesselDistance + circumference + interVesselDistance): + # position = vesselOstiumPositions[-1] + # angleRadians = (distance - (2.0 * vesselsSpanMid + halfInterVesselDistance + halfCircumference + + # interVesselDistance)) / ostiumRadius + # w1 = math.sin(angleRadians) + # w2 = math.cos(angleRadians) + # sideDirection = [(w1 * trackDirection1[c] + w2 * trackDirection2[c]) for c in range(3)] + # print('4', math.degrees(w1), math.degrees(w2)) + # else: + # position = \ + # trackSurface.trackVector(centrePosition, trackDirection1, + # 0.5 * vesselsSpanMid + (circumference + 2.0 * + # (vesselsSpanMid + interVesselDistance)) - distance) + # sideDirection = trackDirection2reverse + # print('5') + + position = trackSurface.findNearestPosition(xOstiumOuter[n1]) + oPositions.append(position) + px, d1, d2 = trackSurface.evaluateCoordinates(position, True) + angleRadians = 2.0 * math.pi / elementsCountAroundOstium * n1 + + cosTheta1 = vector.dotproduct(d1, centralPath.cd3Path[-1])/\ + (vector.magnitude(d1) * vector.magnitude(centralPath.cd3Path[-1])) + cosTheta2 = vector.dotproduct(d2, centralPath.cd2Path[-1]) / \ + (vector.magnitude(d2) * vector.magnitude(centralPath.cd2Path[-1])) + signed1 = cosTheta1 / abs(cosTheta1) + signed2 = cosTheta2 / abs(cosTheta2) + + w1 = signed1 * math.sin(angleRadians) + w2 = signed2 * math.cos(angleRadians) + sideDirection = [(w1 * trackDirection1[c] + w2 * trackDirection2[c]) for c in range(3)] + pd2, pd1, pd3 = calculate_surface_axes(d1, d2, sideDirection) + + # get inner coordinates + opx = px + opd1 = vector.setMagnitude([-d for d in pd1], elementLengthAroundOstiumEnd) + opd2 = vector.setMagnitude(pd2, vector.magnitude(centralPath.cd2Path[0])) # smoothed later + opd3 = vector.setMagnitude(pd3, ostiumWallThickness) + + # node = nodes.createNode(nodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, opx) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, opd1) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, opd2) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, opd3) + # print(nodeIdentifier) + # nodeIdentifier += 1 + + ostiumTotalXi3 = 0.0 + vesselTotalXi3 = 0.0 + ostiumWallThicknessXi3List = [0.0] + vesselWallThicknessXi3List = [0.0] + + for n3 in range(elementsCountThroughWall): + ostiumTotalXi3 += ostiumWallThicknessProportions[n3] + vesselTotalXi3 += vesselWallThicknessProportions[n3] + ostiumWallThicknessXi3List.append(ostiumTotalXi3) + vesselWallThicknessXi3List.append(vesselTotalXi3) + # set coordinates through wall (use copy to avoid references to same list later) + for n3 in range(elementsCountThroughWall + 1): + xi3 = 1 - ostiumWallThicknessXi3List[n3] + ox[n3].append([(opx[c] - opd3[c] * xi3) for c in range(3)]) + od1[n3].append(copy.copy(opd1)) + od2[n3].append(copy.copy(opd2)) + if useCubicHermiteThroughOstiumWall: + od3[n3].append([opd3[c] * ostiumWallThicknessProportions[n3] for c in range(3)]) + distance += elementLength + for n3 in range(elementsCountThroughWall + 1): + od1[n3] = interp.smoothCubicHermiteDerivativesLoop(ox[n3], od1[n3]) + + # for n3 in range(len(ox)): + # for n1 in range(len(ox[n3])): + # node = nodes.createNode(nodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, ox[n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, od1[n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, od2[n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, od3[n3][n1]) + # nodeIdentifier += 1 + + if (vesselWallThickness > 0.0) and (ostiumWallThickness > 0.0): + # commonOstiumWallThickness = 2.0 / (1.0 / vesselWallThickness + 1.0 / ostiumWallThickness) + commonOstiumWallThicknessProportions = [] + commonOstiumWallTotalXi3 = 0.0 + commonOstiumWallThicknessXi3List = [0.0] + for c in range(elementsCountThroughWall + 1): + commonOstiumWallThicknessProportions.append( + (vesselWallThicknessProportions[c] + ostiumWallThicknessProportions[c]) * 0.5) + for n3 in range(elementsCountThroughWall): + commonOstiumWallTotalXi3 += commonOstiumWallThicknessProportions[n3] + commonOstiumWallThicknessXi3List.append(commonOstiumWallTotalXi3) + else: + commonOstiumWallThickness = vesselWallThickness + commonOstiumWallThicknessProportions = vesselWallThicknessProportions + commonOstiumWallThicknessXi3List = vesselWallThicknessXi3List + + # xx = [] + # xd1 = [] + # xd2 = [] + # xd3 = [] + # # coordinates across common ostium, between vessels + # nodesCountFreeEnd = elementsCountsAroundVessels[0] + 1 - elementsCountAcross + # oinc = 0 if (vesselsCount <= 2) else elementsCountAroundMid // (vesselsCount - 2) + # for iv in range(vesselsCount - 1): + # xx .append([None for n3 in range(elementsCountThroughWall + 1)]) + # xd1.append([None for n3 in range(elementsCountThroughWall + 1)]) + # xd2.append([None for n3 in range(elementsCountThroughWall + 1)]) + # xd3.append([None for n3 in range(elementsCountThroughWall + 1)]) + # oa = elementsCountAroundMid - iv * oinc + # ob = elementsCountAroundMid + nodesCountFreeEnd - 1 + iv * oinc + # nx = [ox[elementsCountThroughWall][oa], ox[elementsCountThroughWall][ob]] + # nd1 = [[-d for d in od1[elementsCountThroughWall][oa]], od1[elementsCountThroughWall][ob]] + # nd2 = [[-d for d in od2[elementsCountThroughWall][oa]], od2[elementsCountThroughWall][ob]] + # + # if elementsCountAcross > 1: + # # add centre point, displaced by interVesselHeight + # if vesselsCount == 2: + # position = centrePosition + # else: + # position = trackSurface.trackVector(centrePosition, trackDirection1, + # (iv / (vesselsCount - 2) - 0.5) * vesselsSpanMid) + # mx, d1, d2 = trackSurface.evaluateCoordinates(position, derivatives=True) + # md1, md2, md3 = calculate_surface_axes(d1, d2, trackDirection1) + # nx .insert(1, [(mx[c] + interVesselHeight * md3[c]) for c in range(3)]) + # nd1.insert(1, vector.setMagnitude(md1, elementLengthAroundOstiumMid if (0 < iv < (vesselsCount - 2)) else + # elementLengthAroundOstiumEnd)) + # nd2.insert(1, vector.setMagnitude(md2, ostiumRadius)) + # nd2 = interp.smoothCubicHermiteDerivativesLine(nx, nd2, fixAllDirections=True) + # px, pd2, pe, pxi = interp.sampleCubicHermiteCurves(nx, nd2, elementsCountAcross)[0:4] + # pd1 = interp.interpolateSampleLinear(nd1, pe, pxi) + # pd3 = [vector.setMagnitude(vector.crossproduct3(pd1[n2], pd2[n2]), commonOstiumWallThickness) + # for n2 in range(elementsCountAcross + 1)] + # for n3 in range(elementsCountThroughWall + 1): + # xi3 = 1 - commonOstiumWallThicknessXi3List[n3] + # lx = [([(px[n2][c] - xi3 * pd3[n2][c]) for c in range(3)]) for n2 in range(elementsCountAcross + 1)] + # ld2 = interp.smoothCubicHermiteDerivativesLine(lx, pd2, fixAllDirections=True) + # xx[iv][n3] = lx[1:elementsCountAcross] + # xd1[iv][n3] = copy.deepcopy(pd1[1:elementsCountAcross]) # to be smoothed later + # xd2[iv][n3] = ld2[1:elementsCountAcross] + # # set smoothed d2 on ostium circumference + # od2[n3][oa] = [-d for d in ld2[0]] + # od2[n3][ob] = ld2[-1] + # if useCubicHermiteThroughOstiumWall: + # pd3Element = [vector.setMagnitude(vector.crossproduct3(pd1[n2], pd2[n2]), + # commonOstiumWallThickness * commonOstiumWallThicknessProportions[n3]) + # for n2 in range(elementsCountAcross + 1)] + # xd3[iv][n3] = copy.deepcopy(pd3Element[1:elementsCountAcross]) + # + # get positions of vessel end centres and rings + # vcx = [] + # vcd1 = [] + # vcd2 = [] + # vcd3 = [] + vox = [] + vod1 = [] + vod2 = [] + vod3 = [] + for v in range(vesselsCount): + # elementsCountAroundVessel = elementsCountsAroundVessels[v] + radiansPerElementVessel = 2.0 * math.pi / elementsCountAroundVessel + # useVesselAngleRadians = vesselAngle1Radians + # if vesselsCount > 1: + # useVesselAngleRadians += (v / (vesselsCount - 1) - 0.5) * vesselAngle1SpreadRadians + # vx, vd1, vd2, vd3 = getCircleProjectionAxes(ocx[v], ocd1[v], ocd2[v], ocd3[v], ostiumLength, + # useVesselAngleRadians, vesselAngle2Radians) + # + # node = nodes.createNode(nodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, vx) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, vd1) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, vd2) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, vd3) + # nodeIdentifier += 1 + + # vx, vd1 = createCirclePoints(cxPath[-1], cd2Path[-1], cd3Path[-1], elementsCountsAroundVessels) + # vd1 = [vesselOuterRadius * d for d in vd1] + # vd2 = [-vesselOuterRadius * d for d in vd2] + # vd3 = [-vesselEndDerivative * d for d in vd3] + # vcx.append(vx) + # vcd1.append(vd1) + # vcd2.append(vd2) + # vcd3.append(vd3) + vox.append([]) + vod1.append([]) + vod2.append([]) + vod3.append([]) + + for n3 in range(elementsCountThroughWall + 1): + if xProximal: + vox[-1].append(xProximal[n3]) + vod1[-1].append(d1Proximal[n3]) + vod2[-1].append(d2Proximal[n3]) + vod3[-1].append(d3Proximal[n3]) + else: + radius1 = vector.magnitude(centralPath.cd2Path[0]) - (1.0 - vesselWallThicknessXi3List[n3]) * vesselWallThickness + radius2 = vector.magnitude(centralPath.cd3Path[0]) - (1.0 - vesselWallThicknessXi3List[n3]) * vesselWallThickness + vAxis1 = vector.setMagnitude(centralPath.cd2Path[0], radius1) + vAxis2 = vector.setMagnitude(centralPath.cd3Path[0], radius2) + # print(centralPath.cd2Path[0], centralPath.cd3Path[0]) + # if vesselsCount == 1: + startRadians = 0.0 # 0.5 * math.pi + # else: + # startRadians = 0.5 * radiansPerElementVessel * elementsCountAcross + # if v == (vesselsCount - 1): + # startRadians -= math.pi + px, pd1 = sampleEllipsePoints(centralPath.cxPath[0], vAxis1, vAxis2, 0.0, 2.0 * math.pi, elementsCountAroundVessel) + del px[-1], pd1[-1] + + vox[-1].append(px) + vod1[-1].append(pd1) + vesselEndDerivative = vector.setMagnitude(centralPath.cd1Path[0], arcLength/elementsCountAlong) + vod2[-1].append([vesselEndDerivative] * elementsCountAroundVessel) # need to scale with bending? + if useCubicHermiteThroughVesselWall: + vod3[-1].append([vector.setMagnitude(vector.crossproduct3(d1, vesselEndDerivative), #cd1Path[-1]), + vesselWallThickness * vesselWallThicknessProportions[n3]) + for d1 in pd1]) + + # for v in range(len(vox)): + # for n3 in range(len(vox[v])): + # for n1 in range(len(vox[v][n3])): + # node = nodes.createNode(nodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, vox[v][n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, vod1[v][n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, vod2[v][n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, vod3[v][n3][n1]) + # nodeIdentifier += 1 + + # calculate common ostium vessel node derivatives map + mvPointsx = [None] * vesselsCount + mvPointsd1 = [None] * vesselsCount + mvPointsd2 = [None] * vesselsCount + mvPointsd3 = [None] * vesselsCount + mvDerivativesMap = [None] * vesselsCount + mvMeanCount = [None] * vesselsCount # stores 1 if first reference to common point between vessels, 2 if second. Otherwise 0. + for v in range(vesselsCount): + if vesselsCount == 1: + mvPointsx[v], mvPointsd1[v], mvPointsd2[v], mvPointsd3[v], mvDerivativesMap[v] = \ + ox, od1, od2, od3 if useCubicHermiteThroughOstiumWall else None, None + mvMeanCount[v] = [0] * elementsCountAroundVessel # elementsCountsAroundVessels[v] + # else: + # iv = max(0, v - 1) + # oa = elementsCountAroundMid - iv * oinc + # ob = elementsCountAroundMid + nodesCountFreeEnd - 1 + iv * oinc + # mvPointsx[v] = [] + # mvPointsd1[v] = [] + # mvPointsd2[v] = [] + # mvPointsd3[v] = [] if useCubicHermiteThroughOstiumWall else None + # mvDerivativesMap[v] = [] + # for n3 in range(elementsCountThroughWall + 1): + # mvPointsd1[v].append([]) + # mvPointsd2[v].append([]) + # mvPointsx[v].append([]) + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v].append([]) + # mvDerivativesMap[v].append([]) + # if v == 0: # first end vessel + # mvPointsd1[v][n3] += od1[n3][oa:ob + 1] + # mvPointsd2[v][n3] += od2[n3][oa:ob + 1] + # mvPointsx[v][n3] += ox[n3][oa:ob + 1] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += od3[n3][oa:ob + 1] + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 1, 0), None, (1, 0, 0))) + # for i in range(nodesCountFreeEnd - 2): + # mvDerivativesMap[v][n3].append((None, None, None)) + # mvDerivativesMap[v][n3].append(((1, 0, 0), (1, 1, 0), None, (0, -1, 0))) + # mvPointsx[v][n3] += reversed(xx[iv][n3]) + # mvPointsd1[v][n3] += reversed(xd1[iv][n3]) + # mvPointsd2[v][n3] += reversed(xd2[iv][n3]) + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += reversed(xd3[iv][n3]) + # for i in range(elementsCountAcross - 1): + # mvDerivativesMap[v][n3].append(((0, -1, 0), (1, 0, 0), None)) + # if n3 == 0: + # mvMeanCount[v] = [1] + [0] * (nodesCountFreeEnd - 2) + [1] * elementsCountAcross + # elif v < (vesselsCount - 1): # middle vessels + # # left: + # mvPointsx[v][n3] += ox[n3][oa - oinc:oa + 1] + # mvPointsd1[v][n3] += od1[n3][oa - oinc:oa + 1] + # mvPointsd2[v][n3] += od2[n3][oa - oinc:oa + 1] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += od3[n3][oa - oinc:oa + 1] + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 1, 0), None, (1, 0, 0))) + # for i in range(oinc - 1): + # mvDerivativesMap[v][n3].append((None, None, None)) + # mvDerivativesMap[v][n3].append(((1, 0, 0), (1, 1, 0), None, (0, -1, 0))) + # # across + # mvPointsx[v][n3] += xx[iv][n3] + # mvPointsd1[v][n3] += xd1[iv][n3] + # mvPointsd2[v][n3] += xd2[iv][n3] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += xd3[iv][n3] + # for i in range(elementsCountAcross - 1): + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 0, 0), None)) + # # right + # mvPointsx[v][n3] += ox[n3][ob:ob + oinc + 1] + # mvPointsd1[v][n3] += od1[n3][ob:ob + oinc + 1] + # mvPointsd2[v][n3] += od2[n3][ob:ob + oinc + 1] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += od3[n3][ob:ob + oinc + 1] + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 1, 0), None, (1, 0, 0))) + # for i in range(oinc - 1): + # mvDerivativesMap[v][n3].append((None, None, None)) + # mvDerivativesMap[v][n3].append(((1, 0, 0), (1, 1, 0), None, (0, -1, 0))) + # # across reverse + # mvPointsx[v][n3] += reversed(xx[iv + 1][n3]) + # mvPointsd1[v][n3] += reversed(xd1[iv + 1][n3]) + # mvPointsd2[v][n3] += reversed(xd2[iv + 1][n3]) + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += reversed(xd3[iv + 1][n3]) + # for i in range(elementsCountAcross - 1): + # mvDerivativesMap[v][n3].append(((0, -1, 0), (1, 0, 0), None)) + # if n3 == 0: + # mvMeanCount[v] = [1] + [0] * (oinc - 1) + [2] * (elementsCountAcross + 1) + [0] * (oinc - 1) + \ + # [1] * elementsCountAcross + # else: # last end vessel + # mvPointsx[v][n3] += ox[n3][ob:] + [ox[n3][0]] + # mvPointsd1[v][n3] += od1[n3][ob:] + [od1[n3][0]] + # mvPointsd2[v][n3] += od2[n3][ob:] + [od2[n3][0]] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += od3[n3][ob:] + [od3[n3][0]] + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 1, 0), None, (1, 0, 0))) + # for i in range(nodesCountFreeEnd - 2): + # mvDerivativesMap[v][n3].append((None, None, None)) + # mvDerivativesMap[v][n3].append(((1, 0, 0), (1, 1, 0), None, (0, -1, 0))) + # mvPointsx[v][n3] += xx[iv][n3] + # mvPointsd1[v][n3] += xd1[iv][n3] + # mvPointsd2[v][n3] += xd2[iv][n3] + # if useCubicHermiteThroughOstiumWall: + # mvPointsd3[v][n3] += xd3[iv][n3] + # for i in range(elementsCountAcross - 1): + # mvDerivativesMap[v][n3].append(((0, 1, 0), (-1, 0, 0), None)) + # if n3 == 0: + # mvMeanCount[v] = [2] + [0] * (nodesCountFreeEnd - 2) + [2] * elementsCountAcross + + # calculate derivative 2 around free sides of inlets to fit vessel derivatives + for v in range(vesselsCount): + for n3 in [elementsCountThroughWall]: # was range(2), now using curvature for inside: + # print('v',v,'n3',n3,'elementsAround',elementsCountsAroundVessels[v]) + # print('mvPointsx [v][n3]', mvPointsx [v][n3]) + # print('mvPointsd1[v][n3]', mvPointsd1[v][n3]) + # print('mvPointsd2[v][n3]', mvPointsd2[v][n3]) + # print('mvDerivativesMap[v][n3]', mvDerivativesMap[v][n3]) + for n1 in range(elementsCountAroundVessel): #elementsCountsAroundVessels[v]): + d2Map = mvDerivativesMap[v][n3][n1][1] if (mvDerivativesMap[v] and mvDerivativesMap[v][n3][n1]) \ + else None + sf1 = d2Map[0] if d2Map else 0.0 + sf2 = d2Map[1] if d2Map else 1.0 + nx = [vox[v][n3][n1], mvPointsx[v][n3][n1]] + nd2 = [[d * elementsCountAlong for d in vod2[v][n3][n1]], + [(sf1 * mvPointsd1[v][n3][n1][c] + sf2 * mvPointsd2[v][n3][n1][c]) for c in range(3)]] + nd2f = interp.smoothCubicHermiteDerivativesLine(nx, nd2, fixStartDirection=True, fixEndDirection=True) + ndf = [d / elementsCountAlong for d in nd2f[1]] + # assign components to set original values: + if sf1 == 0: + for c in range(3): + mvPointsd2[v][n3][n1][c] = sf2 * ndf[c] + elif sf2 == 0: + if mvMeanCount[v][n1] < 2: + for c in range(3): + mvPointsd1[v][n3][n1][c] = sf1 * ndf[c] + else: + # take mean of values from this and last vessel + for c in range(3): + mvPointsd1[v][n3][n1][c] = 0.5 * (mvPointsd1[v][n3][n1][c] + sf1 * ndf[c]) + else: + # print('v', v, 'n3', n3, 'n1', n1, ':', vector.magnitude(ndf), 'vs.', vector.magnitude(nd2[1]), + # 'd2Map', d2Map) + pass + + # calculate inner d2 derivatives around ostium from outer using track surface curvature + factor = 1.0 + for n1 in range(elementsCountAroundOstium): + trackDirection = vector.normalise(od2[elementsCountThroughWall][n1]) + trackDistance = factor * vector.magnitude(od2[elementsCountThroughWall][n1]) + tx = [None, ox[elementsCountThroughWall][n1], None] + td1 = [None, vector.setMagnitude(od2[elementsCountThroughWall][n1], trackDistance), None] + td2 = [None, vector.setMagnitude(od1[elementsCountThroughWall][n1], -trackDistance), None] + positionBackward = trackSurface.trackVector(oPositions[n1], trackDirection, -trackDistance) + tx[0], d1, d2 = trackSurface.evaluateCoordinates(positionBackward, derivatives=True) + sd1, sd2, sd3 = calculate_surface_axes(d1, d2, trackDirection) + td1[0] = vector.setMagnitude(sd1, trackDistance) + td2[0] = vector.setMagnitude(sd2, trackDistance) + positionForward = trackSurface.trackVector(oPositions[n1], trackDirection, trackDistance) + tx[2], d1, d2 = trackSurface.evaluateCoordinates(positionForward, derivatives=True) + sd1, sd2, sd3 = calculate_surface_axes(d1, d2, trackDirection) + td1[2] = vector.setMagnitude(sd1, trackDistance) + td2[2] = vector.setMagnitude(sd2, trackDistance) + for n3 in range(elementsCountThroughWall): + xi3 = 1 - ostiumWallThicknessXi3List[n3] + newd2 = interp.projectHermiteCurvesThroughWall(tx, td1, td2, 1, -ostiumWallThickness * xi3)[1] + # assign components to set in all lists: + for c in range(3): + od2[n3][n1][c] = newd2[c] / factor + # for n in [ 0, 1, 2 ]: + # node = nodes.createNode(nodeIdentifier, nodetemplateLinearS3) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, tx [n]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, td1[n]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, td2[n]) + # nodeIdentifier += 1 + + if isOutlet: + # reverse directions of d1 and d2 on vessels and ostium base + for c in range(3): + for n3 in range(elementsCountThroughWall + 1): + for n1 in range(elementsCountAroundOstium): + od1[n3][n1][c] = -od1[n3][n1][c] + od2[n3][n1][c] = -od2[n3][n1][c] + # for iv in range(vesselsCount - 1): + # for n1 in range(elementsCountAcross - 1): + # xd1[iv][n3][n1][c] = -xd1[iv][n3][n1][c] + # xd2[iv][n3][n1][c] = -xd2[iv][n3][n1][c] + for v in range(vesselsCount): + vod2[0][n3][0][c] = -vod2[0][n3][0][c] + for n1 in range(elementsCountAroundVessel): #elementsCountsAroundVessels[v]): + vod1[v][n3][n1][c] = -vod1[v][n3][n1][c] + + # # d2 is referenced all around, so only change once per vessel - NA + # for v in range(vesselsCount): + # vod2[v][0][0][c] = -vod2[v][0][0][c] + # vod2[v][1][0][c] = -vod2[v][1][0][c] + + ############## + # Create nodes + ############## + + oNodeId = [] + for n3 in range(elementsCountThroughWall + 1): + oNodeId.append([]) + for n1 in range(elementsCountAroundOstium): + node = nodes.createNode(nodeIdentifier, + nodetemplate if useCubicHermiteThroughOstiumWall else nodetemplateLinearS3) + cache.setNode(node) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, ox[n3][n1]) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, od1[n3][n1]) + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, od2[n3][n1]) + if useCubicHermiteThroughOstiumWall: + coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, od3[n3][n1]) + oNodeId[n3].append(nodeIdentifier) + # print(nodeIdentifier) + nodeIdentifier += 1 + + # xNodeId = [] + # for iv in range(vesselsCount - 1): + # xNodeId.append([]) + # for n3 in range(elementsCountThroughWall + 1): + # xNodeId[iv].append([]) + # for n2 in range(elementsCountAcross - 1): + # node = nodes.createNode(nodeIdentifier, + # nodetemplate if useCubicHermiteThroughOstiumWall else nodetemplateLinearS3) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, xx[iv][n3][n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, xd1[iv][n3][n2]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, xd2[iv][n3][n2]) + # if useCubicHermiteThroughOstiumWall: + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, xd3[iv][n3][n2]) + # xNodeId[iv][n3].append(nodeIdentifier) + # nodeIdentifier += 1 + + # for v in range(vesselsCount): + # node = nodes.createNode(nodeIdentifier, nodetemplate) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, vcx [v]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, vcd1[v]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, vcd2[v]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, vcd3[v]) + # nodeIdentifier += 1 + # for v in range(vesselsCount): + # for n3 in range(elementsCountThroughWall + 1): + # for n1 in range(elementsCountAroundVessel): + # node = nodes.createNode(nodeIdentifier, + # nodetemplate if useCubicHermiteThroughVesselWall else nodetemplateLinearS3) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, vox [v][n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, vod1[v][n3][n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, vod2[v][n3][n1]) + # if useCubicHermiteThroughVesselWall: + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, vod3[v][n3][n1]) + # #vNodeId.append(nodeIdentifier) + # nodeIdentifier += 1 + + # get identifiers of nodes around each vessel at ostium end + mvNodeId = [None] * vesselsCount + for v in range(vesselsCount): + if vesselsCount == 1: + mvNodeId[v] = oNodeId + # else: + # iv = max(0, v - 1) + # mvNodeId[v] = [None for n3 in range(elementsCountThroughWall + 1)] + # oa = elementsCountAroundMid - iv * oinc + # ob = elementsCountAroundMid + nodesCountFreeEnd - 1 + iv * oinc + # for n3 in range(elementsCountThroughWall + 1): + # if v == 0: # first end vessel + # mvNodeId[v][n3] = oNodeId[n3][oa:ob + 1] + \ + # (list(reversed(xNodeId[iv][n3])) if (v == 0) else xNodeId[iv][n3]) + # elif v == (vesselsCount - 1): # last end vessels + # mvNodeId[v][n3] = oNodeId[n3][ob:] + [oNodeId[n3][0]] + \ + # (list(reversed(xNodeId[iv][n3])) if (v == 0) else xNodeId[iv][n3]) + # else: # mid vessels + # mvNodeId[v][n3] = oNodeId[n3][oa - oinc:oa + 1] + xNodeId[iv][n3] + \ + # oNodeId[n3][ob:ob + oinc + 1] + list(reversed(xNodeId[iv + 1][n3])) + + ################# + # Create elements + ################# + tricubichermite = eftfactory_tricubichermite(mesh, useCrossDerivatives) + tricubicHermiteBasis = fm.createElementbasis(3, Elementbasis.FUNCTION_TYPE_CUBIC_HERMITE) + + eft = tricubichermite.createEftBasic() + elementtemplate = mesh.createElementtemplate() + elementtemplate.setElementShapeType(Element.SHAPE_TYPE_CUBE) + elementtemplate.defineField(coordinates, -1, eft) + + elementtemplateX = mesh.createElementtemplate() + elementtemplateX.setElementShapeType(Element.SHAPE_TYPE_CUBE) + + for v in range(vesselsCount): + if vesselMeshGroups or ostiumMeshGroups: + rowMeshGroups = [] + for i in range(elementsCountAlong): + rowMeshGroups.append(copy.copy(vesselMeshGroups[v]) if vesselMeshGroups else []) + else: + rowMeshGroups = None + if isOutlet: + startPointsx, startPointsd1, startPointsd2, startPointsd3, startNodeId, startDerivativesMap = \ + mvPointsx[v], mvPointsd1[v], mvPointsd2[v], mvPointsd3[v], mvNodeId[v], mvDerivativesMap[v] + endPointsx, endPointsd1, endPointsd2, endPointsd3, endNodeId, endDerivativesMap = \ + vox[v], vod1[v], vod2[v], vod3[v] if useCubicHermiteThroughVesselWall else None, \ + nodeIdProximal if xProximal else None, None + # reverse order of nodes around: + for px in [startPointsx, startPointsd1, startPointsd2, startPointsd3, startNodeId, startDerivativesMap, + endPointsx, endPointsd1, endPointsd2, endPointsd3, endNodeId, endDerivativesMap]: + if px: + for n3 in range(elementsCountThroughWall + 1): + px[n3] = [px[n3][0]] + px[n3][len(px[n3]) - 1:0:-1] + if vesselsCount > 1: + # must switch in and out xi1 maps around corners in startDerivativesMap + for n3 in range(elementsCountThroughWall + 1): + for n1 in range(elementsCountAroundVessel): #elementsCountsAroundVessels[v]): + derivativesMap = startDerivativesMap[n3][n1] + if len(derivativesMap) == 4: + startDerivativesMap[n3][n1] = derivativesMap[3], derivativesMap[1], \ + derivativesMap[2], derivativesMap[0] + if ostiumMeshGroups: + rowMeshGroups[0] += ostiumMeshGroups + else: + startPointsx, startPointsd1, startPointsd2, startPointsd3, startNodeId, startDerivativesMap = \ + vox[v], vod1[v], vod2[v], vod3[v] if useCubicHermiteThroughVesselWall else None, \ + nodeIdProximal if xProximal else None, None + endPointsx, endPointsd1, endPointsd2, endPointsd3, endNodeId, endDerivativesMap = \ + mvPointsx[v], mvPointsd1[v], mvPointsd2[v], mvPointsd3[v], mvNodeId[v], mvDerivativesMap[v] + if ostiumMeshGroups: + rowMeshGroups[-1] += ostiumMeshGroups + + # print('endPointsx ', endPointsx ) + # print('endPointsd1', endPointsd1) + # print('endPointsd2', endPointsd2) + # print('endPointsd3', endPointsd3) + # print('endNodeId', endNodeId) + # print('endDerivativesMap', endDerivativesMap) + + nodeIdentifier, elementIdentifier = createAnnulusMesh3d( + nodes, mesh, nodeIdentifier, elementIdentifier, + startPointsx, startPointsd1, startPointsd2, startPointsd3, startNodeId, startDerivativesMap, + endPointsx, endPointsd1, endPointsd2, endPointsd3, endNodeId, endDerivativesMap, + forceMidLinearXi3=not useCubicHermiteThroughVesselWall, + maxStartThickness=vesselWallThickness, maxEndThickness=vesselWallThickness, + elementsCountRadial=elementsCountAlong, meshGroups=rowMeshGroups, wallAnnotationGroups=wallAnnotationGroups, + coordinates=coordinates) + + # To visualise central path + # nodeIdentifierLine = nodeIdentifier + # for n1 in range(len(centralPath.cxPath)): + # node = nodes.createNode(nodeIdentifier, nodetemplate ) + # cache.setNode(node) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, centralPath.cxPath[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, centralPath.cd1Path[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, centralPath.cd2Path[n1]) + # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, centralPath.cd3Path[n1]) + # nodeIdentifier += 1 + # + # mesh = fm.findMeshByDimension(1) + # cubicHermiteBasis = fm.createElementbasis(1, Elementbasis.FUNCTION_TYPE_CUBIC_HERMITE) + # eft = mesh.createElementfieldtemplate(cubicHermiteBasis) + # elementtemplate = mesh.createElementtemplate() + # elementtemplate.setElementShapeType(Element.SHAPE_TYPE_LINE) + # result = elementtemplate.defineField(coordinates, -1, eft) + # + # for e in range(len(centralPath.cxPath) - 1): + # element = mesh.createElement(elementIdentifier, elementtemplate) + # element.setNodesByIdentifier(eft, [nodeIdentifierLine + e, nodeIdentifierLine + 1 + e]) + # elementIdentifier = elementIdentifier + 1 + + fm.endChange() + return nodeIdentifier, elementIdentifier, (ox, od1, od2, od3, oNodeId, oPositions) + +class CentralPath: + """ + Extracts central path parameters. + """ + def __init__(self, region, centralPath, unitScale, termsAlong=[None]): + """ + :param region: Zinc region to define model in. + :param centralPath: Central path subscaffold from meshtype_1d_path1 + :param unitScale: Unit scale of ostium + :param termsAlong: Annotation terms along length of central path + """ + + tmpRegion = region.createRegion() + centralPath.generate(tmpRegion) + tmpFieldmodule = tmpRegion.getFieldmodule() + tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + + for termName in termsAlong: + tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None + tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) + + if not termName: + cx = cxGroup + cd1 = cd1Group + cd2 = cd2Group + cd3 = cd3Group + cd12 = cd12Group + cd13 = cd13Group + + del tmpNodeset + del tmpGroup + + del tmpCoordinates + del tmpNodes + del tmpFieldmodule + del tmpRegion + + self.cxPath = [] + self.cd1Path = [] + self.cd2Path = [] + self.cd3Path = [] + self.cd12Path = [] + self.cd13Path = [] + + for i in range(len(cx)): + self.cxPath.append([unitScale * x for x in cx[i]]) + self.cd1Path.append([unitScale * cd1 for cd1 in cd1[i]]) + self.cd2Path.append([unitScale * cd2 for cd2 in cd2[i]]) + self.cd3Path.append([unitScale * cd3 for cd3 in cd3[i]]) + self.cd12Path.append([unitScale * cd12 for cd12 in cd12[i]]) + self.cd13Path.append([unitScale * cd13 for cd13 in cd13[i]]) diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_smallintestine1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_smallintestine1.py index 56360ac7..d4fabe59 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_smallintestine1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_smallintestine1.py @@ -12,842 +12,879 @@ from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, findOrCreateAnnotationGroupForTerm, \ getAnnotationGroupForTerm from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.scaffoldpackage import ScaffoldPackage from scaffoldmaker.utils import interpolation as interp from scaffoldmaker.utils import tubemesh from scaffoldmaker.utils import vector -from scaffoldmaker.utils.tubemesh import CylindricalSegmentTubeMeshInnerPoints +from scaffoldmaker.utils.tubemesh import CylindricalSegmentTubeMeshOuterPoints from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ get_nodeset_path_field_parameters -class MeshType_3d_smallintestine1(Scaffold_base): - ''' - Generates a 3-D small intestine mesh with variable numbers - of elements around, along the central line, and through wall. - The small intestine is created by a function that generates - a small intestine segment and uses tubemesh to map the segment - along a central line profile. - ''' +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "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-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-76-77-78-79-80-81-82-83-84-85-86-87-88-89-90-" + "91-92-93-94-95-96-97-98-99-100-101-102-103-104-105-106-107-108-109-110-111-112-113-114-" + "115-116-117-118-119-120-121-122-123-124-125-126-127-128-129-130-131-132-133-134-135-136-" + "137-138-139-140-141-142-143-144-145-146-147-148-149-150-151-152" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ + (1, [[-32.281,-136.261,1061.249], [-6.125,11.114,-0.493], [-5.735,-3.374,-4.823], [-2.070,-0.220,-4.520], [-4.630,-2.238,7.071], [-4.400,2.440,0.570]]), + (2, [[-40.674,-122.300,1060.850], [-5.403,7.321,-2.629], [-4.779,-4.249,-5.161], [2.360,-0.320,0.120], [-5.138,-1.668,6.875], [-0.250,2.080,-4.500]]), + (3, [[-48.346,-108.981,1049.574], [-6.840,19.440,-21.940], [-3.459,-4.108,-5.699], [0.900,0.690,1.570], [-7.043,0.777,3.341], [-0.760,2.950,-2.230]]), + (4, [[-43.450,-95.700,1015.590], [40.730,3.220,-44.800], [-5.240,-3.340,-4.990], [-0.380,4.380,-0.330], [-2.270,6.020,-1.640], [4.590,3.490,-0.790]]), + (5, [[26.760,-119.310,992.030], [58.860,-18.680,-8.450], [0.310,3.940,-6.600], [4.150,2.330,1.070], [2.230,5.490,3.380], [3.360,-4.080,2.370]]), + (6, [[63.862,-132.266,992.002], [9.680,-30.910,-18.900], [5.846,1.916,2.960], [-0.330,-6.200,3.780], [5.300,-1.090,4.490], [-3.680,-1.570,1.510]]), + (7, [[46.280,-139.940,982.680], [-22.680,-4.850,-10.940], [1.050,-7.060,0.970], [-0.930,-3.800,3.220], [-3.190,0.420,6.420], [-5.340,-0.640,-2.850]]), + (8, [[28.560,-141.070,974.610], [3.750,-10.520,-21.300], [1.560,-6.210,3.340], [-1.000,0.060,-0.070], [-6.850,-1.870,-0.290], [1.100,-0.530,-6.400]]), + (9, [[52.390,-146.130,971.400], [18.400,-3.700,0.670], [-1.440,-7.110,0.300], [-0.590,-0.290,-0.540], [0.190,-0.340,-7.250], [2.420,0.060,-1.890]]), + (10, [[63.130,-148.180,973.520], [10.490,-1.410,1.470], [-1.070,-7.160,0.770], [2.410,0.380,0.120], [0.880,-0.900,-7.160], [-2.030,-1.100,0.840]]), + (11, [[72.690,-148.910,974.300], [7.650,3.570,-7.080], [3.500,-6.340,0.580], [0.430,0.200,-1.420], [-3.880,-2.630,-5.520], [-3.490,0.080,4.650]]), + (12, [[71.050,-143.650,964.650], [-5.960,4.700,-11.040], [-0.810,-6.830,-2.470], [-2.360,-0.380,-1.140], [-6.400,-0.430,3.270], [0.270,0.950,6.070]]), + (13, [[61.060,-140.780,954.520], [-17.960,3.880,-6.220], [-1.070,-7.120,-1.370], [0.180,-0.250,1.370], [-2.560,-0.940,6.800], [3.840,0.270,2.130]]), + (14, [[37.990,-136.930,957.170], [-18.820,0.880,5.080], [-0.160,-7.340,0.670], [1.900,0.170,0.590], [1.940,0.610,7.070], [2.120,1.030,-0.120]]), + (15, [[24.260,-138.060,963.160], [-17.400,-6.040,8.510], [2.590,-6.900,0.380], [2.420,1.010,0.690], [2.780,1.420,6.690], [-2.180,-0.670,-0.740]]), + (16, [[6.500,-150.310,973.050], [-8.250,-16.440,-13.420], [4.890,-4.750,2.820], [-1.080,-0.490,-0.280], [-4.820,-1.850,5.240], [-4.270,-0.820,-2.180]]), + (17, [[15.970,-149.800,957.690], [-4.350,-1.250,-14.050], [0.990,-7.390,0.350], [-1.040,-0.780,-0.850], [-6.950,-0.830,2.230], [-0.480,0.190,-0.500]]), + (18, [[8.290,-150.980,954.250], [-3.340,-0.730,-8.150], [1.180,-7.370,0.180], [0.180,0.050,0.370], [-6.710,-1.000,2.840], [0.560,-0.430,-3.270]]), + (19, [[10.770,-150.880,946.760], [5.270,-0.050,-7.150], [1.370,-7.280,1.060], [-0.120,-0.030,0.050], [-5.800,-1.710,-4.270], [2.050,0.220,-4.830]]), + (20, [[18.300,-151.090,941.260], [7.790,0.880,-2.390], [0.880,-7.450,0.160], [0.050,-0.010,-0.900], [-2.150,-0.400,-7.160], [4.520,1.490,-0.770]]), + (21, [[24.850,-149.580,941.590], [5.320,0.620,3.020], [1.330,-7.350,-0.840], [-0.350,0.010,-0.650], [3.510,1.370,-6.460], [3.430,0.580,1.190]]), + (22, [[27.850,-149.810,945.920], [3.490,-0.550,3.990], [0.330,-7.390,-1.300], [-0.750,-0.040,-0.150], [5.610,1.090,-4.760], [-0.580,-0.160,-0.310]]), + (23, [[31.640,-150.640,949.370], [5.770,-0.500,1.810], [-0.280,-7.430,-1.160], [0.320,-0.010,0.320], [2.310,1.020,-7.080], [-4.590,-0.600,-0.740]]), + (24, [[38.160,-150.550,948.480], [5.400,1.270,-4.340], [1.280,-7.400,-0.560], [1.280,0.320,-0.530], [-4.630,-0.350,-5.870], [-4.440,-1.610,3.120]]), + (25, [[40.300,-148.530,942.170], [-0.500,2.450,-7.550], [2.420,-6.730,-2.350], [1.390,0.820,-0.980], [-7.020,-2.420,-0.320], [-0.570,-0.950,1.020]]), + (26, [[36.760,-146.190,935.090], [3.270,5.380,-6.440], [4.320,-5.620,-2.500], [0.260,-0.080,1.070], [-5.500,-2.170,-4.600], [3.600,1.240,-3.410]]), + (27, [[44.600,-142.080,934.770], [8.650,3.530,1.100], [2.850,-7.000,0.020], [-1.020,-0.770,1.000], [0.830,0.310,-7.530], [3.410,1.450,-1.300]]), + (28, [[53.340,-139.440,937.210], [8.310,2.340,2.220], [2.150,-7.250,-0.380], [-0.540,-0.170,-0.420], [1.710,0.890,-7.340], [0.070,0.370,0.030]]), + (29, [[61.180,-137.390,939.220], [8.230,1.720,1.430], [1.690,-7.360,-0.860], [-0.380,-0.100,-0.170], [1.060,1.120,-7.440], [-0.840,-0.070,-0.120]]), + (30, [[69.720,-136.030,940.040], [8.420,1.510,0.050], [1.350,-7.460,-0.740], [0.300,0.210,-0.630], [-0.090,0.740,-7.580], [-3.560,-0.970,1.730]]), + (31, [[77.280,-134.500,939.340], [4.490,4.180,-8.530], [2.310,-6.920,-2.180], [-0.290,0.070,-0.480], [-6.410,-0.930,-3.830], [-3.190,-0.950,5.530]]), + (32, [[71.890,-131.270,929.110], [-6.780,1.090,-6.790], [0.090,-7.530,-1.300], [-0.440,-0.260,1.250], [-5.410,-0.970,5.250], [0.240,0.450,2.900]]), + (33, [[66.110,-131.600,925.900], [-4.090,-0.450,-4.440], [0.540,-7.640,0.280], [0.080,0.050,1.400], [-5.560,-0.210,5.140], [-0.150,0.880,-0.160]]), + (34, [[63.930,-132.090,921.070], [-3.930,-1.160,-4.370], [0.320,-7.470,1.700], [0.720,0.300,0.950], [-5.720,0.870,4.920], [0.660,0.510,0.560]]), + (35, [[58.470,-133.890,917.960], [-6.670,-3.360,-3.670], [2.290,-6.970,2.210], [2.280,0.920,-0.110], [-3.960,0.750,6.500], [2.250,0.030,1.310]]), + (36, [[51.020,-139.090,914.020], [-6.630,-6.740,0.390], [5.400,-5.250,1.130], [1.070,0.420,-1.320], [-0.590,1.020,7.590], [3.120,0.370,0.200]]), + (37, [[46.770,-145.490,918.120], [-5.050,-4.370,2.870], [4.810,-5.920,-0.550], [-1.310,-0.890,-0.940], [2.680,1.520,7.030], [1.260,-0.680,-0.120]]), + (38, [[41.950,-147.920,919.780], [-5.030,-2.380,1.940], [2.900,-7.030,-1.100], [-1.320,-0.680,-0.330], [2.770,0.010,7.180], [-0.110,-1.000,0.120]]), + (39, [[36.760,-150.210,922.000], [-5.100,-1.680,1.580], [2.030,-7.330,-1.240], [-0.510,-0.220,0.810], [2.440,-0.560,7.300], [-0.450,0.500,0.130]]), + (40, [[31.890,-151.330,922.990], [-5.710,-1.250,1.560], [1.770,-7.500,0.460], [-0.570,-0.180,0.730], [1.840,0.880,7.450], [-2.050,0.330,0.030]]), + (41, [[25.550,-152.650,925.180], [-6.280,-0.560,-2.170], [0.700,-7.710,-0.030], [-0.690,-0.090,-0.620], [-2.500,-0.250,7.310], [-3.190,-0.780,-0.830]]), + (42, [[22.170,-152.270,920.060], [-4.850,0.300,-4.200], [0.270,-7.700,-0.850], [-0.240,-0.020,0.240], [-5.020,-0.810,5.760], [2.410,0.370,-0.060]]), + (43, [[16.600,-152.110,917.510], [-6.970,0.000,2.680], [0.200,-7.740,0.510], [-0.300,-0.030,0.600], [2.770,0.540,7.210], [5.780,0.370,-0.740]]), + (44, [[13.120,-152.320,924.900], [-3.730,0.410,7.150], [-0.450,-7.750,0.210], [-0.140,-0.020,-0.160], [6.780,-0.300,3.550], [-0.230,-0.180,0.200]]), + (45, [[9.440,-151.370,931.310], [-7.880,0.190,2.810], [-0.130,-7.780,0.170], [0.490,-0.010,0.120], [2.610,0.120,7.310], [-3.700,0.330,2.080]]), + (46, [[1.230,-152.170,928.310], [-8.130,-0.720,-1.080], [0.620,-7.760,0.490], [0.090,-0.010,-0.290], [-1.060,0.400,7.710], [1.430,-0.160,-0.650]]), + (47, [[-5.970,-152.740,928.930], [-5.640,-0.310,4.390], [0.170,-7.800,-0.330], [-0.930,0.040,0.090], [4.760,-0.160,6.120], [3.980,-0.840,-4.110]]), + (48, [[-8.050,-152.700,935.120], [0.840,0.430,7.280], [-1.310,-7.670,0.600], [-1.080,0.170,0.740], [7.520,-1.340,-0.790], [0.790,-0.430,-1.110]]), + (49, [[-4.180,-151.980,940.930], [-5.500,2.850,8.020], [-2.070,-7.440,1.220], [-0.370,0.070,-0.100], [6.170,-0.960,4.570], [-3.010,0.560,4.290]]), + (50, [[-15.920,-150.230,939.850], [-11.530,2.830,0.080], [-1.870,-7.620,-0.020], [0.120,0.150,0.780], [0.040,-0.030,7.840], [0.810,0.000,-1.160]]), + (51, [[-25.870,-146.770,940.970], [-2.690,4.150,9.230], [-1.800,-7.150,2.690], [0.690,0.200,1.480], [7.250,-0.880,2.510], [1.720,-1.410,-6.490]]), + (52, [[-19.430,-146.580,946.990], [7.700,1.830,5.130], [-0.490,-7.140,3.290], [1.240,-0.130,-0.090], [4.500,-2.940,-5.700], [-0.590,-0.040,-3.450]]), + (53, [[-11.610,-143.430,950.540], [5.250,2.520,5.680], [0.830,-7.420,2.520], [0.750,-0.240,-0.870], [5.910,-1.040,-5.000], [0.830,1.410,0.570]]), + (54, [[-9.220,-141.820,956.880], [3.600,1.580,5.200], [1.220,-7.660,1.480], [-0.050,-0.130,-0.420], [6.390,0.150,-4.470], [0.120,0.280,0.100]]), + (55, [[-4.880,-140.390,960.700], [3.780,1.360,4.900], [0.780,-7.720,1.540], [0.070,-0.060,-0.650], [6.230,-0.310,-4.720], [0.530,0.530,1.660]]), + (56, [[-1.980,-139.200,966.470], [0.650,0.130,7.290], [1.420,-7.780,0.010], [0.230,-0.060,-0.880], [7.610,1.390,-0.700], [0.660,0.740,3.140]]), + (57, [[-4.150,-140.360,973.960], [-2.380,-0.650,10.170], [1.190,-7.830,-0.220], [-0.650,-0.070,-0.200], [7.500,1.090,1.830], [-0.210,-0.700,2.000]]), + (58, [[-6.206,-140.381,984.826], [-3.997,1.953,8.625], [-0.240,-7.940,-0.400], [-0.770,0.020,-0.440], [7.090,-0.380,3.280], [-1.820,-1.020,2.460]]), + (59, [[-11.071,-137.239,990.534], [-6.502,2.564,3.616], [-0.730,-7.850,-1.030], [0.040,-0.000,-0.150], [4.330,-1.250,6.510], [-3.510,-0.150,2.180]]), + (60, [[-18.114,-135.562,991.751], [-6.821,0.865,-0.438], [-0.170,-7.940,-0.730], [0.590,-0.040,0.750], [-0.320,-0.720,7.930], [-4.070,0.690,0.160]]), + (61, [[-24.108,-135.469,989.949], [-5.560,-1.043,-2.740], [0.530,-7.940,0.630], [-0.080,0.160,1.480], [-4.270,0.240,6.690], [-3.140,0.950,-2.220]]), + (62, [[-28.764,-137.545,986.518], [-3.033,-3.486,-4.184], [-0.280,-7.620,2.380], [-1.430,0.310,0.610], [-7.020,1.290,3.320], [-0.940,0.180,-5.150]]), + (63, [[-29.636,-141.811,982.334], [1.634,-2.756,-5.189], [-2.170,-7.290,2.440], [-1.160,0.110,-0.290], [-7.100,1.030,-3.250], [0.490,-0.350,-4.870]]), + (64, [[-24.820,-145.190,978.580], [4.650,-2.180,-4.590], [-2.130,-7.580,1.440], [0.290,-0.260,-0.910], [-5.460,0.450,-5.750], [-0.330,0.230,1.000]]), + (65, [[-20.750,-146.910,974.010], [1.230,-0.700,-6.940], [-1.580,-7.840,0.510], [0.080,-0.090,-0.690], [-7.590,1.430,-1.480], [0.460,0.350,5.770]]), + (66, [[-23.390,-146.100,967.330], [-6.320,1.650,-4.010], [-2.030,-7.760,0.010], [-0.160,0.070,0.360], [-4.040,1.070,6.800], [4.830,-0.400,4.280]]), + (67, [[-30.600,-144.330,967.780], [-6.690,2.040,2.190], [-1.930,-7.690,1.270], [0.050,0.000,0.440], [2.650,0.580,7.550], [3.030,-0.350,0.340]]), + (68, [[-36.170,-142.250,971.340], [-6.590,1.940,2.270], [-1.940,-7.730,1.010], [0.040,-0.010,0.090], [2.700,0.310,7.560], [0.370,-0.020,-0.150]]), + (69, [[-43.400,-140.590,972.070], [-6.040,1.970,2.740], [-1.830,-7.710,1.480], [0.020,0.340,1.180], [3.470,0.560,7.230], [2.300,-0.410,-2.270]]), + (70, [[-47.620,-138.630,976.140], [-1.780,2.680,4.620], [-1.870,-7.070,3.390], [0.010,0.350,0.980], [7.300,-0.460,3.080], [1.720,-1.440,-3.710]]), + (71, [[-47.100,-135.980,980.160], [0.980,1.950,4.050], [-1.830,-6.900,3.760], [0.210,-0.140,-0.200], [7.550,-2.370,-0.680], [0.040,-0.760,-2.210]]), + (72, [[-45.780,-134.750,984.020], [1.920,1.940,5.580], [-1.460,-7.340,3.050], [-0.530,0.370,0.090], [7.430,-2.220,-1.790], [-0.240,0.260,1.070]]), + (73, [[-42.419,-130.149,990.122], [-1.920,7.780,7.360], [-3.780,-5.370,4.690], [-2.140,1.260,-0.060], [6.910,-1.720,3.610], [-3.470,2.540,4.150]]), + (74, [[-48.414,-118.983,992.238], [-8.280,6.980,-7.760], [-5.960,-5.080,1.790], [0.610,-1.110,-1.840], [-2.030,4.630,6.340], [-6.540,1.980,-0.430]]), + (75, [[-54.520,-122.570,980.900], [-5.100,0.460,-13.050], [-2.600,-7.660,0.750], [2.850,-1.090,0.850], [-7.020,2.660,2.840], [-2.860,-1.790,-2.310]]), + (76, [[-56.534,-121.929,967.273], [-3.400,-6.950,-12.830], [-2.036,-6.714,3.150], [-1.690,1.750,1.250], [-7.800,0.860,1.600], [1.210,-0.700,-4.510]]), + (77, [[-57.601,-134.069,961.014], [4.440,-11.120,-4.920], [-6.170,-3.970,3.410], [-1.800,0.340,-0.380], [-4.460,1.190,-6.700], [1.720,-0.860,-3.600]]), + (78, [[-53.650,-142.090,958.040], [8.150,-8.950,-3.450], [-4.950,-5.680,3.060], [2.040,-1.620,-0.110], [-3.750,-0.620,-7.230], [-0.920,-0.860,0.970]]), + (79, [[-43.780,-150.900,953.550], [6.860,-6.210,-10.820], [-1.570,-7.380,3.240], [0.100,-0.470,-1.480], [-6.930,-0.360,-4.180], [-0.500,1.880,6.120]]), + (80, [[-42.790,-151.920,940.920], [-10.160,7.350,-12.870], [-4.740,-6.680,-0.070], [-1.780,0.370,-1.940], [-4.810,3.350,5.710], [1.370,1.930,5.900]]), + (81, [[-59.560,-139.320,940.870], [-10.470,7.530,-10.550], [-4.670,-6.770,-0.210], [-0.780,0.740,0.770], [-4.390,2.820,6.370], [-0.630,1.740,-4.220]]), + (82, [[-61.190,-138.430,930.230], [-0.370,-2.040,-12.190], [-5.970,-5.520,1.110], [-0.860,0.960,0.960], [-5.640,5.920,-0.830], [0.650,-0.720,-6.690]]), + (83, [[-60.050,-143.370,918.840], [6.120,-9.410,-3.110], [-6.440,-4.780,1.790], [0.250,-0.370,-0.760], [-2.750,0.780,-7.780], [3.390,-3.100,-3.060]]), + (84, [[-54.810,-148.970,924.540], [7.070,-6.600,2.050], [-5.610,-6.050,-0.170], [0.760,-0.860,-0.330], [1.380,-1.050,-8.130], [-1.610,1.400,1.580]]), + (85, [[-48.000,-154.670,922.570], [3.540,-3.720,-7.480], [-4.830,-6.610,1.000], [1.210,-0.760,-0.140], [-5.850,3.580,-4.550], [-4.060,1.810,3.830]]), + (86, [[-49.390,-154.510,914.460], [0.270,0.350,-10.670], [-3.110,-7.640,-0.330], [1.860,-0.790,-0.480], [-7.540,3.070,-0.100], [1.640,-1.570,-0.540]]), + (87, [[-46.730,-154.010,904.000], [18.990,-1.890,-1.480], [-0.780,-8.190,0.400], [1.310,-0.300,0.500], [-0.670,-0.340,-8.190], [5.190,-2.310,-4.980]]), + (88, [[-31.900,-157.000,923.200], [20.270,-2.840,5.710], [-1.280,-8.040,0.540], [1.630,0.180,0.170], [2.100,-0.860,-7.850], [-3.210,-0.770,1.420]]), + (89, [[-17.040,-158.470,917.330], [10.690,1.600,-10.940], [1.940,-7.840,0.740], [0.870,0.010,-0.110], [-5.440,-1.880,-5.580], [-1.710,0.190,-0.090]]), + (90, [[-12.920,-154.880,905.590], [14.280,1.560,-5.120], [1.010,-8.000,0.370], [-0.980,-0.090,-0.580], [-2.650,-0.690,-7.580], [1.890,1.140,-1.150]]), + (91, [[0.790,-157.220,913.220], [17.050,-0.100,-3.500], [-0.160,-8.010,-0.530], [0.240,0.090,-0.240], [-1.610,0.550,-7.830], [0.100,0.160,0.010]]), + (92, [[11.370,-154.850,899.810], [20.470,4.340,-7.040], [1.620,-7.800,-0.100], [0.670,0.240,-0.620], [-2.500,-0.420,-7.540], [-1.600,0.070,0.920]]), + (93, [[35.280,-149.960,905.730], [15.010,5.710,-13.200], [0.800,-7.500,-2.330], [1.120,0.330,0.340], [-5.360,1.170,-5.590], [-1.050,-1.380,0.950]]), + (94, [[31.510,-148.900,893.070], [11.510,6.020,-14.640], [3.170,-7.130,-0.440], [1.650,0.510,0.450], [-5.440,-2.110,-5.150], [2.200,-0.030,-0.530]]), + (95, [[53.210,-142.180,892.150], [16.130,8.560,4.600], [3.960,-6.330,-2.130], [0.420,0.200,0.800], [0.580,2.810,-7.250], [3.440,1.000,-0.610]]), + (96, [[61.915,-135.512,899.756], [10.425,5.807,7.557], [4.220,-6.470,0.220], [-1.030,-0.530,1.150], [2.810,1.590,-7.040], [-2.200,-1.800,0.660]]), + (97, [[72.652,-131.499,906.138], [13.270,2.580,-11.410], [1.590,-7.520,0.150], [-0.630,-0.250,0.200], [-4.770,-1.120,-5.790], [-4.380,-1.930,4.880]]), + (98, [[70.933,-136.139,889.296], [-12.490,-8.250,-22.650], [3.260,-6.840,0.700], [0.840,0.360,-0.040], [-5.890,-2.380,4.110], [0.640,-0.370,7.040]]), + (99, [[47.820,-142.630,864.930], [-22.720,-8.470,-7.520], [2.750,-7.000,-0.430], [0.030,0.230,-1.270], [-1.940,-1.200,7.190], [5.330,1.350,0.110]]), + (100, [[33.710,-147.840,866.620], [-7.310,-5.020,5.800], [3.020,-6.590,-1.880], [-0.710,0.240,-1.450], [4.500,0.350,5.980], [2.350,2.560,-6.780]]), + (101, [[33.450,-149.550,870.080], [6.660,-2.670,8.620], [1.910,-6.380,-3.460], [-0.810,0.030,-0.860], [5.650,3.480,-3.300], [0.800,2.080,-6.770]]), + (102, [[48.500,-149.860,877.560], [8.440,-1.400,10.880], [1.840,-6.880,-2.310], [-0.550,-0.390,1.170], [5.590,2.820,-3.970], [-1.370,-2.160,5.890]]), + (103, [[49.170,-151.340,885.880], [-14.130,-2.760,6.710], [0.940,-7.250,-1.010], [-0.570,0.330,-0.410], [3.260,-0.510,6.640], [-3.090,-3.470,6.170]]), + (104, [[30.330,-151.820,877.700], [-17.160,1.530,-4.960], [0.920,-5.490,-4.890], [-1.510,-0.140,0.400], [-1.940,-4.930,5.180], [0.640,-0.130,0.130]]), + (105, [[16.360,-149.060,875.570], [-10.970,1.710,5.380], [-1.800,-6.980,-1.460], [-0.540,-0.730,1.970], [2.830,-2.080,6.450], [2.860,1.800,-0.060]]), + (106, [[11.690,-148.720,883.920], [-10.140,1.000,8.830], [-0.940,-7.280,-0.260], [0.660,-0.150,1.090], [4.710,-0.800,5.500], [-0.400,1.320,0.040]]), + (107, [[-3.830,-146.990,890.110], [-14.280,1.090,0.550], [-0.520,-7.220,0.830], [0.360,0.010,-0.260], [0.340,0.810,7.240], [-1.670,-0.060,0.660]]), + (108, [[-14.790,-146.520,886.710], [-10.850,0.220,0.510], [-0.160,-7.240,-0.380], [0.730,0.030,-0.300], [0.330,-0.390,7.230], [2.180,0.020,-0.940]]), + (109, [[-23.910,-146.550,890.530], [-7.400,-0.950,6.580], [0.980,-7.160,0.070], [-0.520,0.100,0.630], [4.680,0.690,5.370], [0.750,0.450,-0.150]]), + (110, [[-28.030,-148.180,898.370], [-13.610,2.900,3.800], [-1.230,-7.020,0.960], [-1.430,0.370,-0.840], [2.040,0.580,6.860], [-3.990,-0.650,0.170]]), + (111, [[-42.020,-140.320,889.270], [-9.930,7.700,-9.680], [-1.440,-6.120,-3.390], [0.840,-0.040,-0.890], [-5.330,-1.240,4.490], [-3.620,0.110,-4.100]]), + (112, [[-47.830,-133.820,880.590], [1.670,2.810,-9.020], [0.190,-6.800,-2.080], [0.020,-0.240,2.820], [-6.870,0.170,-1.220], [2.630,-0.650,-5.170]]), + (113, [[-43.360,-134.640,876.970], [7.370,-1.120,-1.770], [-0.610,-6.830,1.800], [-0.490,-0.090,1.490], [-1.840,-1.590,-6.650], [3.370,-0.420,-3.090]]), + (114, [[-34.800,-135.760,878.370], [7.330,-0.800,-0.160], [-0.760,-7.020,0.280], [-0.510,0.020,-0.710], [-0.180,-0.260,-7.060], [-2.440,1.360,1.660]]), + (115, [[-29.320,-136.240,877.180], [3.390,-0.800,-5.310], [-1.570,-6.870,0.040], [-0.230,0.050,0.030], [-5.670,1.270,-3.820], [-3.220,0.720,3.410]]), + (116, [[-30.610,-136.870,870.770], [-0.250,-0.250,-5.290], [-1.190,-6.910,0.380], [0.280,-0.030,-0.030], [-6.790,1.180,0.270], [0.350,-0.330,-1.210]]), + (117, [[-30.230,-136.860,867.080], [2.790,-0.450,-3.890], [-0.940,-6.950,0.140], [0.330,-0.030,-0.120], [-5.570,0.670,-4.070], [3.300,-0.630,-3.480]]), + (118, [[-25.370,-137.760,865.060], [8.760,-0.500,1.850], [-0.440,-6.980,0.180], [0.240,0.000,-0.170], [1.430,-0.270,-6.840], [3.730,-0.350,-1.770]]), + (119, [[-17.010,-136.930,873.250], [9.540,-0.880,-1.350], [-0.710,-6.910,-0.470], [-0.790,0.170,0.250], [-0.920,0.560,-6.870], [-3.990,0.940,2.860]]), + (120, [[-14.620,-138.100,867.370], [2.470,-1.150,-8.780], [-1.880,-6.660,0.340], [1.250,0.410,-0.040], [-6.320,1.680,-1.990], [-1.180,0.210,1.020]]), + (121, [[-13.210,-138.670,858.260], [15.020,8.840,-1.860], [3.370,-5.940,-1.020], [3.020,0.320,-0.460], [-1.140,0.510,-6.800], [4.300,-0.760,-2.960]]), + (122, [[-2.010,-129.090,875.920], [14.730,5.570,5.540], [2.300,-6.430,0.360], [-3.380,0.090,1.420], [2.260,0.450,-6.450], [-4.260,0.280,1.850]]), + (123, [[5.710,-128.310,873.450], [4.220,-3.800,-6.920], [-2.330,-6.100,1.930], [1.540,1.120,0.790], [-5.490,0.890,-3.830], [-2.900,-1.920,4.890]]), + (124, [[3.860,-133.450,867.510], [-1.780,-5.980,-7.590], [4.850,-4.160,2.140], [1.960,0.650,1.010], [-4.520,-3.360,3.710], [0.300,-2.100,1.250]]), + (125, [[2.440,-139.690,858.800], [7.020,-5.190,-6.230], [0.110,-5.150,4.400], [-1.690,-0.890,0.210], [-5.060,-2.920,-3.280], [2.220,0.250,-4.490]]), + (126, [[11.980,-140.150,859.350], [17.700,2.250,-1.140], [0.950,-6.060,2.790], [1.390,-0.390,-2.080], [-0.040,-2.820,-6.130], [2.190,0.110,-1.390]]), + (127, [[35.300,-132.990,854.910], [8.740,9.550,-15.220], [4.050,-5.230,-0.960], [0.820,0.890,-2.820], [-4.430,-2.650,-4.200], [-1.330,-1.300,4.050]]), + (128, [[29.930,-128.550,843.920], [-12.950,5.120,-19.360], [3.680,-4.210,-3.570], [-1.410,0.000,-0.870], [-4.190,-4.930,1.490], [1.700,-0.300,5.110]]), + (129, [[9.390,-125.790,820.060], [-27.750,1.440,5.840], [-0.470,-6.580,-0.630], [-1.270,-0.920,1.780], [1.320,-0.720,6.460], [4.740,2.190,-0.360]]), + (130, [[4.650,-126.740,840.920], [-6.020,1.180,15.730], [0.130,-6.590,0.550], [-0.730,0.090,0.190], [6.110,0.310,2.320], [-2.110,0.210,1.570]]), + (131, [[0.040,-125.010,849.260], [-9.240,1.850,1.000], [-1.260,-6.450,0.320], [0.680,0.070,-0.540], [0.750,0.180,6.550], [-5.740,-0.820,-0.600]]), + (132, [[-4.440,-124.790,843.150], [-5.020,0.460,-16.660], [1.260,-6.430,-0.560], [1.980,0.080,-0.420], [-6.090,-1.340,1.790], [-4.270,-1.020,-2.570]]), + (133, [[-4.100,-124.240,817.800], [-14.820,-5.980,-12.690], [2.230,-6.130,0.290], [-0.080,-0.020,0.180], [-3.880,-1.170,5.070], [6.330,1.590,-0.020]]), + (134, [[-13.820,-128.400,823.840], [-7.490,-1.580,13.510], [1.550,-6.330,0.120], [-0.550,0.000,0.710], [5.490,1.400,3.200], [4.920,1.220,-2.010]]), + (135, [[-15.540,-126.400,839.810], [-2.260,3.630,12.780], [1.060,-6.110,1.920], [-1.860,0.050,-0.360], [6.210,1.310,0.730], [-0.950,-1.430,1.430]]), + (136, [[-17.860,-122.190,848.910], [-6.970,2.290,6.400], [-1.900,-6.170,0.140], [0.210,-0.110,-0.730], [4.060,-1.150,4.850], [-5.500,-0.820,1.290]]), + (137, [[-24.460,-122.950,849.040], [-11.050,-2.260,-14.690], [1.030,-6.350,0.200], [1.600,-0.050,0.470], [-5.050,-0.700,3.900], [-6.400,0.950,-0.750]]), + (138, [[-23.980,-124.710,821.700], [-13.900,-3.450,-17.210], [-1.090,-5.980,2.080], [-0.110,-0.110,-0.760], [-4.880,2.110,3.530], [5.050,-0.430,0.870]]), + (139, [[-38.600,-127.220,820.180], [-12.580,-0.430,8.780], [-0.020,-6.390,-0.330], [-0.170,-0.020,-0.170], [3.670,-0.290,5.240], [4.860,-1.540,-2.070]]), + (140, [[-42.520,-125.650,832.780], [1.330,2.910,14.250], [-1.250,-6.100,1.370], [-0.030,0.210,1.190], [6.110,-1.310,-0.300], [1.080,-0.260,-3.490]]), + (141, [[-35.800,-121.920,845.730], [4.200,3.780,10.200], [0.010,-5.960,2.200], [-0.160,0.230,0.570], [5.880,-0.780,-2.130], [0.090,0.030,0.690]]), + (142, [[-33.620,-118.720,852.840], [0.500,3.010,6.470], [-0.930,-5.650,2.700], [-0.790,-0.030,-0.570], [6.150,-1.010,0.000], [-0.330,-0.030,2.500]]), + (143, [[-34.440,-116.110,858.280], [-2.640,1.810,5.040], [-1.710,-5.940,1.230], [0.580,-0.290,-1.410], [5.320,-0.890,3.110], [-1.830,0.370,2.710]]), + (144, [[-38.380,-115.330,862.170], [-6.050,-0.340,2.350], [0.220,-6.280,-0.340], [1.370,-0.090,-0.250], [2.280,-0.240,5.850], [-4.210,0.450,0.940]]), + (145, [[-44.500,-116.930,861.580], [-11.590,-3.810,-10.160], [1.110,-6.090,1.020], [0.440,0.120,0.610], [-4.130,0.030,4.700], [-4.540,0.050,-0.790]]), + (146, [[-51.780,-120.720,839.030], [-15.880,-5.450,-10.360], [1.830,-5.970,0.320], [-1.360,0.270,0.870], [-3.220,-0.700,5.310], [4.290,0.490,0.090]]), + (147, [[-64.650,-124.350,841.480], [-11.510,0.420,9.850], [0.150,-6.190,0.440], [-0.550,0.330,1.540], [3.970,0.430,4.630], [4.380,-0.520,-2.900]]), + (148, [[-69.370,-119.950,854.330], [5.110,4.210,16.620], [-1.330,-5.740,1.870], [0.690,0.270,0.730], [5.670,-1.740,-1.310], [0.560,-1.580,-4.180]]), + (149, [[-55.630,-118.570,867.170], [8.190,15.700,8.570], [-2.415,-2.636,3.160], [0.890,1.630,1.440], [4.280,-1.310,-1.700], [0.130,0.200,0.140]]), + (150, [[-52.380,-100.900,869.760], [4.760,24.010,12.610], [-3.169,0.219,3.447], [-0.280,-0.300,-1.610], [4.600,-0.510,-0.770], [-2.290,1.100,4.280]]), + (151, [[-41.730,-76.290,892.900], [-14.020,14.240,19.650], [-3.750,-3.589,-1.622], [3.240,-2.890,0.750], [1.930,-2.620,3.270], [-5.090,5.860,6.610]]), + (152, [[-60.630,-80.530,895.250], [-6.170,-10.100,-5.870], [2.660,0.730,-4.050], [2.380,0.990,-1.140], [3.310,-2.970,1.640], [2.380,0.990,-1.140]]) + ] ), - centralPathDefaultScaffoldPackages = { - 'Cattle 1' : ScaffoldPackage(MeshType_1d_path1, { - 'scaffoldSettings' : { - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Coordinate dimensions' : 3, - 'Length' : 1.0, - 'Number of elements' : 536 - }, - 'meshEdits' : exnode_string_from_nodeset_field_parameters( - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ -502.30, 732.10, 92.00 ], [ -49.80, -90.70, 0.00 ], [ 0.00, 0.00, 10.00 ], [ 0.00, 0.00, 0.00 ], [ -8.77, 4.81, 0.00 ], [ 0.00, 0.00, 0.00 ] ] ), - (2, [ [ -543.10, 654.80, 92.00 ], [ -31.70, -64.00, 0.00 ], [ 0.00, 0.00, 10.00 ], [ 0.00, 0.00, 0.00 ], [ -8.96, 4.44, 0.00 ], [ 0.00, 0.00, 0.00 ] ] ), - (3, [ [ -566.20, 605.00, 92.00 ], [ -43.40, -40.20, 0.00 ], [ 0.00, 0.00, 10.00 ], [ 0.00, 0.00, 0.00 ], [ -6.80, 7.34, 0.00 ], [ 0.00, 0.00, 0.00 ] ] ), - (4, [ [ -623.90, 583.60, 92.00 ], [ -58.90, 0.00, 0.00 ], [ 0.00, 0.00, 10.00 ], [ 0.00, 0.00, 0.00 ], [ 0.00, 10.00, 0.00 ], [ 0.00, 0.00, 0.00 ] ] ), - (5, [ [ -674.40, 602.30, 92.00 ], [ -25.80, 24.90, 0.00 ], [ 0.00, 0.00, 10.00 ], [ 1.57, 1.24, -0.27 ], [ 6.94, 7.20, 0.00 ], [ 1.57, 1.24, -0.27 ] ] ), - (6, [ [ -676.30, 613.40, 92.00 ], [ 21.70, 17.10, -7.50 ], [ 2.05, 1.62, 9.65 ], [ 1.52, 0.69, -0.22 ], [ 6.19, -7.86, 0.01 ], [ 1.52, 0.69, -0.22 ] ] ), - (7, [ [ -638.20, 613.20, 80.50 ], [ 47.90, 1.90, -11.30 ], [ 2.29, 0.09, 9.73 ], [ -0.55, 2.15, -1.26 ], [ 0.39, -9.99, -0.00 ], [ -0.55, 2.15, -1.25 ] ] ), - (8, [ [ -586.80, 617.60, 72.10 ], [ 3.30, 41.00, -47.10 ], [ 0.61, 7.52, 6.56 ], [ -1.76, 0.56, -0.15 ], [ 9.97, -0.79, -0.02 ], [ -1.77, 0.56, -0.14 ] ] ), - (9, [ [ -644.60, 633.70, 57.50 ], [ -52.20, 4.60, -6.70 ], [ -1.25, 0.12, 9.92 ], [ 0.12, -4.47, 1.05 ], [ 0.89, 9.96, -0.01 ], [ 0.12, -4.47, 1.05 ] ] ), - (10, [ [ -677.20, 630.20, 57.50 ], [ 0.10, -43.70, -12.10 ], [ -0.00, -2.66, 9.64 ], [ 1.58, -0.74, -0.11 ], [ -10.00, -0.01, -0.00 ], [ 1.58, -0.74, -0.10 ] ] ), - (11, [ [ -632.90, 609.90, 50.60 ], [ 51.90, -16.20, -11.70 ], [ 2.02, -0.63, 9.77 ], [ 0.39, -1.35, -0.70 ], [ -2.97, -9.55, -0.00 ], [ 0.39, -1.35, -0.70 ] ] ), - (12, [ [ -581.30, 601.00, 35.40 ], [ 4.90, -48.00, -34.50 ], [ 0.57, -5.79, 8.13 ], [ -1.42, 0.41, 0.08 ], [ -9.95, -1.01, -0.02 ], [ -1.42, 0.40, 0.08 ] ] ), - (13, [ [ -631.70, 589.30, 35.90 ], [ -57.50, 19.90, -5.30 ], [ -0.82, 0.28, 9.96 ], [ -2.13, 7.48, -3.39 ], [ 3.27, 9.45, 0.00 ], [ -2.13, 7.47, -3.39 ] ] ), - (14, [ [ -667.40, 632.00, 27.30 ], [ -60.00, -18.80, -39.10 ], [ -3.71, 9.21, 1.15 ], [ -1.20, -0.91, -9.00 ], [ 4.52, 2.88, -8.44 ], [ -1.20, -0.91, -9.00 ] ] ), - (15, [ [ -666.40, 558.00, 7.70 ], [ -33.70, -54.60, 46.30 ], [ -2.57, -5.27, -8.10 ], [ -1.72, -4.99, -3.68 ], [ 8.68, -4.95, 0.47 ], [ -1.72, -4.99, -3.68 ] ] ), - (16, [ [ -698.00, 570.70, 66.50 ], [ -52.90, 5.40, 48.50 ], [ -6.71, -2.24, -7.06 ], [ -2.86, -0.08, 4.78 ], [ 0.98, -9.72, 2.16 ], [ -2.87, -0.08, 4.78 ] ] ), - (17, [ [ -760.20, 567.80, 94.30 ], [ -13.60, 33.40, 46.80 ], [ -8.32, -5.37, 1.39 ], [ 4.50, 1.96, 8.55 ], [ 5.04, -6.28, 5.92 ], [ 4.51, 1.96, 8.55 ] ] ), - (18, [ [ -724.50, 582.10, 93.50 ], [ 45.90, 1.10, -0.90 ], [ 0.19, -0.07, 10.00 ], [ 4.20, 2.65, 4.23 ], [ 0.23, -10.00, -0.07 ], [ 4.20, 2.65, 4.24 ] ] ), - (19, [ [ -681.80, 570.00, 92.80 ], [ 28.80, -21.00, -0.70 ], [ 0.24, 0.02, 10.02 ], [ -0.11, -0.21, 0.02 ], [ -5.91, -8.09, 0.16 ], [ -0.11, -0.21, 0.02 ] ] ), - (20, [ [ -667.90, 548.90, 92.30 ], [ 3.90, -28.50, -1.00 ], [ 0.03, -0.37, 10.03 ], [ -0.05, -0.00, 0.02 ], [ -9.94, -1.38, -0.02 ], [ -0.05, -0.00, 0.02 ] ] ), - (21, [ [ -677.10, 520.90, 91.00 ], [ -27.30, -11.70, 0.60 ], [ 0.17, 0.09, 10.06 ], [ -0.32, 0.01, 0.01 ], [ -3.97, 9.24, -0.02 ], [ -0.32, 0.01, 0.01 ] ] ), - (22, [ [ -700.50, 532.40, 92.90 ], [ -14.40, 20.00, -0.20 ], [ -0.56, -0.30, 10.06 ], [ -0.35, 0.31, 0.00 ], [ 8.16, 5.88, 0.63 ], [ -0.36, 0.32, 0.00 ] ] ), - (23, [ [ -703.50, 552.30, 91.10 ], [ -16.60, 15.00, -1.80 ], [ -0.63, 0.54, 10.06 ], [ -0.38, 0.11, -0.02 ], [ 6.75, 7.50, 0.02 ], [ -0.39, 0.11, -0.02 ] ] ), - (24, [ [ -726.50, 553.80, 90.20 ], [ -21.70, -2.90, -3.00 ], [ -1.37, -0.18, 10.02 ], [ -1.63, -5.16, -4.21 ], [ -1.35, 10.02, -0.00 ], [ -1.63, -5.16, -4.21 ] ] ), - (25, [ [ -739.60, 548.10, 86.40 ], [ 15.30, -13.20, -28.20 ], [ -3.76, -9.13, 2.25 ], [ -1.48, -2.79, -8.86 ], [ -8.28, 2.07, -5.44 ], [ -1.48, -2.79, -8.86 ] ] ), - (26, [ [ -694.50, 550.10, 70.60 ], [ 44.70, -4.70, -16.30 ], [ -3.06, 2.92, -9.23 ], [ 1.47, 4.72, -6.06 ], [ 1.90, 9.68, 2.43 ], [ 1.47, 4.71, -6.06 ] ] ), - (27, [ [ -652.70, 539.30, 54.70 ], [ 26.40, -22.50, -3.70 ], [ -0.85, 0.66, -10.13 ], [ 0.77, -2.83, -0.13 ], [ 6.61, 7.75, -0.05 ], [ 0.77, -2.82, -0.13 ] ] ), - (28, [ [ -644.90, 520.20, 58.60 ], [ -8.40, -26.00, 7.10 ], [ -0.80, -2.45, -9.87 ], [ -0.33, -0.93, 0.06 ], [ 9.70, -3.15, -0.00 ], [ -0.33, -0.92, 0.06 ] ] ), - (29, [ [ -670.50, 503.30, 65.20 ], [ -49.20, -7.40, 8.40 ], [ -1.67, -0.25, -10.09 ], [ -0.69, -1.22, 1.36 ], [ 1.54, -10.11, -0.00 ], [ -0.69, -1.22, 1.37 ] ] ), - (30, [ [ -723.20, 522.10, 69.80 ], [ 13.50, 42.00, -69.30 ], [ -1.98, -8.44, -5.51 ], [ -0.28, -0.80, 0.83 ], [ -9.93, 2.58, -0.38 ], [ -0.28, -0.80, 0.83 ] ] ), - (31, [ [ -641.70, 515.00, 30.80 ], [ 50.00, -30.40, -15.00 ], [ -2.21, 1.29, -10.01 ], [ 1.71, -0.27, -1.09 ], [ 5.37, 8.83, -0.05 ], [ 1.71, -0.28, -1.09 ] ] ), - (32, [ [ -631.40, 498.10, 31.40 ], [ -4.50, -28.10, 4.10 ], [ -0.02, -1.49, -10.24 ], [ 0.71, -0.99, -0.15 ], [ 10.22, -1.61, 0.21 ], [ 0.71, -0.99, -0.15 ] ] ), - (33, [ [ -652.60, 477.30, 37.00 ], [ -50.00, -6.30, 6.60 ], [ -1.34, -0.02, -10.29 ], [ -1.33, 1.31, 0.06 ], [ 1.29, -10.29, -0.15 ], [ -1.33, 1.31, 0.06 ] ] ), - (34, [ [ -711.30, 508.40, 47.40 ], [ -65.20, 35.30, 20.70 ], [ -2.68, 0.96, -10.02 ], [ -4.19, 0.21, 3.24 ], [ -4.87, -9.20, 0.42 ], [ -4.19, 0.21, 3.24 ] ] ), - (35, [ [ -756.90, 547.90, 71.40 ], [ -13.40, -32.80, 30.60 ], [ -9.76, 0.39, -3.77 ], [ -0.16, -0.33, -0.99 ], [ 2.37, -7.50, -6.91 ], [ -0.16, -0.33, -0.99 ] ] ), - (36, [ [ -764.20, 524.80, 82.70 ], [ 2.40, -34.00, -3.00 ], [ -7.09, 0.16, -7.72 ], [ 1.12, 1.17, 2.11 ], [ 7.69, 1.14, -7.04 ], [ 1.12, 1.17, 2.11 ] ] ), - (37, [ [ -733.10, 495.70, 71.40 ], [ -9.60, -50.80, 23.30 ], [ -8.61, 3.72, 4.77 ], [ 3.16, -1.87, 8.64 ], [ -5.81, -2.81, -8.30 ], [ 3.17, -1.87, 8.64 ] ] ), - (38, [ [ -714.70, 462.80, 83.00 ], [ 19.70, -9.40, 0.00 ], [ -1.38, -2.86, 10.06 ], [ -2.27, 2.74, -8.49 ], [ -4.34, -9.07, -3.17 ], [ -2.27, 2.74, -8.49 ] ] ), - (39, [ [ -703.00, 463.20, 92.20 ], [ -6.90, 19.30, 27.80 ], [ -8.20, 4.34, -5.03 ], [ -0.98, 2.71, -11.42 ], [ -6.31, -7.60, 3.73 ], [ -0.98, 2.71, -11.43 ] ] ), - (40, [ [ -722.30, 486.20, 90.20 ], [ -30.40, 26.10, -0.90 ], [ 0.20, -0.15, -10.58 ], [ 4.54, -2.26, -3.13 ], [ -6.88, -8.04, -0.02 ], [ 4.54, -2.26, -3.13 ] ] ), - (41, [ [ -745.10, 520.90, 90.70 ], [ -10.10, 19.90, 1.10 ], [ -0.24, 0.48, -10.60 ], [ 0.25, -0.06, -0.02 ], [ -9.47, -4.79, -0.00 ], [ 0.25, -0.06, -0.02 ] ] ), - (42, [ [ -724.50, 528.30, 92.00 ], [ 61.80, -0.90, 2.80 ], [ 0.46, -0.02, -10.62 ], [ -0.36, -0.13, 0.04 ], [ 0.13, 10.63, -0.01 ], [ -0.36, -0.13, 0.04 ] ] ), - (43, [ [ -691.00, 492.20, 92.50 ], [ 65.60, -18.50, -13.50 ], [ -1.98, 0.57, -10.46 ], [ -1.69, 0.78, 0.19 ], [ 2.91, 10.26, 0.01 ], [ -1.70, 0.78, 0.19 ] ] ), - (44, [ [ -640.00, 474.10, 57.50 ], [ 42.10, -24.20, -15.10 ], [ -2.75, 1.58, -10.23 ], [ 1.45, -0.62, -0.23 ], [ 5.34, 9.28, -0.00 ], [ 1.45, -0.63, -0.23 ] ] ), - (45, [ [ -611.10, 454.00, 57.30 ], [ -5.20, -35.60, 0.00 ], [ 0.00, 0.00, -10.73 ], [ 1.27, -0.75, -0.25 ], [ 10.62, -1.55, -0.00 ], [ 1.28, -0.75, -0.25 ] ] ), - (46, [ [ -640.70, 443.80, 57.50 ], [ -30.10, -5.20, 0.10 ], [ -0.04, -0.02, -10.76 ], [ 0.00, 0.00, -0.02 ], [ 1.82, -10.60, 0.01 ], [ 0.00, 0.00, -0.02 ] ] ), - (47, [ [ -667.60, 443.10, 57.50 ], [ -25.60, 5.80, 0.00 ], [ 0.00, 0.00, -10.77 ], [ 0.86, -0.09, 0.06 ], [ -2.38, -10.51, -0.00 ], [ 0.85, -0.09, 0.06 ] ] ), - (48, [ [ -702.10, 461.20, 42.90 ], [ -35.10, 4.20, -7.10 ], [ 2.12, -0.26, -10.59 ], [ -2.58, -3.51, 4.12 ], [ -1.28, -10.73, 0.01 ], [ -2.58, -3.51, 4.12 ] ] ), - (49, [ [ -751.10, 480.00, 41.40 ], [ -2.70, -4.20, 52.00 ], [ -6.95, -8.26, -1.02 ], [ 0.95, -1.86, -0.23 ], [ 8.30, -6.97, -0.12 ], [ 0.95, -1.86, -0.23 ] ] ), - (50, [ [ -740.70, 460.80, 81.10 ], [ 28.50, -35.40, 18.50 ], [ 2.29, -5.05, -9.35 ], [ 0.35, 3.93, -4.00 ], [ 9.49, 5.25, -0.74 ], [ 0.34, 3.93, -4.00 ] ] ), - (51, [ [ -715.80, 438.10, 60.60 ], [ 47.50, 3.90, -28.60 ], [ -5.59, -0.46, -9.35 ], [ -2.22, 3.02, -0.69 ], [ -0.89, 10.87, -0.00 ], [ -2.22, 3.03, -0.69 ] ] ), - (52, [ [ -690.60, 420.70, 23.60 ], [ 72.60, -48.00, -9.80 ], [ -1.03, 0.68, -10.87 ], [ 3.33, -0.90, -0.75 ], [ 6.02, 9.13, 0.00 ], [ 3.33, -0.90, -0.75 ] ] ), - (53, [ [ -634.40, 437.80, 2.60 ], [ -11.70, 62.00, -18.70 ], [ 0.57, -3.08, -10.53 ], [ 0.70, -0.09, -0.11 ], [ -10.80, -2.04, 0.01 ], [ 0.70, -0.10, -0.11 ] ] ), - (54, [ [ -685.40, 456.30, 14.80 ], [ -80.30, 28.90, -4.40 ], [ 0.54, -0.19, -11.01 ], [ -0.87, 2.09, -0.22 ], [ -3.73, -10.38, -0.00 ], [ -0.87, 2.09, -0.22 ] ] ), - (55, [ [ -713.80, 509.70, 13.10 ], [ -37.40, 33.30, 7.40 ], [ -1.21, 1.06, -10.95 ], [ -3.03, -3.15, 1.90 ], [ -7.35, -8.28, 0.01 ], [ -3.03, -3.15, 1.91 ] ] ), - (56, [ [ -762.90, 511.80, 46.30 ], [ -17.40, -20.30, 31.30 ], [ -5.49, -6.40, -7.24 ], [ -0.62, -3.81, 1.50 ], [ 8.45, -7.22, -0.02 ], [ -0.62, -3.81, 1.50 ] ] ), - (57, [ [ -778.20, 487.30, 79.10 ], [ -7.60, -16.30, 20.80 ], [ -3.55, -7.65, -7.29 ], [ 6.65, 7.15, 6.52 ], [ 10.11, -4.70, 0.01 ], [ 6.65, 7.16, 6.52 ] ] ), - (58, [ [ -800.50, 488.70, 56.50 ], [ -2.60, 28.50, -35.30 ], [ 7.23, 6.89, 5.01 ], [ 6.13, 4.32, 8.27 ], [ 8.49, -5.32, -4.94 ], [ 6.13, 4.32, 8.26 ] ] ), - (59, [ [ -767.60, 546.30, 28.50 ], [ 27.50, 29.90, 28.50 ], [ 4.20, -8.95, 5.32 ], [ -7.20, -5.78, -5.89 ], [ 8.34, -0.54, -7.50 ], [ -7.20, -5.78, -5.89 ] ] ), - (60, [ [ -730.30, 549.50, 39.80 ], [ 38.00, -16.90, -12.30 ], [ -5.37, -9.00, -4.10 ], [ 0.16, 0.75, -3.25 ], [ -0.99, 5.13, -9.97 ], [ 0.16, 0.75, -3.25 ] ] ), - (61, [ [ -695.50, 539.60, -1.80 ], [ -25.60, -41.70, -52.60 ], [ 8.66, -7.11, 1.44 ], [ 5.87, 1.82, -1.72 ], [ -6.04, -5.82, 7.57 ], [ 5.87, 1.82, -1.71 ] ] ), - (62, [ [ -753.60, 538.10, 17.50 ], [ -40.40, -47.50, 4.70 ], [ 5.33, -5.37, -8.46 ], [ -2.66, -0.56, -4.61 ], [ 6.83, -5.06, 7.52 ], [ -2.66, -0.56, -4.61 ] ] ), - (63, [ [ -716.70, 466.20, -1.60 ], [ -40.40, -47.80, 46.20 ], [ 3.56, -8.94, -6.13 ], [ -1.22, -1.90, 1.22 ], [ 9.07, -1.07, 6.83 ], [ -1.22, -1.90, 1.22 ] ] ), - (64, [ [ -774.90, 492.50, 14.30 ], [ 4.60, -28.40, 48.20 ], [ 2.79, -9.47, -5.82 ], [ -2.63, -0.59, 0.48 ], [ 11.08, 2.86, 0.65 ], [ -2.63, -0.59, 0.47 ] ] ), - (65, [ [ -755.00, 488.60, 92.30 ], [ -28.50, 3.50, 3.80 ], [ -1.91, -10.12, -5.16 ], [ -0.86, -0.12, -0.18 ], [ 0.72, -5.33, 10.19 ], [ -0.86, -0.12, -0.18 ] ] ), - (66, [ [ -793.80, 484.40, 104.20 ], [ -32.90, 3.60, -1.30 ], [ -0.86, -9.98, -5.76 ], [ 6.84, 4.46, 2.66 ], [ -1.01, -5.69, 10.00 ], [ 6.84, 4.46, 2.66 ] ] ), - (67, [ [ -790.70, 455.50, 85.30 ], [ -2.30, -19.40, -39.70 ], [ 11.49, -1.41, 0.00 ], [ 7.31, 8.14, 4.70 ], [ -1.27, -10.32, 5.09 ], [ 7.31, 8.13, 4.70 ] ] ), - (68, [ [ -801.70, 464.20, 17.70 ], [ 26.10, -25.90, -35.60 ], [ 9.60, 5.94, 2.78 ], [ -7.03, 6.33, -0.90 ], [ 2.70, -8.07, 7.92 ], [ -7.03, 6.33, -0.90 ] ] ), - (69, [ [ -762.40, 459.90, 21.70 ], [ 25.40, 2.00, 17.80 ], [ -0.61, 11.64, -0.39 ], [ -1.65, 0.95, -2.28 ], [ -6.67, -0.03, 9.56 ], [ -1.65, 0.96, -2.28 ] ] ), - (70, [ [ -762.80, 454.40, 83.50 ], [ -1.60, 18.90, 65.10 ], [ 10.10, 5.74, -1.38 ], [ -0.60, -1.49, 6.17 ], [ -5.90, 9.68, -2.92 ], [ -0.60, -1.49, 6.16 ] ] ), - (71, [ [ -767.20, 479.00, 107.60 ], [ -24.80, -1.90, 8.70 ], [ 2.70, 6.90, 9.09 ], [ -9.96, -2.61, 4.05 ], [ -2.90, 9.45, -6.31 ], [ -9.96, -2.61, 4.05 ] ] ), - (72, [ [ -795.10, 432.40, 92.80 ], [ -9.10, -19.70, -41.40 ], [ -11.22, -1.54, 3.22 ], [ -2.62, -8.20, -1.68 ], [ -2.72, 10.57, -4.41 ], [ -2.62, -8.20, -1.68 ] ] ), - (73, [ [ -769.20, 411.90, 25.90 ], [ 68.40, -16.90, -33.00 ], [ 1.09, -9.41, 7.07 ], [ 5.91, 1.76, 3.98 ], [ -5.53, -6.68, -8.04 ], [ 5.92, 1.76, 3.98 ] ] ), - (74, [ [ -679.40, 419.00, 45.00 ], [ 55.50, 10.70, -0.20 ], [ -0.68, 3.92, 11.21 ], [ 1.23, 4.77, 1.54 ], [ 2.17, -10.99, 3.98 ], [ 1.23, 4.77, 1.54 ] ] ), - (75, [ [ -624.80, 428.10, 30.90 ], [ 37.00, 1.10, -8.30 ], [ 2.38, 3.47, 11.16 ], [ 0.65, -3.43, 0.31 ], [ 1.06, -11.41, 3.32 ], [ 0.65, -3.43, 0.31 ] ] ), - (76, [ [ -596.10, 415.90, 17.90 ], [ 13.70, -50.50, -10.30 ], [ 1.44, -1.92, 11.71 ], [ -2.26, -0.16, -0.25 ], [ -11.48, -3.22, 0.88 ], [ -2.26, -0.16, -0.25 ] ] ), - (77, [ [ -633.70, 383.40, 10.50 ], [ -53.90, -32.70, 2.90 ], [ -2.73, 5.47, 10.32 ], [ -3.48, 1.84, -0.84 ], [ -5.57, 8.70, -6.09 ], [ -3.48, 1.84, -0.84 ] ] ), - (78, [ [ -721.00, 400.40, -2.40 ], [ -84.80, 146.00, 5.60 ], [ -4.89, -3.24, 10.54 ], [ 0.98, -2.25, 0.71 ], [ 9.21, 5.13, 5.85 ], [ 0.98, -2.25, 0.71 ] ] ), - (79, [ [ -838.90, 413.20, 12.20 ], [ -5.80, 0.00, 0.00 ], [ -0.00, 2.57, 11.87 ], [ -4.26, -1.08, -0.91 ], [ 0.00, 11.87, -2.57 ], [ -4.26, -1.08, -0.91 ] ] ), - (80, [ [ -841.90, 390.30, 9.10 ], [ 23.70, -40.80, 14.10 ], [ -6.15, 0.07, 10.50 ], [ -3.54, -1.63, -0.61 ], [ -8.72, -6.80, -5.06 ], [ -3.54, -1.63, -0.61 ] ] ), - (81, [ [ -785.00, 366.40, 25.00 ], [ 68.10, -25.40, 20.50 ], [ -3.33, 0.56, 11.73 ], [ 2.70, 1.81, 0.59 ], [ -4.10, -11.48, -0.62 ], [ 2.70, 1.81, 0.59 ] ] ), - (82, [ [ -715.10, 372.10, 29.90 ], [ 45.50, 7.30, 0.60 ], [ -0.77, 3.83, 11.62 ], [ 1.10, 0.20, 0.24 ], [ 1.79, -11.48, 3.90 ], [ 1.10, 0.20, 0.25 ] ] ), - (83, [ [ -676.70, 381.70, 46.00 ], [ 33.50, -1.60, 1.70 ], [ -0.56, 2.17, 12.08 ], [ -2.24, 0.19, -0.76 ], [ -0.74, -12.08, 2.14 ], [ -2.25, 0.19, -0.76 ] ] ), - (84, [ [ -624.70, 387.70, 43.50 ], [ 20.20, 30.90, -2.50 ], [ -5.85, 4.65, 9.80 ], [ 0.24, -5.21, -0.06 ], [ 8.51, -4.93, 7.42 ], [ 0.24, -5.21, -0.06 ] ] ), - (85, [ [ -620.00, 414.70, 50.80 ], [ -23.20, 24.50, 6.10 ], [ -2.40, -5.02, 11.02 ], [ 3.51, -2.77, 1.11 ], [ 8.77, 7.03, 5.11 ], [ 3.51, -2.77, 1.11 ] ] ), - (86, [ [ -667.60, 418.50, 51.40 ], [ -25.90, -0.20, 2.60 ], [ 1.20, 2.97, 11.96 ], [ 0.14, 4.53, 0.11 ], [ -0.37, 12.02, -2.95 ], [ 0.14, 4.53, 0.11 ] ] ), - (87, [ [ -705.40, 416.80, 61.80 ], [ -55.10, -17.10, 0.00 ], [ -1.49, 4.67, 11.40 ], [ -3.64, 0.65, -0.93 ], [ -3.42, 10.87, -4.90 ], [ -3.64, 0.65, -0.93 ] ] ), - (88, [ [ -749.80, 368.90, 72.20 ], [ -21.40, -38.20, -0.90 ], [ -6.74, 3.55, 9.85 ], [ 2.52, 2.85, -1.54 ], [ -8.52, 4.96, -7.61 ], [ 2.52, 2.84, -1.54 ] ] ), - (89, [ [ -794.90, 366.10, 65.90 ], [ -29.10, -4.30, 9.30 ], [ 1.33, 9.22, 8.31 ], [ 4.72, 2.23, -0.88 ], [ -3.91, 8.25, -8.52 ], [ 4.71, 2.23, -0.88 ] ] ), - (90, [ [ -808.20, 363.30, 93.30 ], [ 18.80, -10.20, 29.80 ], [ 3.64, 8.98, 7.91 ], [ 1.12, -0.05, -0.24 ], [ -6.53, -2.71, 10.32 ], [ 1.12, -0.05, -0.24 ] ] ), - (91, [ [ -772.30, 355.10, 95.70 ], [ 43.70, -4.20, -0.20 ], [ 3.42, 9.15, 7.86 ], [ -2.39, -0.32, 0.63 ], [ 1.77, -8.08, 9.42 ], [ -2.39, -0.32, 0.63 ] ] ), - (92, [ [ -723.70, 356.50, 92.00 ], [ 34.80, 14.40, -6.20 ], [ -1.72, 8.22, 9.35 ], [ 2.61, -4.95, 1.60 ], [ 4.88, -8.24, 8.14 ], [ 2.61, -4.94, 1.59 ] ] ), - (93, [ [ -704.10, 380.20, 92.30 ], [ -4.50, 25.20, 1.10 ], [ 6.07, 0.59, 11.02 ], [ -0.50, 1.17, -0.66 ], [ 10.81, 2.18, -6.07 ], [ -0.50, 1.17, -0.66 ] ] ), - (94, [ [ -724.40, 396.00, 92.70 ], [ -30.00, -4.70, -0.50 ], [ -1.56, 9.32, 8.35 ], [ -4.52, 4.97, -1.53 ], [ -1.10, 8.28, -9.45 ], [ -4.52, 4.97, -1.53 ] ] ), - (95, [ [ -761.40, 390.00, 92.00 ], [ -26.80, -4.40, -1.30 ], [ -1.95, 9.30, 8.33 ], [ 3.52, -0.78, 0.05 ], [ -0.92, 8.30, -9.48 ], [ 3.52, -0.78, 0.05 ] ] ), - (96, [ [ -796.40, 394.20, 92.00 ], [ -19.90, 14.60, -1.10 ], [ 5.31, 7.80, 8.45 ], [ 2.73, 0.40, -0.79 ], [ 5.37, 6.54, -9.42 ], [ 2.73, 0.40, -0.79 ] ] ), - (97, [ [ -808.00, 419.20, 92.00 ], [ 22.20, 4.70, -19.80 ], [ 4.02, 9.89, 6.85 ], [ -2.50, 1.30, -0.56 ], [ 7.57, -7.69, 6.66 ], [ -2.50, 1.30, -0.56 ] ] ), - (98, [ [ -772.40, 406.20, 98.30 ], [ 40.50, -7.10, 9.50 ], [ -0.00, 10.20, 7.59 ], [ -5.63, 0.13, -2.26 ], [ -3.58, -7.28, 9.79 ], [ -5.64, 0.13, -2.26 ] ] ), - (99, [ [ -743.70, 434.90, 88.30 ], [ -18.90, -10.80, -19.80 ], [ -7.56, 10.12, 1.74 ], [ -5.23, -2.29, -1.22 ], [ 6.19, 6.22, -9.25 ], [ -5.24, -2.29, -1.23 ] ] ), - (100, [ [ -799.10, 394.00, 52.00 ], [ -21.00, -22.00, -12.00 ], [ -9.00, 4.23, 8.07 ], [ 7.99, -2.65, 4.28 ], [ -3.86, 8.50, -8.76 ], [ 7.99, -2.64, 4.28 ] ] ), - (101, [ [ -804.50, 342.90, 51.10 ], [ 18.40, -46.20, 24.50 ], [ 5.55, 3.84, 10.93 ], [ 5.00, 2.57, 0.35 ], [ -9.65, -4.07, 7.43 ], [ 5.00, 2.57, 0.35 ] ] ), - (102, [ [ -779.40, 314.90, 94.50 ], [ 43.80, -11.60, 23.20 ], [ 0.11, 9.64, 8.54 ], [ -2.57, 2.84, -1.17 ], [ -4.80, -7.71, 9.14 ], [ -2.57, 2.84, -1.17 ] ] ), - (103, [ [ -725.70, 321.90, 94.80 ], [ 50.50, 2.40, -4.10 ], [ 0.22, 9.72, 8.51 ], [ 2.24, -0.48, -0.06 ], [ 1.18, -8.49, 9.67 ], [ 2.24, -0.48, -0.06 ] ] ), - (104, [ [ -673.60, 342.20, 84.90 ], [ 40.10, -23.10, 1.40 ], [ 4.71, 8.65, 8.43 ], [ 2.31, -3.92, 1.73 ], [ -4.45, -7.17, 9.84 ], [ 2.31, -3.92, 1.73 ] ] ), - (105, [ [ -654.80, 296.30, 92.00 ], [ 7.30, -43.20, 5.10 ], [ 5.10, 2.22, 11.75 ], [ -3.45, -3.20, 1.92 ], [ -11.76, -1.38, 5.36 ], [ -3.45, -3.19, 1.92 ] ] ), - (106, [ [ -638.40, 213.80, 96.30 ], [ -29.60, -31.80, 0.00 ], [ -4.73, 4.39, 11.35 ], [ 4.65, 2.69, -1.87 ], [ -8.31, 7.73, -6.45 ], [ 4.65, 2.69, -1.87 ] ] ), - (107, [ [ -671.50, 206.00, 94.00 ], [ -29.50, 25.20, 0.10 ], [ 6.31, 7.31, 8.82 ], [ 7.00, -1.55, -0.71 ], [ 5.73, 6.71, -9.66 ], [ 7.00, -1.56, -0.71 ] ] ), - (108, [ [ -693.10, 254.60, 92.00 ], [ -5.80, 31.80, 6.00 ], [ 7.56, -0.62, 10.70 ], [ 0.22, -0.48, 0.58 ], [ 10.46, 3.29, -7.20 ], [ 0.22, -0.48, 0.58 ] ] ), - (109, [ [ -692.70, 282.10, 99.60 ], [ -11.70, 28.50, 0.00 ], [ 7.22, 2.91, 10.58 ], [ -4.53, 4.59, -0.52 ], [ 9.81, 3.97, -7.79 ], [ -4.53, 4.59, -0.52 ] ] ), - (110, [ [ -714.50, 303.80, 105.30 ], [ -27.80, -10.40, 3.10 ], [ -2.20, 8.74, 9.59 ], [ -5.61, -1.93, 0.96 ], [ -4.25, 8.71, -8.91 ], [ -5.61, -1.93, 0.96 ] ] ), - (111, [ [ -732.90, 276.20, 100.40 ], [ -10.50, -24.20, -5.40 ], [ -3.94, -1.07, 12.54 ], [ 1.14, -6.02, 1.63 ], [ -11.48, 5.69, -3.12 ], [ 1.15, -6.02, 1.63 ] ] ), - (112, [ [ -739.60, 242.40, 94.90 ], [ 6.20, -21.60, 0.00 ], [ 0.16, -3.20, 12.82 ], [ 1.60, 0.58, 0.34 ], [ -11.46, -6.54, -0.73 ], [ 1.60, 0.58, 0.33 ] ] ), - (113, [ [ -729.90, 208.40, 92.90 ], [ 31.10, -37.00, 1.30 ], [ -0.79, 0.16, 13.21 ], [ -0.08, 2.62, 0.24 ], [ -10.29, -8.31, -0.51 ], [ -0.08, 2.62, 0.25 ] ] ), - (114, [ [ -671.40, 183.60, 95.20 ], [ 26.20, 4.60, -18.30 ], [ 0.71, 1.43, 13.18 ], [ 0.74, 0.62, 0.01 ], [ -2.74, -12.05, 4.85 ], [ 0.74, 0.62, 0.01 ] ] ), - (115, [ [ -676.50, 223.40, 56.90 ], [ -64.00, 41.80, -9.80 ], [ 0.72, 1.43, 13.23 ], [ 0.01, 0.00, 0.05 ], [ 8.61, 10.08, -1.39 ], [ 0.00, 0.01, 0.05 ] ] ), - (116, [ [ -680.80, 291.90, 29.60 ], [ 125.60, 70.80, -6.60 ], [ 0.72, 1.44, 13.29 ], [ -0.00, 0.00, 0.05 ], [ 7.21, -11.24, 0.87 ], [ 0.00, 0.01, 0.05 ] ] ), - (117, [ [ -714.10, 347.30, 15.30 ], [ -19.50, 82.90, -38.40 ], [ 0.72, 1.44, 13.34 ], [ 0.00, 0.00, 0.06 ], [ 13.34, -1.38, 0.85 ], [ 0.00, 0.01, 0.06 ] ] ), - (118, [ [ -801.90, 404.60, -7.10 ], [ -58.90, -30.30, 2.30 ], [ 0.73, 1.45, 13.41 ], [ 0.00, 0.00, 0.05 ], [ -5.43, 12.33, -0.98 ], [ 0.00, 0.01, 0.05 ] ] ), - (119, [ [ -808.70, 365.80, -13.70 ], [ 44.60, -53.00, -15.80 ], [ 0.73, 1.45, 13.45 ], [ -0.00, 0.00, 0.05 ], [ -11.98, -5.91, 2.26 ], [ 0.00, 0.01, 0.05 ] ] ), - (120, [ [ -688.00, 338.40, -11.70 ], [ 63.80, -48.80, 8.70 ], [ 0.73, 1.46, 13.53 ], [ 0.00, 0.01, 0.07 ], [ -7.42, -11.30, 1.72 ], [ 0.00, 0.01, 0.07 ] ] ), - (121, [ [ -673.00, 259.50, -3.20 ], [ 81.00, -7.10, 7.50 ], [ 0.73, 1.47, 13.59 ], [ 0.00, 0.01, 0.06 ], [ 0.51, -13.58, 1.69 ], [ 0.00, 0.01, 0.06 ] ] ), - (122, [ [ -674.40, 198.70, 27.60 ], [ -166.70, -5.50, 78.50 ], [ 0.74, 1.48, 13.66 ], [ 0.01, 0.01, 0.08 ], [ -5.65, 12.51, 0.86 ], [ 0.00, 0.01, 0.08 ] ] ), - (123, [ [ -751.20, 330.40, 5.60 ], [ -146.40, -62.90, 102.70 ], [ 0.74, 1.49, 13.77 ], [ 0.01, 0.01, 0.10 ], [ -10.32, 8.91, 2.56 ], [ 0.01, 0.01, 0.10 ] ] ), - (124, [ [ -771.40, 224.30, -0.50 ], [ -206.60, 3.00, -5.40 ], [ 0.75, 1.50, 13.86 ], [ 0.01, 0.01, 0.09 ], [ 1.33, 13.82, -1.48 ], [ 0.00, 0.01, 0.09 ] ] ), - (125, [ [ -809.20, 353.00, 16.20 ], [ -189.70, 36.40, -2.10 ], [ 0.75, 1.51, 13.96 ], [ 0.01, 0.00, 0.06 ], [ 3.24, 13.58, -1.62 ], [ 0.00, 0.01, 0.06 ] ] ), - (126, [ [ -838.20, 311.90, 41.30 ], [ 13.30, -30.30, 21.40 ], [ 0.76, 1.51, 14.00 ], [ 0.00, 0.01, 0.03 ], [ -9.33, -9.46, 4.73 ], [ 0.00, 0.00, 0.03 ] ] ), - (127, [ [ -817.10, 288.00, 42.40 ], [ 34.40, -12.20, 0.70 ], [ 0.76, 1.52, 14.02 ], [ -0.00, 0.01, 0.03 ], [ -4.27, -13.36, 1.69 ], [ 0.00, 0.00, 0.03 ] ] ), - (128, [ [ -752.40, 294.00, 78.80 ], [ 68.30, 9.10, 2.00 ], [ 0.76, 1.52, 14.08 ], [ 0.00, 0.01, 0.05 ], [ 3.16, -13.75, 1.44 ], [ 0.00, 0.01, 0.05 ] ] ), - (129, [ [ -741.40, 241.80, 54.90 ], [ -60.00, -10.60, -17.50 ], [ 0.76, 1.53, 14.13 ], [ 0.01, 0.01, 0.05 ], [ 2.67, 13.98, 0.02 ], [ 0.00, 0.01, 0.05 ] ] ), - (130, [ [ -802.80, 226.00, 43.40 ], [ -39.00, 36.40, 14.80 ], [ 0.77, 1.53, 14.17 ], [ 0.00, 0.01, 0.04 ], [ 5.91, 12.99, -0.45 ], [ 0.00, 0.00, 0.04 ] ] ), - (131, [ [ -833.10, 266.00, 68.30 ], [ -22.10, 29.70, 29.30 ], [ 0.77, 1.54, 14.21 ], [ 0.00, 0.00, 0.03 ], [ 3.57, 13.06, 4.65 ], [ 0.00, 0.00, 0.03 ] ] ), - (132, [ [ -822.70, 279.50, 92.00 ], [ 26.60, 9.70, 0.30 ], [ 0.77, 1.54, 14.23 ], [ -0.00, -0.00, 0.02 ], [ 6.18, -12.88, 1.20 ], [ 0.00, 0.00, 0.02 ] ] ), - (133, [ [ -799.30, 280.50, 92.00 ], [ 19.60, -7.30, 0.00 ], [ 0.77, 1.54, 14.25 ], [ -0.00, -0.00, 0.02 ], [ -4.80, -13.42, 1.71 ], [ 0.00, 0.00, 0.02 ] ] ), - (134, [ [ -788.60, 264.40, 92.00 ], [ -4.80, -26.50, 0.00 ], [ 0.77, 1.54, 14.27 ], [ -0.00, -0.00, 0.02 ], [ -13.74, 4.17, 0.48 ], [ 0.00, 0.00, 0.02 ] ] ), - (135, [ [ -814.90, 246.10, 92.00 ], [ -26.10, -9.00, 1.30 ], [ 0.77, 1.54, 14.29 ], [ 0.00, 0.01, 0.02 ], [ -4.20, 13.71, -1.23 ], [ 0.00, 0.00, 0.02 ] ] ), - (136, [ [ -826.20, 223.00, 92.00 ], [ 12.30, -25.30, 0.00 ], [ 0.77, 1.55, 14.31 ], [ 0.00, 0.01, 0.02 ], [ -13.33, -5.30, 1.37 ], [ 0.00, 0.00, 0.02 ] ] ), - (137, [ [ -802.80, 203.40, 92.00 ], [ 45.00, 8.60, 0.00 ], [ 0.77, 1.55, 14.33 ], [ 0.00, 0.00, 0.03 ], [ 3.72, -13.88, 1.38 ], [ 0.00, 0.00, 0.03 ] ] ), - (138, [ [ -783.70, 237.40, 92.10 ], [ 32.00, -1.80, -16.20 ], [ 0.78, 1.55, 14.36 ], [ 0.01, 0.00, 0.03 ], [ -5.24, -12.85, 4.06 ], [ 0.00, 0.00, 0.03 ] ] ), - (139, [ [ -754.40, 192.40, 70.50 ], [ 45.00, -18.70, -9.80 ], [ 0.78, 1.56, 14.40 ], [ 5.40, -1.59, -6.72 ], [ -7.57, -12.17, 2.24 ], [ 5.40, -1.59, -6.72 ] ] ), - (140, [ [ -680.80, 179.60, 31.60 ], [ 3.90, -10.60, -67.30 ], [ 14.18, -2.40, -2.32 ], [ -5.09, -0.39, -13.72 ], [ -1.81, -14.39, -1.36 ], [ -5.09, -0.39, -13.72 ] ] ), - (141, [ [ -737.10, 190.00, 35.60 ], [ -37.20, 15.70, 15.30 ], [ -4.87, -0.09, -13.78 ], [ -6.37, 1.87, -5.13 ], [ -4.36, -13.86, 1.59 ], [ -6.37, 1.87, -5.13 ] ] ), - (142, [ [ -781.90, 194.00, 48.10 ], [ -20.90, -6.20, -4.10 ], [ -2.21, 1.47, -14.40 ], [ -2.28, 2.28, 1.31 ], [ 0.21, -14.37, -2.80 ], [ -2.28, 2.28, 1.31 ] ] ), - (143, [ [ -802.30, 178.10, 41.90 ], [ -11.30, -27.20, 3.00 ], [ -7.37, 4.17, -11.97 ], [ -3.69, -0.20, 1.59 ], [ 11.43, -3.27, -8.59 ], [ -3.69, -0.20, 1.59 ] ] ), - (144, [ [ -799.10, 145.80, 39.00 ], [ 22.40, -22.60, -18.40 ], [ -9.21, 0.32, -11.44 ], [ -1.30, -2.70, 0.36 ], [ 7.14, 11.63, -5.43 ], [ -1.30, -2.69, 0.36 ] ] ), - (145, [ [ -731.20, 157.30, 2.00 ], [ 50.10, -43.00, -3.70 ], [ -9.25, 0.32, -11.48 ], [ -0.04, -0.00, -0.04 ], [ 2.50, 13.49, -5.40 ], [ -0.04, 0.00, -0.05 ] ] ), - (146, [ [ -669.40, 112.80, 4.40 ], [ 136.30, 170.20, -47.50 ], [ -9.29, 0.32, -11.53 ], [ -0.05, 0.00, -0.06 ], [ -10.54, 6.75, 7.91 ], [ -0.04, 0.00, -0.06 ] ] ), - (147, [ [ -750.70, 184.10, 17.70 ], [ -76.40, -20.30, -34.70 ], [ -9.34, 0.32, -11.59 ], [ -0.04, 0.00, -0.06 ], [ -8.52, -9.53, -7.65 ], [ -0.05, 0.00, -0.06 ] ] ), - (148, [ [ -840.70, 197.30, -8.00 ], [ -65.70, -54.00, -27.90 ], [ -9.38, 0.32, -11.65 ], [ -0.04, 0.00, -0.05 ], [ -0.45, -11.86, -9.11 ], [ -0.04, 0.00, -0.05 ] ] ), - (149, [ [ -770.00, 153.90, -18.30 ], [ 146.60, 96.20, 29.90 ], [ -9.43, 0.33, -11.70 ], [ 9.19, 1.65, -0.79 ], [ -14.26, 2.89, 3.77 ], [ 9.19, 1.65, -0.79 ] ] ), - (150, [ [ -687.80, 179.20, -17.80 ], [ 93.00, 6.90, 16.70 ], [ 6.85, 3.24, -13.05 ], [ 9.87, 3.45, 8.75 ], [ 3.05, 14.36, 3.50 ], [ 9.86, 3.45, 8.75 ] ] ), - (151, [ [ -660.00, 168.80, 104.60 ], [ -61.10, -12.30, 52.70 ], [ 6.81, 7.53, 11.29 ], [ -10.02, -0.74, 9.08 ], [ -7.36, 12.69, -3.93 ], [ -10.02, -0.74, 9.08 ] ] ), - (152, [ [ -732.50, 164.50, 92.40 ], [ -75.70, -13.60, -3.40 ], [ -8.83, 3.96, 11.77 ], [ -7.28, -3.78, 0.66 ], [ -9.24, 10.65, -5.78 ], [ -7.28, -3.78, 0.66 ] ] ), - (153, [ [ -785.80, 124.60, 91.40 ], [ -10.20, -35.80, -2.20 ], [ -8.66, -0.00, 12.60 ], [ 6.65, -4.80, 1.10 ], [ -12.54, 2.40, -8.41 ], [ 6.65, -4.79, 1.10 ] ] ), - (154, [ [ -759.00, 91.20, 83.60 ], [ 119.50, -1.50, 4.30 ], [ 3.31, -5.48, 13.92 ], [ 5.90, -3.29, 1.00 ], [ 3.90, -13.84, -5.30 ], [ 5.90, -3.29, 1.00 ] ] ), - (155, [ [ -640.80, 136.60, 98.60 ], [ 46.60, 50.10, 7.60 ], [ -4.70, -3.76, 14.19 ], [ -2.83, 0.60, 0.12 ], [ 7.80, -13.29, 0.39 ], [ -2.82, 0.60, 0.12 ] ] ), - (156, [ [ -579.70, 151.60, 100.30 ], [ 19.20, -49.70, 4.50 ], [ -4.72, -3.77, 14.23 ], [ -0.02, -0.02, 0.05 ], [ -11.83, -8.30, -5.49 ], [ -0.02, -0.01, 0.05 ] ] ), - (157, [ [ -626.30, 99.70, 102.90 ], [ -45.20, -3.50, 0.20 ], [ -4.73, -3.79, 14.28 ], [ 0.63, 2.69, 0.49 ], [ -6.14, 13.83, 3.44 ], [ 0.63, 2.69, 0.49 ] ] ), - (158, [ [ -677.50, 87.90, 102.10 ], [ -1.10, -44.00, 15.60 ], [ -3.61, 0.95, 15.10 ], [ -0.22, -0.88, -0.12 ], [ -14.64, -4.84, -2.01 ], [ -0.22, -0.88, -0.12 ] ] ), - (159, [ [ -658.60, 70.80, 123.20 ], [ 64.50, -18.30, 7.60 ], [ -4.75, -3.80, 14.34 ], [ -0.57, -2.37, -0.37 ], [ -5.27, -13.73, -5.13 ], [ -0.57, -2.36, -0.37 ] ] ), - (160, [ [ -663.80, 52.80, 121.60 ], [ -54.40, -14.30, -27.10 ], [ -4.76, -3.81, 14.36 ], [ -0.01, -0.01, 0.03 ], [ -3.89, 14.85, 2.76 ], [ -0.01, -0.01, 0.03 ] ] ), - (161, [ [ -714.90, 78.70, 84.40 ], [ -26.00, -24.40, -65.40 ], [ -4.77, -3.82, 14.40 ], [ -0.02, -0.01, 0.05 ], [ -4.68, 12.40, 8.31 ], [ -0.02, -0.01, 0.05 ] ] ), - (162, [ [ -658.40, 32.50, 83.90 ], [ 2.10, 116.00, -7.20 ], [ -4.79, -3.83, 14.47 ], [ -0.02, -0.01, 0.06 ], [ 14.11, -4.76, 5.01 ], [ -0.02, -0.02, 0.06 ] ] ), - (163, [ [ -604.60, 113.30, 63.50 ], [ -28.80, 78.00, -53.10 ], [ -4.81, -3.85, 14.53 ], [ -0.02, -0.02, 0.06 ], [ 12.18, -0.65, 10.02 ], [ -0.02, -0.02, 0.06 ] ] ), - (164, [ [ -692.90, 147.10, 50.50 ], [ -30.70, 48.10, -22.50 ], [ -4.84, -3.87, 14.59 ], [ -0.02, -0.01, 0.06 ], [ 13.01, 4.40, 7.92 ], [ -0.02, -0.02, 0.06 ] ] ), - (165, [ [ -760.40, 156.30, 47.10 ], [ 12.40, -68.30, 10.10 ], [ -4.85, -3.88, 14.65 ], [ -0.01, -0.01, 0.05 ], [ -12.81, -8.18, -4.68 ], [ -0.02, -0.01, 0.05 ] ] ), - (166, [ [ -714.60, 117.30, 46.30 ], [ 59.10, -31.90, -3.20 ], [ -4.87, -3.89, 14.69 ], [ 3.35, -1.81, -0.44 ], [ -9.91, -11.19, -5.58 ], [ 3.35, -1.81, -0.44 ] ] ), - (167, [ [ -642.10, 94.70, 41.50 ], [ 86.40, 3.30, -36.50 ], [ 2.64, -7.93, 13.65 ], [ 8.28, 8.12, -9.98 ], [ -5.51, -13.70, -6.17 ], [ 8.28, 8.12, -9.98 ] ] ), - (168, [ [ -636.10, 134.80, 16.40 ], [ 117.50, 19.20, -27.50 ], [ 11.57, 10.42, -3.86 ], [ 5.09, 10.44, -9.95 ], [ 14.85, 3.25, 5.13 ], [ 5.09, 10.44, -9.94 ] ] ), - (169, [ [ -578.20, 88.00, 25.20 ], [ 2.50, -59.30, 17.40 ], [ 11.61, 10.46, -3.87 ], [ 0.54, -10.37, 3.35 ], [ 0.34, 13.63, 8.56 ], [ 0.54, -10.38, 3.35 ] ] ), - (170, [ [ -631.30, 39.10, 34.60 ], [ -128.70, -21.40, -13.20 ], [ 12.62, -9.73, 2.64 ], [ -7.55, -13.18, 3.33 ], [ 9.45, 3.13, 12.72 ], [ -7.54, -13.18, 3.33 ] ] ), - (171, [ [ -704.70, 57.70, 8.40 ], [ -125.70, -34.50, 10.50 ], [ -3.96, -15.50, 2.62 ], [ -13.98, 6.42, -1.88 ], [ -7.24, 0.06, 14.50 ], [ -13.98, 6.42, -1.88 ] ] ), - (172, [ [ -784.50, 117.60, 16.90 ], [ 39.80, 42.00, -36.30 ], [ -14.44, 7.33, -1.76 ], [ 1.81, 11.47, -8.58 ], [ 1.08, 6.87, 14.73 ], [ 1.81, 11.48, -8.57 ] ] ), - (173, [ [ -699.80, 123.10, -24.30 ], [ 55.40, -153.80, -40.30 ], [ -0.55, 7.65, -14.46 ], [ 7.44, 0.19, -6.84 ], [ 13.82, 8.28, 2.90 ], [ 7.45, 0.19, -6.84 ] ] ), - (174, [ [ -800.50, 108.10, -31.70 ], [ -87.40, 47.70, 13.70 ], [ -0.55, 7.69, -14.53 ], [ -0.00, 0.03, -0.05 ], [ -9.81, -11.69, -6.13 ], [ 0.00, 0.03, -0.05 ] ] ), - (175, [ [ -802.60, 73.80, -45.80 ], [ 60.70, -32.10, -7.20 ], [ -0.55, 7.71, -14.56 ], [ -0.00, 0.02, -0.05 ], [ 5.33, 14.05, 6.79 ], [ 0.00, 0.02, -0.05 ] ] ), - (176, [ [ -700.50, 58.60, -44.70 ], [ 56.40, 29.00, 19.90 ], [ -0.55, 7.74, -14.63 ], [ 0.00, 0.03, -0.05 ], [ -9.95, 11.61, 6.37 ], [ 0.00, 0.03, -0.05 ] ] ), - (177, [ [ -650.80, 100.60, -19.70 ], [ 52.40, 82.20, 48.00 ], [ -0.55, 7.77, -14.67 ], [ -2.79, -2.28, -0.32 ], [ -14.95, 6.17, 3.78 ], [ -2.78, -2.28, -0.33 ] ] ), - (178, [ [ -659.10, 149.90, -29.60 ], [ 34.00, 79.40, 15.20 ], [ -5.71, 3.52, -15.24 ], [ -0.18, -0.13, -0.05 ], [ -15.05, 3.41, 6.24 ], [ -0.18, -0.13, -0.05 ] ] ), - (179, [ [ -609.50, 156.90, -23.70 ], [ 15.60, -53.60, -14.70 ], [ -0.56, 7.80, -14.74 ], [ 2.21, 1.85, 0.20 ], [ 14.69, 7.51, 2.51 ], [ 2.21, 1.85, 0.20 ] ] ), - (180, [ [ -609.70, 110.70, -23.20 ], [ 40.80, -48.10, -0.90 ], [ -0.56, 7.82, -14.77 ], [ -2.04, -1.11, 0.02 ], [ 7.42, 14.22, 4.72 ], [ -2.04, -1.11, 0.02 ] ] ), - (181, [ [ -646.50, 26.10, -11.20 ], [ -162.60, -77.40, 15.80 ], [ -7.08, 4.22, -14.63 ], [ -2.07, 0.47, 11.78 ], [ 2.94, -15.18, -6.54 ], [ -2.07, 0.47, 11.79 ] ] ), - (182, [ [ -611.30, 41.40, 96.10 ], [ 57.30, 45.80, -2.40 ], [ -3.08, 10.25, 13.06 ], [ -0.50, -9.06, 9.07 ], [ 11.26, -7.87, 9.80 ], [ -0.50, -9.06, 9.07 ] ] ), - (183, [ [ -577.60, 74.90, 90.60 ], [ 55.80, -10.00, 15.40 ], [ -5.16, -4.13, 15.57 ], [ -1.04, -7.16, 1.27 ], [ -1.68, -16.12, -4.83 ], [ -1.04, -7.15, 1.27 ] ] ), - (184, [ [ -584.90, 34.80, 107.90 ], [ -13.40, -36.10, 14.60 ], [ -5.17, -4.14, 15.60 ], [ -0.01, -0.00, 0.03 ], [ -15.74, -6.26, 0.66 ], [ -0.01, -0.01, 0.03 ] ] ), - (185, [ [ -599.80, -4.20, 106.40 ], [ -10.50, -58.00, -59.30 ], [ -5.18, -4.14, 15.63 ], [ -0.01, -0.00, 0.03 ], [ -12.83, 10.88, 2.29 ], [ -0.01, -0.01, 0.03 ] ] ), - (186, [ [ -560.70, -5.80, 103.50 ], [ 22.80, 77.00, 53.00 ], [ -5.19, -4.15, 15.66 ], [ -0.01, -0.01, 0.04 ], [ 15.79, -3.31, 5.42 ], [ -0.01, -0.01, 0.04 ] ] ), - (187, [ [ -539.50, 62.70, 103.50 ], [ 25.80, 91.30, 0.00 ], [ -5.20, -4.16, 15.71 ], [ -0.01, -0.01, 0.04 ], [ 13.65, -9.49, 3.87 ], [ -0.01, -0.01, 0.04 ] ] ), - (188, [ [ -509.90, 125.70, 103.50 ], [ 40.90, 31.10, 0.00 ], [ -5.22, -4.18, 15.75 ], [ -0.01, -0.01, 0.03 ], [ 4.21, -16.58, -0.17 ], [ -0.01, -0.01, 0.03 ] ] ), - (189, [ [ -480.30, 136.30, 103.50 ], [ 27.90, -1.50, 0.00 ], [ -5.23, -4.18, 15.77 ], [ -0.00, 0.00, 0.02 ], [ -5.84, -15.48, -4.46 ], [ -0.01, -0.00, 0.02 ] ] ), - (190, [ [ -463.80, 126.60, 103.50 ], [ 2.20, -41.60, 0.00 ], [ -5.23, -4.18, 15.79 ], [ -0.00, -0.00, 0.02 ], [ -15.56, -4.73, -5.44 ], [ -0.01, -0.01, 0.02 ] ] ), - (191, [ [ -502.40, 82.30, 103.50 ], [ -23.60, -27.20, 0.00 ], [ -5.24, -4.19, 15.83 ], [ -0.01, -0.01, 0.02 ], [ -16.28, 5.39, -1.21 ], [ -0.01, -0.01, 0.02 ] ] ), - (192, [ [ -509.30, 56.80, 103.50 ], [ 23.00, -22.90, 0.00 ], [ -5.25, -4.20, 15.84 ], [ -0.01, -0.01, 0.02 ], [ -11.71, -10.69, -6.68 ], [ -0.01, -0.01, 0.02 ] ] ), - (193, [ [ -475.50, 64.70, 103.50 ], [ 44.10, -1.90, 0.00 ], [ -5.26, -4.21, 15.86 ], [ -0.01, -0.01, 0.03 ], [ -5.75, -15.63, -4.43 ], [ -0.01, -0.01, 0.03 ] ] ), - (194, [ [ -430.20, 49.30, 103.50 ], [ 14.50, -56.10, 1.00 ], [ -5.27, -4.21, 15.90 ], [ -0.01, -0.01, 0.04 ], [ -14.56, -7.00, -6.10 ], [ -0.01, -0.01, 0.04 ] ] ), - (195, [ [ -469.90, 5.30, 104.60 ], [ -58.90, -25.60, -18.20 ], [ -5.28, -4.22, 15.94 ], [ -0.01, -0.01, 0.04 ], [ -8.97, 14.76, 1.17 ], [ -0.01, -0.01, 0.04 ] ] ), - (196, [ [ -530.20, 8.80, 71.20 ], [ -89.40, 9.00, -28.70 ], [ -5.30, -4.24, 15.98 ], [ -0.01, -0.01, 0.04 ], [ 0.47, 16.73, 4.60 ], [ -0.01, -0.01, 0.04 ] ] ), - (197, [ [ -549.80, 51.30, 74.50 ], [ 56.60, 60.50, 38.30 ], [ -5.31, -4.25, 16.02 ], [ -0.01, -0.01, 0.04 ], [ 12.78, -11.75, 1.14 ], [ -0.01, -0.01, 0.04 ] ] ), - (198, [ [ -531.30, 109.40, 71.30 ], [ 86.60, 49.60, 3.50 ], [ -5.32, -4.26, 16.06 ], [ -0.02, -0.01, 0.05 ], [ 2.78, -17.18, -1.27 ], [ -0.02, -0.01, 0.05 ] ] ), - (199, [ [ -456.50, 140.50, 51.60 ], [ 45.40, 11.90, -8.30 ], [ -5.34, -4.27, 16.11 ], [ -0.02, -0.01, 0.05 ], [ -5.25, -16.65, -1.17 ], [ -0.02, -0.01, 0.05 ] ] ), - (200, [ [ -423.00, 81.00, 50.80 ], [ -44.50, -103.30, -0.20 ], [ -5.36, -4.28, 16.16 ], [ -0.02, -0.02, 0.07 ], [ -17.24, 0.87, -3.24 ], [ -0.02, -0.02, 0.07 ] ] ), - (201, [ [ -549.80, 34.30, 52.00 ], [ -12.30, -134.80, -12.90 ], [ -5.39, -4.31, 16.25 ], [ -0.02, -0.02, 0.08 ], [ -16.81, -1.21, -5.26 ], [ -0.03, -0.02, 0.08 ] ] ), - (202, [ [ -465.30, -17.50, 49.30 ], [ -46.30, -108.10, -19.60 ], [ -5.41, -4.33, 16.33 ], [ 2.96, 6.02, -0.20 ], [ -16.81, 4.20, -3.77 ], [ 2.95, 6.02, -0.20 ] ] ), - (203, [ [ -578.60, -16.50, 42.30 ], [ -82.70, 25.50, -15.40 ], [ 0.72, 8.13, 15.84 ], [ -3.24, 8.71, -6.08 ], [ 7.05, 14.46, -7.67 ], [ -3.24, 8.71, -6.08 ] ] ), - (204, [ [ -536.60, 25.20, 15.60 ], [ 37.70, 57.90, -21.80 ], [ -8.45, 14.47, 6.22 ], [ -2.87, -6.71, 0.69 ], [ 12.08, 3.54, 12.69 ], [ -2.87, -6.71, 0.69 ] ] ), - (205, [ [ -529.00, 93.90, 11.80 ], [ 61.50, 67.50, -4.90 ], [ -5.47, -4.37, 16.50 ], [ 1.52, -9.66, 5.29 ], [ 6.71, -16.55, 1.52 ], [ 1.52, -9.66, 5.29 ] ] ), - (206, [ [ -468.20, 137.50, 16.60 ], [ 50.60, 13.70, -2.50 ], [ -5.48, -4.39, 16.55 ], [ -0.02, -0.01, 0.05 ], [ -2.85, -17.58, -2.46 ], [ -0.02, -0.01, 0.05 ] ] ), - (207, [ [ -398.80, 135.90, 16.10 ], [ 54.50, -33.90, -12.10 ], [ -5.50, -4.40, 16.59 ], [ -0.02, -0.01, 0.04 ], [ -13.91, -10.03, -5.53 ], [ -0.01, -0.01, 0.04 ] ] ), - (208, [ [ -378.80, 78.80, 14.50 ], [ -8.10, -48.90, 36.10 ], [ -5.51, -4.41, 16.63 ], [ -0.01, -0.01, 0.04 ], [ -12.52, -12.24, 4.45 ], [ -0.01, -0.01, 0.04 ] ] ), - (209, [ [ -398.00, 36.20, 45.80 ], [ -34.00, -45.80, 24.00 ], [ -5.52, -4.42, 16.67 ], [ -0.01, -0.01, 0.04 ], [ -17.64, -2.43, 3.29 ], [ -0.01, -0.01, 0.04 ] ] ), - (210, [ [ -442.20, -17.60, 57.50 ], [ -86.50, -40.80, 33.20 ], [ -5.54, -4.43, 16.71 ], [ -0.02, -0.01, 0.05 ], [ -15.53, 7.63, 5.49 ], [ -0.02, -0.01, 0.05 ] ] ), - (211, [ [ -533.50, -18.10, 72.80 ], [ -62.70, -13.50, 25.80 ], [ -5.56, -4.45, 16.77 ], [ -0.01, -0.01, 0.05 ], [ -12.65, 10.76, 7.49 ], [ -0.01, -0.01, 0.04 ] ] ), - (212, [ [ -559.10, -59.00, 75.10 ], [ 21.70, -55.50, 8.30 ], [ -5.57, -4.45, 16.81 ], [ -0.01, -0.01, 0.04 ], [ -13.30, -10.90, -6.13 ], [ -0.01, -0.01, 0.04 ] ] ), - (213, [ [ -500.70, -84.90, 81.00 ], [ 63.70, 28.70, 0.20 ], [ -5.58, -4.47, 16.85 ], [ -0.02, -0.02, 0.05 ], [ 0.67, -18.20, -1.80 ], [ -0.02, -0.01, 0.05 ] ] ), - (214, [ [ -421.10, -26.60, 49.00 ], [ 38.30, 45.90, -36.30 ], [ -5.61, -4.48, 16.92 ], [ -0.02, -0.02, 0.05 ], [ 0.68, -16.06, 8.91 ], [ -0.02, -0.01, 0.05 ] ] ), - (215, [ [ -382.00, 4.70, 3.40 ], [ 8.90, 68.80, -40.90 ], [ -5.62, -4.50, 16.96 ], [ -0.01, -0.01, 0.04 ], [ 10.76, -10.19, 10.95 ], [ -0.01, -0.01, 0.04 ] ] ), - (216, [ [ -389.10, 52.20, -22.10 ], [ -29.80, 81.20, -22.40 ], [ -5.63, -4.50, 17.00 ], [ -0.01, -0.01, 0.04 ], [ 16.48, 1.20, 8.24 ], [ -0.01, -0.01, 0.04 ] ] ), - (217, [ [ -412.00, 118.00, -36.80 ], [ -99.40, 115.40, 42.30 ], [ -5.65, -4.52, 17.04 ], [ -0.02, -0.02, 0.05 ], [ 10.62, 12.72, 8.25 ], [ -0.02, -0.01, 0.05 ] ] ), - (218, [ [ -500.70, 120.50, -22.30 ], [ -52.50, -122.90, 19.40 ], [ -5.67, -4.53, 17.11 ], [ -0.02, -0.02, 0.08 ], [ -18.33, -2.16, -2.14 ], [ -0.03, -0.02, 0.08 ] ] ), - (219, [ [ -430.50, 6.20, -21.60 ], [ -110.00, -102.90, 20.20 ], [ -5.70, -4.56, 17.20 ], [ -0.04, -0.03, 0.10 ], [ -17.92, 5.26, 0.70 ], [ -0.03, -0.03, 0.10 ] ] ), - (220, [ [ -561.60, 93.90, -37.50 ], [ -136.90, -93.80, 13.70 ], [ -5.74, -4.59, 17.31 ], [ -0.03, -0.02, 0.10 ], [ -16.55, 8.84, 1.26 ], [ -0.03, -0.03, 0.10 ] ] ), - (221, [ [ -478.90, -3.90, -57.80 ], [ 64.00, -137.50, 21.40 ], [ -5.77, -4.61, 17.41 ], [ 6.63, 6.39, -0.25 ], [ -13.24, -11.81, -6.52 ], [ 6.62, 6.39, -0.25 ] ] ), - (222, [ [ -431.20, -73.10, -4.70 ], [ -33.20, -2.10, 83.80 ], [ 5.72, 6.46, 16.91 ], [ -1.05, -1.02, 0.11 ], [ -11.35, 11.23, 10.26 ], [ -1.05, -1.01, 0.11 ] ] ), - (223, [ [ -498.10, -26.50, 1.10 ], [ -106.30, 89.80, -35.30 ], [ -5.81, -4.65, 17.53 ], [ -6.98, -6.72, 0.41 ], [ 11.98, 12.58, 7.79 ], [ -6.98, -6.72, 0.41 ] ] ), - (224, [ [ -612.20, 36.10, 28.20 ], [ -42.00, -52.50, 15.50 ], [ -5.84, -4.67, 17.62 ], [ -0.02, -0.01, 0.06 ], [ -19.10, 0.99, 0.89 ], [ -0.02, -0.02, 0.06 ] ] ), - (225, [ [ -599.60, -31.30, 28.40 ], [ 13.40, -54.20, -7.20 ], [ -5.85, -4.68, 17.67 ], [ -0.02, -0.01, 0.04 ], [ -17.41, -4.28, -6.86 ], [ -0.01, -0.01, 0.04 ] ] ), - (226, [ [ -551.10, -68.30, 48.80 ], [ 70.00, -22.30, 2.00 ], [ -5.87, -4.69, 17.71 ], [ -0.02, -0.01, 0.04 ], [ -8.76, -15.91, -6.35 ], [ -0.01, -0.01, 0.04 ] ] ), - (227, [ [ -489.30, -77.50, 38.10 ], [ 74.30, 17.00, -23.00 ], [ -5.88, -4.70, 17.75 ], [ -0.01, -0.01, 0.04 ], [ -8.41, -17.35, 0.23 ], [ -0.01, -0.01, 0.04 ] ] ), - (228, [ [ -463.60, -26.20, 12.80 ], [ -33.30, 65.70, 20.70 ], [ -5.90, -4.72, 17.80 ], [ -0.02, -0.02, 0.06 ], [ 15.11, 9.01, 8.02 ], [ -0.02, -0.02, 0.06 ] ] ), - (229, [ [ -582.60, 39.80, -15.30 ], [ -97.00, -93.30, -56.80 ], [ -5.93, -4.74, 17.89 ], [ -0.03, -0.02, 0.09 ], [ -13.28, 14.18, -0.64 ], [ -0.03, -0.02, 0.09 ] ] ), - (230, [ [ -535.10, -48.00, -7.60 ], [ 163.70, -58.30, -145.00 ], [ -5.95, -4.76, 17.97 ], [ -0.02, -0.02, 0.08 ], [ -18.23, -5.43, 4.37 ], [ -0.03, -0.02, 0.08 ] ] ), - (231, [ [ -451.00, -130.20, 37.30 ], [ -10.40, 16.50, 63.10 ], [ -5.98, -4.79, 18.06 ], [ -0.02, -0.02, 0.06 ], [ 6.41, 1.38, 18.49 ], [ -0.02, -0.02, 0.06 ] ] ), - (232, [ [ -404.70, -90.30, 45.30 ], [ 28.50, 23.80, -5.20 ], [ -6.00, -4.80, 18.11 ], [ -0.02, -0.01, 0.04 ], [ 3.14, -19.36, 1.56 ], [ -0.01, -0.01, 0.04 ] ] ), - (233, [ [ -373.40, -43.10, 39.40 ], [ 5.90, 71.90, -6.80 ], [ -6.01, -4.81, 18.14 ], [ 0.41, 8.07, -8.50 ], [ 16.98, -7.83, 6.23 ], [ 0.41, 8.07, -8.50 ] ] ), - (234, [ [ -350.70, 43.10, -5.50 ], [ 0.30, -23.00, -85.30 ], [ -4.83, 18.19, -6.12 ], [ 3.76, 0.99, -18.90 ], [ 19.16, 4.38, -2.31 ], [ 3.76, 0.98, -18.90 ] ] ), - (235, [ [ -326.20, -52.10, 3.90 ], [ 120.10, -136.40, 45.10 ], [ 1.61, -3.65, -19.46 ], [ 8.00, -8.11, -5.57 ], [ 14.41, 13.59, -1.41 ], [ 8.00, -8.11, -5.57 ] ] ), - (236, [ [ -415.40, -151.90, 68.80 ], [ -13.60, -50.50, -41.70 ], [ 11.95, 8.73, -13.42 ], [ -5.91, 8.77, 17.85 ], [ 15.71, -9.68, 7.65 ], [ -5.91, 8.77, 17.85 ] ] ), - (237, [ [ -353.60, -118.40, -8.30 ], [ 36.00, 49.60, -67.80 ], [ -4.64, 15.12, 12.19 ], [ -6.76, -0.33, 14.51 ], [ 16.78, -2.81, 10.45 ], [ -6.76, -0.33, 14.52 ] ] ), - (238, [ [ -394.00, -54.90, -43.90 ], [ -58.50, 62.10, 18.60 ], [ -3.17, 9.16, 17.42 ], [ -2.87, -4.30, 1.63 ], [ 2.17, 19.78, -1.25 ], [ -2.88, -4.30, 1.64 ] ] ), - (239, [ [ -374.20, 70.30, -64.10 ], [ -51.80, 111.20, -42.80 ], [ -12.32, 7.26, 13.82 ], [ -4.29, -2.14, -1.16 ], [ 11.60, 15.19, 5.49 ], [ -4.31, -2.13, -1.15 ] ] ), - (240, [ [ -480.40, 88.90, -81.20 ], [ -77.00, -72.50, -24.50 ], [ -12.13, 4.91, 14.92 ], [ 4.11, -0.54, 2.38 ], [ -10.25, 12.01, -12.03 ], [ 4.12, -0.54, 2.40 ] ] ), - (241, [ [ -447.70, 23.20, -62.70 ], [ 98.20, -53.90, -35.40 ], [ -5.03, 5.74, 18.28 ], [ 6.87, 3.25, 0.83 ], [ -16.98, -8.10, 6.21 ], [ 6.89, 3.27, 0.84 ] ] ), - (242, [ [ -382.90, -144.70, -29.60 ], [ -142.90, -41.30, 110.60 ], [ 1.32, 14.36, 13.47 ], [ 2.82, 3.81, -2.16 ], [ -14.51, 10.33, -8.50 ], [ 2.83, 3.84, -2.15 ] ] ), - (243, [ [ -481.80, -39.40, -48.90 ], [ -146.60, -39.20, 12.20 ], [ 1.32, 14.32, 13.43 ], [ -0.00, -0.05, -0.04 ], [ -0.87, 14.04, -13.76 ], [ 0.00, -0.03, -0.03 ] ] ), - (244, [ [ -453.60, -166.50, -38.80 ], [ 150.00, -6.00, -58.50 ], [ 1.32, 14.27, 13.39 ], [ -0.01, -0.05, -0.05 ], [ 0.80, -12.79, 14.84 ], [ 0.00, -0.03, -0.03 ] ] ), - (245, [ [ -534.60, 2.00, -60.70 ], [ -321.90, 11.50, 28.90 ], [ 1.31, 14.21, 13.34 ], [ -0.01, -0.04, -0.04 ], [ -1.19, 13.41, -14.16 ], [ 0.00, -0.03, -0.03 ] ] ), - (246, [ [ -620.80, 88.60, -65.80 ], [ -173.30, -112.90, -24.50 ], [ 1.31, 14.17, 13.30 ], [ -0.00, -0.04, -0.04 ], [ 3.06, 16.52, -9.87 ], [ 0.00, -0.03, -0.02 ] ] ), - (247, [ [ -601.00, -61.20, -12.30 ], [ 87.00, -77.00, 21.40 ], [ 1.31, 14.13, 13.26 ], [ 9.17, -14.24, -6.83 ], [ -15.51, -5.72, 10.20 ], [ 9.27, -14.39, -6.89 ] ] ), - (248, [ [ -524.30, -72.50, -58.30 ], [ -55.40, -200.40, -26.20 ], [ 16.67, -9.71, 1.85 ], [ 5.34, -1.84, -3.12 ], [ -4.21, -6.04, 17.93 ], [ 5.41, -1.85, -3.14 ] ] ), - (249, [ [ -516.70, -125.70, 44.60 ], [ 99.10, -71.00, 10.10 ], [ 10.37, 14.01, 8.37 ], [ 1.88, 3.64, -8.37 ], [ -5.23, -6.48, 17.45 ], [ 1.91, 3.68, -8.47 ] ] ), - (250, [ [ -511.50, -154.20, 13.70 ], [ -22.70, 29.20, -59.80 ], [ 15.95, 8.57, -6.73 ], [ -3.65, -0.47, 0.86 ], [ 3.16, -14.02, -12.90 ], [ -3.69, -0.47, 0.87 ] ] ), - (251, [ [ -507.90, -150.60, -52.20 ], [ 77.80, 65.80, -26.70 ], [ 1.29, 14.04, 13.17 ], [ -8.54, 3.17, 11.58 ], [ 16.50, -6.06, 7.94 ], [ -8.65, 3.22, 11.73 ] ] ), - (252, [ [ -501.90, -69.20, -84.50 ], [ 124.80, -47.20, -52.70 ], [ 1.29, 14.00, 13.15 ], [ -0.00, -0.03, -0.03 ], [ -6.41, -9.18, 15.66 ], [ -0.00, -0.02, -0.02 ] ] ), - (253, [ [ -435.40, -182.40, -85.30 ], [ 133.20, -88.90, 11.70 ], [ 1.29, 13.97, 13.11 ], [ -6.83, -0.95, -2.07 ], [ -13.01, -7.62, 11.89 ], [ -6.94, -0.95, -2.09 ] ] ), - (254, [ [ -364.90, -190.70, -12.50 ], [ -54.90, -42.00, 69.00 ], [ -11.49, 12.22, 9.26 ], [ -5.25, 1.16, -5.56 ], [ -16.97, -6.24, -6.34 ], [ -5.33, 1.18, -5.63 ] ] ), - (255, [ [ -340.30, -163.80, 48.10 ], [ 128.90, 72.90, -11.00 ], [ -10.62, 15.74, 2.32 ], [ 1.45, 0.79, 0.19 ], [ 0.86, -2.05, 19.00 ], [ 1.47, 0.81, 0.20 ] ] ), - (256, [ [ -317.00, -143.90, -26.80 ], [ -88.40, -30.90, -19.80 ], [ -8.52, 13.49, 10.49 ], [ 6.33, -0.81, 5.07 ], [ -1.83, 11.02, -15.49 ], [ 6.43, -0.81, 5.16 ] ] ), - (257, [ [ -358.50, -142.30, -98.10 ], [ -66.10, 25.40, -1.30 ], [ 1.28, 13.87, 13.01 ], [ 6.65, 0.24, 1.70 ], [ 1.62, 13.39, -13.47 ], [ 6.77, 0.26, 1.74 ] ] ), - (258, [ [ -360.30, 29.80, -104.30 ], [ 133.20, -2.90, 37.90 ], [ 1.28, 13.82, 12.96 ], [ -6.70, -8.71, 0.72 ], [ 0.26, -12.21, 14.54 ], [ -6.84, -8.87, 0.75 ] ] ), - (259, [ [ -315.60, -96.60, -32.70 ], [ 59.80, 120.90, 165.90 ], [ -11.84, -3.18, 14.42 ], [ 4.77, -4.90, 1.16 ], [ 12.32, -9.78, 10.52 ], [ 4.87, -4.98, 1.20 ] ] ), - (260, [ [ -314.20, 51.50, -89.10 ], [ 14.30, 127.70, -5.60 ], [ 10.40, 3.75, 15.28 ], [ -1.05, -1.37, -0.07 ], [ 15.80, 2.03, -10.10 ], [ -1.08, -1.40, -0.05 ] ] ), - (261, [ [ -333.70, 97.10, 47.00 ], [ 52.00, 38.50, 28.60 ], [ -11.07, -4.90, 14.39 ], [ -3.38, 4.27, -19.59 ], [ 6.15, -17.76, 0.41 ], [ -3.45, 4.37, -20.04 ] ] ), - (262, [ [ -304.70, 120.30, -32.00 ], [ 62.80, -40.80, -60.10 ], [ -3.09, 7.47, -16.93 ], [ 3.93, 2.96, -20.26 ], [ 15.41, 10.71, 0.20 ], [ 4.01, 3.02, -20.74 ] ] ), - (263, [ [ -235.30, -46.60, 17.40 ], [ 156.60, -68.60, 59.20 ], [ -7.31, -8.51, -14.95 ], [ 11.87, -4.32, 3.21 ], [ 1.54, 13.58, -12.75 ], [ 12.18, -4.43, 3.27 ] ] ), - (264, [ [ -160.60, 8.90, 41.90 ], [ 96.20, 60.70, -14.40 ], [ 13.67, -6.24, -11.05 ], [ 7.32, 9.43, 12.02 ], [ 1.39, 12.62, -13.67 ], [ 7.50, 9.68, 12.33 ] ] ), - (265, [ [ -233.60, 108.70, 14.10 ], [ -196.10, -54.60, -35.60 ], [ 1.25, 13.53, 12.70 ], [ -6.34, 10.06, 12.10 ], [ 5.57, 13.67, -11.32 ], [ -6.50, 10.34, 12.42 ] ] ), - (266, [ [ -327.10, -7.90, -1.40 ], [ 30.20, -91.10, 80.60 ], [ 1.24, 13.49, 12.66 ], [ -1.77, -3.98, 2.52 ], [ -18.20, -1.26, 3.28 ], [ -1.82, -4.08, 2.60 ] ] ), - (267, [ [ -223.10, 8.60, 56.80 ], [ 64.40, 127.00, 90.60 ], [ -1.99, 6.25, 17.29 ], [ 5.46, -14.42, -3.87 ], [ 14.70, 2.28, 10.98 ], [ 5.63, -14.85, -3.98 ] ] ), - (268, [ [ -253.90, 87.40, 105.10 ], [ -5.80, 39.60, 111.40 ], [ 10.24, -13.76, 6.80 ], [ -1.00, 9.40, -0.35 ], [ 15.17, 10.40, -1.53 ], [ -1.03, 9.68, -0.35 ] ] ), - (269, [ [ -243.10, 128.50, 112.80 ], [ 95.00, 13.80, 1.40 ], [ 1.24, 13.41, 12.59 ], [ -4.00, 12.07, 2.56 ], [ 4.92, -11.96, 13.14 ], [ -4.12, 12.44, 2.65 ] ] ), - (270, [ [ -198.40, 111.30, 103.50 ], [ 29.70, -22.50, 0.00 ], [ 1.24, 13.40, 12.58 ], [ -0.01, -0.01, -0.01 ], [ -13.25, -5.74, 11.43 ], [ 0.00, -0.01, -0.01 ] ] ), - (271, [ [ -179.80, 86.80, 103.50 ], [ 15.50, -40.20, -2.20 ], [ 1.23, 13.39, 12.57 ], [ -0.01, -0.01, -0.01 ], [ -15.58, 7.24, 6.61 ], [ 0.00, -0.01, -0.01 ] ] ), - (272, [ [ -181.00, 44.30, 103.40 ], [ -23.30, -31.20, 0.00 ], [ 1.23, 13.38, 12.56 ], [ -0.00, -0.01, -0.01 ], [ -3.20, 16.69, -7.02 ], [ 0.00, -0.01, -0.01 ] ] ), - (273, [ [ -212.60, 28.50, 103.50 ], [ -45.50, -9.50, 0.00 ], [ 1.23, 13.37, 12.55 ], [ -0.00, -0.01, -0.01 ], [ 1.29, 13.09, -12.83 ], [ 0.00, -0.01, -0.01 ] ] ), - (274, [ [ -268.30, 32.40, 103.80 ], [ -47.70, 23.20, -5.70 ], [ 1.23, 13.35, 12.54 ], [ -0.00, -0.01, -0.02 ], [ 3.87, 12.54, -12.83 ], [ 0.00, -0.01, -0.01 ] ] ), - (275, [ [ -303.20, 68.70, 92.20 ], [ -16.00, 43.30, -4.00 ], [ 1.23, 13.34, 12.52 ], [ -0.00, -0.01, -0.02 ], [ 9.07, 14.46, -6.70 ], [ 0.00, -0.01, -0.01 ] ] ), - (276, [ [ -264.40, 113.10, 92.20 ], [ 96.40, 13.40, -16.30 ], [ 1.23, 13.32, 12.51 ], [ -0.00, -0.02, -0.02 ], [ 4.82, -12.29, 12.69 ], [ 0.00, -0.01, -0.01 ] ] ), - (277, [ [ -194.80, 79.90, 66.60 ], [ 66.40, 101.30, -2.50 ], [ 1.23, 13.30, 12.48 ], [ -0.00, -0.02, -0.02 ], [ 17.04, 2.78, 6.03 ], [ 0.00, -0.02, -0.02 ] ] ), - (278, [ [ -259.90, 145.40, 69.10 ], [ -50.20, 11.70, 0.70 ], [ 1.23, 13.27, 12.46 ], [ -0.00, -0.02, -0.02 ], [ 0.71, 12.60, -13.18 ], [ 0.00, -0.01, -0.01 ] ] ), - (279, [ [ -332.40, 128.50, 76.00 ], [ -49.00, -52.40, -1.30 ], [ 1.23, 13.25, 12.44 ], [ -0.00, -0.02, -0.02 ], [ -1.51, 16.32, -7.96 ], [ 0.00, -0.01, -0.01 ] ] ), - (280, [ [ -350.80, 61.90, 80.80 ], [ -2.80, -49.40, 0.50 ], [ 1.23, 13.24, 12.42 ], [ -0.00, -0.02, -0.02 ], [ -11.79, 13.85, 0.34 ], [ 0.00, -0.01, -0.01 ] ] ), - (281, [ [ -310.50, 4.10, 73.40 ], [ 145.80, -25.20, -6.40 ], [ 1.22, 13.22, 12.40 ], [ -0.01, -0.02, -0.02 ], [ -3.10, -11.99, 13.29 ], [ 0.00, -0.01, -0.01 ] ] ), - (282, [ [ -271.10, -43.80, 94.40 ], [ 16.10, -48.30, 3.80 ], [ 1.22, 13.20, 12.39 ], [ -0.00, -0.01, -0.01 ], [ -16.23, 6.76, 4.48 ], [ 0.00, -0.01, -0.01 ] ] ), - (283, [ [ -270.90, -77.40, 103.40 ], [ 39.70, -14.80, 1.00 ], [ 1.21, 13.19, 12.38 ], [ -0.00, -0.01, -0.01 ], [ -7.61, -10.46, 12.70 ], [ 0.00, -0.01, -0.01 ] ] ), - (284, [ [ -220.70, -87.80, 97.40 ], [ 44.90, 15.00, 0.00 ], [ 1.21, 13.17, 12.36 ], [ -0.00, -0.01, -0.01 ], [ 8.97, -10.04, 12.11 ], [ 0.00, -0.01, -0.01 ] ] ), - (285, [ [ -173.40, -67.30, 82.30 ], [ -11.80, 54.90, -11.40 ], [ 1.21, 13.16, 12.35 ], [ -0.00, -0.02, -0.02 ], [ 12.41, 11.79, -5.84 ], [ 0.00, -0.01, -0.01 ] ] ), - (286, [ [ -229.90, -30.60, 62.70 ], [ -49.80, 8.30, -5.90 ], [ 1.21, 13.14, 12.33 ], [ -0.00, -0.02, -0.01 ], [ 4.00, 11.86, -13.02 ], [ 0.00, -0.01, -0.01 ] ] ), - (287, [ [ -291.70, -26.70, 39.10 ], [ -43.90, 3.80, 0.00 ], [ 1.21, 13.12, 12.32 ], [ -0.00, -0.01, -0.01 ], [ 1.14, 12.27, -13.17 ], [ 0.00, -0.01, -0.01 ] ] ), - (288, [ [ -323.60, -28.80, 45.90 ], [ -29.10, -6.00, 15.70 ], [ 1.21, 13.11, 12.31 ], [ -0.00, -0.01, -0.01 ], [ -10.37, 10.80, -10.04 ], [ 0.00, -0.01, -0.00 ] ] ), - (289, [ [ -340.40, -46.90, 56.00 ], [ -7.70, -28.60, -0.30 ], [ 1.21, 13.10, 12.30 ], [ -0.00, -0.01, -0.01 ], [ -8.34, 15.83, -2.10 ], [ 0.00, -0.01, -0.01 ] ] ), - (290, [ [ -341.70, -83.90, 64.30 ], [ 5.20, -25.30, 4.60 ], [ 1.21, 13.10, 12.29 ], [ -0.00, -0.01, -0.02 ], [ -16.18, 7.65, 1.97 ], [ 0.00, -0.01, -0.01 ] ] ), - (291, [ [ -327.60, -149.50, 76.40 ], [ 26.30, -22.60, 3.30 ], [ 1.21, 13.08, 12.27 ], [ -0.01, -0.02, -0.02 ], [ -14.04, -4.99, 10.05 ], [ 0.00, -0.01, -0.01 ] ] ), - (292, [ [ -277.60, -101.40, 42.90 ], [ 45.10, -4.20, 0.00 ], [ 1.20, 13.05, 12.26 ], [ -0.00, -0.02, -0.01 ], [ -1.15, -12.20, 13.11 ], [ 0.00, -0.01, -0.01 ] ] ), - (293, [ [ -231.00, -108.20, 27.80 ], [ 42.40, 14.10, 0.00 ], [ 1.20, 13.04, 12.24 ], [ -0.00, -0.01, -0.02 ], [ 8.85, -9.96, 12.00 ], [ 0.00, -0.01, -0.01 ] ] ), - (294, [ [ -180.10, -109.90, 40.70 ], [ 59.10, -19.40, 39.60 ], [ 1.20, 13.03, 12.23 ], [ -0.00, -0.01, -0.02 ], [ -6.93, -10.23, 12.96 ], [ 0.00, -0.01, -0.01 ] ] ), - (295, [ [ -174.70, -116.60, 80.30 ], [ -37.40, 27.50, 45.00 ], [ 1.20, 13.02, 12.21 ], [ -0.00, -0.02, -0.02 ], [ -11.59, 13.58, 1.25 ], [ 0.00, -0.01, -0.01 ] ] ), - (296, [ [ -300.70, -86.10, 54.30 ], [ -63.80, -23.10, 55.90 ], [ 1.20, 12.98, 12.18 ], [ -0.00, -0.03, -0.03 ], [ -13.97, 8.69, -6.90 ], [ 0.00, -0.02, -0.02 ] ] ), - (297, [ [ -289.00, -163.30, 110.50 ], [ -99.30, -43.30, 98.20 ], [ 1.20, 12.96, 12.15 ], [ -0.00, -0.03, -0.04 ], [ -14.68, 8.02, -6.09 ], [ 0.00, -0.02, -0.02 ] ] ), - (298, [ [ -323.00, -11.30, 56.10 ], [ 39.10, 49.20, -8.90 ], [ 1.20, 12.91, 12.11 ], [ -0.01, -0.02, -0.02 ], [ 16.77, -0.61, 5.76 ], [ 0.00, -0.01, -0.01 ] ] ), - (299, [ [ -277.50, 6.40, 49.70 ], [ 95.70, -13.00, 0.00 ], [ 1.18, 12.89, 12.10 ], [ -0.01, -0.02, -0.01 ], [ -2.18, -11.91, 12.93 ], [ 0.00, -0.01, -0.01 ] ] ), - (300, [ [ -191.40, -10.90, 80.50 ], [ 62.80, -7.70, 9.50 ], [ 1.18, 12.87, 12.07 ], [ -0.00, -0.02, -0.02 ], [ -1.98, -11.85, 12.98 ], [ 0.00, -0.01, -0.01 ] ] ), - (301, [ [ -133.30, 24.30, 81.00 ], [ 42.20, 67.00, 0.00 ], [ 1.18, 12.85, 12.06 ], [ -0.00, -0.02, -0.01 ], [ 16.33, 3.31, 5.85 ], [ 0.00, -0.01, -0.01 ] ] ), - (302, [ [ -125.40, 67.10, 93.50 ], [ -20.50, 21.20, -1.40 ], [ 1.18, 12.84, 12.04 ], [ -0.00, -0.01, -0.01 ], [ 3.82, 13.92, -10.13 ], [ 0.00, -0.01, -0.01 ] ] ), - (303, [ [ -181.30, 58.00, 64.50 ], [ -62.10, -31.80, -29.80 ], [ 1.18, 12.82, 12.03 ], [ -0.00, -0.02, -0.02 ], [ 9.05, 14.02, -5.65 ], [ 0.00, -0.01, -0.01 ] ] ), - (304, [ [ -295.90, 96.80, 39.60 ], [ -106.30, -114.70, -51.10 ], [ 1.18, 12.78, 11.99 ], [ -0.00, -0.04, -0.03 ], [ 4.27, 16.73, -3.27 ], [ 0.00, -0.02, -0.02 ] ] ), - (305, [ [ -170.50, 62.70, -13.20 ], [ -26.90, -123.60, 24.00 ], [ 1.18, 12.74, 11.96 ], [ -0.01, -0.04, -0.04 ], [ -11.71, 12.55, -3.44 ], [ 0.00, -0.02, -0.02 ] ] ), - (306, [ [ -274.30, 42.90, 28.40 ], [ -12.60, -108.50, -11.40 ], [ 1.17, 12.71, 11.92 ], [ -0.01, -0.04, -0.04 ], [ -8.86, 15.01, 1.14 ], [ 0.00, -0.02, -0.02 ] ] ), - (307, [ [ -142.90, -22.50, 18.30 ], [ 11.70, 9.50, 57.30 ], [ 1.17, 12.66, 11.88 ], [ 1.17, -1.58, 1.19 ], [ -7.62, 0.99, 15.61 ], [ 1.23, -1.65, 1.27 ] ] ), - (308, [ [ -150.90, -36.10, 84.20 ], [ -5.30, -48.90, 32.20 ], [ 2.86, 10.39, 13.63 ], [ 0.04, -0.08, 0.03 ], [ -16.90, 3.99, 0.66 ], [ 0.05, -0.07, 0.04 ] ] ), - (309, [ [ -135.30, -105.30, 94.80 ], [ -3.20, -32.60, 55.90 ], [ 1.17, 12.62, 11.85 ], [ 5.63, -11.05, 0.16 ], [ -17.04, -0.33, 3.25 ], [ 5.94, -11.65, 0.17 ] ] ), - (310, [ [ -138.40, -135.90, 107.80 ], [ 4.80, -33.70, -0.70 ], [ 10.40, -4.95, 12.96 ], [ 5.06, -12.37, -7.66 ], [ -12.07, -8.08, 9.47 ], [ 5.34, -13.05, -8.09 ] ] ), - (311, [ [ -150.80, -112.60, 40.60 ], [ 1.40, 115.30, 8.10 ], [ 5.48, -4.87, -15.68 ], [ -8.73, -1.10, -16.85 ], [ -15.37, -5.30, -5.93 ], [ -9.22, -1.17, -17.79 ] ] ), - (312, [ [ -176.80, 19.30, -24.60 ], [ 67.20, 241.30, -20.60 ], [ -10.06, -8.08, -11.46 ], [ -5.04, -2.23, 0.97 ], [ -14.20, -5.24, 8.27 ], [ -5.32, -2.36, 1.00 ] ] ), - (313, [ [ -276.70, 70.90, -69.10 ], [ -51.90, -162.20, 10.10 ], [ -3.19, -9.19, -14.18 ], [ 2.84, -0.45, -1.11 ], [ 11.33, -12.94, 0.29 ], [ 3.00, -0.48, -1.18 ] ] ), - (314, [ [ -221.20, 2.30, -47.30 ], [ -165.70, -117.10, -0.90 ], [ -3.19, -9.17, -14.15 ], [ 0.01, 0.02, 0.03 ], [ 1.62, -16.13, 5.61 ], [ 0.00, 0.01, 0.02 ] ] ), - (315, [ [ -283.70, -70.80, -59.10 ], [ 66.20, -75.00, 17.60 ], [ -3.18, -9.15, -14.11 ], [ 0.01, 0.02, 0.03 ], [ 13.47, 6.99, -7.92 ], [ 0.00, 0.01, 0.02 ] ] ), - (316, [ [ -200.90, -32.00, -51.70 ], [ 94.90, 36.10, 50.70 ], [ -3.18, -9.13, -14.09 ], [ 7.54, 1.13, 2.34 ], [ -10.31, 6.59, -11.92 ], [ 8.01, 1.20, 2.48 ] ] ), - (317, [ [ -114.90, 21.00, -43.50 ], [ 88.80, 141.00, 123.30 ], [ 12.65, -6.78, -9.20 ], [ 10.12, 6.89, 4.80 ], [ -4.22, 8.30, -14.28 ], [ 10.75, 7.32, 5.08 ] ] ), - (318, [ [ -154.40, 135.80, -62.60 ], [ -78.30, -1.00, -2.30 ], [ 15.19, 6.14, -4.52 ], [ -4.73, 11.66, 5.50 ], [ 15.36, -4.77, -5.50 ], [ -5.02, 12.40, 5.84 ] ] ), - (319, [ [ -274.80, 136.50, 7.90 ], [ 22.10, 45.90, 70.80 ], [ 3.20, 16.54, 1.79 ], [ -5.93, 5.11, 3.12 ], [ -9.70, 7.92, 11.41 ], [ -6.30, 5.46, 3.32 ] ] ), - (320, [ [ -141.60, 114.90, 31.30 ], [ 60.30, 66.50, 26.50 ], [ 3.20, 16.48, 1.79 ], [ -0.01, -0.03, -0.00 ], [ 5.81, 9.90, 12.39 ], [ 0.00, -0.02, 0.00 ] ] ), - (321, [ [ -108.40, 101.20, 30.10 ], [ 11.30, -64.60, -17.80 ], [ 3.19, 16.47, 1.79 ], [ 5.73, -9.33, 0.72 ], [ 0.02, 13.69, 9.85 ], [ 6.12, -9.95, 0.76 ] ] ), - (322, [ [ -117.50, 36.30, 28.10 ], [ -11.80, -88.50, 4.40 ], [ 15.95, -4.24, 3.38 ], [ 7.09, -9.12, -1.91 ], [ -3.44, -1.01, 16.46 ], [ 7.57, -9.72, -2.04 ] ] ), - (323, [ [ -123.00, -16.90, 76.90 ], [ -5.40, -40.50, 20.40 ], [ 16.63, -0.25, -2.49 ], [ -0.21, 4.61, -0.38 ], [ 2.66, 9.67, 13.50 ], [ -0.21, 4.92, -0.40 ] ] ), - (324, [ [ -83.50, -94.80, 124.40 ], [ -5.30, -37.10, -69.10 ], [ 15.15, 5.23, 4.96 ], [ -0.96, 3.46, 4.71 ], [ 2.79, -9.28, 13.70 ], [ -1.00, 3.70, 5.04 ] ] ), - (325, [ [ -114.60, -3.80, -22.00 ], [ -48.40, -89.30, -74.40 ], [ 15.09, 5.21, 4.94 ], [ 0.13, -7.07, -4.33 ], [ 4.35, 1.79, 16.03 ], [ 0.15, -7.57, -4.63 ] ] ), - (326, [ [ -106.10, -89.80, 24.00 ], [ -40.70, -98.90, -72.10 ], [ 15.33, -6.21, -2.04 ], [ 0.23, -2.61, -5.35 ], [ -2.24, -10.03, 13.12 ], [ 0.26, -2.79, -5.73 ] ] ), - (327, [ [ -134.60, -44.80, -44.70 ], [ -45.50, -59.20, -129.40 ], [ 15.55, -0.63, -5.87 ], [ -4.55, 4.11, -6.56 ], [ 1.59, -15.49, 5.83 ], [ -4.87, 4.41, -7.04 ] ] ), - (328, [ [ -152.20, -122.40, -0.90 ], [ -138.70, -24.00, -10.70 ], [ 5.62, 1.83, -15.50 ], [ -2.19, -5.54, 0.63 ], [ 7.35, -14.87, -0.48 ], [ -2.34, -5.95, 0.67 ] ] ), - (329, [ [ -215.00, -66.50, -51.90 ], [ -95.40, -77.80, 7.50 ], [ 10.89, -11.43, -4.96 ], [ 4.44, -4.77, 7.49 ], [ 5.00, -2.22, 15.63 ], [ 4.78, -5.13, 8.04 ] ] ), - (330, [ [ -281.50, -141.60, -97.10 ], [ -33.10, -74.40, -0.80 ], [ 14.52, -7.85, -0.46 ], [ 2.14, 2.15, 2.68 ], [ -0.17, -1.50, 16.44 ], [ 2.32, 2.30, 2.88 ] ] ), - (331, [ [ -142.90, -169.80, -24.70 ], [ 57.10, 22.50, 62.40 ], [ 14.46, -7.83, -0.46 ], [ -0.05, 0.02, 0.00 ], [ 10.09, 12.44, -3.77 ], [ -0.03, 0.02, 0.00 ] ] ), - (332, [ [ -114.90, -94.60, 56.00 ], [ -22.70, -27.90, 103.30 ], [ 14.42, -7.80, -0.46 ], [ -0.04, 0.02, 0.00 ], [ 7.79, 13.89, 3.94 ], [ -0.03, 0.01, 0.00 ] ] ), - (333, [ [ -165.80, -210.20, 55.70 ], [ -82.80, 8.90, -63.60 ], [ 14.38, -7.78, -0.46 ], [ -0.04, 0.02, 0.00 ], [ 4.52, -10.09, 12.05 ], [ -0.03, 0.01, 0.00 ] ] ), - (334, [ [ -221.80, -171.30, -25.00 ], [ -110.60, -77.10, -27.50 ], [ 14.34, -7.76, -0.46 ], [ -7.05, 1.07, -6.62 ], [ 4.40, 0.73, 15.69 ], [ -7.61, 1.16, -7.17 ] ] ), - (335, [ [ -212.40, -201.20, 82.90 ], [ 136.90, 5.40, 26.70 ], [ -1.40, -5.38, -15.28 ], [ 1.17, -0.16, 1.14 ], [ -3.98, 14.55, -6.08 ], [ 1.28, -0.18, 1.23 ] ] ), - (336, [ [ -187.10, -132.60, 25.20 ], [ -87.20, 10.40, -111.30 ], [ 14.26, -7.71, -0.46 ], [ 9.16, 4.06, 10.76 ], [ -0.57, -12.13, 10.74 ], [ 9.93, 4.39, 11.65 ] ] ), - (337, [ [ -324.00, -192.70, -37.00 ], [ -25.10, -36.30, 21.20 ], [ 14.59, 5.03, 4.77 ], [ 0.10, 4.80, 1.97 ], [ -1.03, 15.54, 4.28 ], [ 0.13, 5.20, 2.14 ] ] ), - (338, [ [ -280.20, -208.50, 37.40 ], [ -89.00, -10.60, 119.10 ], [ 14.55, 5.03, 4.77 ], [ -10.49, 2.92, -7.65 ], [ -1.23, 14.85, -6.15 ], [ -11.39, 3.18, -8.31 ] ] ), - (339, [ [ -271.90, -187.90, 119.40 ], [ 42.70, 34.80, 6.60 ], [ -6.06, 10.79, -10.27 ], [ -5.42, 1.49, -5.96 ], [ -7.05, 7.74, 12.21 ], [ -5.88, 1.63, -6.48 ] ] ), - (340, [ [ -252.20, -147.10, 107.10 ], [ 22.70, 45.10, -4.00 ], [ -4.00, 10.18, -11.77 ], [ 2.55, 1.22, 0.64 ], [ -6.00, 12.89, 7.48 ], [ 2.78, 1.34, 0.69 ] ] ), - (341, [ [ -216.60, -117.80, 95.70 ], [ 40.30, -19.20, -0.50 ], [ -0.92, 13.36, -8.84 ], [ 9.63, -2.95, 8.59 ], [ -1.90, 10.78, 11.74 ], [ 10.48, -3.21, 9.35 ] ] ), - (342, [ [ -210.30, -154.50, 112.40 ], [ -20.60, -33.90, 26.20 ], [ 14.48, 5.00, 4.74 ], [ 9.65, -5.25, 8.52 ], [ -3.00, 15.18, 4.18 ], [ 10.51, -5.71, 9.27 ] ] ), - (343, [ [ -241.10, -217.80, 103.30 ], [ -99.30, -50.40, -38.80 ], [ 14.45, 4.98, 4.74 ], [ -2.89, 1.23, -6.88 ], [ 12.97, 6.01, 7.20 ], [ -3.14, 1.34, -7.50 ] ] ), - (344, [ [ -262.00, -235.10, 20.00 ], [ 83.30, -4.40, -126.20 ], [ 7.63, 7.92, -11.58 ], [ -0.53, 0.21, -1.21 ], [ 14.45, -0.38, -6.79 ], [ -0.57, 0.23, -1.31 ] ] ), - (345, [ [ -341.30, -228.90, -31.50 ], [ 21.90, 106.10, -95.20 ], [ 14.39, 4.97, 4.71 ], [ 3.58, -1.58, 8.69 ], [ 7.16, -8.20, -11.63 ], [ 3.93, -1.72, 9.48 ] ] ), - (346, [ [ -223.00, -253.50, -46.00 ], [ 3.40, 60.90, -83.80 ], [ 14.34, 4.95, 4.69 ], [ 0.66, -1.98, -3.36 ], [ 6.75, -11.99, -7.93 ], [ 0.74, -2.16, -3.66 ] ] ), - (347, [ [ -309.60, -169.80, -81.10 ], [ 21.90, 106.10, -95.20 ], [ 15.68, 1.07, -1.89 ], [ -7.72, -0.17, -9.71 ], [ -0.02, -6.82, -14.29 ], [ -8.44, -0.18, -10.64 ] ] ), - (348, [ [ -209.50, -219.10, -37.80 ], [ 53.10, -46.50, -77.10 ], [ -1.67, 4.84, -14.93 ], [ -6.57, 1.42, -4.92 ], [ 14.28, 5.25, -4.20 ], [ -7.20, 1.56, -5.40 ] ] ), - (349, [ [ -173.60, -172.20, -85.40 ], [ -26.90, 37.00, -15.30 ], [ -1.67, 4.82, -14.90 ], [ 3.86, -5.85, 4.16 ], [ -15.11, -0.60, -4.38 ], [ 4.24, -6.42, 4.55 ] ] ), - (350, [ [ -291.30, -84.30, -106.00 ], [ 97.00, 135.70, 42.80 ], [ 9.54, -12.11, -2.88 ], [ 6.72, -8.15, 5.15 ], [ -2.01, 0.14, -15.56 ], [ 7.39, -8.96, 5.63 ] ] ), - (351, [ [ -120.90, -148.90, -48.40 ], [ 39.70, 69.50, -18.40 ], [ 10.75, -9.49, -6.16 ], [ 0.44, 1.01, -1.23 ], [ -8.04, -0.66, -13.36 ], [ 0.50, 1.10, -1.36 ] ] ), - (352, [ [ -144.10, -35.10, -76.70 ], [ -46.20, 4.30, -3.90 ], [ 10.72, -9.46, -6.13 ], [ -0.03, 0.02, 0.02 ], [ 9.56, -8.00, 9.32 ], [ -0.02, 0.02, 0.01 ] ] ), - (353, [ [ -190.90, -106.20, -108.70 ], [ -85.30, 10.90, -25.60 ], [ 10.69, -9.44, -6.13 ], [ -0.03, 0.02, 0.01 ], [ 5.65, -10.04, 10.41 ], [ -0.02, 0.01, 0.01 ] ] ), - (354, [ [ -285.70, -73.50, -145.80 ], [ -88.80, -66.70, -0.90 ], [ 10.67, -9.42, -6.10 ], [ -0.03, 0.03, 0.02 ], [ 5.85, -3.27, 13.96 ], [ -0.02, 0.02, 0.01 ] ] ), - (355, [ [ -321.80, -178.80, -111.70 ], [ -31.80, -89.20, 89.10 ], [ 10.64, -9.39, -6.09 ], [ -0.02, 0.02, 0.01 ], [ 10.69, 6.03, 9.37 ], [ -0.02, 0.01, 0.01 ] ] ), - (356, [ [ -371.60, -176.40, -124.40 ], [ 19.20, 94.50, -4.50 ], [ 10.62, -9.37, -6.08 ], [ -1.15, 5.43, -2.83 ], [ -7.74, -5.92, -11.94 ], [ -1.26, 6.01, -3.14 ] ] ), - (357, [ [ -321.80, -83.50, -118.80 ], [ -75.90, 112.20, -24.80 ], [ 7.94, 3.35, -12.73 ], [ -7.87, 9.63, -2.48 ], [ -10.12, -7.92, -8.43 ], [ -8.72, 10.67, -2.75 ] ] ), - (358, [ [ -395.50, -163.20, -123.30 ], [ -53.40, -89.20, 1.10 ], [ -5.72, 9.53, -10.56 ], [ 1.54, 4.94, 6.19 ], [ 11.70, -0.90, -9.86 ], [ 1.72, 5.48, 6.85 ] ] ), - (359, [ [ -473.40, -148.90, -123.50 ], [ -56.10, 65.20, -46.90 ], [ 6.94, 13.55, -1.43 ], [ 8.17, -9.27, 2.34 ], [ 2.25, -0.33, -15.12 ], [ 9.07, -10.30, 2.58 ] ] ), - (360, [ [ -429.70, -106.40, -120.50 ], [ 163.60, -61.70, -10.20 ], [ 10.52, -9.29, -6.02 ], [ -2.78, -9.61, -6.54 ], [ 14.14, 0.27, -5.75 ], [ -3.09, -10.68, -7.28 ] ] ), - (361, [ [ -402.50, -38.30, -145.20 ], [ -67.70, 81.20, 4.50 ], [ 0.22, -3.27, -14.88 ], [ -6.38, 6.43, -3.19 ], [ -9.17, -12.03, 1.78 ], [ -7.10, 7.14, -3.56 ] ] ), - (362, [ [ -461.90, -56.90, -150.00 ], [ -80.10, -50.60, 3.70 ], [ -3.60, 3.42, -14.37 ], [ -5.47, 3.23, 2.15 ], [ 6.98, -12.63, -4.79 ], [ -6.09, 3.59, 2.38 ] ] ), - (363, [ [ -522.70, -134.30, -113.60 ], [ -48.30, 6.50, 89.20 ], [ -11.56, 1.39, -9.73 ], [ -0.45, 2.83, 1.70 ], [ -0.44, -14.95, -2.51 ], [ -0.50, 3.16, 1.88 ] ] ), - (364, [ [ -492.60, -30.90, -110.50 ], [ -4.70, 62.60, 70.10 ], [ -4.04, 9.38, -11.16 ], [ 3.44, 3.64, -0.64 ], [ -14.31, -4.82, 0.82 ], [ 3.83, 4.07, -0.73 ] ] ), - (365, [ [ -562.40, -79.20, -83.10 ], [ -57.30, 18.40, 43.90 ], [ -4.03, 9.36, -11.13 ], [ 0.01, -0.02, 0.03 ], [ -7.38, -11.22, -6.88 ], [ 0.01, -0.02, 0.02 ] ] ), - (366, [ [ -607.00, 13.50, -78.80 ], [ 37.30, 101.70, -7.80 ], [ -4.02, 9.33, -11.10 ], [ 0.01, -0.03, 0.03 ], [ -6.92, 11.73, 6.39 ], [ 0.01, -0.02, 0.02 ] ] ), - (367, [ [ -511.10, 40.20, -112.70 ], [ 103.50, -93.30, -48.20 ], [ -4.01, 9.30, -11.07 ], [ 0.11, -3.57, -1.75 ], [ 6.48, 12.30, 5.65 ], [ 0.12, -3.99, -1.97 ] ] ), - (368, [ [ -523.20, -9.50, -122.50 ], [ -147.00, 5.30, 22.40 ], [ -3.83, 3.08, -14.15 ], [ -0.01, -3.23, -1.48 ], [ -2.71, -14.50, -2.64 ], [ -0.01, -3.61, -1.67 ] ] ), - (369, [ [ -588.70, -24.10, -95.80 ], [ 34.00, -42.60, 1.70 ], [ -4.00, 2.57, -14.17 ], [ 0.65, 0.95, 0.15 ], [ 7.91, 12.58, -1.68 ], [ 0.72, 1.07, 0.16 ] ] ), - (370, [ [ -532.30, -72.30, -120.30 ], [ 111.50, -25.50, -41.10 ], [ -2.56, 4.94, -13.85 ], [ 1.57, 2.29, 0.53 ], [ 5.77, 13.30, 3.55 ], [ 1.76, 2.57, 0.59 ] ] ), - (371, [ [ -460.90, -12.40, -123.40 ], [ 176.70, 55.60, 45.00 ], [ -0.83, 7.12, -13.05 ], [ 0.80, 1.00, 0.37 ], [ -7.13, 11.38, 6.42 ], [ 0.90, 1.13, 0.40 ] ] ), - (372, [ [ -427.40, 65.30, -95.70 ], [ -43.60, 32.50, -16.00 ], [ -0.99, 6.89, -13.12 ], [ 0.27, 0.90, 0.56 ], [ -12.05, -4.99, -7.11 ], [ 0.30, 1.02, 0.62 ] ] ), - (373, [ [ -471.40, 54.70, -118.00 ], [ -79.10, -33.90, 8.90 ], [ -0.50, 8.37, -12.23 ], [ -0.62, 1.29, 1.01 ], [ 7.66, -9.63, -8.27 ], [ -0.70, 1.46, 1.13 ] ] ), - (374, [ [ -580.40, 127.50, -99.50 ], [ 11.00, 31.00, 79.80 ], [ -3.95, 9.17, -10.90 ], [ 1.47, 0.43, 0.17 ], [ -13.32, -4.88, -4.15 ], [ 1.66, 0.50, 0.18 ] ] ), - (375, [ [ -556.80, 144.60, -36.30 ], [ 82.20, -21.40, 6.30 ], [ 0.21, 9.40, -11.37 ], [ 0.42, 0.00, -0.03 ], [ -0.73, 11.74, 8.90 ], [ 0.47, 0.02, -0.04 ] ] ), - (376, [ [ -519.60, 126.70, -112.70 ], [ 103.30, -10.80, -25.10 ], [ -3.93, 9.13, -10.86 ], [ -2.19, -0.16, 0.28 ], [ 1.14, 11.64, 8.94 ], [ -2.48, -0.17, 0.31 ] ] ), - (377, [ [ -425.90, 145.30, -95.20 ], [ 0.10, 5.40, 86.10 ], [ -3.92, 9.10, -10.83 ], [ 0.01, -0.03, 0.03 ], [ -9.77, -4.54, -9.97 ], [ 0.01, -0.02, 0.02 ] ] ), - (378, [ [ -512.40, 124.30, -46.70 ], [ -26.40, -6.80, -45.50 ], [ -3.91, 9.07, -10.80 ], [ 0.01, -0.02, 0.03 ], [ 4.17, -3.30, -13.64 ], [ 0.01, -0.01, 0.02 ] ] ), - (379, [ [ -476.90, 99.10, -97.70 ], [ 61.40, -4.20, -24.70 ], [ -3.90, 9.06, -10.77 ], [ 0.01, -0.02, 0.03 ], [ 3.89, 11.44, 8.21 ], [ 0.01, -0.01, 0.02 ] ] ), - (380, [ [ -371.40, 119.00, -116.30 ], [ 47.50, 67.00, 21.40 ], [ -3.89, 9.03, -10.74 ], [ 3.72, 1.74, 2.21 ], [ -9.50, 6.80, 8.69 ], [ 4.22, 1.99, 2.49 ] ] ), - (381, [ [ -341.60, 157.90, -39.40 ], [ -130.40, -15.20, -17.30 ], [ 3.62, 12.58, -6.31 ], [ 0.70, 2.51, 4.56 ], [ 6.49, -6.21, -11.42 ], [ 0.79, 2.87, 5.16 ] ] ), - (382, [ [ -401.40, 155.50, -49.20 ], [ -44.00, 17.80, 118.30 ], [ -0.22, 14.41, -1.67 ], [ -2.23, 0.58, 5.83 ], [ -13.79, -0.71, -4.45 ], [ -2.54, 0.67, 6.62 ] ] ), - (383, [ [ -326.70, 144.80, -18.40 ], [ 68.80, -24.00, -65.20 ], [ -0.21, 13.25, 5.81 ], [ 0.05, -0.90, -4.01 ], [ 2.29, -2.16, 14.12 ], [ 0.06, -1.01, -4.56 ] ] ), - (384, [ [ -264.80, 135.60, -54.60 ], [ 15.70, 44.40, 54.40 ], [ -0.12, 12.55, -7.14 ], [ 3.05, -0.30, -4.66 ], [ -13.39, 2.90, 4.57 ], [ 3.48, -0.33, -5.31 ] ] ), - (385, [ [ -311.00, 161.60, 22.30 ], [ 30.30, -19.60, 79.00 ], [ 6.48, 12.73, -1.86 ], [ 2.95, 0.10, 1.93 ], [ -11.96, 7.06, 3.81 ], [ 3.37, 0.13, 2.19 ] ] ), - (386, [ [ -216.70, 146.00, 34.60 ], [ 48.10, -13.40, 2.20 ], [ 5.72, 12.74, -3.34 ], [ -0.36, -0.13, -1.13 ], [ 2.21, 2.94, 13.89 ], [ -0.41, -0.13, -1.29 ] ] ), - (387, [ [ -127.20, 99.80, 74.20 ], [ 48.10, -23.70, 1.30 ], [ 5.78, 12.45, -4.09 ], [ 3.97, -5.53, 2.44 ], [ 1.13, 3.99, 13.71 ], [ 4.55, -6.30, 2.78 ] ] ), - (388, [ [ -31.50, 35.80, 58.00 ], [ 9.60, -94.20, 34.00 ], [ 14.11, 1.08, 1.91 ], [ -4.96, -6.31, 9.74 ], [ -2.06, 3.67, 13.65 ], [ -5.67, -7.21, 11.15 ] ] ), - (389, [ [ -93.20, 47.90, 78.70 ], [ -40.40, 4.30, -4.70 ], [ 0.38, -1.89, 14.12 ], [ -13.30, 3.09, -2.34 ], [ 3.43, 13.68, 2.08 ], [ -15.22, 3.54, -2.68 ] ] ), - (390, [ [ -83.60, 41.80, 21.70 ], [ -25.40, 95.30, -36.30 ], [ -12.54, 6.62, -1.22 ], [ 1.19, 7.30, -7.96 ], [ -1.11, 12.61, 6.50 ], [ 1.37, 8.37, -9.11 ] ] ), - (391, [ [ -94.90, 120.00, -16.70 ], [ 54.70, 18.00, -1.30 ], [ 6.95, 12.37, 0.40 ], [ 13.15, -4.37, 2.41 ], [ 10.33, 2.73, 9.34 ], [ 15.08, -5.02, 2.76 ] ] ), - (392, [ [ -6.00, 8.70, 44.40 ], [ -86.70, -73.70, -3.60 ], [ 8.62, -10.35, 4.25 ], [ 1.39, -7.11, -5.37 ], [ -3.08, 2.96, 13.47 ], [ 1.61, -8.16, -6.18 ] ] ), - (393, [ [ -69.50, 67.10, -5.30 ], [ -28.20, -6.40, -92.20 ], [ 9.82, -6.91, -7.36 ], [ -1.75, 10.80, -4.15 ], [ -7.45, -11.82, -1.74 ], [ -2.01, 12.43, -4.77 ] ] ), - (394, [ [ -80.80, -39.40, -67.40 ], [ 124.60, -54.30, 39.80 ], [ 4.34, 13.18, -2.10 ], [ -6.39, 8.82, 4.76 ], [ -4.51, 3.77, 12.74 ], [ -7.36, 10.17, 5.48 ] ] ), - (395, [ [ -47.50, 28.90, -23.70 ], [ 59.80, -55.90, 69.30 ], [ -2.73, 13.54, 2.28 ], [ 6.16, -4.72, 4.76 ], [ -13.90, 0.67, 1.53 ], [ 7.12, -5.43, 5.49 ] ] ), - (396, [ [ -37.50, -11.90, -20.60 ], [ -26.30, -38.40, 68.20 ], [ 10.22, 6.22, 7.23 ], [ 7.91, -7.09, -3.25 ], [ -8.44, 10.83, 2.63 ], [ 9.13, -8.18, -3.75 ] ] ), - (397, [ [ -36.80, -10.90, 27.50 ], [ -1.60, 7.40, 38.00 ], [ 13.48, -0.66, -3.58 ], [ 1.34, -2.85, -4.47 ], [ 0.14, 12.27, -6.66 ], [ 1.56, -3.28, -5.16 ] ] ), - (398, [ [ -42.70, -8.00, 62.70 ], [ -6.50, 1.70, 7.10 ], [ 13.47, -0.66, -3.57 ], [ -0.01, 0.00, 0.01 ], [ 7.61, 5.38, -10.38 ], [ -0.01, 0.00, 0.00 ] ] ), - (399, [ [ -63.30, 1.20, 96.30 ], [ -26.00, 27.20, 0.00 ], [ 13.46, -0.65, -3.56 ], [ -0.01, 0.00, 0.00 ], [ 4.17, -9.52, -9.28 ], [ -0.01, 0.00, 0.00 ] ] ), - (400, [ [ -78.00, 27.60, 100.90 ], [ 37.30, 13.80, 0.20 ], [ 13.44, -0.65, -3.56 ], [ -8.40, -4.20, 4.36 ], [ 10.36, 7.70, -5.21 ], [ -9.71, -4.86, 5.05 ] ] ), - (401, [ [ -31.50, 35.20, 105.20 ], [ 15.60, -22.20, 3.00 ], [ -6.21, -10.50, 6.66 ], [ -11.72, -1.75, 3.45 ], [ -1.00, -9.14, -10.43 ], [ -13.57, -2.02, 3.99 ] ] ), - (402, [ [ -34.50, -1.20, 104.80 ], [ -10.90, -26.50, -24.40 ], [ -11.67, -5.84, 4.76 ], [ 4.66, -0.01, -4.41 ], [ -8.41, 5.84, -9.38 ], [ 5.39, -0.02, -5.10 ] ] ), - (403, [ [ -5.70, 4.10, 69.80 ], [ 22.60, 26.50, -0.50 ], [ 6.31, -12.00, -2.94 ], [ 11.49, 4.26, -3.48 ], [ -5.65, -1.98, -12.51 ], [ 13.31, 4.94, -4.03 ] ] ), - (404, [ [ -8.00, 34.90, 79.80 ], [ -9.00, 30.20, 23.80 ], [ 13.38, -0.65, -3.55 ], [ 3.58, 5.76, -0.31 ], [ -1.03, 2.91, -13.51 ], [ 4.16, 6.67, -0.35 ] ] ), - (405, [ [ -24.40, 59.80, 98.70 ], [ -18.30, 17.30, 14.10 ], [ 13.37, -0.65, -3.54 ], [ -1.58, 4.17, -0.52 ], [ 4.91, -2.07, -12.78 ], [ -1.83, 4.84, -0.61 ] ] ), - (406, [ [ -52.80, 83.20, 117.00 ], [ -19.40, 32.60, 10.00 ], [ 9.96, 8.38, -4.68 ], [ -1.64, -2.45, 7.05 ], [ -6.44, 0.93, -12.20 ], [ -1.90, -2.84, 8.18 ] ] ), - (407, [ [ -33.10, 94.80, 102.90 ], [ 22.10, -6.20, -30.40 ], [ 9.77, -3.52, 9.11 ], [ 0.95, -7.69, 3.13 ], [ -4.89, -12.92, 0.37 ], [ 1.10, -8.91, 3.63 ] ] ), - (408, [ [ -19.60, 67.80, 71.00 ], [ -12.00, 23.60, -71.10 ], [ 12.39, -5.00, -3.48 ], [ -0.41, 5.00, -8.19 ], [ -5.72, -12.24, -2.83 ], [ -0.47, 5.81, -9.51 ] ] ), - (409, [ [ -69.80, 126.80, 91.50 ], [ -61.80, 12.70, 9.10 ], [ 6.67, 11.38, -3.94 ], [ 1.21, 0.41, 0.04 ], [ 2.20, -3.82, -13.04 ], [ 1.42, 0.48, 0.04 ] ] ), - (410, [ [ -121.30, 169.50, 92.00 ], [ -11.10, 37.00, 0.00 ], [ 13.27, -0.64, -3.52 ], [ 1.04, -10.30, 0.16 ], [ -2.09, -5.25, -12.53 ], [ 1.22, -11.98, 0.19 ] ] ), - (411, [ [ -114.50, 225.50, 92.00 ], [ 69.10, 44.90, 0.00 ], [ 9.34, -9.39, -3.58 ], [ -8.87, -5.78, -0.28 ], [ 0.32, 4.48, -12.97 ], [ -10.32, -6.73, -0.33 ] ] ), - (412, [ [ -65.20, 213.40, 92.00 ], [ 33.20, -32.20, 0.00 ], [ -4.05, -12.45, -4.05 ], [ -9.41, 1.68, -1.87 ], [ 6.95, -1.10, -11.76 ], [ -10.96, 1.95, -2.18 ] ] ), - (413, [ [ -41.70, 168.20, 81.00 ], [ 8.20, -39.50, -1.80 ], [ -9.73, -6.34, -7.24 ], [ -1.36, 1.33, -1.36 ], [ 7.72, -2.55, -11.01 ], [ -1.58, 1.55, -1.59 ] ] ), - (414, [ [ -32.20, 130.30, 62.30 ], [ 24.30, -54.00, -19.60 ], [ -7.50, -8.97, -7.08 ], [ 1.34, -1.11, -0.38 ], [ 6.07, -1.01, -12.21 ], [ 1.56, -1.30, -0.45 ] ] ), - (415, [ [ 13.30, 68.90, 25.90 ], [ 74.40, 51.70, -56.50 ], [ -8.09, -6.79, -8.63 ], [ 6.57, -0.10, 0.78 ], [ -10.81, 8.18, 1.49 ], [ 7.67, -0.13, 0.90 ] ] ), - (416, [ [ -52.20, 119.90, -39.10 ], [ -64.10, -49.60, 36.30 ], [ 7.97, -9.91, -4.78 ], [ 7.36, 2.12, -1.37 ], [ 8.29, 1.02, 10.72 ], [ 8.61, 2.47, -1.62 ] ] ), - (417, [ [ 0.60, 40.90, -6.30 ], [ -35.10, -73.30, -52.20 ], [ 7.52, -3.08, -10.84 ], [ -8.63, 0.31, 2.35 ], [ 4.57, -12.15, 3.87 ], [ -10.11, 0.35, 2.75 ] ] ), - (418, [ [ -93.60, 68.70, -44.60 ], [ -75.00, 91.80, -77.60 ], [ -9.58, -9.51, 0.20 ], [ -8.60, -3.22, 5.56 ], [ -4.44, 4.58, 11.90 ], [ -10.08, -3.79, 6.52 ] ] ), - (419, [ [ -10.30, 30.20, -41.90 ], [ 25.00, -66.20, -30.80 ], [ -9.55, -9.48, 0.20 ], [ 8.19, 6.85, 5.89 ], [ -2.35, -0.51, -13.24 ], [ 9.62, 8.03, 6.92 ] ] ), - (420, [ [ -50.40, -34.50, -84.60 ], [ -46.00, 102.90, -35.50 ], [ 6.06, 3.56, 11.44 ], [ 6.94, 5.55, 5.15 ], [ 12.08, 0.28, -5.85 ], [ 8.16, 6.52, 6.07 ] ] ), - (421, [ [ -41.40, 32.40, -58.90 ], [ -91.30, 85.20, -56.10 ], [ 5.92, 2.99, 11.63 ], [ -2.72, 1.28, 0.04 ], [ 13.04, 1.06, -2.87 ], [ -3.20, 1.52, 0.06 ] ] ), - (422, [ [ -114.30, -19.20, -124.30 ], [ -81.00, 8.40, 9.10 ], [ -0.41, 6.85, 11.45 ], [ 0.59, -0.71, 0.09 ], [ -1.94, 11.52, -6.46 ], [ 0.71, -0.83, 0.13 ] ] ), - (423, [ [ -129.50, 59.30, -86.40 ], [ -83.60, 13.00, 50.80 ], [ 5.70, 2.51, 11.77 ], [ 2.54, -3.98, 0.65 ], [ -1.06, 13.11, -2.07 ], [ 3.00, -4.70, 0.79 ] ] ), - (424, [ [ -193.40, -50.20, -121.30 ], [ -158.00, 10.70, 45.10 ], [ 2.87, -0.94, 12.92 ], [ -2.63, 2.52, -0.11 ], [ 0.40, 13.23, 0.91 ], [ -3.10, 2.98, -0.11 ] ] ), - (425, [ [ -260.70, 9.90, -99.50 ], [ -72.10, -15.50, -24.10 ], [ 0.38, 5.69, 11.94 ], [ -1.24, 1.76, -0.01 ], [ 4.21, 12.01, -3.59 ], [ -1.46, 2.09, 0.01 ] ] ), - (426, [ [ -339.40, -58.30, -138.90 ], [ -98.20, 0.40, -23.00 ], [ 0.56, 1.96, 13.03 ], [ -1.75, 1.21, -0.89 ], [ 3.91, 12.54, -1.11 ], [ -2.08, 1.44, -1.04 ] ] ), - (427, [ [ -392.70, 8.10, -127.60 ], [ 58.00, 12.90, -44.30 ], [ -2.91, 7.53, 10.38 ], [ -0.09, 0.88, -0.16 ], [ 0.70, -7.63, 10.68 ], [ -0.11, 1.05, -0.17 ] ] ), - (428, [ [ -318.60, -12.70, -117.30 ], [ 82.30, 72.00, 33.30 ], [ -0.08, 4.36, 12.37 ], [ 0.82, -1.67, 0.99 ], [ 11.05, -4.97, 5.02 ], [ 0.97, -1.97, 1.19 ] ] ), - (429, [ [ -400.20, 75.30, -134.70 ], [ 185.90, 159.10, 45.20 ], [ -2.86, 5.38, 11.56 ], [ -0.07, 1.98, -1.16 ], [ 8.95, -6.98, 6.47 ], [ -0.09, 2.36, -1.36 ] ] ), - (430, [ [ -297.10, 32.20, -114.40 ], [ 170.70, 159.00, 13.00 ], [ -0.38, 8.26, 10.06 ], [ -1.28, 1.68, -1.81 ], [ 10.70, -3.35, 6.62 ], [ -1.53, 2.01, -2.14 ] ] ), - (431, [ [ -183.70, 12.90, -89.70 ], [ 13.00, 150.40, -5.30 ], [ -5.33, 8.76, 7.95 ], [ -3.94, -4.23, -0.25 ], [ 8.91, 7.45, 5.78 ], [ -4.71, -5.05, -0.28 ] ] ), - (432, [ [ -336.80, 87.50, -103.70 ], [ -17.50, 86.10, 36.10 ], [ -8.00, -1.41, 10.03 ], [ 4.82, 0.55, 1.73 ], [ 8.89, 2.44, 9.03 ], [ 5.77, 0.68, 2.09 ] ] ), - (433, [ [ -251.90, 87.50, -90.80 ], [ 85.40, -108.30, 36.10 ], [ 1.28, 5.52, 11.55 ], [ 2.95, -0.08, 1.37 ], [ -10.47, -6.21, 4.16 ], [ 3.53, -0.09, 1.66 ] ] ), - (434, [ [ -181.50, 101.00, -68.40 ], [ 88.50, -70.20, 49.50 ], [ -0.99, -0.33, 12.80 ], [ -1.06, -4.88, 0.18 ], [ -3.84, -12.21, 1.05 ], [ -1.27, -5.85, 0.23 ] ] ), - (435, [ [ -170.30, 54.60, -111.80 ], [ 73.70, -24.10, -48.10 ], [ -0.96, -4.33, 12.02 ], [ -2.34, 5.28, -2.64 ], [ -10.28, -7.63, -0.60 ], [ -2.81, 6.35, -3.16 ] ] ), - (436, [ [ -123.20, 76.70, -98.70 ], [ 73.80, 14.70, 83.70 ], [ -5.26, 8.63, 7.84 ], [ -4.11, 1.60, -5.47 ], [ -3.10, -8.59, 8.96 ], [ -4.95, 1.91, -6.57 ] ] ), - (437, [ [ -53.70, 112.30, -68.10 ], [ -112.20, 97.90, 113.50 ], [ -9.05, -8.99, 0.20 ], [ -1.90, -8.86, -3.85 ], [ 5.04, -4.93, 10.63 ], [ -2.30, -10.67, -4.63 ] ] ), - (438, [ [ -42.10, 136.80, 15.40 ], [ 139.60, -1.80, 110.30 ], [ -9.03, -8.96, 0.19 ], [ 2.10, -1.42, -0.53 ], [ 0.16, -5.68, -11.38 ], [ 2.52, -1.73, -0.64 ] ] ), - (439, [ [ 8.20, 95.10, 34.30 ], [ -24.80, -1.90, 92.70 ], [ -5.35, -11.49, -0.74 ], [ 0.32, 0.74, 3.30 ], [ 10.88, -5.37, 3.73 ], [ 0.37, 0.88, 3.99 ] ] ), - (440, [ [ 16.90, 122.10, 92.60 ], [ 26.30, 5.60, 42.10 ], [ -7.67, -8.20, 5.88 ], [ -1.66, 0.65, -1.50 ], [ 7.57, -9.56, -3.46 ], [ -2.01, 0.77, -1.81 ] ] ), - (441, [ [ 25.30, 149.50, 92.30 ], [ -11.10, 35.90, 0.00 ], [ -8.98, -8.92, 0.19 ], [ -0.75, -0.41, -3.28 ], [ 1.91, -5.55, 11.22 ], [ -0.91, -0.50, -3.96 ] ] ), - (442, [ [ -9.30, 181.40, 93.40 ], [ -17.10, 39.40, 0.00 ], [ -8.97, -8.90, 0.19 ], [ 0.35, 9.47, -2.05 ], [ 2.00, -4.14, 11.77 ], [ 0.42, 11.45, -2.48 ] ] ), - (443, [ [ -3.30, 218.30, 94.20 ], [ 39.10, 16.20, 0.00 ], [ -8.33, 8.77, -3.63 ], [ 8.92, 8.72, -0.98 ], [ -5.40, 1.69, 11.29 ], [ 10.79, 10.55, -1.19 ] ] ), - (444, [ [ 33.30, 192.20, 83.10 ], [ 42.50, -69.90, -17.10 ], [ 10.72, 6.53, -1.13 ], [ 12.06, -2.03, 2.94 ], [ 2.40, -1.80, 12.25 ], [ 14.60, -2.45, 3.56 ] ] ), - (445, [ [ 29.00, 113.80, 73.30 ], [ 13.20, -7.90, -43.20 ], [ 11.33, 4.84, 2.53 ], [ 0.73, -5.94, -0.50 ], [ 4.14, -11.41, 3.31 ], [ 0.89, -7.19, -0.61 ] ] ), - (446, [ [ 53.50, 137.40, 54.40 ], [ 22.90, 17.80, 6.30 ], [ 12.12, -3.29, -0.12 ], [ 0.39, -1.17, -2.28 ], [ 6.30, 7.07, -8.25 ], [ 0.48, -1.41, -2.77 ] ] ), - (447, [ [ 57.60, 178.10, 62.90 ], [ -9.40, 32.20, -3.10 ], [ 12.11, 2.57, -2.03 ], [ -0.01, 2.18, -0.71 ], [ -1.50, -2.38, -12.23 ], [ -0.01, 2.65, -0.87 ] ] ), - (448, [ [ 40.10, 195.20, 59.60 ], [ -3.40, 25.80, -0.90 ], [ 12.10, 2.57, -2.03 ], [ -0.01, -0.00, 0.00 ], [ -2.05, 0.34, -12.36 ], [ -0.01, 0.00, 0.00 ] ] ), - (449, [ [ 57.30, 231.00, 78.90 ], [ -15.50, 11.50, 19.40 ], [ 12.09, 2.57, -2.03 ], [ -0.01, -0.00, 0.00 ], [ 1.41, 4.39, -11.64 ], [ -0.01, 0.00, 0.00 ] ] ), - (450, [ [ 34.30, 245.80, 93.80 ], [ -46.90, 3.20, 0.00 ], [ 12.07, 2.57, -2.02 ], [ -0.01, -0.00, 0.00 ], [ 11.71, -2.83, -3.38 ], [ -0.01, 0.00, 0.00 ] ] ), - (451, [ [ 5.80, 255.40, 92.60 ], [ 2.30, 2.40, 34.80 ], [ 12.06, 2.57, -2.02 ], [ -4.14, -6.59, -1.04 ], [ -2.76, 12.07, -1.70 ], [ -5.03, -8.01, -1.27 ] ] ), - (452, [ [ 37.80, 263.40, 105.50 ], [ 25.30, 1.40, 0.00 ], [ 3.38, -11.25, -4.21 ], [ -9.58, -6.24, -0.76 ], [ 2.52, 4.36, -11.42 ], [ -11.64, -7.58, -0.92 ] ] ), - (453, [ [ 72.90, 262.00, 95.30 ], [ 27.10, -36.00, -29.30 ], [ -7.12, -9.62, -3.48 ], [ -3.75, 0.11, 0.48 ], [ -0.52, 2.46, -12.21 ], [ -4.56, 0.13, 0.57 ] ] ), - (454, [ [ 74.30, 240.00, 41.90 ], [ 65.30, -11.40, -10.10 ], [ 0.06, -11.97, -3.42 ], [ 7.15, -0.12, 0.45 ], [ 1.32, 2.88, -12.04 ], [ 8.71, -0.16, 0.54 ] ] ), - (455, [ [ 104.20, 247.50, 91.20 ], [ 23.80, 44.00, 5.50 ], [ 7.18, -9.81, -2.58 ], [ 2.79, 12.36, 2.88 ], [ -3.76, -2.77, -11.51 ], [ 3.41, 15.07, 3.51 ] ] ), - (456, [ [ 105.20, 286.30, 78.80 ], [ -59.10, 14.70, 15.40 ], [ 6.69, 10.28, 1.84 ], [ -4.20, 11.14, 0.08 ], [ 1.14, 2.57, -12.08 ], [ -5.12, 13.58, 0.10 ] ] ), - (457, [ [ 79.00, 257.00, 53.90 ], [ -35.60, -5.00, -14.30 ], [ -1.41, 12.02, -2.63 ], [ -5.03, 0.93, -0.98 ], [ 4.13, -1.99, -11.51 ], [ -6.14, 1.14, -1.19 ] ] ), - (458, [ [ 20.00, 252.70, 43.90 ], [ -73.70, -16.00, -8.60 ], [ -2.90, 12.01, 0.43 ], [ -4.01, -3.06, -0.71 ], [ 1.04, 0.70, -12.30 ], [ -4.90, -3.72, -0.87 ] ] ), - (459, [ [ -18.80, 195.30, 54.90 ], [ -24.50, -54.20, -37.40 ], [ -10.04, 5.15, -4.98 ], [ -3.78, -3.64, -2.86 ], [ 5.83, 1.93, -10.71 ], [ -4.63, -4.44, -3.50 ] ] ), - (460, [ [ -85.50, 167.30, 15.40 ], [ -18.50, -23.90, -52.20 ], [ -10.02, 5.14, -4.96 ], [ 5.22, -1.93, -3.52 ], [ 4.78, 5.04, -10.16 ], [ 6.38, -2.36, -4.33 ] ] ), - (461, [ [ -9.90, 178.40, 10.90 ], [ 70.50, -60.80, 38.30 ], [ 0.64, 1.20, -12.20 ], [ 3.58, -3.04, -3.48 ], [ 3.47, 11.76, -0.64 ], [ 4.38, -3.72, -4.28 ] ] ), - (462, [ [ 40.80, 131.00, 22.30 ], [ 93.00, 82.10, -75.60 ], [ -3.07, -0.91, -11.82 ], [ -0.17, -2.60, 0.37 ], [ -4.81, 11.24, -0.76 ], [ -0.21, -3.20, 0.44 ] ] ), - (463, [ [ 15.50, 223.00, 15.30 ], [ 66.30, 73.50, -18.10 ], [ 0.99, -4.10, -11.46 ], [ 5.85, -2.68, 3.02 ], [ -9.29, 7.17, -3.38 ], [ 7.19, -3.30, 3.69 ] ] ), - (464, [ [ 84.50, 187.60, 6.70 ], [ 63.20, -22.90, 74.10 ], [ 8.35, -6.35, -6.19 ], [ 1.95, 3.39, 0.57 ], [ 7.47, 9.60, -0.52 ], [ 2.40, 4.17, 0.68 ] ] ), - (465, [ [ 81.80, 195.00, 99.00 ], [ 85.20, -17.50, -8.30 ], [ 4.26, 3.34, -10.87 ], [ -5.95, 3.42, -2.24 ], [ 6.90, 9.29, 3.68 ], [ -7.33, 4.21, -2.77 ] ] ), - (466, [ [ 144.30, 215.80, 88.40 ], [ 56.60, 35.60, -14.80 ], [ -2.94, 2.55, -11.47 ], [ -6.00, -0.83, 0.66 ], [ -4.28, 10.83, 3.34 ], [ -7.40, -1.02, 0.80 ] ] ), - (467, [ [ 178.40, 287.40, 86.20 ], [ 6.50, 74.90, -2.80 ], [ -7.52, 1.67, -9.31 ], [ -2.09, -5.60, 3.23 ], [ -9.09, 2.44, 7.58 ], [ -2.58, -6.92, 3.98 ] ] ), - (468, [ [ 160.50, 350.90, 83.50 ], [ -55.40, 54.50, 2.60 ], [ -7.51, -7.89, -5.18 ], [ 4.12, -6.89, 3.11 ], [ -3.11, -4.19, 10.88 ], [ 5.08, -8.53, 3.83 ] ] ), - (469, [ [ 79.50, 372.50, 92.00 ], [ -94.70, -10.00, 12.80 ], [ 1.80, -11.41, -3.37 ], [ 8.18, 5.30, -0.77 ], [ 2.89, -2.97, 11.29 ], [ 10.12, 6.55, -0.96 ] ] ), - (470, [ [ 56.20, 296.40, 44.30 ], [ 5.10, -77.10, -40.60 ], [ 8.64, 4.24, -7.16 ], [ -0.89, 8.18, -2.63 ], [ 8.30, -3.68, 7.84 ], [ -1.10, 10.13, -3.27 ] ] ), - (471, [ [ 86.50, 241.90, 24.50 ], [ 53.00, -52.30, 0.20 ], [ 2.60, 7.44, -9.01 ], [ -3.05, -2.57, -2.05 ], [ 3.89, 8.81, 7.11 ], [ -3.77, -3.18, -2.56 ] ] ), - (472, [ [ 152.10, 205.80, 56.00 ], [ 63.60, -8.30, 10.00 ], [ 3.21, -2.16, -11.30 ], [ -0.12, -2.70, -1.03 ], [ 3.42, 11.35, -1.45 ], [ -0.15, -3.35, -1.29 ] ] ), - (473, [ [ 198.40, 215.10, 56.00 ], [ 38.20, 22.50, -1.40 ], [ 2.66, -0.84, -11.59 ], [ -0.74, 1.84, -0.19 ], [ -3.99, 11.03, -2.14 ], [ -0.92, 2.29, -0.25 ] ] ), - (474, [ [ 231.60, 243.60, 55.70 ], [ 23.70, 41.90, -1.20 ], [ 1.74, 1.49, -11.69 ], [ -0.06, 0.95, 0.02 ], [ -8.93, 7.83, -0.84 ], [ -0.08, 1.18, 0.02 ] ] ), - (475, [ [ 254.20, 308.60, 53.70 ], [ -36.30, 58.90, 0.00 ], [ 3.07, 0.19, -11.48 ], [ 1.44, -1.14, 0.41 ], [ -9.01, -7.25, -2.71 ], [ 1.80, -1.42, 0.49 ] ] ), - (476, [ [ 201.60, 339.10, 45.30 ], [ -53.50, 14.40, -12.40 ], [ 4.61, -0.82, -10.90 ], [ 1.75, -3.67, 9.37 ], [ -0.90, -11.83, 0.08 ], [ 2.19, -4.57, 11.67 ] ] ), - (477, [ [ 225.60, 364.90, 17.70 ], [ 84.00, -17.10, -36.30 ], [ 6.57, -7.03, 6.90 ], [ -1.74, -1.93, 11.58 ], [ 0.08, -9.62, -6.91 ], [ -2.17, -2.41, 14.45 ] ] ), - (478, [ [ 262.20, 310.80, 24.60 ], [ 19.90, -60.50, 3.10 ], [ 0.45, -3.90, 11.14 ], [ -3.49, 2.51, 2.39 ], [ -9.02, -7.61, -0.58 ], [ -4.35, 3.12, 3.00 ] ] ), - (479, [ [ 266.70, 240.60, 17.50 ], [ -54.80, -92.30, 1.00 ], [ -0.30, -2.05, 11.61 ], [ -0.74, 1.97, 0.30 ], [ -10.99, 4.18, 0.80 ], [ -0.93, 2.46, 0.39 ] ] ), - (480, [ [ 191.50, 210.20, 17.50 ], [ -54.20, -18.80, 19.40 ], [ -1.03, 0.06, 11.71 ], [ 0.91, 2.69, -0.23 ], [ -7.82, 8.71, 1.12 ], [ 1.14, 3.36, -0.27 ] ] ), - (481, [ [ 126.50, 239.40, 20.10 ], [ -85.50, -4.10, -17.80 ], [ 1.33, 3.26, 11.19 ], [ 1.41, 1.92, -0.33 ], [ 3.78, 10.85, -2.36 ], [ 1.77, 2.40, -0.39 ] ] ), - (482, [ [ 27.70, 256.90, -12.00 ], [ 25.60, 34.70, 43.20 ], [ 1.31, 3.24, 11.15 ], [ -0.00, -0.01, -0.03 ], [ 8.36, 2.10, 7.89 ], [ 0.00, -0.01, -0.02 ] ] ), - (483, [ [ 83.20, 288.30, -1.00 ], [ 33.20, -4.80, -3.70 ], [ 1.31, 3.23, 11.13 ], [ -0.00, -0.01, -0.03 ], [ -1.61, -11.04, 3.41 ], [ 0.00, -0.01, -0.02 ] ] ), - (484, [ [ 213.40, 266.00, 3.10 ], [ 68.30, 112.60, 23.20 ], [ 1.31, 3.23, 11.08 ], [ -0.00, -0.01, -0.03 ], [ 11.48, -0.96, 1.46 ], [ 0.00, -0.01, -0.02 ] ] ), - (485, [ [ 188.20, 299.90, 26.40 ], [ -48.40, -18.80, 4.40 ], [ 1.31, 3.21, 11.06 ], [ -0.00, -0.01, -0.02 ], [ -2.92, 10.90, -2.63 ], [ 0.00, -0.00, -0.01 ] ] ), - (486, [ [ 130.20, 290.80, 30.50 ], [ -44.60, 71.50, 28.90 ], [ 1.31, 3.21, 11.04 ], [ -0.01, -0.01, -0.02 ], [ 5.06, 10.37, -0.87 ], [ 0.00, -0.00, -0.01 ] ] ), - (487, [ [ 136.70, 339.40, 47.80 ], [ -100.80, 75.50, 26.60 ], [ 1.30, 3.20, 11.02 ], [ -0.01, -0.01, -0.03 ], [ 3.35, 10.74, -2.62 ], [ 0.00, -0.01, -0.02 ] ] ), - (488, [ [ 47.80, 248.50, 21.60 ], [ -98.10, 56.50, 2.30 ], [ 1.30, 3.19, 10.97 ], [ -0.00, -0.01, -0.04 ], [ 4.81, 9.88, -3.40 ], [ 0.00, -0.01, -0.02 ] ] ), - (489, [ [ 59.30, 327.60, 28.10 ], [ 34.80, 103.20, -11.30 ], [ 1.29, 3.18, 10.94 ], [ -0.00, -0.01, -0.03 ], [ 11.37, -1.46, -0.44 ], [ 0.00, -0.01, -0.02 ] ] ), - (490, [ [ 158.50, 381.30, 13.00 ], [ 145.50, -5.80, -42.40 ], [ 1.29, 3.17, 10.90 ], [ -0.01, -0.01, -0.04 ], [ -1.38, -10.74, 3.63 ], [ 0.00, -0.01, -0.03 ] ] ), - (491, [ [ 240.70, 304.70, -6.30 ], [ 49.30, -67.70, -27.10 ], [ 1.28, 3.15, 10.86 ], [ -0.01, -0.01, -0.03 ], [ -10.21, -2.59, 4.31 ], [ 0.00, -0.01, -0.02 ] ] ), - (492, [ [ 240.40, 234.90, -17.20 ], [ -74.10, -88.50, 16.10 ], [ 1.28, 3.15, 10.83 ], [ -0.00, -0.01, -0.03 ], [ -7.57, 8.36, -1.27 ], [ 0.00, -0.01, -0.02 ] ] ), - (493, [ [ 173.00, 289.90, -12.50 ], [ 56.50, 158.10, 0.10 ], [ 1.28, 3.14, 10.80 ], [ -0.00, -0.01, -0.04 ], [ 11.31, -0.44, -0.15 ], [ 0.00, -0.01, -0.02 ] ] ), - (494, [ [ 109.50, 348.10, -9.70 ], [ -74.10, -88.50, 16.10 ], [ 1.28, 3.13, 10.76 ], [ -0.01, -0.01, -0.02 ], [ -7.52, 8.31, -1.26 ], [ 0.00, -0.00, -0.01 ] ] ), - (495, [ [ 88.40, 320.90, -6.10 ], [ -71.10, -68.40, 21.40 ], [ 1.27, 3.12, 10.75 ], [ -0.01, -0.01, -0.01 ], [ -7.43, 8.34, -1.49 ], [ 0.00, -0.00, -0.01 ] ] ), - (496, [ [ 61.80, 280.20, -37.60 ], [ 69.10, -114.80, -49.00 ], [ 1.27, 3.12, 10.73 ], [ -0.00, -0.01, -0.03 ], [ -10.27, -1.14, 4.45 ], [ 0.00, -0.00, -0.02 ] ] ), - (497, [ [ 132.90, 264.70, -28.90 ], [ -44.70, -165.90, -57.30 ], [ 1.26, 3.11, 10.70 ], [ -0.00, -0.01, -0.04 ], [ -7.20, 8.23, 2.46 ], [ 0.00, -0.01, -0.02 ] ] ), - (498, [ [ 147.20, 179.70, 61.30 ], [ 91.20, -36.60, 30.40 ], [ 1.26, 3.10, 10.65 ], [ -0.01, -0.01, -0.04 ], [ -1.90, -10.20, 4.13 ], [ 0.00, -0.01, -0.02 ] ] ), - (499, [ [ 238.20, 177.20, 65.00 ], [ 18.30, -82.80, -18.10 ], [ 1.25, 3.09, 10.62 ], [ -6.46, -1.97, -8.08 ], [ -10.53, 2.18, 2.87 ], [ -8.32, -2.53, -10.38 ] ] ), - (500, [ [ 197.80, 161.40, 50.30 ], [ 67.60, 35.60, -126.70 ], [ -10.39, -0.45, -3.92 ], [ 0.94, -2.52, -10.53 ], [ -2.01, 10.32, 3.58 ], [ 1.21, -3.24, -13.56 ] ] ), - (501, [ [ 254.20, 183.80, 49.30 ], [ -11.80, 23.50, 62.10 ], [ 3.91, -1.89, -10.20 ], [ 10.29, -1.14, 3.54 ], [ 0.06, -1.92, -10.91 ], [ 13.26, -1.47, 4.56 ] ] ), - (502, [ [ 277.70, 254.80, 52.00 ], [ -1.10, 48.50, -21.40 ], [ 10.34, -2.74, 2.80 ], [ 0.61, 0.19, -0.28 ], [ 1.53, -7.63, -7.85 ], [ 0.80, 0.24, -0.38 ] ] ), - (503, [ [ 291.40, 209.50, 13.10 ], [ -39.30, -47.20, -6.60 ], [ 5.80, -1.63, -9.23 ], [ -3.43, 0.14, -6.40 ], [ 7.81, -5.38, 5.63 ], [ -4.42, 0.18, -8.27 ] ] ), - (504, [ [ 227.20, 207.90, 6.30 ], [ -93.70, -69.70, -8.90 ], [ 3.44, -2.43, -10.16 ], [ 0.12, 0.05, 0.07 ], [ 6.29, -8.07, 4.03 ], [ 0.16, 0.06, 0.08 ] ] ), - (505, [ [ 186.40, 164.40, 16.90 ], [ -71.70, -61.20, -10.00 ], [ 5.78, -1.62, -9.19 ], [ 1.27, 0.44, 0.54 ], [ 7.54, -6.04, 5.21 ], [ 1.65, 0.57, 0.68 ] ] ), - (506, [ [ 118.40, 159.70, 1.30 ], [ -74.40, 26.40, -38.50 ], [ 5.76, -1.62, -9.17 ], [ -0.02, 0.00, 0.03 ], [ -2.33, -10.70, 0.23 ], [ -0.01, 0.00, 0.02 ] ] ), - (507, [ [ 42.70, 245.00, -45.30 ], [ 77.70, 116.50, 19.30 ], [ 5.74, -1.62, -9.13 ], [ -0.03, 0.01, 0.04 ], [ -6.98, 6.28, -5.54 ], [ -0.02, 0.00, 0.03 ] ] ), - (508, [ [ 159.90, 180.50, -31.40 ], [ 106.20, 76.60, 20.20 ], [ 5.71, -1.60, -9.08 ], [ -0.03, 0.01, 0.04 ], [ -3.19, 9.46, -4.24 ], [ -0.02, 0.00, 0.03 ] ] ), - (509, [ [ 134.10, 292.30, -47.10 ], [ 34.50, 97.60, 13.80 ], [ 5.68, -1.60, -9.05 ], [ -0.02, 0.01, 0.03 ], [ -8.51, 2.98, -5.95 ], [ -0.01, 0.00, 0.02 ] ] ), - (510, [ [ 193.30, 275.10, -46.30 ], [ 23.80, -61.70, 26.10 ], [ 5.67, -1.59, -9.02 ], [ -3.56, 1.74, -0.59 ], [ 8.40, 5.13, 4.38 ], [ -4.64, 2.27, -0.79 ] ] ), - (511, [ [ 190.90, 187.00, -52.20 ], [ 66.50, -39.30, 3.60 ], [ -2.01, 2.15, -10.33 ], [ -3.82, 1.31, -0.79 ], [ 2.31, 10.47, 0.68 ], [ -5.00, 1.72, -1.05 ] ] ), - (512, [ [ 254.20, 247.30, -47.60 ], [ -23.50, 92.50, 19.80 ], [ -1.63, 0.82, -10.55 ], [ 0.99, -1.69, -0.13 ], [ -9.94, -3.80, 1.15 ], [ 1.29, -2.21, -0.20 ] ] ), - (513, [ [ 228.40, 321.30, -41.20 ], [ 52.70, 188.20, -7.70 ], [ -0.11, -1.17, -10.61 ], [ 3.62, -1.19, 0.81 ], [ -10.46, 2.15, -0.18 ], [ 4.76, -1.57, 1.05 ] ] ), - (514, [ [ 176.60, 339.50, -38.20 ], [ -78.70, 16.00, 21.50 ], [ 5.61, -1.57, -8.92 ], [ 2.47, -0.17, 0.74 ], [ 6.18, -8.52, -1.64 ], [ 3.25, -0.23, 0.96 ] ] ), - (515, [ [ 119.00, 367.30, -29.70 ], [ -127.00, 18.70, 4.70 ], [ 5.59, -1.57, -8.90 ], [ -0.02, 0.00, 0.03 ], [ 4.78, -9.48, 0.52 ], [ -0.01, 0.00, 0.02 ] ] ), - (516, [ [ 91.40, 252.30, -63.20 ], [ 23.10, -112.20, 118.60 ], [ 5.57, -1.57, -8.86 ], [ -0.03, 0.01, 0.04 ], [ 6.52, 8.32, 0.32 ], [ -0.02, 0.00, 0.03 ] ] ), - (517, [ [ 175.10, 162.40, -53.90 ], [ -54.80, -66.80, 32.70 ], [ 5.54, -1.56, -8.82 ], [ -0.03, 0.01, 0.04 ], [ 10.06, 0.55, 3.06 ], [ -0.02, 0.00, 0.03 ] ] ), - (518, [ [ 70.80, 203.50, -65.80 ], [ -102.40, -41.90, -13.50 ], [ 5.52, -1.55, -8.78 ], [ -0.02, 0.01, 0.03 ], [ 6.25, -7.45, 3.92 ], [ -0.01, 0.00, 0.02 ] ] ), - (519, [ [ 52.30, 140.20, -39.60 ], [ -180.50, -24.10, 75.00 ], [ 5.51, -1.54, -8.75 ], [ -0.01, 0.01, 0.02 ], [ 9.17, -4.92, -1.03 ], [ -0.01, 0.00, 0.01 ] ] ), - (520, [ [ 6.80, 106.50, -47.40 ], [ -171.30, 31.80, -4.10 ], [ 5.49, -1.54, -8.74 ], [ -0.02, 0.00, 0.02 ], [ 3.75, -9.72, 0.64 ], [ -0.01, 0.00, 0.02 ] ] ), - (521, [ [ 27.90, 191.60, -30.80 ], [ -96.90, 52.70, -49.30 ], [ 5.48, -1.54, -8.71 ], [ -0.02, 0.00, 0.03 ], [ -3.21, -9.88, -0.54 ], [ -0.01, 0.00, 0.02 ] ] ), - (522, [ [ -17.90, 115.60, -73.10 ], [ -104.10, 42.30, 14.10 ], [ 5.45, -1.54, -8.67 ], [ -0.02, 0.01, 0.04 ], [ 3.08, -9.78, -1.45 ], [ -0.01, 0.00, 0.02 ] ] ), - (523, [ [ 1.90, 223.30, -37.40 ], [ 44.00, 82.00, -9.10 ], [ 5.43, -1.53, -8.63 ], [ -0.02, 0.01, 0.03 ], [ -6.75, 5.34, -5.68 ], [ -0.01, 0.00, 0.02 ] ] ), - (524, [ [ 33.20, 282.60, -58.50 ], [ -23.00, 67.10, -26.70 ], [ 5.41, -1.52, -8.61 ], [ 0.79, 3.52, 4.91 ], [ -8.17, -4.48, -4.35 ], [ 1.08, 4.71, 6.57 ] ] ), - (525, [ [ 67.80, 358.20, -24.30 ], [ -2.30, 0.30, 54.60 ], [ 7.28, 6.66, 2.78 ], [ 1.46, 2.72, 1.91 ], [ -6.74, 7.41, 2.19 ], [ 1.97, 3.65, 2.54 ] ] ), - (526, [ [ 40.70, 358.70, 43.40 ], [ -22.60, 47.20, 59.80 ], [ 8.42, 5.16, -2.63 ], [ -2.81, 1.16, 1.68 ], [ -5.07, 4.81, -7.46 ], [ -3.76, 1.57, 2.26 ] ] ), - (527, [ [ 29.20, 413.00, 41.50 ], [ -60.50, 10.90, 19.00 ], [ 2.27, 8.57, 5.05 ], [ -2.85, 2.07, 3.48 ], [ -2.44, 5.56, -8.20 ], [ -3.83, 2.79, 4.68 ] ] ), - (528, [ [ -26.50, 361.80, 43.10 ], [ -56.30, 17.20, 1.60 ], [ 3.56, 8.95, 3.27 ], [ 2.65, -1.03, -4.10 ], [ 1.38, 3.02, -9.62 ], [ 3.58, -1.38, -5.52 ] ] ), - (529, [ [ -23.40, 393.00, 43.00 ], [ -7.70, 31.40, -0.90 ], [ 6.85, 7.25, -1.93 ], [ -0.97, 0.74, -1.25 ], [ -2.97, 4.65, -8.53 ], [ -1.31, 1.01, -1.68 ] ] ), - (530, [ [ -36.60, 415.60, 41.80 ], [ -25.50, 17.70, 1.00 ], [ 2.83, 9.74, -0.36 ], [ -4.02, 1.55, 1.19 ], [ -3.16, 1.63, -9.51 ], [ -5.42, 2.09, 1.60 ] ] ), - (531, [ [ -70.00, 421.50, 45.40 ], [ -30.80, -9.50, 1.40 ], [ -1.19, 10.06, 0.33 ], [ -5.91, -4.42, 2.80 ], [ 1.19, 0.79, -10.03 ], [ -7.98, -5.96, 3.78 ] ] ), - (532, [ [ -90.30, 401.60, 44.50 ], [ -15.10, -33.40, -0.70 ], [ -8.70, 1.66, 4.91 ], [ -2.95, -8.68, 2.68 ], [ -5.26, 0.39, -8.65 ], [ -3.98, -11.72, 3.63 ] ] ), - (533, [ [ -91.80, 361.20, 44.50 ], [ 35.10, -38.10, -18.40 ], [ -4.90, -7.44, 4.78 ], [ 6.01, -6.11, -1.81 ], [ -5.53, -1.71, -8.29 ], [ 8.12, -8.26, -2.44 ] ] ), - (534, [ [ -38.80, 367.10, 17.80 ], [ 33.30, 56.60, -27.60 ], [ 4.46, -9.04, 0.44 ], [ 6.11, 6.76, -2.78 ], [ -5.61, -6.12, -5.73 ], [ 8.27, 9.14, -3.76 ] ] ), - (535, [ [ -55.20, 436.50, 11.50 ], [ -50.10, 54.50, -0.10 ], [ 6.83, 7.37, -0.54 ], [ 0.24, 8.59, -0.86 ], [ -0.93, 0.22, -10.01 ], [ 0.34, 11.63, -1.17 ] ] ), - (536, [ [ -121.40, 460.30, 17.10 ], [ -86.80, 60.90, -1.80 ], [ 5.06, 8.57, -1.28 ], [ 0.90, -2.49, -1.08 ], [ -1.24, -0.68, -9.93 ], [ 1.24, -3.38, -1.46 ] ] ), - (537, [ [ -164.50, 536.10, -17.30 ], [ -9.90, 55.20, -8.50 ], [ 9.53, 1.13, -2.81 ], [ 8.03, -12.39, -1.98 ], [ -2.54, -2.06, -9.45 ], [ 10.93, -16.81, -2.68 ] ] ) ] ), - 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-17', + 'identifierRanges': '1-150', + 'name': get_smallintestine_term('small intestine')[0], + 'ontId': get_smallintestine_term('small intestine')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-5', 'name': get_smallintestine_term('duodenum')[0], 'ontId': get_smallintestine_term('duodenum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '18-235', + 'identifierRanges': '6-82', 'name': get_smallintestine_term('jejunum')[0], 'ontId': get_smallintestine_term('jejunum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '236-536', + 'identifierRanges': '83-150', 'name': get_smallintestine_term('ileum')[0], 'ontId': get_smallintestine_term('ileum')[1] }] - }), - 'Human 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif "Cattle 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Coordinate dimensions': 3, - 'Length': 1.0, - 'Number of elements': 150 + "Structure": "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-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-76-77-78-79-80-81-82-83-84-85-86-87-88-89-90-" + "91-92-93-94-95-96-97-98-99-100-101-102-103-104-105-106-107-108-109-110-111-112-113-114-" + "115-116-117-118-119-120-121-122-123-124-125-126-127-128-129-130-131-132-133-134-135-136-" + "137-138-139-140-141-142-143-144-145-146-147-148-149-150-151-152-153-154-155-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-182-183-184-185-186-187-188-189-190-191-192-193-194-195-196-197-198-199-200-201-202-" + "203-204-205-206-207-208-209-210-211-212-213-214-215-216-217-218-219-220-221-222-223-224-" + "225-226-227-228-229-230-231-232-233-234-235-236-237-238-239-240-241-242-243-244-245-246-" + "247-248-249-250-251-252-253-254-255-256-257-258-259-260-261-262-263-264-265-266-267-268-" + "269-270-271-272-273-274-275-276-277-278-279-280-281-282-283-284-285-286-287-288-289-290-" + "291-292-293-294-295-296-297-298-299-300-301-302-303-304-305-306-307-308-309-310-311-312-" + "313-314-315-316-317-318-319-320-321-322-323-324-325-326-327-328-329-330-331-332-333-334-" + "335-336-337-338-339-340-341-342-343-344-345-346-347-348-349-350-351-352-353-354-355-356-" + "357-358-359-360-361-362-363-364-365-366-367-368-369-370-371-372-373-374-375-376-377-378-" + "379-380-381-382-383-384-385-386-387-388-389-390-391-392-393-394-395-396-397-398-399-400-" + "401-402-403-404-405-406-407-408-409-410-411-412-413-414-415-416-417-418-419-420-421-422-" + "423-424-425-426-427-428-429-430-431-432-433-434-435-436-437-438-439-440-441-442-443-444-" + "445-446-447-448-449-450-451-452-453-454-455-456-457-458-459-460-461-462-463-464-465-466-" + "467-468-469-470-471-472-473-474-475-476-477-478-479-480-481-482-483-484-485-486-487-488-" + "489-490-491-492-493-494-495-496-497-498-499-500-501-502-503-504-505-506-507-508-509-510-" + "511-512-513-514-515-516-517-518-519-520-521-522-523-524-525-526-527-528-529-530-531-532-" + "533-534-535-536-537" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( - [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ - (1, [ [ -40.03, -124.48, 1057.88 ], [ -9.88, 12.23, -4.08 ], [ -4.33, -5.88, -7.13 ], [ 2.36, -0.32, 0.12 ], [ -3.77, -1.79, 3.76 ], [ -0.25, 2.08, -4.50] ] ), - (2, [ [ -49.64, -111.67, 1050.88 ], [ -6.84, 19.44, -21.94 ], [ -1.59, -6.21, -5.00 ], [ 0.90, 0.69, 1.57 ], [ -6.92, 0.02, 2.18 ], [ -0.76, 2.95, -2.23] ] ), - (3, [ [ -43.45, -95.70, 1015.59 ], [ 40.73, 3.22, -44.80 ], [ -4.94, -3.15, -4.71 ], [ -0.38, 4.38, -0.33 ], [ -2.12, 5.61, -1.53 ], [ 4.59, 3.49, -0.79] ] ), - (4, [ [ 26.76, -119.31, 992.03 ], [ 58.86, -18.68, -8.45 ], [ 0.29, 3.71, -6.21 ], [ 4.15, 2.33, 1.07 ], [ 2.08, 5.13, 3.16 ], [ 3.36, -4.08, 2.37] ] ), - (5, [ [ 68.06, -131.66, 993.83 ], [ 9.68, -30.91, -18.90 ], [ 3.82, 3.44, -3.68 ], [ -0.33, -6.20, 3.78 ], [ 4.96, -1.02, 4.20 ], [ -3.68, -1.57, 1.51] ] ), - (6, [ [ 46.28, -139.94, 982.68 ], [ -22.68, -4.85, -10.94 ], [ 0.98, -6.62, 0.91 ], [ -0.93, -3.80, 3.22 ], [ -2.99, 0.39, 6.02 ], [ -5.34, -0.64, -2.85] ] ), - (7, [ [ 28.56, -141.07, 974.61 ], [ 3.75, -10.52, -21.30 ], [ 1.46, -5.82, 3.13 ], [ -1.00, 0.06, -0.07 ], [ -6.42, -1.75, -0.27 ], [ 1.10, -0.53, -6.40] ] ), - (8, [ [ 52.39, -146.13, 971.40 ], [ 18.40, -3.70, 0.67 ], [ -1.35, -6.67, 0.28 ], [ -0.59, -0.29, -0.54 ], [ 0.18, -0.32, -6.80 ], [ 2.42, 0.06, -1.89] ] ), - (9, [ [ 63.13, -148.18, 973.52 ], [ 10.49, -1.41, 1.47 ], [ -1.00, -6.72, 0.72 ], [ 2.41, 0.38, 0.12 ], [ 0.83, -0.84, -6.72 ], [ -2.03, -1.10, 0.84] ] ), - (10, [ [ 72.69, -148.91, 974.30 ], [ 7.65, 3.57, -7.08 ], [ 3.28, -5.95, 0.54 ], [ 0.43, 0.20, -1.42 ], [ -3.64, -2.47, -5.18 ], [ -3.49, 0.08, 4.65] ] ), - (11, [ [ 71.05, -143.65, 964.65 ], [ -5.96, 4.70, -11.04 ], [ -0.76, -6.41, -2.32 ], [ -2.36, -0.38, -1.14 ], [ -6.00, -0.40, 3.07 ], [ 0.27, 0.95, 6.07] ] ), - (12, [ [ 61.06, -140.78, 954.52 ], [ -17.96, 3.88, -6.22 ], [ -1.00, -6.68, -1.29 ], [ 0.18, -0.25, 1.37 ], [ -2.40, -0.88, 6.38 ], [ 3.84, 0.27, 2.13] ] ), - (13, [ [ 37.99, -136.93, 957.17 ], [ -18.82, 0.88, 5.08 ], [ -0.15, -6.89, 0.63 ], [ 1.90, 0.17, 0.59 ], [ 1.82, 0.57, 6.64 ], [ 2.12, 1.03, -0.12] ] ), - (14, [ [ 24.26, -138.06, 963.16 ], [ -17.40, -6.04, 8.51 ], [ 2.43, -6.48, 0.36 ], [ 2.42, 1.01, 0.69 ], [ 2.61, 1.33, 6.28 ], [ -2.18, -0.67, -0.74] ] ), - (15, [ [ 6.50, -150.31, 973.05 ], [ -8.25, -16.44, -13.42 ], [ 4.59, -4.46, 2.65 ], [ -1.08, -0.49, -0.28 ], [ -4.53, -1.74, 4.92 ], [ -4.27, -0.82, -2.18] ] ), - (16, [ [ 15.97, -149.80, 957.69 ], [ -4.35, -1.25, -14.05 ], [ 0.93, -6.94, 0.33 ], [ -1.04, -0.78, -0.85 ], [ -6.52, -0.78, 2.09 ], [ -0.48, 0.19, -0.50] ] ), - (17, [ [ 8.29, -150.98, 954.25 ], [ -3.34, -0.73, -8.15 ], [ 1.11, -6.93, 0.17 ], [ 0.18, 0.05, 0.37 ], [ -6.30, -0.94, 2.67 ], [ 0.56, -0.43, -3.27] ] ), - (18, [ [ 10.77, -150.88, 946.76 ], [ 5.27, -0.05, -7.15 ], [ 1.29, -6.84, 1.00 ], [ -0.12, -0.03, 0.05 ], [ -5.45, -1.61, -4.01 ], [ 2.05, 0.22, -4.83] ] ), - (19, [ [ 18.30, -151.09, 941.26 ], [ 7.79, 0.88, -2.39 ], [ 0.83, -7.00, 0.15 ], [ 0.05, -0.01, -0.90 ], [ -2.02, -0.38, -6.73 ], [ 4.52, 1.49, -0.77] ] ), - (20, [ [ 24.85, -149.58, 941.59 ], [ 5.32, 0.62, 3.02 ], [ 1.25, -6.91, -0.79 ], [ -0.35, 0.01, -0.65 ], [ 3.30, 1.29, -6.07 ], [ 3.43, 0.58, 1.19] ] ), - (21, [ [ 27.85, -149.81, 945.92 ], [ 3.49, -0.55, 3.99 ], [ 0.31, -6.95, -1.22 ], [ -0.75, -0.04, -0.15 ], [ 5.27, 1.02, -4.47 ], [ -0.58, -0.16, -0.31] ] ), - (22, [ [ 31.64, -150.64, 949.37 ], [ 5.77, -0.50, 1.81 ], [ -0.26, -6.99, -1.09 ], [ 0.32, -0.01, 0.32 ], [ 2.17, 0.96, -6.66 ], [ -4.59, -0.60, -0.74] ] ), - (23, [ [ 38.16, -150.55, 948.48 ], [ 5.40, 1.27, -4.34 ], [ 1.20, -6.96, -0.53 ], [ 1.28, 0.32, -0.53 ], [ -4.35, -0.33, -5.52 ], [ -4.44, -1.61, 3.12] ] ), - (24, [ [ 40.30, -148.53, 942.17 ], [ -0.50, 2.45, -7.55 ], [ 2.28, -6.33, -2.21 ], [ 1.39, 0.82, -0.98 ], [ -6.59, -2.27, -0.30 ], [ -0.57, -0.95, 1.02] ] ), - (25, [ [ 36.76, -146.19, 935.09 ], [ 3.27, 5.38, -6.44 ], [ 4.06, -5.28, -2.35 ], [ 0.26, -0.08, 1.07 ], [ -5.17, -2.04, -4.32 ], [ 3.60, 1.24, -3.41] ] ), - (26, [ [ 44.60, -142.08, 934.77 ], [ 8.65, 3.53, 1.10 ], [ 2.68, -6.58, 0.02 ], [ -1.02, -0.77, 1.00 ], [ 0.78, 0.29, -7.08 ], [ 3.41, 1.45, -1.30] ] ), - (27, [ [ 53.34, -139.44, 937.21 ], [ 8.31, 2.34, 2.22 ], [ 2.02, -6.82, -0.36 ], [ -0.54, -0.17, -0.42 ], [ 1.61, 0.84, -6.90 ], [ 0.07, 0.37, 0.03] ] ), - (28, [ [ 61.18, -137.39, 939.22 ], [ 8.23, 1.72, 1.43 ], [ 1.59, -6.92, -0.81 ], [ -0.38, -0.10, -0.17 ], [ 1.00, 1.05, -7.00 ], [ -0.84, -0.07, -0.12] ] ), - (29, [ [ 69.72, -136.03, 940.04 ], [ 8.42, 1.51, 0.05 ], [ 1.27, -7.02, -0.70 ], [ 0.30, 0.21, -0.63 ], [ -0.08, 0.70, -7.13 ], [ -3.56, -0.97, 1.73] ] ), - (30, [ [ 77.28, -134.50, 939.34 ], [ 4.49, 4.18, -8.53 ], [ 2.17, -6.51, -2.05 ], [ -0.29, 0.07, -0.48 ], [ -6.03, -0.87, -3.60 ], [ -3.19, -0.95, 5.53] ] ), - (31, [ [ 71.89, -131.27, 929.11 ], [ -6.78, 1.09, -6.79 ], [ 0.08, -7.09, -1.22 ], [ -0.44, -0.26, 1.25 ], [ -5.09, -0.91, 4.94 ], [ 0.24, 0.45, 2.90] ] ), - (32, [ [ 66.11, -131.60, 925.90 ], [ -4.09, -0.45, -4.44 ], [ 0.51, -7.19, 0.26 ], [ 0.08, 0.05, 1.40 ], [ -5.23, -0.20, 4.83 ], [ -0.15, 0.88, -0.16] ] ), - (33, [ [ 63.93, -132.09, 921.07 ], [ -3.93, -1.16, -4.37 ], [ 0.30, -7.03, 1.60 ], [ 0.72, 0.30, 0.95 ], [ -5.38, 0.82, 4.63 ], [ 0.66, 0.51, 0.56] ] ), - (34, [ [ 58.47, -133.89, 917.96 ], [ -6.67, -3.36, -3.67 ], [ 2.16, -6.56, 2.08 ], [ 2.28, 0.92, -0.11 ], [ -3.73, 0.71, 6.12 ], [ 2.25, 0.03, 1.31] ] ), - (35, [ [ 51.02, -139.09, 914.02 ], [ -6.63, -6.74, 0.39 ], [ 5.08, -4.94, 1.06 ], [ 1.07, 0.42, -1.32 ], [ -0.56, 0.96, 7.15 ], [ 3.12, 0.37, 0.20] ] ), - (36, [ [ 46.77, -145.49, 918.12 ], [ -5.05, -4.37, 2.87 ], [ 4.53, -5.57, -0.52 ], [ -1.31, -0.89, -0.94 ], [ 2.52, 1.43, 6.62 ], [ 1.26, -0.68, -0.12] ] ), - (37, [ [ 41.95, -147.92, 919.78 ], [ -5.03, -2.38, 1.94 ], [ 2.73, -6.62, -1.04 ], [ -1.32, -0.68, -0.33 ], [ 2.61, 0.01, 6.76 ], [ -0.11, -1.00, 0.12] ] ), - (38, [ [ 36.76, -150.21, 922.00 ], [ -5.10, -1.68, 1.58 ], [ 1.91, -6.90, -1.17 ], [ -0.51, -0.22, 0.81 ], [ 2.30, -0.53, 6.87 ], [ -0.45, 0.50, 0.13] ] ), - (39, [ [ 31.89, -151.33, 922.99 ], [ -5.71, -1.25, 1.56 ], [ 1.67, -7.06, 0.43 ], [ -0.57, -0.18, 0.73 ], [ 1.73, 0.83, 7.02 ], [ -2.05, 0.33, 0.03] ] ), - (40, [ [ 25.55, -152.65, 925.18 ], [ -6.28, -0.56, -2.17 ], [ 0.66, -7.26, -0.03 ], [ -0.69, -0.09, -0.62 ], [ -2.35, -0.24, 6.88 ], [ -3.19, -0.78, -0.83] ] ), - (41, [ [ 22.17, -152.27, 920.06 ], [ -4.85, 0.30, -4.20 ], [ 0.25, -7.25, -0.80 ], [ -0.24, -0.02, 0.24 ], [ -4.73, -0.76, 5.42 ], [ 2.41, 0.37, -0.06] ] ), - (42, [ [ 16.60, -152.11, 917.51 ], [ -6.97, 0.00, 2.68 ], [ 0.19, -7.29, 0.48 ], [ -0.30, -0.03, 0.60 ], [ 2.61, 0.51, 6.79 ], [ 5.78, 0.37, -0.74] ] ), - (43, [ [ 13.12, -152.32, 924.90 ], [ -3.73, 0.41, 7.15 ], [ -0.42, -7.30, 0.20 ], [ -0.14, -0.02, -0.16 ], [ 6.38, -0.28, 3.34 ], [ -0.23, -0.18, 0.20] ] ), - (44, [ [ 9.44, -151.37, 931.31 ], [ -7.88, 0.19, 2.81 ], [ -0.12, -7.33, 0.16 ], [ 0.49, -0.01, 0.12 ], [ 2.46, 0.11, 6.89 ], [ -3.70, 0.33, 2.08] ] ), - (45, [ [ 1.23, -152.17, 928.31 ], [ -8.13, -0.72, -1.08 ], [ 0.58, -7.31, 0.46 ], [ 0.09, -0.01, -0.29 ], [ -1.00, 0.38, 7.26 ], [ 1.43, -0.16, -0.65] ] ), - (46, [ [ -5.97, -152.74, 928.93 ], [ -5.64, -0.31, 4.39 ], [ 0.16, -7.35, -0.31 ], [ -0.93, 0.04, 0.09 ], [ 4.48, -0.15, 5.76 ], [ 3.98, -0.84, -4.11] ] ), - (47, [ [ -8.05, -152.70, 935.12 ], [ 0.84, 0.43, 7.28 ], [ -1.23, -7.23, 0.57 ], [ -1.08, 0.17, 0.74 ], [ 7.08, -1.26, -0.74 ], [ 0.79, -0.43, -1.11] ] ), - (48, [ [ -4.18, -151.98, 940.93 ], [ -5.50, 2.85, 8.02 ], [ -1.95, -7.01, 1.15 ], [ -0.37, 0.07, -0.10 ], [ 5.81, -0.90, 4.30 ], [ -3.01, 0.56, 4.29] ] ), - (49, [ [ -15.92, -150.23, 939.85 ], [ -11.53, 2.83, 0.08 ], [ -1.76, -7.18, -0.02 ], [ 0.12, 0.15, 0.78 ], [ 0.04, -0.03, 7.39 ], [ 0.81, 0.00, -1.16] ] ), - (50, [ [ -25.87, -146.77, 940.97 ], [ -2.69, 4.15, 9.23 ], [ -1.70, -6.74, 2.54 ], [ 0.69, 0.20, 1.48 ], [ 6.83, -0.83, 2.36 ], [ 1.72, -1.41, -6.49] ] ), - (51, [ [ -19.43, -146.58, 946.99 ], [ 7.70, 1.83, 5.13 ], [ -0.46, -6.73, 3.10 ], [ 1.24, -0.13, -0.09 ], [ 4.24, -2.77, -5.37 ], [ -0.59, -0.04, -3.45] ] ), - (52, [ [ -11.61, -143.43, 950.54 ], [ 5.25, 2.52, 5.68 ], [ 0.78, -7.00, 2.38 ], [ 0.75, -0.24, -0.87 ], [ 5.57, -0.98, -4.71 ], [ 0.83, 1.41, 0.57] ] ), - (53, [ [ -9.22, -141.82, 956.88 ], [ 3.60, 1.58, 5.20 ], [ 1.15, -7.22, 1.40 ], [ -0.05, -0.13, -0.42 ], [ 6.02, 0.14, -4.21 ], [ 0.12, 0.28, 0.10] ] ), - (54, [ [ -4.88, -140.39, 960.70 ], [ 3.78, 1.36, 4.90 ], [ 0.74, -7.28, 1.45 ], [ 0.07, -0.06, -0.65 ], [ 5.87, -0.29, -4.45 ], [ 0.53, 0.53, 1.66] ] ), - (55, [ [ -1.98, -139.20, 966.47 ], [ 0.65, 0.13, 7.29 ], [ 1.34, -7.34, 0.01 ], [ 0.23, -0.06, -0.88 ], [ 7.17, 1.31, -0.66 ], [ 0.66, 0.74, 3.14] ] ), - (56, [ [ -4.15, -140.36, 973.96 ], [ -2.38, -0.65, 10.17 ], [ 1.12, -7.39, -0.21 ], [ -0.65, -0.07, -0.20 ], [ 7.07, 1.03, 1.72 ], [ -0.21, -0.70, 2.00] ] ), - (57, [ [ -6.44, -140.06, 986.68 ], [ -4.21, -0.33, 9.07 ], [ -0.23, -7.49, -0.38 ], [ -0.77, 0.02, -0.44 ], [ 6.68, -0.36, 3.09 ], [ -1.82, -1.02, 2.46] ] ), - (58, [ [ -10.86, -140.67, 991.98 ], [ -5.80, 0.04, 3.85 ], [ -0.69, -7.41, -0.97 ], [ 0.04, -0.00, -0.15 ], [ 4.08, -1.18, 6.14 ], [ -3.51, -0.15, 2.18] ] ), - (59, [ [ -17.28, -140.01, 993.95 ], [ -7.30, 0.18, -0.28 ], [ -0.16, -7.49, -0.69 ], [ 0.59, -0.04, 0.75 ], [ -0.30, -0.68, 7.48 ], [ -4.07, 0.69, 0.16] ] ), - (60, [ [ -24.40, -140.40, 991.18 ], [ -6.25, -0.73, -3.97 ], [ 0.50, -7.49, 0.59 ], [ -0.08, 0.16, 1.48 ], [ -4.03, 0.23, 6.31 ], [ -3.14, 0.95, -2.22] ] ), - (61, [ [ -29.47, -141.40, 986.35 ], [ -2.47, -1.37, -4.69 ], [ -0.26, -7.19, 2.25 ], [ -1.43, 0.31, 0.61 ], [ -6.62, 1.22, 3.13 ], [ -0.94, 0.18, -5.15] ] ), - (62, [ [ -29.90, -142.61, 982.98 ], [ 1.86, -2.14, -4.74 ], [ -2.05, -6.88, 2.30 ], [ -1.16, 0.11, -0.29 ], [ -6.69, 0.97, -3.06 ], [ 0.49, -0.35, -4.87] ] ), - (63, [ [ -24.82, -145.19, 978.58 ], [ 4.65, -2.18, -4.59 ], [ -2.01, -7.15, 1.36 ], [ 0.29, -0.26, -0.91 ], [ -5.15, 0.42, -5.42 ], [ -0.33, 0.23, 1.00] ] ), - (64, [ [ -20.75, -146.91, 974.01 ], [ 1.23, -0.70, -6.94 ], [ -1.49, -7.40, 0.48 ], [ 0.08, -0.09, -0.69 ], [ -7.16, 1.35, -1.40 ], [ 0.46, 0.35, 5.77] ] ), - (65, [ [ -23.39, -146.10, 967.33 ], [ -6.32, 1.65, -4.01 ], [ -1.92, -7.32, 0.01 ], [ -0.16, 0.07, 0.36 ], [ -3.81, 1.01, 6.42 ], [ 4.83, -0.40, 4.28] ] ), - (66, [ [ -30.60, -144.33, 967.78 ], [ -6.69, 2.04, 2.19 ], [ -1.82, -7.26, 1.20 ], [ 0.05, 0.00, 0.44 ], [ 2.50, 0.55, 7.13 ], [ 3.03, -0.35, 0.34] ] ), - (67, [ [ -36.17, -142.25, 971.34 ], [ -6.59, 1.94, 2.27 ], [ -1.83, -7.30, 0.95 ], [ 0.04, -0.01, 0.09 ], [ 2.55, 0.29, 7.14 ], [ 0.37, -0.02, -0.15] ] ), - (68, [ [ -43.40, -140.59, 972.07 ], [ -6.04, 1.97, 2.74 ], [ -1.73, -7.28, 1.40 ], [ 0.02, 0.34, 1.18 ], [ 3.28, 0.53, 6.83 ], [ 2.30, -0.41, -2.27] ] ), - (69, [ [ -47.62, -138.63, 976.14 ], [ -1.78, 2.68, 4.62 ], [ -1.77, -6.68, 3.20 ], [ 0.01, 0.35, 0.98 ], [ 6.89, -0.43, 2.91 ], [ 1.72, -1.44, -3.71] ] ), - (70, [ [ -47.10, -135.98, 980.16 ], [ 0.98, 1.95, 4.05 ], [ -1.73, -6.52, 3.55 ], [ 0.21, -0.14, -0.20 ], [ 7.12, -2.24, -0.64 ], [ 0.04, -0.76, -2.21] ] ), - (71, [ [ -45.78, -134.75, 984.02 ], [ 1.92, 1.94, 5.58 ], [ -1.38, -6.93, 2.88 ], [ -0.53, 0.37, 0.09 ], [ 7.01, -2.09, -1.69 ], [ -0.24, 0.26, 1.07] ] ), - (72, [ [ -43.37, -132.13, 990.97 ], [ -1.92, 7.78, 7.36 ], [ -3.57, -5.07, 4.43 ], [ -2.14, 1.26, -0.06 ], [ 6.52, -1.62, 3.41 ], [ -3.47, 2.54, 4.15] ] ), - (73, [ [ -50.92, -122.17, 992.94 ], [ -8.28, 6.98, -7.76 ], [ -5.63, -4.80, 1.69 ], [ 0.61, -1.11, -1.84 ], [ -1.92, 4.37, 5.99 ], [ -6.54, 1.98, -0.43] ] ), - (74, [ [ -54.52, -122.57, 980.90 ], [ -5.10, 0.46, -13.05 ], [ -2.46, -7.24, 0.71 ], [ 2.85, -1.09, 0.85 ], [ -6.63, 2.51, 2.68 ], [ -2.86, -1.79, -2.31] ] ), - (75, [ [ -60.93, -121.16, 967.78 ], [ -3.40, -6.95, -12.83 ], [ 0.01, -6.78, 3.67 ], [ -1.69, 1.75, 1.25 ], [ -7.36, 0.81, 1.51 ], [ 1.21, -0.70, -4.51] ] ), - (76, [ [ -59.94, -133.62, 960.46 ], [ 4.44, -11.12, -4.92 ], [ -5.83, -3.75, 3.22 ], [ -1.80, 0.34, -0.38 ], [ -4.21, 1.12, -6.33 ], [ 1.72, -0.86, -3.60] ] ), - (77, [ [ -53.65, -142.09, 958.04 ], [ 8.15, -8.95, -3.45 ], [ -4.68, -5.37, 2.89 ], [ 2.04, -1.62, -0.11 ], [ -3.54, -0.59, -6.83 ], [ -0.92, -0.86, 0.97] ] ), - (78, [ [ -43.78, -150.90, 953.55 ], [ 6.86, -6.21, -10.82 ], [ -1.48, -6.98, 3.06 ], [ 0.10, -0.47, -1.48 ], [ -6.55, -0.34, -3.95 ], [ -0.50, 1.88, 6.12] ] ), - (79, [ [ -42.79, -151.92, 940.92 ], [ -10.16, 7.35, -12.87 ], [ -4.48, -6.31, -0.07 ], [ -1.78, 0.37, -1.94 ], [ -4.55, 3.17, 5.40 ], [ 1.37, 1.93, 5.90] ] ), - (80, [ [ -59.56, -139.32, 940.87 ], [ -10.47, 7.53, -10.55 ], [ -4.41, -6.40, -0.20 ], [ -0.78, 0.74, 0.77 ], [ -4.15, 2.67, 6.02 ], [ -0.63, 1.74, -4.22] ] ), - (81, [ [ -61.19, -138.43, 930.23 ], [ -0.37, -2.04, -12.19 ], [ -5.64, -5.22, 1.05 ], [ -0.86, 0.96, 0.96 ], [ -5.33, 5.60, -0.78 ], [ 0.65, -0.72, -6.69] ] ), - (82, [ [ -60.05, -143.37, 918.84 ], [ 6.12, -9.41, -3.11 ], [ -6.09, -4.52, 1.69 ], [ 0.25, -0.37, -0.76 ], [ -2.60, 0.74, -7.36 ], [ 3.39, -3.10, -3.06] ] ), - (83, [ [ -54.81, -148.97, 924.54 ], [ 7.07, -6.60, 2.05 ], [ -5.30, -5.72, -0.16 ], [ 0.76, -0.86, -0.33 ], [ 1.31, -0.99, -7.69 ], [ -1.61, 1.40, 1.58] ] ), - (84, [ [ -48.00, -154.67, 922.57 ], [ 3.54, -3.72, -7.48 ], [ -4.57, -6.25, 0.95 ], [ 1.21, -0.76, -0.14 ], [ -5.53, 3.38, -4.30 ], [ -4.06, 1.81, 3.83] ] ), - (85, [ [ -49.39, -154.51, 914.46 ], [ 0.27, 0.35, -10.67 ], [ -2.94, -7.22, -0.31 ], [ 1.86, -0.79, -0.48 ], [ -7.12, 2.90, -0.09 ], [ 1.64, -1.57, -0.54] ] ), - (86, [ [ -46.73, -154.01, 904.00 ], [ 18.99, -1.89, -1.48 ], [ -0.74, -7.74, 0.38 ], [ 1.31, -0.30, 0.50 ], [ -0.63, -0.32, -7.74 ], [ 5.19, -2.31, -4.98] ] ), - (87, [ [ -31.90, -157.00, 923.20 ], [ 20.27, -2.84, 5.71 ], [ -1.21, -7.60, 0.51 ], [ 1.63, 0.18, 0.17 ], [ 1.98, -0.81, -7.42 ], [ -3.21, -0.77, 1.42] ] ), - (88, [ [ -17.04, -158.47, 917.33 ], [ 10.69, 1.60, -10.94 ], [ 1.83, -7.40, 0.70 ], [ 0.87, 0.01, -0.11 ], [ -5.13, -1.77, -5.27 ], [ -1.71, 0.19, -0.09] ] ), - (89, [ [ -12.92, -154.88, 905.59 ], [ 14.28, 1.56, -5.12 ], [ 0.95, -7.55, 0.35 ], [ -0.98, -0.09, -0.58 ], [ -2.50, -0.65, -7.16 ], [ 1.89, 1.14, -1.15] ] ), - (90, [ [ 0.79, -157.22, 913.22 ], [ 17.05, -0.10, -3.50 ], [ -0.15, -7.56, -0.50 ], [ 0.24, 0.09, -0.24 ], [ -1.52, 0.52, -7.39 ], [ 0.10, 0.16, 0.01] ] ), - (91, [ [ 11.37, -154.85, 899.81 ], [ 20.47, 4.34, -7.04 ], [ 1.53, -7.36, -0.09 ], [ 0.67, 0.24, -0.62 ], [ -2.36, -0.40, -7.11 ], [ -1.60, 0.07, 0.92] ] ), - (92, [ [ 35.28, -149.96, 905.73 ], [ 15.01, 5.71, -13.20 ], [ 0.75, -7.07, -2.20 ], [ 1.12, 0.33, 0.34 ], [ -5.05, 1.10, -5.27 ], [ -1.05, -1.38, 0.95] ] ), - (93, [ [ 31.51, -148.90, 893.07 ], [ 11.51, 6.02, -14.64 ], [ 2.99, -6.72, -0.41 ], [ 1.65, 0.51, 0.45 ], [ -5.13, -1.99, -4.85 ], [ 2.20, -0.03, -0.53] ] ), - (94, [ [ 53.21, -142.18, 892.15 ], [ 16.13, 8.56, 4.60 ], [ 3.73, -5.96, -2.01 ], [ 0.42, 0.20, 0.80 ], [ 0.55, 2.65, -6.83 ], [ 3.44, 1.00, -0.61] ] ), - (95, [ [ 62.43, -134.45, 898.99 ], [ 11.35, 7.61, 6.27 ], [ 3.97, -6.09, 0.21 ], [ -1.03, -0.53, 1.15 ], [ 2.65, 1.50, -6.63 ], [ -2.20, -1.80, 0.66] ] ), - (96, [ [ 74.83, -127.92, 903.83 ], [ 13.27, 2.58, -11.41 ], [ 1.50, -7.08, 0.14 ], [ -0.63, -0.25, 0.20 ], [ -4.49, -1.05, -5.45 ], [ -4.38, -1.93, 4.88] ] ), - (97, [ [ 72.51, -133.32, 887.20 ], [ -12.49, -8.25, -22.65 ], [ 3.07, -6.44, 0.66 ], [ 0.84, 0.36, -0.04 ], [ -5.54, -2.24, 3.87 ], [ 0.64, -0.37, 7.04] ] ), - (98, [ [ 47.82, -142.63, 864.93 ], [ -22.72, -8.47, -7.52 ], [ 2.59, -6.58, -0.40 ], [ 0.03, 0.23, -1.27 ], [ -1.82, -1.13, 6.76 ], [ 5.33, 1.35, 0.11] ] ), - (99, [ [ 33.71, -147.84, 866.62 ], [ -7.31, -5.02, 5.80 ], [ 2.84, -6.19, -1.77 ], [ -0.71, 0.24, -1.45 ], [ 4.23, 0.33, 5.62 ], [ 2.35, 2.56, -6.78] ] ), - (100, [ [ 33.45, -149.55, 870.08 ], [ 6.66, -2.67, 8.62 ], [ 1.80, -6.00, -3.25 ], [ -0.81, 0.03, -0.86 ], [ 5.31, 3.27, -3.10 ], [ 0.80, 2.08, -6.77] ] ), - (101, [ [ 48.50, -149.86, 877.56 ], [ 8.44, -1.40, 10.88 ], [ 1.73, -6.47, -2.17 ], [ -0.55, -0.39, 1.17 ], [ 5.25, 2.65, -3.73 ], [ -1.37, -2.16, 5.89] ] ), - (102, [ [ 49.17, -151.34, 885.88 ], [ -14.13, -2.76, 6.71 ], [ 0.88, -6.81, -0.95 ], [ -0.57, 0.33, -0.41 ], [ 3.06, -0.48, 6.24 ], [ -3.09, -3.47, 6.17] ] ), - (103, [ [ 30.33, -151.82, 877.70 ], [ -17.16, 1.53, -4.96 ], [ 0.86, -5.16, -4.59 ], [ -1.51, -0.14, 0.40 ], [ -1.82, -4.63, 4.87 ], [ 0.64, -0.13, 0.13] ] ), - (104, [ [ 16.36, -149.06, 875.57 ], [ -10.97, 1.71, 5.38 ], [ -1.69, -6.55, -1.37 ], [ -0.54, -0.73, 1.97 ], [ 2.66, -1.95, 6.05 ], [ 2.86, 1.80, -0.06] ] ), - (105, [ [ 11.69, -148.72, 883.92 ], [ -10.14, 1.00, 8.83 ], [ -0.88, -6.83, -0.24 ], [ 0.66, -0.15, 1.09 ], [ 4.42, -0.75, 5.16 ], [ -0.40, 1.32, 0.04] ] ), - (106, [ [ -3.83, -146.99, 890.11 ], [ -14.28, 1.09, 0.55 ], [ -0.49, -6.77, 0.78 ], [ 0.36, 0.01, -0.26 ], [ 0.32, 0.76, 6.79 ], [ -1.67, -0.06, 0.66] ] ), - (107, [ [ -14.79, -146.52, 886.71 ], [ -10.85, 0.22, 0.51 ], [ -0.15, -6.79, -0.36 ], [ 0.73, 0.03, -0.30 ], [ 0.31, -0.37, 6.78 ], [ 2.18, 0.02, -0.94] ] ), - (108, [ [ -23.91, -146.55, 890.53 ], [ -7.40, -0.95, 6.58 ], [ 0.92, -6.71, 0.07 ], [ -0.52, 0.10, 0.63 ], [ 4.39, 0.65, 5.03 ], [ 0.75, 0.45, -0.15] ] ), - (109, [ [ -28.03, -148.18, 898.37 ], [ -13.61, 2.90, 3.80 ], [ -1.15, -6.58, 0.90 ], [ -1.43, 0.37, -0.84 ], [ 1.91, 0.54, 6.43 ], [ -3.99, -0.65, 0.17] ] ), - (110, [ [ -42.02, -140.32, 889.27 ], [ -9.93, 7.70, -9.68 ], [ -1.35, -5.73, -3.18 ], [ 0.84, -0.04, -0.89 ], [ -4.99, -1.16, 4.20 ], [ -3.62, 0.11, -4.10] ] ), - (111, [ [ -47.83, -133.82, 880.59 ], [ 1.67, 2.81, -9.02 ], [ 0.18, -6.37, -1.95 ], [ 0.02, -0.24, 2.82 ], [ -6.43, 0.16, -1.14 ], [ 2.63, -0.65, -5.17] ] ), - (112, [ [ -43.36, -134.64, 876.97 ], [ 7.37, -1.12, -1.77 ], [ -0.57, -6.40, 1.69 ], [ -0.49, -0.09, 1.49 ], [ -1.72, -1.49, -6.23 ], [ 3.37, -0.42, -3.09] ] ), - (113, [ [ -34.80, -135.76, 878.37 ], [ 7.33, -0.80, -0.16 ], [ -0.71, -6.57, 0.26 ], [ -0.51, 0.02, -0.71 ], [ -0.17, -0.24, -6.61 ], [ -2.44, 1.36, 1.66] ] ), - (114, [ [ -29.32, -136.24, 877.18 ], [ 3.39, -0.80, -5.31 ], [ -1.47, -6.43, 0.04 ], [ -0.23, 0.05, 0.03 ], [ -5.30, 1.19, -3.57 ], [ -3.22, 0.72, 3.41] ] ), - (115, [ [ -30.61, -136.87, 870.77 ], [ -0.25, -0.25, -5.29 ], [ -1.11, -6.47, 0.36 ], [ 0.28, -0.03, -0.03 ], [ -6.35, 1.10, 0.25 ], [ 0.35, -0.33, -1.21] ] ), - (116, [ [ -30.23, -136.86, 867.08 ], [ 2.79, -0.45, -3.89 ], [ -0.88, -6.50, 0.13 ], [ 0.33, -0.03, -0.12 ], [ -5.21, 0.63, -3.81 ], [ 3.30, -0.63, -3.48] ] ), - (117, [ [ -25.37, -137.76, 865.06 ], [ 8.76, -0.50, 1.85 ], [ -0.41, -6.53, 0.17 ], [ 0.24, 0.00, -0.17 ], [ 1.34, -0.25, -6.40 ], [ 3.73, -0.35, -1.77] ] ), - (118, [ [ -17.01, -136.93, 873.25 ], [ 9.54, -0.88, -1.35 ], [ -0.66, -6.46, -0.44 ], [ -0.79, 0.17, 0.25 ], [ -0.86, 0.52, -6.43 ], [ -3.99, 0.94, 2.86] ] ), - (119, [ [ -14.62, -138.10, 867.37 ], [ 2.47, -1.15, -8.78 ], [ -1.76, -6.23, 0.32 ], [ 1.25, 0.41, -0.04 ], [ -5.90, 1.57, -1.86 ], [ -1.18, 0.21, 1.02] ] ), - (120, [ [ -13.21, -138.67, 858.26 ], [ 15.02, 8.84, -1.86 ], [ 3.15, -5.55, -0.95 ], [ 3.02, 0.32, -0.46 ], [ -1.07, 0.48, -6.36 ], [ 4.30, -0.76, -2.96] ] ), - (121, [ [ -2.01, -129.09, 875.92 ], [ 14.73, 5.57, 5.54 ], [ 2.15, -6.01, 0.34 ], [ -3.38, 0.09, 1.42 ], [ 2.11, 0.42, -6.03 ], [ -4.26, 0.28, 1.85] ] ), - (122, [ [ 5.71, -128.31, 873.45 ], [ 4.22, -3.80, -6.92 ], [ -2.18, -5.70, 1.80 ], [ 1.54, 1.12, 0.79 ], [ -5.12, 0.83, -3.57 ], [ -2.90, -1.92, 4.89] ] ), - (123, [ [ 3.86, -133.45, 867.51 ], [ -1.78, -5.98, -7.59 ], [ 4.53, -3.88, 2.00 ], [ 1.96, 0.65, 1.01 ], [ -4.22, -3.14, 3.46 ], [ 0.30, -2.10, 1.25] ] ), - (124, [ [ 2.44, -139.69, 858.80 ], [ 7.02, -5.19, -6.23 ], [ 0.10, -4.81, 4.11 ], [ -1.69, -0.89, 0.21 ], [ -4.72, -2.72, -3.06 ], [ 2.22, 0.25, -4.49] ] ), - (125, [ [ 11.98, -140.15, 859.35 ], [ 17.70, 2.25, -1.14 ], [ 0.89, -5.66, 2.60 ], [ 1.39, -0.39, -2.08 ], [ -0.04, -2.63, -5.72 ], [ 2.19, 0.11, -1.39] ] ), - (126, [ [ 35.30, -132.99, 854.91 ], [ 8.74, 9.55, -15.22 ], [ 3.78, -4.88, -0.90 ], [ 0.82, 0.89, -2.82 ], [ -4.13, -2.47, -3.92 ], [ -1.33, -1.30, 4.05] ] ), - (127, [ [ 29.93, -128.55, 843.92 ], [ -12.95, 5.12, -19.36 ], [ 3.43, -3.92, -3.33 ], [ -1.41, 0.00, -0.87 ], [ -3.91, -4.60, 1.39 ], [ 1.70, -0.30, 5.11] ] ), - (128, [ [ 9.39, -125.79, 820.06 ], [ -27.75, 1.44, 5.84 ], [ -0.44, -6.13, -0.59 ], [ -1.27, -0.92, 1.78 ], [ 1.23, -0.67, 6.02 ], [ 4.74, 2.19, -0.36] ] ), - (129, [ [ 4.65, -126.74, 840.92 ], [ -6.02, 1.18, 15.73 ], [ 0.12, -6.14, 0.51 ], [ -0.73, 0.09, 0.19 ], [ 5.69, 0.29, 2.16 ], [ -2.11, 0.21, 1.57] ] ), - (130, [ [ 0.04, -125.01, 849.26 ], [ -9.24, 1.85, 1.00 ], [ -1.17, -6.01, 0.30 ], [ 0.68, 0.07, -0.54 ], [ 0.70, 0.17, 6.10 ], [ -5.74, -0.82, -0.60] ] ), - (131, [ [ -4.44, -124.79, 843.15 ], [ -5.02, 0.46, -16.66 ], [ 1.17, -5.99, -0.52 ], [ 1.98, 0.08, -0.42 ], [ -5.67, -1.25, 1.67 ], [ -4.27, -1.02, -2.57] ] ), - (132, [ [ -4.10, -124.24, 817.80 ], [ -14.82, -5.98, -12.69 ], [ 2.08, -5.71, 0.27 ], [ -0.08, -0.02, 0.18 ], [ -3.61, -1.09, 4.72 ], [ 6.33, 1.59, -0.02] ] ), - (133, [ [ -13.82, -128.40, 823.84 ], [ -7.49, -1.58, 13.51 ], [ 1.44, -5.89, 0.11 ], [ -0.55, 0.00, 0.71 ], [ 5.11, 1.30, 2.98 ], [ 4.92, 1.22, -2.01] ] ), - (134, [ [ -15.54, -126.40, 839.81 ], [ -2.26, 3.63, 12.78 ], [ 0.99, -5.69, 1.79 ], [ -1.86, 0.05, -0.36 ], [ 5.77, 1.22, 0.68 ], [ -0.95, -1.43, 1.43] ] ), - (135, [ [ -17.86, -122.19, 848.91 ], [ -6.97, 2.29, 6.40 ], [ -1.77, -5.74, 0.13 ], [ 0.21, -0.11, -0.73 ], [ 3.78, -1.07, 4.51 ], [ -5.50, -0.82, 1.29] ] ), - (136, [ [ -24.46, -122.95, 849.04 ], [ -11.05, -2.26, -14.69 ], [ 0.96, -5.91, 0.19 ], [ 1.60, -0.05, 0.47 ], [ -4.70, -0.65, 3.63 ], [ -6.40, 0.95, -0.75] ] ), - (137, [ [ -23.98, -124.71, 821.70 ], [ -13.90, -3.45, -17.21 ], [ -1.01, -5.56, 1.93 ], [ -0.11, -0.11, -0.76 ], [ -4.54, 1.96, 3.28 ], [ 5.05, -0.43, 0.87] ] ), - (138, [ [ -38.60, -127.22, 820.18 ], [ -12.58, -0.43, 8.78 ], [ -0.02, -5.94, -0.31 ], [ -0.17, -0.02, -0.17 ], [ 3.41, -0.27, 4.87 ], [ 4.86, -1.54, -2.07] ] ), - (139, [ [ -42.52, -125.65, 832.78 ], [ 1.33, 2.91, 14.25 ], [ -1.16, -5.67, 1.27 ], [ -0.03, 0.21, 1.19 ], [ 5.67, -1.22, -0.28 ], [ 1.08, -0.26, -3.49] ] ), - (140, [ [ -35.80, -121.92, 845.73 ], [ 4.20, 3.78, 10.20 ], [ 0.01, -5.54, 2.04 ], [ -0.16, 0.23, 0.57 ], [ 5.46, -0.72, -1.98 ], [ 0.09, 0.03, 0.69] ] ), - (141, [ [ -33.62, -118.72, 852.84 ], [ 0.50, 3.01, 6.47 ], [ -0.86, -5.25, 2.51 ], [ -0.79, -0.03, -0.57 ], [ 5.71, -0.94, 0.00 ], [ -0.33, -0.03, 2.50] ] ), - (142, [ [ -34.44, -116.11, 858.28 ], [ -2.64, 1.81, 5.04 ], [ -1.59, -5.52, 1.14 ], [ 0.58, -0.29, -1.41 ], [ 4.94, -0.83, 2.89 ], [ -1.83, 0.37, 2.71] ] ), - (143, [ [ -38.38, -115.33, 862.17 ], [ -6.05, -0.34, 2.35 ], [ 0.20, -5.83, -0.32 ], [ 1.37, -0.09, -0.25 ], [ 2.12, -0.22, 5.43 ], [ -4.21, 0.45, 0.94] ] ), - (144, [ [ -44.50, -116.93, 861.58 ], [ -11.59, -3.81, -10.16 ], [ 1.03, -5.65, 0.95 ], [ 0.44, 0.12, 0.61 ], [ -3.83, 0.03, 4.36 ], [ -4.54, 0.05, -0.79] ] ), - (145, [ [ -51.78, -120.72, 839.03 ], [ -15.88, -5.45, -10.36 ], [ 1.70, -5.54, 0.30 ], [ -1.36, 0.27, 0.87 ], [ -2.99, -0.65, 4.93 ], [ 4.29, 0.49, 0.09] ] ), - (146, [ [ -64.65, -124.35, 841.48 ], [ -11.51, 0.42, 9.85 ], [ 0.14, -5.74, 0.41 ], [ -0.55, 0.33, 1.54 ], [ 3.68, 0.40, 4.29 ], [ 4.38, -0.52, -2.90] ] ), - (147, [ [ -69.37, -119.95, 854.33 ], [ 5.11, 4.21, 16.62 ], [ -1.23, -5.32, 1.73 ], [ 0.69, 0.27, 0.73 ], [ 5.25, -1.61, -1.21 ], [ 0.56, -1.58, -4.18] ] ), - (148, [ [ -55.63, -118.57, 867.17 ], [ 8.19, 15.70, 8.57 ], [ 0.64, -2.10, 3.23 ], [ 0.89, 1.63, 1.44 ], [ 3.88, -1.19, -1.54 ], [ 0.13, 0.20, 0.14] ] ), - (149, [ [ -52.38, -100.90, 869.76 ], [ 4.76, 24.01, 12.61 ], [ 0.45, -2.26, 4.14 ], [ -0.28, -0.30, -1.61 ], [ 4.16, -0.46, -0.70 ], [ -2.29, 1.10, 4.28] ] ), - (150, [ [ -41.73, -76.29, 892.90 ], [ -14.02, 14.24, 19.65 ], [ -3.16, -2.70, -0.30 ], [ 3.24, -2.89, 0.75 ], [ 1.74, -2.36, 2.95 ], [ -5.09, 5.86, 6.61] ] ), - (151, [ [ -58.69, -78.02, 896.31 ], [ -2.60, -3.83, -1.89 ], [ 4.23, -2.00, -1.76 ], [ 3.24, -2.89, 0.75 ], [ 0.59, -2.51, 4.28 ], [ -5.09, 5.86, 6.61] ] ) ] ), - + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[-502.30,732.10,92.00], [-49.80,-90.70,0.00], [0.00,0.00,12.00], [0.00,0.00,0.00], [-10.52,5.77,0.00], [0.00,0.00,0.00]]), + (2, [[-543.10,654.80,92.00], [-31.70,-64.00,0.00], [0.00,0.00,12.00], [0.00,0.00,0.00], [-10.75,5.33,0.00], [0.00,0.00,0.00]]), + (3, [[-566.20,605.00,92.00], [-43.40,-40.20,0.00], [0.00,0.00,12.00], [0.00,0.00,0.00], [-8.16,8.81,0.00], [0.00,0.00,0.00]]), + (4, [[-623.90,583.60,92.00], [-58.90,0.00,0.00], [0.00,0.00,12.00], [0.00,0.00,0.00], [0.00,12.00,0.00], [0.00,0.00,0.00]]), + (5, [[-674.40,602.30,92.00], [-25.80,24.90,0.00], [0.00,0.00,12.00], [1.57,1.24,-0.27], [8.33,8.64,0.00], [1.57,1.24,-0.27]]), + (6, [[-676.30,613.40,92.00], [21.70,17.10,-7.50], [2.46,1.94,11.58], [1.52,0.69,-0.22], [7.43,-9.43,0.01], [1.52,0.69,-0.22]]), + (7, [[-638.20,613.20,80.50], [47.90,1.90,-11.30], [2.75,0.11,11.68], [-0.55,2.15,-1.26], [0.47,-11.99,-0.00], [-0.55,2.15,-1.25]]), + (8, [[-586.80,617.60,72.10], [3.30,41.00,-47.10], [0.73,9.02,7.87], [-1.76,0.56,-0.15], [11.96,-0.95,-0.02], [-1.77,0.56,-0.14]]), + (9, [[-644.60,633.70,57.50], [-52.20,4.60,-6.70], [-1.50,0.14,11.90], [0.12,-4.47,1.05], [1.07,11.95,-0.01], [0.12,-4.47,1.05]]), + (10, [[-677.20,630.20,57.50], [0.10,-43.70,-12.10], [-0.00,-3.19,11.57], [1.58,-0.74,-0.11], [-12.00,-0.01,-0.00], [1.58,-0.74,-0.10]]), + (11, [[-632.90,609.90,50.60], [51.90,-16.20,-11.70], [2.42,-0.76,11.72], [0.39,-1.35,-0.70], [-3.56,-11.46,-0.00], [0.39,-1.35,-0.70]]), + (12, [[-581.30,601.00,35.40], [4.90,-48.00,-34.50], [0.68,-6.95,9.76], [-1.42,0.41,0.08], [-11.94,-1.21,-0.02], [-1.42,0.40,0.08]]), + (13, [[-631.70,589.30,35.90], [-57.50,19.90,-5.30], [-0.98,0.34,11.95], [-2.13,7.48,-3.39], [3.92,11.34,0.00], [-2.13,7.47,-3.39]]), + (14, [[-667.40,632.00,27.30], [-60.00,-18.80,-39.10], [-4.45,11.05,1.38], [-1.20,-0.91,-9.00], [5.42,3.46,-10.13], [-1.20,-0.91,-9.00]]), + (15, [[-666.40,558.00,7.70], [-33.70,-54.60,46.30], [-3.08,-6.32,-9.72], [-1.72,-4.99,-3.68], [10.42,-5.94,0.56], [-1.72,-4.99,-3.68]]), + (16, [[-698.00,570.70,66.50], [-52.90,5.40,48.50], [-8.05,-2.69,-8.47], [-2.86,-0.08,4.78], [1.18,-11.66,2.59], [-2.87,-0.08,4.78]]), + (17, [[-760.20,567.80,94.30], [-13.60,33.40,46.80], [-9.98,-6.44,1.67], [4.50,1.96,8.55], [6.05,-7.54,7.10], [4.51,1.96,8.55]]), + (18, [[-724.50,582.10,93.50], [45.90,1.10,-0.90], [0.23,-0.08,12.00], [4.20,2.65,4.23], [0.28,-12.00,-0.08], [4.20,2.65,4.24]]), + (19, [[-681.80,570.00,92.80], [28.80,-21.00,-0.70], [0.29,0.02,12.02], [-0.11,-0.21,0.02], [-7.09,-9.70,0.19], [-0.11,-0.21,0.02]]), + (20, [[-667.90,548.90,92.30], [3.90,-28.50,-1.00], [0.04,-0.44,12.03], [-0.05,-0.00,0.02], [-11.92,-1.66,-0.02], [-0.05,-0.00,0.02]]), + (21, [[-677.10,520.90,91.00], [-27.30,-11.70,0.60], [0.20,0.11,12.06], [-0.32,0.01,0.01], [-4.76,11.08,-0.02], [-0.32,0.01,0.01]]), + (22, [[-700.50,532.40,92.90], [-14.40,20.00,-0.20], [-0.67,-0.36,12.06], [-0.35,0.31,0.00], [9.78,7.05,0.76], [-0.36,0.32,0.00]]), + (23, [[-703.50,552.30,91.10], [-16.60,15.00,-1.80], [-0.75,0.65,12.05], [-0.38,0.11,-0.02], [8.09,8.99,0.02], [-0.39,0.11,-0.02]]), + (24, [[-726.50,553.80,90.20], [-21.70,-2.90,-3.00], [-1.64,-0.22,12.00], [-1.63,-5.16,-4.21], [-1.62,12.00,-0.00], [-1.63,-5.16,-4.21]]), + (25, [[-739.60,548.10,86.40], [15.30,-13.20,-28.20], [-4.50,-10.93,2.69], [-1.48,-2.79,-8.86], [-9.92,2.48,-6.51], [-1.48,-2.79,-8.86]]), + (26, [[-694.50,550.10,70.60], [44.70,-4.70,-16.30], [-3.66,3.50,-11.05], [1.47,4.72,-6.06], [2.27,11.59,2.91], [1.47,4.71,-6.06]]), + (27, [[-652.70,539.30,54.70], [26.40,-22.50,-3.70], [-1.02,0.79,-12.12], [0.77,-2.83,-0.13], [7.91,9.27,-0.06], [0.77,-2.82,-0.13]]), + (28, [[-644.90,520.20,58.60], [-8.40,-26.00,7.10], [-0.96,-2.93,-11.81], [-0.33,-0.93,0.06], [11.60,-3.77,-0.00], [-0.33,-0.92,0.06]]), + (29, [[-670.50,503.30,65.20], [-49.20,-7.40,8.40], [-2.00,-0.30,-12.06], [-0.69,-1.22,1.36], [1.84,-12.09,-0.00], [-0.69,-1.22,1.37]]), + (30, [[-723.20,522.10,69.80], [13.50,42.00,-69.30], [-2.37,-10.08,-6.58], [-0.28,-0.80,0.83], [-11.86,3.08,-0.45], [-0.28,-0.80,0.83]]), + (31, [[-641.70,515.00,30.80], [50.00,-30.40,-15.00], [-2.64,1.54,-11.95], [1.71,-0.27,-1.09], [6.41,10.54,-0.06], [1.71,-0.28,-1.09]]), + (32, [[-631.40,498.10,31.40], [-4.50,-28.10,4.10], [-0.02,-1.78,-12.22], [0.71,-0.99,-0.15], [12.20,-1.92,0.25], [0.71,-0.99,-0.15]]), + (33, [[-652.60,477.30,37.00], [-50.00,-6.30,6.60], [-1.60,-0.02,-12.27], [-1.33,1.31,0.06], [1.54,-12.27,-0.18], [-1.33,1.31,0.06]]), + (34, [[-711.30,508.40,47.40], [-65.20,35.30,20.70], [-3.19,1.14,-11.94], [-4.19,0.21,3.24], [-5.80,-10.97,0.50], [-4.19,0.21,3.24]]), + (35, [[-756.90,547.90,71.40], [-13.40,-32.80,30.60], [-11.62,0.46,-4.49], [-0.16,-0.33,-0.99], [2.82,-8.93,-8.23], [-0.16,-0.33,-0.99]]), + (36, [[-764.20,524.80,82.70], [2.40,-34.00,-3.00], [-8.44,0.19,-9.19], [1.12,1.17,2.11], [9.16,1.36,-8.38], [1.12,1.17,2.11]]), + (37, [[-733.10,495.70,71.40], [-9.60,-50.80,23.30], [-10.25,4.43,5.68], [3.16,-1.87,8.64], [-6.92,-3.34,-9.88], [3.17,-1.87,8.64]]), + (38, [[-714.70,462.80,83.00], [19.70,-9.40,0.00], [-1.64,-3.40,11.97], [-2.27,2.74,-8.49], [-5.16,-10.79,-3.77], [-2.27,2.74,-8.49]]), + (39, [[-703.00,463.20,92.20], [-6.90,19.30,27.80], [-9.75,5.16,-5.98], [-0.98,2.71,-11.42], [-7.51,-9.04,4.44], [-0.98,2.71,-11.43]]), + (40, [[-722.30,486.20,90.20], [-30.40,26.10,-0.90], [0.24,-0.18,-12.58], [4.54,-2.26,-3.13], [-8.18,-9.56,-0.02], [4.54,-2.26,-3.13]]), + (41, [[-745.10,520.90,90.70], [-10.10,19.90,1.10], [-0.29,0.57,-12.60], [0.25,-0.06,-0.02], [-11.25,-5.69,-0.00], [0.25,-0.06,-0.02]]), + (42, [[-724.50,528.30,92.00], [61.80,-0.90,2.80], [0.55,-0.02,-12.62], [-0.36,-0.13,0.04], [0.15,12.63,-0.01], [-0.36,-0.13,0.04]]), + (43, [[-691.00,492.20,92.50], [65.60,-18.50,-13.50], [-2.35,0.68,-12.42], [-1.69,0.78,0.19], [3.46,12.18,0.01], [-1.70,0.78,0.19]]), + (44, [[-640.00,474.10,57.50], [42.10,-24.20,-15.10], [-3.26,1.88,-12.14], [1.45,-0.62,-0.23], [6.34,11.01,-0.00], [1.45,-0.63,-0.23]]), + (45, [[-611.10,454.00,57.30], [-5.20,-35.60,0.00], [0.00,0.00,-12.73], [1.27,-0.75,-0.25], [12.60,-1.84,-0.00], [1.28,-0.75,-0.25]]), + (46, [[-640.70,443.80,57.50], [-30.10,-5.20,0.10], [-0.05,-0.02,-12.76], [0.00,0.00,-0.02], [2.16,-12.57,0.01], [0.00,0.00,-0.02]]), + (47, [[-667.60,443.10,57.50], [-25.60,5.80,0.00], [0.00,0.00,-12.77], [0.86,-0.09,0.06], [-2.82,-12.46,-0.00], [0.85,-0.09,0.06]]), + (48, [[-702.10,461.20,42.90], [-35.10,4.20,-7.10], [2.51,-0.31,-12.55], [-2.58,-3.51,4.12], [-1.52,-12.72,0.01], [-2.58,-3.51,4.12]]), + (49, [[-751.10,480.00,41.40], [-2.70,-4.20,52.00], [-8.23,-9.78,-1.21], [0.95,-1.86,-0.23], [9.83,-8.26,-0.14], [0.95,-1.86,-0.23]]), + (50, [[-740.70,460.80,81.10], [28.50,-35.40,18.50], [2.71,-5.98,-11.07], [0.35,3.93,-4.00], [11.24,6.22,-0.88], [0.34,3.93,-4.00]]), + (51, [[-715.80,438.10,60.60], [47.50,3.90,-28.60], [-6.62,-0.54,-11.07], [-2.22,3.02,-0.69], [-1.05,12.86,-0.00], [-2.22,3.03,-0.69]]), + (52, [[-690.60,420.70,23.60], [72.60,-48.00,-9.80], [-1.22,0.80,-12.86], [3.33,-0.90,-0.75], [7.12,10.80,0.00], [3.33,-0.90,-0.75]]), + (53, [[-634.40,437.80,2.60], [-11.70,62.00,-18.70], [0.67,-3.64,-12.45], [0.70,-0.09,-0.11], [-12.77,-2.41,0.01], [0.70,-0.10,-0.11]]), + (54, [[-685.40,456.30,14.80], [-80.30,28.90,-4.40], [0.64,-0.22,-13.01], [-0.87,2.09,-0.22], [-4.41,-12.26,-0.00], [-0.87,2.09,-0.22]]), + (55, [[-713.80,509.70,13.10], [-37.40,33.30,7.40], [-1.43,1.25,-12.93], [-3.03,-3.15,1.90], [-8.68,-9.78,0.01], [-3.03,-3.15,1.91]]), + (56, [[-762.90,511.80,46.30], [-17.40,-20.30,31.30], [-6.48,-7.55,-8.54], [-0.62,-3.81,1.50], [9.97,-8.52,-0.02], [-0.62,-3.81,1.50]]), + (57, [[-778.20,487.30,79.10], [-7.60,-16.30,20.80], [-4.19,-9.02,-8.60], [6.65,7.15,6.52], [11.92,-5.54,0.01], [6.65,7.16,6.52]]), + (58, [[-800.50,488.70,56.50], [-2.60,28.50,-35.30], [8.52,8.12,5.91], [6.13,4.32,8.27], [10.01,-6.27,-5.82], [6.13,4.32,8.26]]), + (59, [[-767.60,546.30,28.50], [27.50,29.90,28.50], [4.95,-10.54,6.27], [-7.20,-5.78,-5.89], [9.83,-0.64,-8.84], [-7.20,-5.78,-5.89]]), + (60, [[-730.30,549.50,39.80], [38.00,-16.90,-12.30], [-6.32,-10.60,-4.83], [0.16,0.75,-3.25], [-1.17,6.04,-11.74], [0.16,0.75,-3.25]]), + (61, [[-695.50,539.60,-1.80], [-25.60,-41.70,-52.60], [10.19,-8.37,1.69], [5.87,1.82,-1.72], [-7.11,-6.85,8.91], [5.87,1.82,-1.71]]), + (62, [[-753.60,538.10,17.50], [-40.40,-47.50,4.70], [6.27,-6.32,-9.95], [-2.66,-0.56,-4.61], [8.03,-5.95,8.85], [-2.66,-0.56,-4.61]]), + (63, [[-716.70,466.20,-1.60], [-40.40,-47.80,46.20], [4.18,-10.51,-7.20], [-1.22,-1.90,1.22], [10.66,-1.26,8.03], [-1.22,-1.90,1.22]]), + (64, [[-774.90,492.50,14.30], [4.60,-28.40,48.20], [3.28,-11.12,-6.84], [-2.63,-0.59,0.48], [13.01,3.36,0.76], [-2.63,-0.59,0.47]]), + (65, [[-755.00,488.60,92.30], [-28.50,3.50,3.80], [-2.24,-11.88,-6.06], [-0.86,-0.12,-0.18], [0.84,-6.26,11.96], [-0.86,-0.12,-0.18]]), + (66, [[-793.80,484.40,104.20], [-32.90,3.60,-1.30], [-1.01,-11.71,-6.76], [6.84,4.46,2.66], [-1.18,-6.68,11.73], [6.84,4.46,2.66]]), + (67, [[-790.70,455.50,85.30], [-2.30,-19.40,-39.70], [13.48,-1.65,0.00], [7.31,8.14,4.70], [-1.49,-12.10,5.97], [7.31,8.13,4.70]]), + (68, [[-801.70,464.20,17.70], [26.10,-25.90,-35.60], [11.25,6.96,3.26], [-7.03,6.33,-0.90], [3.16,-9.46,9.28], [-7.03,6.33,-0.90]]), + (69, [[-762.40,459.90,21.70], [25.40,2.00,17.80], [-0.71,13.64,-0.46], [-1.65,0.95,-2.28], [-7.81,-0.04,11.20], [-1.65,0.96,-2.28]]), + (70, [[-762.80,454.40,83.50], [-1.60,18.90,65.10], [11.83,6.72,-1.62], [-0.60,-1.49,6.17], [-6.91,11.33,-3.42], [-0.60,-1.49,6.16]]), + (71, [[-767.20,479.00,107.60], [-24.80,-1.90,8.70], [3.16,8.08,10.64], [-9.96,-2.61,4.05], [-3.39,11.06,-7.39], [-9.96,-2.61,4.05]]), + (72, [[-795.10,432.40,92.80], [-9.10,-19.70,-41.40], [-13.13,-1.80,3.77], [-2.62,-8.20,-1.68], [-3.18,12.37,-5.16], [-2.62,-8.20,-1.68]]), + (73, [[-769.20,411.90,25.90], [68.40,-16.90,-33.00], [1.27,-11.00,8.27], [5.91,1.76,3.98], [-6.47,-7.81,-9.40], [5.92,1.76,3.98]]), + (74, [[-679.40,419.00,45.00], [55.50,10.70,-0.20], [-0.79,4.58,13.09], [1.23,4.77,1.54], [2.54,-12.84,4.65], [1.23,4.77,1.54]]), + (75, [[-624.80,428.10,30.90], [37.00,1.10,-8.30], [2.78,4.05,13.03], [0.65,-3.43,0.31], [1.24,-13.32,3.88], [0.65,-3.43,0.31]]), + (76, [[-596.10,415.90,17.90], [13.70,-50.50,-10.30], [1.68,-2.24,13.67], [-2.26,-0.16,-0.25], [-13.40,-3.76,1.03], [-2.26,-0.16,-0.25]]), + (77, [[-633.70,383.40,10.50], [-53.90,-32.70,2.90], [-3.19,6.38,12.04], [-3.48,1.84,-0.84], [-6.50,10.15,-7.11], [-3.48,1.84,-0.84]]), + (78, [[-721.00,400.40,-2.40], [-84.80,146.00,5.60], [-5.70,-3.78,12.29], [0.98,-2.25,0.71], [10.74,5.98,6.82], [0.98,-2.25,0.71]]), + (79, [[-838.90,413.20,12.20], [-5.80,0.00,0.00], [-0.00,2.99,13.82], [-4.26,-1.08,-0.91], [0.00,13.82,-2.99], [-4.26,-1.08,-0.91]]), + (80, [[-841.90,390.30,9.10], [23.70,-40.80,14.10], [-7.16,0.08,12.23], [-3.54,-1.63,-0.61], [-10.15,-7.92,-5.89], [-3.54,-1.63,-0.61]]), + (81, [[-785.00,366.40,25.00], [68.10,-25.40,20.50], [-3.88,0.65,13.65], [2.70,1.81,0.59], [-4.77,-13.36,-0.72], [2.70,1.81,0.59]]), + (82, [[-715.10,372.10,29.90], [45.50,7.30,0.60], [-0.90,4.45,13.52], [1.10,0.20,0.24], [2.08,-13.35,4.54], [1.10,0.20,0.25]]), + (83, [[-676.70,381.70,46.00], [33.50,-1.60,1.70], [-0.65,2.52,14.05], [-2.24,0.19,-0.76], [-0.86,-14.05,2.49], [-2.25,0.19,-0.76]]), + (84, [[-624.70,387.70,43.50], [20.20,30.90,-2.50], [-6.80,5.40,11.39], [0.24,-5.21,-0.06], [9.89,-5.73,8.62], [0.24,-5.21,-0.06]]), + (85, [[-620.00,414.70,50.80], [-23.20,24.50,6.10], [-2.79,-5.83,12.81], [3.51,-2.77,1.11], [10.19,8.17,5.94], [3.51,-2.77,1.11]]), + (86, [[-667.60,418.50,51.40], [-25.90,-0.20,2.60], [1.39,3.45,13.89], [0.14,4.53,0.11], [-0.43,13.96,-3.43], [0.14,4.53,0.11]]), + (87, [[-705.40,416.80,61.80], [-55.10,-17.10,0.00], [-1.73,5.42,13.24], [-3.64,0.65,-0.93], [-3.97,12.62,-5.69], [-3.64,0.65,-0.93]]), + (88, [[-749.80,368.90,72.20], [-21.40,-38.20,-0.90], [-7.82,4.12,11.43], [2.52,2.85,-1.54], [-9.89,5.76,-8.83], [2.52,2.84,-1.54]]), + (89, [[-794.90,366.10,65.90], [-29.10,-4.30,9.30], [1.54,10.70,9.64], [4.72,2.23,-0.88], [-4.54,9.57,-9.88], [4.71,2.23,-0.88]]), + (90, [[-808.20,363.30,93.30], [18.80,-10.20,29.80], [4.22,10.42,9.17], [1.12,-0.05,-0.24], [-7.57,-3.14,11.97], [1.12,-0.05,-0.24]]), + (91, [[-772.30,355.10,95.70], [43.70,-4.20,-0.20], [3.97,10.61,9.11], [-2.39,-0.32,0.63], [2.05,-9.37,10.92], [-2.39,-0.32,0.63]]), + (92, [[-723.70,356.50,92.00], [34.80,14.40,-6.20], [-1.99,9.53,10.84], [2.61,-4.95,1.60], [5.66,-9.55,9.44], [2.61,-4.94,1.59]]), + (93, [[-704.10,380.20,92.30], [-4.50,25.20,1.10], [7.03,0.68,12.77], [-0.50,1.17,-0.66], [12.53,2.53,-7.03], [-0.50,1.17,-0.66]]), + (94, [[-724.40,396.00,92.70], [-30.00,-4.70,-0.50], [-1.81,10.80,9.67], [-4.52,4.97,-1.53], [-1.27,9.59,-10.95], [-4.52,4.97,-1.53]]), + (95, [[-761.40,390.00,92.00], [-26.80,-4.40,-1.30], [-2.26,10.77,9.65], [3.52,-0.78,0.05], [-1.07,9.61,-10.98], [3.52,-0.78,0.05]]), + (96, [[-796.40,394.20,92.00], [-19.90,14.60,-1.10], [6.15,9.03,9.78], [2.73,0.40,-0.79], [6.22,7.57,-10.91], [2.73,0.40,-0.79]]), + (97, [[-808.00,419.20,92.00], [22.20,4.70,-19.80], [4.65,11.45,7.93], [-2.50,1.30,-0.56], [8.76,-8.90,7.71], [-2.50,1.30,-0.56]]), + (98, [[-772.40,406.20,98.30], [40.50,-7.10,9.50], [-0.00,11.80,8.78], [-5.63,0.13,-2.26], [-4.14,-8.43,11.33], [-5.64,0.13,-2.26]]), + (99, [[-743.70,434.90,88.30], [-18.90,-10.80,-19.80], [-8.75,11.71,2.01], [-5.23,-2.29,-1.22], [7.16,7.20,-10.70], [-5.24,-2.29,-1.23]]), + (100, [[-799.10,394.00,52.00], [-21.00,-22.00,-12.00], [-10.41,4.89,9.33], [7.99,-2.65,4.28], [-4.46,9.83,-10.13], [7.99,-2.64,4.28]]), + (101, [[-804.50,342.90,51.10], [18.40,-46.20,24.50], [6.41,4.44,12.63], [5.00,2.57,0.35], [-11.15,-4.70,8.59], [5.00,2.57,0.35]]), + (102, [[-779.40,314.90,94.50], [43.80,-11.60,23.20], [0.13,11.14,9.87], [-2.57,2.84,-1.17], [-5.55,-8.91,10.56], [-2.57,2.84,-1.17]]), + (103, [[-725.70,321.90,94.80], [50.50,2.40,-4.10], [0.25,11.22,9.83], [2.24,-0.48,-0.06], [1.36,-9.80,11.17], [2.24,-0.48,-0.06]]), + (104, [[-673.60,342.20,84.90], [40.10,-23.10,1.40], [5.44,9.98,9.73], [2.31,-3.92,1.73], [-5.14,-8.28,11.36], [2.31,-3.92,1.73]]), + (105, [[-654.80,296.30,92.00], [7.30,-43.20,5.10], [5.88,2.56,13.56], [-3.45,-3.20,1.92], [-13.57,-1.59,6.18], [-3.45,-3.19,1.92]]), + (106, [[-638.40,213.80,96.30], [-29.60,-31.80,0.00], [-5.45,5.06,13.09], [4.65,2.69,-1.87], [-9.58,8.91,-7.44], [4.65,2.69,-1.87]]), + (107, [[-671.50,206.00,94.00], [-29.50,25.20,0.10], [7.27,8.43,10.17], [7.00,-1.55,-0.71], [6.61,7.74,-11.14], [7.00,-1.56,-0.71]]), + (108, [[-693.10,254.60,92.00], [-5.80,31.80,6.00], [8.71,-0.71,12.33], [0.22,-0.48,0.58], [12.05,3.79,-8.30], [0.22,-0.48,0.58]]), + (109, [[-692.70,282.10,99.60], [-11.70,28.50,0.00], [8.32,3.35,12.19], [-4.53,4.59,-0.52], [11.30,4.57,-8.98], [-4.53,4.59,-0.52]]), + (110, [[-714.50,303.80,105.30], [-27.80,-10.40,3.10], [-2.53,10.07,11.05], [-5.61,-1.93,0.96], [-4.90,10.03,-10.26], [-5.61,-1.93,0.96]]), + (111, [[-732.90,276.20,100.40], [-10.50,-24.20,-5.40], [-4.54,-1.23,14.44], [1.14,-6.02,1.63], [-13.22,6.55,-3.59], [1.15,-6.02,1.63]]), + (112, [[-739.60,242.40,94.90], [6.20,-21.60,0.00], [0.18,-3.68,14.76], [1.60,0.58,0.34], [-13.19,-7.53,-0.84], [1.60,0.58,0.33]]), + (113, [[-729.90,208.40,92.90], [31.10,-37.00,1.30], [-0.91,0.18,15.21], [-0.08,2.62,0.24], [-11.84,-9.57,-0.59], [-0.08,2.62,0.25]]), + (114, [[-671.40,183.60,95.20], [26.20,4.60,-18.30], [0.82,1.65,15.17], [0.74,0.62,0.01], [-3.15,-13.87,5.58], [0.74,0.62,0.01]]), + (115, [[-676.50,223.40,56.90], [-64.00,41.80,-9.80], [0.83,1.64,15.22], [0.01,0.00,0.05], [9.90,11.59,-1.60], [0.00,0.01,0.05]]), + (116, [[-680.80,291.90,29.60], [125.60,70.80,-6.60], [0.83,1.66,15.28], [-0.00,0.00,0.05], [8.29,-12.92,1.00], [0.00,0.01,0.05]]), + (117, [[-714.10,347.30,15.30], [-19.50,82.90,-38.40], [0.83,1.65,15.33], [0.00,0.00,0.06], [15.33,-1.59,0.98], [0.00,0.01,0.06]]), + (118, [[-801.90,404.60,-7.10], [-58.90,-30.30,2.30], [0.84,1.66,15.40], [0.00,0.00,0.05], [-6.23,14.16,-1.13], [0.00,0.01,0.05]]), + (119, [[-808.70,365.80,-13.70], [44.60,-53.00,-15.80], [0.84,1.66,15.44], [-0.00,0.00,0.05], [-13.75,-6.78,2.59], [0.00,0.01,0.05]]), + (120, [[-688.00,338.40,-11.70], [63.80,-48.80,8.70], [0.84,1.67,15.52], [0.00,0.01,0.07], [-8.51,-12.96,1.97], [0.00,0.01,0.07]]), + (121, [[-673.00,259.50,-3.20], [81.00,-7.10,7.50], [0.84,1.68,15.58], [0.00,0.01,0.06], [0.58,-15.56,1.94], [0.00,0.01,0.06]]), + (122, [[-674.40,198.70,27.60], [-166.70,-5.50,78.50], [0.85,1.70,15.65], [0.01,0.01,0.08], [-6.47,14.33,0.99], [0.00,0.01,0.08]]), + (123, [[-751.20,330.40,5.60], [-146.40,-62.90,102.70], [0.85,1.70,15.76], [0.01,0.01,0.10], [-11.81,10.19,2.93], [0.01,0.01,0.10]]), + (124, [[-771.40,224.30,-0.50], [-206.60,3.00,-5.40], [0.86,1.71,15.85], [0.01,0.01,0.09], [1.52,15.80,-1.69], [0.00,0.01,0.09]]), + (125, [[-809.20,353.00,16.20], [-189.70,36.40,-2.10], [0.86,1.72,15.95], [0.01,0.00,0.06], [3.70,15.51,-1.85], [0.00,0.01,0.06]]), + (126, [[-838.20,311.90,41.30], [13.30,-30.30,21.40], [0.87,1.72,15.99], [0.00,0.01,0.03], [-10.65,-10.80,5.40], [0.00,0.00,0.03]]), + (127, [[-817.10,288.00,42.40], [34.40,-12.20,0.70], [0.87,1.74,16.01], [-0.00,0.01,0.03], [-4.87,-15.25,1.93], [0.00,0.00,0.03]]), + (128, [[-752.40,294.00,78.80], [68.30,9.10,2.00], [0.87,1.73,16.07], [0.00,0.01,0.05], [3.61,-15.69,1.64], [0.00,0.01,0.05]]), + (129, [[-741.40,241.80,54.90], [-60.00,-10.60,-17.50], [0.87,1.74,16.12], [0.01,0.01,0.05], [3.05,15.94,0.02], [0.00,0.01,0.05]]), + (130, [[-802.80,226.00,43.40], [-39.00,36.40,14.80], [0.88,1.74,16.16], [0.00,0.01,0.04], [6.74,14.81,-0.51], [0.00,0.00,0.04]]), + (131, [[-833.10,266.00,68.30], [-22.10,29.70,29.30], [0.88,1.76,16.20], [0.00,0.00,0.03], [4.07,14.88,5.30], [0.00,0.00,0.03]]), + (132, [[-822.70,279.50,92.00], [26.60,9.70,0.30], [0.88,1.75,16.22], [-0.00,-0.00,0.02], [7.04,-14.68,1.37], [0.00,0.00,0.02]]), + (133, [[-799.30,280.50,92.00], [19.60,-7.30,0.00], [0.88,1.75,16.24], [-0.00,-0.00,0.02], [-5.47,-15.29,1.95], [0.00,0.00,0.02]]), + (134, [[-788.60,264.40,92.00], [-4.80,-26.50,0.00], [0.88,1.75,16.26], [-0.00,-0.00,0.02], [-15.65,4.75,0.55], [0.00,0.00,0.02]]), + (135, [[-814.90,246.10,92.00], [-26.10,-9.00,1.30], [0.88,1.75,16.28], [0.00,0.01,0.02], [-4.78,15.62,-1.40], [0.00,0.00,0.02]]), + (136, [[-826.20,223.00,92.00], [12.30,-25.30,0.00], [0.88,1.77,16.30], [0.00,0.01,0.02], [-15.18,-6.04,1.56], [0.00,0.00,0.02]]), + (137, [[-802.80,203.40,92.00], [45.00,8.60,0.00], [0.88,1.76,16.32], [0.00,0.00,0.03], [4.24,-15.80,1.57], [0.00,0.00,0.03]]), + (138, [[-783.70,237.40,92.10], [32.00,-1.80,-16.20], [0.89,1.76,16.35], [0.01,0.00,0.03], [-5.96,-14.63,4.62], [0.00,0.00,0.03]]), + (139, [[-754.40,192.40,70.50], [45.00,-18.70,-9.80], [0.89,1.78,16.39], [5.40,-1.59,-6.72], [-8.61,-13.85,2.55], [5.40,-1.59,-6.72]]), + (140, [[-680.80,179.60,31.60], [3.90,-10.60,-67.30], [16.13,-2.73,-2.64], [-5.09,-0.39,-13.72], [-2.06,-16.37,-1.55], [-5.09,-0.39,-13.72]]), + (141, [[-737.10,190.00,35.60], [-37.20,15.70,15.30], [-5.54,-0.10,-15.67], [-6.37,1.87,-5.13], [-4.96,-15.76,1.81], [-6.37,1.87,-5.13]]), + (142, [[-781.90,194.00,48.10], [-20.90,-6.20,-4.10], [-2.51,1.67,-16.37], [-2.28,2.28,1.31], [0.24,-16.33,-3.18], [-2.28,2.28,1.31]]), + (143, [[-802.30,178.10,41.90], [-11.30,-27.20,3.00], [-8.38,4.74,-13.60], [-3.69,-0.20,1.59], [12.99,-3.72,-9.76], [-3.69,-0.20,1.59]]), + (144, [[-799.10,145.80,39.00], [22.40,-22.60,-18.40], [-10.46,0.36,-13.00], [-1.30,-2.70,0.36], [8.11,13.21,-6.17], [-1.30,-2.69,0.36]]), + (145, [[-731.20,157.30,2.00], [50.10,-43.00,-3.70], [-10.50,0.36,-13.04], [-0.04,-0.00,-0.04], [2.84,15.32,-6.13], [-0.04,0.00,-0.05]]), + (146, [[-669.40,112.80,4.40], [136.30,170.20,-47.50], [-10.54,0.36,-13.09], [-0.05,0.00,-0.06], [-11.96,7.66,8.98], [-0.04,0.00,-0.06]]), + (147, [[-750.70,184.10,17.70], [-76.40,-20.30,-34.70], [-10.59,0.36,-13.15], [-0.04,0.00,-0.06], [-9.66,-10.81,-8.68], [-0.05,0.00,-0.06]]), + (148, [[-840.70,197.30,-8.00], [-65.70,-54.00,-27.90], [-10.63,0.36,-13.21], [-0.04,0.00,-0.05], [-0.51,-13.45,-10.33], [-0.04,0.00,-0.05]]), + (149, [[-770.00,153.90,-18.30], [146.60,96.20,29.90], [-10.68,0.37,-13.26], [9.19,1.65,-0.79], [-16.16,3.27,4.27], [9.19,1.65,-0.79]]), + (150, [[-687.80,179.20,-17.80], [93.00,6.90,16.70], [7.76,3.67,-14.78], [9.87,3.45,8.75], [3.45,16.26,3.96], [9.86,3.45,8.75]]), + (151, [[-660.00,168.80,104.60], [-61.10,-12.30,52.70], [7.71,8.52,12.78], [-10.02,-0.74,9.08], [-8.33,14.36,-4.45], [-10.02,-0.74,9.08]]), + (152, [[-732.50,164.50,92.40], [-75.70,-13.60,-3.40], [-9.99,4.48,13.31], [-7.28,-3.78,0.66], [-10.45,12.05,-6.54], [-7.28,-3.78,0.66]]), + (153, [[-785.80,124.60,91.40], [-10.20,-35.80,-2.20], [-9.79,-0.00,14.25], [6.65,-4.80,1.10], [-14.18,2.71,-9.51], [6.65,-4.79,1.10]]), + (154, [[-759.00,91.20,83.60], [119.50,-1.50,4.30], [3.74,-6.20,15.74], [5.90,-3.29,1.00], [4.41,-15.65,-5.99], [5.90,-3.29,1.00]]), + (155, [[-640.80,136.60,98.60], [46.60,50.10,7.60], [-5.31,-4.25,16.03], [-2.83,0.60,0.12], [8.81,-15.01,0.44], [-2.82,0.60,0.12]]), + (156, [[-579.70,151.60,100.30], [19.20,-49.70,4.50], [-5.33,-4.26,16.07], [-0.02,-0.02,0.05], [-13.36,-9.37,-6.20], [-0.02,-0.01,0.05]]), + (157, [[-626.30,99.70,102.90], [-45.20,-3.50,0.20], [-5.34,-4.28,16.12], [0.63,2.69,0.49], [-6.93,15.61,3.88], [0.63,2.69,0.49]]), + (158, [[-677.50,87.90,102.10], [-1.10,-44.00,15.60], [-4.07,1.07,17.04], [-0.22,-0.88,-0.12], [-16.52,-5.46,-2.27], [-0.22,-0.88,-0.12]]), + (159, [[-658.60,70.80,123.20], [64.50,-18.30,7.60], [-5.36,-4.29,16.18], [-0.57,-2.37,-0.37], [-5.95,-15.49,-5.79], [-0.57,-2.36,-0.37]]), + (160, [[-663.80,52.80,121.60], [-54.40,-14.30,-27.10], [-5.37,-4.30,16.20], [-0.01,-0.01,0.03], [-4.39,16.75,3.11], [-0.01,-0.01,0.03]]), + (161, [[-714.90,78.70,84.40], [-26.00,-24.40,-65.40], [-5.38,-4.31,16.24], [-0.02,-0.01,0.05], [-5.28,13.99,9.37], [-0.02,-0.01,0.05]]), + (162, [[-658.40,32.50,83.90], [2.10,116.00,-7.20], [-5.40,-4.32,16.31], [-0.02,-0.01,0.06], [15.91,-5.37,5.65], [-0.02,-0.02,0.06]]), + (163, [[-604.60,113.30,63.50], [-28.80,78.00,-53.10], [-5.42,-4.34,16.37], [-0.02,-0.02,0.06], [13.72,-0.73,11.29], [-0.02,-0.02,0.06]]), + (164, [[-692.90,147.10,50.50], [-30.70,48.10,-22.50], [-5.45,-4.36,16.43], [-0.02,-0.01,0.06], [14.65,4.96,8.92], [-0.02,-0.02,0.06]]), + (165, [[-760.40,156.30,47.10], [12.40,-68.30,10.10], [-5.46,-4.37,16.49], [-0.01,-0.01,0.05], [-14.42,-9.21,-5.27], [-0.02,-0.01,0.05]]), + (166, [[-714.60,117.30,46.30], [59.10,-31.90,-3.20], [-5.48,-4.38,16.53], [3.35,-1.81,-0.44], [-11.15,-12.59,-6.28], [3.35,-1.81,-0.44]]), + (167, [[-642.10,94.70,41.50], [86.40,3.30,-36.50], [2.97,-8.92,15.36], [8.28,8.12,-9.98], [-6.20,-15.41,-6.94], [8.28,8.12,-9.98]]), + (168, [[-636.10,134.80,16.40], [117.50,19.20,-27.50], [13.01,11.72,-4.34], [5.09,10.44,-9.95], [16.70,3.66,5.77], [5.09,10.44,-9.94]]), + (169, [[-578.20,88.00,25.20], [2.50,-59.30,17.40], [13.05,11.76,-4.35], [0.54,-10.37,3.35], [0.38,15.32,9.62], [0.54,-10.38,3.35]]), + (170, [[-631.30,39.10,34.60], [-128.70,-21.40,-13.20], [14.18,-10.93,2.97], [-7.55,-13.18,3.33], [10.62,3.52,14.30], [-7.54,-13.18,3.33]]), + (171, [[-704.70,57.70,8.40], [-125.70,-34.50,10.50], [-4.45,-17.41,2.94], [-13.98,6.42,-1.88], [-8.13,0.07,16.29], [-13.98,6.42,-1.88]]), + (172, [[-784.50,117.60,16.90], [39.80,42.00,-36.30], [-16.21,8.23,-1.98], [1.81,11.47,-8.58], [1.21,7.71,16.54], [1.81,11.48,-8.57]]), + (173, [[-699.80,123.10,-24.30], [55.40,-153.80,-40.30], [-0.62,8.58,-16.23], [7.44,0.19,-6.84], [15.51,9.29,3.25], [7.45,0.19,-6.84]]), + (174, [[-800.50,108.10,-31.70], [-87.40,47.70,13.70], [-0.62,8.63,-16.30], [-0.00,0.03,-0.05], [-11.00,-13.11,-6.88], [0.00,0.03,-0.05]]), + (175, [[-802.60,73.80,-45.80], [60.70,-32.10,-7.20], [-0.62,8.65,-16.33], [-0.00,0.02,-0.05], [5.98,15.75,7.61], [0.00,0.02,-0.05]]), + (176, [[-700.50,58.60,-44.70], [56.40,29.00,19.90], [-0.62,8.67,-16.40], [0.00,0.03,-0.05], [-11.15,13.01,7.14], [0.00,0.03,-0.05]]), + (177, [[-650.80,100.60,-19.70], [52.40,82.20,48.00], [-0.62,8.71,-16.44], [-2.79,-2.28,-0.32], [-16.75,6.91,4.24], [-2.78,-2.28,-0.33]]), + (178, [[-659.10,149.90,-29.60], [34.00,79.40,15.20], [-6.40,3.94,-17.07], [-0.18,-0.13,-0.05], [-16.86,3.82,6.99], [-0.18,-0.13,-0.05]]), + (179, [[-609.50,156.90,-23.70], [15.60,-53.60,-14.70], [-0.63,8.73,-16.51], [2.21,1.85,0.20], [16.45,8.41,2.81], [2.21,1.85,0.20]]), + (180, [[-609.70,110.70,-23.20], [40.80,-48.10,-0.90], [-0.63,8.76,-16.54], [-2.04,-1.11,0.02], [8.31,15.92,5.28], [-2.04,-1.11,0.02]]), + (181, [[-646.50,26.10,-11.20], [-162.60,-77.40,15.80], [-7.92,4.72,-16.37], [-2.07,0.47,11.78], [3.29,-16.99,-7.32], [-2.07,0.47,11.79]]), + (182, [[-611.30,41.40,96.10], [57.30,45.80,-2.40], [-3.44,11.46,14.61], [-0.50,-9.06,9.07], [12.59,-8.80,10.96], [-0.50,-9.06,9.07]]), + (183, [[-577.60,74.90,90.60], [55.80,-10.00,15.40], [-5.77,-4.62,17.41], [-1.04,-7.16,1.27], [-1.88,-18.03,-5.40], [-1.04,-7.15,1.27]]), + (184, [[-584.90,34.80,107.90], [-13.40,-36.10,14.60], [-5.78,-4.63,17.44], [-0.01,-0.00,0.03], [-17.60,-7.00,0.74], [-0.01,-0.01,0.03]]), + (185, [[-599.80,-4.20,106.40], [-10.50,-58.00,-59.30], [-5.79,-4.63,17.47], [-0.01,-0.00,0.03], [-14.34,12.16,2.56], [-0.01,-0.01,0.03]]), + (186, [[-560.70,-5.80,103.50], [22.80,77.00,53.00], [-5.80,-4.64,17.50], [-0.01,-0.01,0.04], [17.65,-3.70,6.06], [-0.01,-0.01,0.04]]), + (187, [[-539.50,62.70,103.50], [25.80,91.30,0.00], [-5.81,-4.65,17.55], [-0.01,-0.01,0.04], [15.25,-10.60,4.32], [-0.01,-0.01,0.04]]), + (188, [[-509.90,125.70,103.50], [40.90,31.10,0.00], [-5.83,-4.67,17.59], [-0.01,-0.01,0.03], [4.70,-18.52,-0.19], [-0.01,-0.01,0.03]]), + (189, [[-480.30,136.30,103.50], [27.90,-1.50,0.00], [-5.84,-4.67,17.61], [-0.00,0.00,0.02], [-6.52,-17.29,-4.98], [-0.01,-0.00,0.02]]), + (190, [[-463.80,126.60,103.50], [2.20,-41.60,0.00], [-5.84,-4.67,17.63], [-0.00,-0.00,0.02], [-17.37,-5.28,-6.07], [-0.01,-0.01,0.02]]), + (191, [[-502.40,82.30,103.50], [-23.60,-27.20,0.00], [-5.85,-4.68,17.67], [-0.01,-0.01,0.02], [-18.17,6.02,-1.35], [-0.01,-0.01,0.02]]), + (192, [[-509.30,56.80,103.50], [23.00,-22.90,0.00], [-5.86,-4.69,17.68], [-0.01,-0.01,0.02], [-13.07,-11.93,-7.46], [-0.01,-0.01,0.02]]), + (193, [[-475.50,64.70,103.50], [44.10,-1.90,0.00], [-5.87,-4.70,17.70], [-0.01,-0.01,0.03], [-6.42,-17.44,-4.94], [-0.01,-0.01,0.03]]), + (194, [[-430.20,49.30,103.50], [14.50,-56.10,1.00], [-5.88,-4.70,17.74], [-0.01,-0.01,0.04], [-16.25,-7.81,-6.81], [-0.01,-0.01,0.04]]), + (195, [[-469.90,5.30,104.60], [-58.90,-25.60,-18.20], [-5.89,-4.71,17.78], [-0.01,-0.01,0.04], [-10.01,16.47,1.31], [-0.01,-0.01,0.04]]), + (196, [[-530.20,8.80,71.20], [-89.40,9.00,-28.70], [-5.91,-4.73,17.82], [-0.01,-0.01,0.04], [0.52,18.66,5.13], [-0.01,-0.01,0.04]]), + (197, [[-549.80,51.30,74.50], [56.60,60.50,38.30], [-5.92,-4.74,17.86], [-0.01,-0.01,0.04], [14.25,-13.10,1.27], [-0.01,-0.01,0.04]]), + (198, [[-531.30,109.40,71.30], [86.60,49.60,3.50], [-5.93,-4.75,17.90], [-0.02,-0.01,0.05], [3.10,-19.15,-1.42], [-0.02,-0.01,0.05]]), + (199, [[-456.50,140.50,51.60], [45.40,11.90,-8.30], [-5.95,-4.76,17.95], [-0.02,-0.01,0.05], [-5.85,-18.55,-1.30], [-0.02,-0.01,0.05]]), + (200, [[-423.00,81.00,50.80], [-44.50,-103.30,-0.20], [-5.97,-4.77,18.00], [-0.02,-0.02,0.07], [-19.20,0.97,-3.61], [-0.02,-0.02,0.07]]), + (201, [[-549.80,34.30,52.00], [-12.30,-134.80,-12.90], [-6.00,-4.80,18.09], [-0.02,-0.02,0.08], [-18.71,-1.35,-5.86], [-0.03,-0.02,0.08]]), + (202, [[-465.30,-17.50,49.30], [-46.30,-108.10,-19.60], [-6.02,-4.82,18.17], [2.96,6.02,-0.20], [-18.71,4.67,-4.20], [2.95,6.02,-0.20]]), + (203, [[-578.60,-16.50,42.30], [-82.70,25.50,-15.40], [0.80,9.04,17.62], [-3.24,8.71,-6.08], [7.84,16.08,-8.53], [-3.24,8.71,-6.08]]), + (204, [[-536.60,25.20,15.60], [37.70,57.90,-21.80], [-9.40,16.09,6.92], [-2.87,-6.71,0.69], [13.43,3.94,14.11], [-2.87,-6.71,0.69]]), + (205, [[-529.00,93.90,11.80], [61.50,67.50,-4.90], [-6.08,-4.86,18.34], [1.52,-9.66,5.29], [7.46,-18.40,1.69], [1.52,-9.66,5.29]]), + (206, [[-468.20,137.50,16.60], [50.60,13.70,-2.50], [-6.09,-4.88,18.39], [-0.02,-0.01,0.05], [-3.17,-19.54,-2.73], [-0.02,-0.01,0.05]]), + (207, [[-398.80,135.90,16.10], [54.50,-33.90,-12.10], [-6.11,-4.89,18.43], [-0.02,-0.01,0.04], [-15.45,-11.14,-6.14], [-0.01,-0.01,0.04]]), + (208, [[-378.80,78.80,14.50], [-8.10,-48.90,36.10], [-6.12,-4.90,18.47], [-0.01,-0.01,0.04], [-13.91,-13.60,4.94], [-0.01,-0.01,0.04]]), + (209, [[-398.00,36.20,45.80], [-34.00,-45.80,24.00], [-6.13,-4.91,18.51], [-0.01,-0.01,0.04], [-19.59,-2.70,3.65], [-0.01,-0.01,0.04]]), + (210, [[-442.20,-17.60,57.50], [-86.50,-40.80,33.20], [-6.15,-4.92,18.55], [-0.02,-0.01,0.05], [-17.24,8.47,6.09], [-0.02,-0.01,0.05]]), + (211, [[-533.50,-18.10,72.80], [-62.70,-13.50,25.80], [-6.17,-4.94,18.61], [-0.01,-0.01,0.05], [-14.04,11.94,8.31], [-0.01,-0.01,0.04]]), + (212, [[-559.10,-59.00,75.10], [21.70,-55.50,8.30], [-6.18,-4.94,18.65], [-0.01,-0.01,0.04], [-14.76,-12.09,-6.80], [-0.01,-0.01,0.04]]), + (213, [[-500.70,-84.90,81.00], [63.70,28.70,0.20], [-6.19,-4.96,18.69], [-0.02,-0.02,0.05], [0.74,-20.19,-2.00], [-0.02,-0.01,0.05]]), + (214, [[-421.10,-26.60,49.00], [38.30,45.90,-36.30], [-6.22,-4.97,18.76], [-0.02,-0.02,0.05], [0.75,-17.81,9.88], [-0.02,-0.01,0.05]]), + (215, [[-382.00,4.70,3.40], [8.90,68.80,-40.90], [-6.23,-4.99,18.80], [-0.01,-0.01,0.04], [11.93,-11.30,12.14], [-0.01,-0.01,0.04]]), + (216, [[-389.10,52.20,-22.10], [-29.80,81.20,-22.40], [-6.24,-4.99,18.84], [-0.01,-0.01,0.04], [18.27,1.33,9.13], [-0.01,-0.01,0.04]]), + (217, [[-412.00,118.00,-36.80], [-99.40,115.40,42.30], [-6.26,-5.01,18.88], [-0.02,-0.02,0.05], [11.77,14.09,9.14], [-0.02,-0.01,0.05]]), + (218, [[-500.70,120.50,-22.30], [-52.50,-122.90,19.40], [-6.28,-5.02,18.95], [-0.02,-0.02,0.08], [-20.30,-2.39,-2.37], [-0.03,-0.02,0.08]]), + (219, [[-430.50,6.20,-21.60], [-110.00,-102.90,20.20], [-6.31,-5.05,19.04], [-0.04,-0.03,0.10], [-19.84,5.82,0.77], [-0.03,-0.03,0.10]]), + (220, [[-561.60,93.90,-37.50], [-136.90,-93.80,13.70], [-6.35,-5.08,19.15], [-0.03,-0.02,0.10], [-18.31,9.78,1.39], [-0.03,-0.03,0.10]]), + (221, [[-478.90,-3.90,-57.80], [64.00,-137.50,21.40], [-6.38,-5.10,19.25], [6.63,6.39,-0.25], [-14.64,-13.06,-7.21], [6.62,6.39,-0.25]]), + (222, [[-431.20,-73.10,-4.70], [-33.20,-2.10,83.80], [6.32,7.14,18.69], [-1.05,-1.02,0.11], [-12.55,12.41,11.34], [-1.05,-1.01,0.11]]), + (223, [[-498.10,-26.50,1.10], [-106.30,89.80,-35.30], [-6.42,-5.14,19.37], [-6.98,-6.72,0.41], [13.24,13.90,8.61], [-6.98,-6.72,0.41]]), + (224, [[-612.20,36.10,28.20], [-42.00,-52.50,15.50], [-6.45,-5.16,19.46], [-0.02,-0.01,0.06], [-21.10,1.09,0.98], [-0.02,-0.02,0.06]]), + (225, [[-599.60,-31.30,28.40], [13.40,-54.20,-7.20], [-6.46,-5.17,19.51], [-0.02,-0.01,0.04], [-19.22,-4.73,-7.57], [-0.01,-0.01,0.04]]), + (226, [[-551.10,-68.30,48.80], [70.00,-22.30,2.00], [-6.48,-5.18,19.55], [-0.02,-0.01,0.04], [-9.67,-17.56,-7.01], [-0.01,-0.01,0.04]]), + (227, [[-489.30,-77.50,38.10], [74.30,17.00,-23.00], [-6.49,-5.19,19.59], [-0.01,-0.01,0.04], [-9.28,-19.15,0.25], [-0.01,-0.01,0.04]]), + (228, [[-463.60,-26.20,12.80], [-33.30,65.70,20.70], [-6.51,-5.21,19.64], [-0.02,-0.02,0.06], [16.67,9.94,8.85], [-0.02,-0.02,0.06]]), + (229, [[-582.60,39.80,-15.30], [-97.00,-93.30,-56.80], [-6.54,-5.23,19.73], [-0.03,-0.02,0.09], [-14.65,15.64,-0.71], [-0.03,-0.02,0.09]]), + (230, [[-535.10,-48.00,-7.60], [163.70,-58.30,-145.00], [-6.56,-5.25,19.81], [-0.02,-0.02,0.08], [-20.10,-5.99,4.82], [-0.03,-0.02,0.08]]), + (231, [[-451.00,-130.20,37.30], [-10.40,16.50,63.10], [-6.59,-5.28,19.90], [-0.02,-0.02,0.06], [7.06,1.52,20.37], [-0.02,-0.02,0.06]]), + (232, [[-404.70,-90.30,45.30], [28.50,23.80,-5.20], [-6.61,-5.29,19.95], [-0.02,-0.01,0.04], [3.46,-21.33,1.72], [-0.01,-0.01,0.04]]), + (233, [[-373.40,-43.10,39.40], [5.90,71.90,-6.80], [-6.62,-5.30,19.98], [0.41,8.07,-8.50], [18.70,-8.62,6.86], [0.41,8.07,-8.50]]), + (234, [[-350.70,43.10,-5.50], [0.30,-23.00,-85.30], [-5.32,20.03,-6.74], [3.76,0.99,-18.90], [21.10,4.82,-2.54], [3.76,0.98,-18.90]]), + (235, [[-326.20,-52.10,3.90], [120.10,-136.40,45.10], [1.77,-4.02,-21.42], [8.00,-8.11,-5.57], [15.86,14.96,-1.55], [8.00,-8.11,-5.57]]), + (236, [[-415.40,-151.90,68.80], [-13.60,-50.50,-41.70], [13.15,9.60,-14.76], [-5.91,8.77,17.85], [17.28,-10.65,8.42], [-5.91,8.77,17.85]]), + (237, [[-353.60,-118.40,-8.30], [36.00,49.60,-67.80], [-5.10,16.63,13.41], [-6.76,-0.33,14.51], [18.46,-3.09,11.50], [-6.76,-0.33,14.52]]), + (238, [[-394.00,-54.90,-43.90], [-58.50,62.10,18.60], [-3.49,10.08,19.17], [-2.87,-4.30,1.63], [2.39,21.76,-1.38], [-2.88,-4.30,1.64]]), + (239, [[-374.20,70.30,-64.10], [-51.80,111.20,-42.80], [-13.56,7.99,15.21], [-4.29,-2.14,-1.16], [12.77,16.72,6.04], [-4.31,-2.13,-1.15]]), + (240, [[-480.40,88.90,-81.20], [-77.00,-72.50,-24.50], [-13.35,5.40,16.42], [4.11,-0.54,2.38], [-11.28,13.22,-13.24], [4.12,-0.54,2.40]]), + (241, [[-447.70,23.20,-62.70], [98.20,-53.90,-35.40], [-5.54,6.32,20.13], [6.87,3.25,0.83], [-18.69,-8.92,6.84], [6.89,3.27,0.84]]), + (242, [[-382.90,-144.70,-29.60], [-142.90,-41.30,110.60], [1.45,15.82,14.84], [2.82,3.81,-2.16], [-15.98,11.38,-9.36], [2.83,3.84,-2.15]]), + (243, [[-481.80,-39.40,-48.90], [-146.60,-39.20,12.20], [1.45,15.78,14.80], [-0.00,-0.05,-0.04], [-0.96,15.47,-15.16], [0.00,-0.03,-0.03]]), + (244, [[-453.60,-166.50,-38.80], [150.00,-6.00,-58.50], [1.45,15.73,14.76], [-0.01,-0.05,-0.05], [0.88,-14.09,16.35], [0.00,-0.03,-0.03]]), + (245, [[-534.60,2.00,-60.70], [-321.90,11.50,28.90], [1.44,15.66,14.71], [-0.01,-0.04,-0.04], [-1.31,14.78,-15.61], [0.00,-0.03,-0.03]]), + (246, [[-620.80,88.60,-65.80], [-173.30,-112.90,-24.50], [1.44,15.62,14.67], [-0.00,-0.04,-0.04], [3.37,18.22,-10.88], [0.00,-0.03,-0.02]]), + (247, [[-601.00,-61.20,-12.30], [87.00,-77.00,21.40], [1.44,15.59,14.63], [9.17,-14.24,-6.83], [-17.11,-6.31,11.25], [9.27,-14.39,-6.89]]), + (248, [[-524.30,-72.50,-58.30], [-55.40,-200.40,-26.20], [18.39,-10.71,2.04], [5.34,-1.84,-3.12], [-4.64,-6.66,19.78], [5.41,-1.85,-3.14]]), + (249, [[-516.70,-125.70,44.60], [99.10,-71.00,10.10], [11.44,15.46,9.24], [1.88,3.64,-8.37], [-5.77,-7.15,19.26], [1.91,3.68,-8.47]]), + (250, [[-511.50,-154.20,13.70], [-22.70,29.20,-59.80], [17.60,9.46,-7.43], [-3.65,-0.47,0.86], [3.49,-15.47,-14.24], [-3.69,-0.47,0.87]]), + (251, [[-507.90,-150.60,-52.20], [77.80,65.80,-26.70], [1.42,15.50,14.54], [-8.54,3.17,11.58], [18.21,-6.69,8.76], [-8.65,3.22,11.73]]), + (252, [[-501.90,-69.20,-84.50], [124.80,-47.20,-52.70], [1.42,15.45,14.52], [-0.00,-0.03,-0.03], [-7.08,-10.13,17.29], [-0.00,-0.02,-0.02]]), + (253, [[-435.40,-182.40,-85.30], [133.20,-88.90,11.70], [1.42,15.43,14.48], [-6.83,-0.95,-2.07], [-14.37,-8.41,13.13], [-6.94,-0.95,-2.09]]), + (254, [[-364.90,-190.70,-12.50], [-54.90,-42.00,69.00], [-12.69,13.50,10.23], [-5.25,1.16,-5.56], [-18.74,-6.89,-7.00], [-5.33,1.18,-5.63]]), + (255, [[-340.30,-163.80,48.10], [128.90,72.90,-11.00], [-11.73,17.39,2.56], [1.45,0.79,0.19], [0.95,-2.26,20.99], [1.47,0.81,0.20]]), + (256, [[-317.00,-143.90,-26.80], [-88.40,-30.90,-19.80], [-9.41,14.90,11.59], [6.33,-0.81,5.07], [-2.02,12.17,-17.11], [6.43,-0.81,5.16]]), + (257, [[-358.50,-142.30,-98.10], [-66.10,25.40,-1.30], [1.41,15.33,14.38], [6.65,0.24,1.70], [1.79,14.79,-14.88], [6.77,0.26,1.74]]), + (258, [[-360.30,29.80,-104.30], [133.20,-2.90,37.90], [1.41,15.28,14.32], [-6.70,-8.71,0.72], [0.29,-13.50,16.07], [-6.84,-8.87,0.75]]), + (259, [[-315.60,-96.60,-32.70], [59.80,120.90,165.90], [-13.09,-3.52,15.94], [4.77,-4.90,1.16], [13.62,-10.81,11.63], [4.87,-4.98,1.20]]), + (260, [[-314.20,51.50,-89.10], [14.30,127.70,-5.60], [11.50,4.15,16.90], [-1.05,-1.37,-0.07], [17.48,2.25,-11.17], [-1.08,-1.40,-0.05]]), + (261, [[-333.70,97.10,47.00], [52.00,38.50,28.60], [-12.25,-5.42,15.92], [-3.38,4.27,-19.59], [6.80,-19.65,0.45], [-3.45,4.37,-20.04]]), + (262, [[-304.70,120.30,-32.00], [62.80,-40.80,-60.10], [-3.42,8.27,-18.73], [3.93,2.96,-20.26], [17.05,11.85,0.22], [4.01,3.02,-20.74]]), + (263, [[-235.30,-46.60,17.40], [156.60,-68.60,59.20], [-8.09,-9.42,-16.55], [11.87,-4.32,3.21], [1.70,15.03,-14.11], [12.18,-4.43,3.27]]), + (264, [[-160.60,8.90,41.90], [96.20,60.70,-14.40], [15.14,-6.91,-12.23], [7.32,9.43,12.02], [1.54,13.97,-15.14], [7.50,9.68,12.33]]), + (265, [[-233.60,108.70,14.10], [-196.10,-54.60,-35.60], [1.38,14.98,14.07], [-6.34,10.06,12.10], [6.17,15.14,-12.54], [-6.50,10.34,12.42]]), + (266, [[-327.10,-7.90,-1.40], [30.20,-91.10,80.60], [1.37,14.95,14.03], [-1.77,-3.98,2.52], [-20.16,-1.40,3.63], [-1.82,-4.08,2.60]]), + (267, [[-223.10,8.60,56.80], [64.40,127.00,90.60], [-2.21,6.93,19.16], [5.46,-14.42,-3.87], [16.29,2.53,12.17], [5.63,-14.85,-3.98]]), + (268, [[-253.90,87.40,105.10], [-5.80,39.60,111.40], [11.35,-15.25,7.54], [-1.00,9.40,-0.35], [16.81,11.53,-1.70], [-1.03,9.68,-0.35]]), + (269, [[-243.10,128.50,112.80], [95.00,13.80,1.40], [1.37,14.86,13.96], [-4.00,12.07,2.56], [5.45,-13.26,14.57], [-4.12,12.44,2.65]]), + (270, [[-198.40,111.30,103.50], [29.70,-22.50,0.00], [1.37,14.85,13.95], [-0.01,-0.01,-0.01], [-14.69,-6.36,12.67], [0.00,-0.01,-0.01]]), + (271, [[-179.80,86.80,103.50], [15.50,-40.20,-2.20], [1.36,14.84,13.94], [-0.01,-0.01,-0.01], [-17.27,8.03,7.33], [0.00,-0.01,-0.01]]), + (272, [[-181.00,44.30,103.40], [-23.30,-31.20,0.00], [1.36,14.83,13.93], [-0.00,-0.01,-0.01], [-3.55,18.51,-7.78], [0.00,-0.01,-0.01]]), + (273, [[-212.60,28.50,103.50], [-45.50,-9.50,0.00], [1.36,14.82,13.92], [-0.00,-0.01,-0.01], [1.43,14.51,-14.23], [0.00,-0.01,-0.01]]), + (274, [[-268.30,32.40,103.80], [-47.70,23.20,-5.70], [1.36,14.80,13.91], [-0.00,-0.01,-0.02], [4.29,13.91,-14.23], [0.00,-0.01,-0.01]]), + (275, [[-303.20,68.70,92.20], [-16.00,43.30,-4.00], [1.36,14.80,13.89], [-0.00,-0.01,-0.02], [10.06,16.04,-7.43], [0.00,-0.01,-0.01]]), + (276, [[-264.40,113.10,92.20], [96.40,13.40,-16.30], [1.36,14.77,13.88], [-0.00,-0.02,-0.02], [5.35,-13.63,14.08], [0.00,-0.01,-0.01]]), + (277, [[-194.80,79.90,66.60], [66.40,101.30,-2.50], [1.36,14.76,13.85], [-0.00,-0.02,-0.02], [18.90,3.08,6.69], [0.00,-0.02,-0.02]]), + (278, [[-259.90,145.40,69.10], [-50.20,11.70,0.70], [1.36,14.72,13.83], [-0.00,-0.02,-0.02], [0.79,13.98,-14.62], [0.00,-0.01,-0.01]]), + (279, [[-332.40,128.50,76.00], [-49.00,-52.40,-1.30], [1.37,14.70,13.81], [-0.00,-0.02,-0.02], [-1.68,18.11,-8.83], [0.00,-0.01,-0.01]]), + (280, [[-350.80,61.90,80.80], [-2.80,-49.40,0.50], [1.37,14.70,13.79], [-0.00,-0.02,-0.02], [-13.09,15.37,0.38], [0.00,-0.01,-0.01]]), + (281, [[-310.50,4.10,73.40], [145.80,-25.20,-6.40], [1.35,14.68,13.77], [-0.01,-0.02,-0.02], [-3.44,-13.31,14.75], [0.00,-0.01,-0.01]]), + (282, [[-271.10,-43.80,94.40], [16.10,-48.30,3.80], [1.35,14.65,13.76], [-0.00,-0.01,-0.01], [-18.02,7.51,4.97], [0.00,-0.01,-0.01]]), + (283, [[-270.90,-77.40,103.40], [39.70,-14.80,1.00], [1.34,14.65,13.75], [-0.00,-0.01,-0.01], [-8.45,-11.61,14.10], [0.00,-0.01,-0.01]]), + (284, [[-220.70,-87.80,97.40], [44.90,15.00,0.00], [1.34,14.63,13.73], [-0.00,-0.01,-0.01], [9.96,-11.15,13.45], [0.00,-0.01,-0.01]]), + (285, [[-173.40,-67.30,82.30], [-11.80,54.90,-11.40], [1.34,14.62,13.72], [-0.00,-0.02,-0.02], [13.78,13.09,-6.49], [0.00,-0.01,-0.01]]), + (286, [[-229.90,-30.60,62.70], [-49.80,8.30,-5.90], [1.34,14.60,13.70], [-0.00,-0.02,-0.01], [4.44,13.17,-14.46], [0.00,-0.01,-0.01]]), + (287, [[-291.70,-26.70,39.10], [-43.90,3.80,0.00], [1.34,14.57,13.69], [-0.00,-0.01,-0.01], [1.27,13.63,-14.63], [0.00,-0.01,-0.01]]), + (288, [[-323.60,-28.80,45.90], [-29.10,-6.00,15.70], [1.34,14.56,13.68], [-0.00,-0.01,-0.01], [-11.52,12.00,-11.15], [0.00,-0.01,-0.00]]), + (289, [[-340.40,-46.90,56.00], [-7.70,-28.60,-0.30], [1.34,14.55,13.67], [-0.00,-0.01,-0.01], [-9.27,17.59,-2.33], [0.00,-0.01,-0.01]]), + (290, [[-341.70,-83.90,64.30], [5.20,-25.30,4.60], [1.34,14.56,13.66], [-0.00,-0.01,-0.02], [-17.98,8.50,2.19], [0.00,-0.01,-0.01]]), + (291, [[-327.60,-149.50,76.40], [26.30,-22.60,3.30], [1.34,14.54,13.64], [-0.01,-0.02,-0.02], [-15.60,-5.55,11.17], [0.00,-0.01,-0.01]]), + (292, [[-277.60,-101.40,42.90], [45.10,-4.20,0.00], [1.33,14.50,13.63], [-0.00,-0.02,-0.01], [-1.28,-13.56,14.57], [0.00,-0.01,-0.01]]), + (293, [[-231.00,-108.20,27.80], [42.40,14.10,0.00], [1.33,14.49,13.61], [-0.00,-0.01,-0.02], [9.84,-11.07,13.34], [0.00,-0.01,-0.01]]), + (294, [[-180.10,-109.90,40.70], [59.10,-19.40,39.60], [1.33,14.48,13.60], [-0.00,-0.01,-0.02], [-7.70,-11.37,14.41], [0.00,-0.01,-0.01]]), + (295, [[-174.70,-116.60,80.30], [-37.40,27.50,45.00], [1.33,14.48,13.58], [-0.00,-0.02,-0.02], [-12.89,15.10,1.39], [0.00,-0.01,-0.01]]), + (296, [[-300.70,-86.10,54.30], [-63.80,-23.10,55.90], [1.33,14.44,13.55], [-0.00,-0.03,-0.03], [-15.54,9.66,-7.67], [0.00,-0.02,-0.02]]), + (297, [[-289.00,-163.30,110.50], [-99.30,-43.30,98.20], [1.33,14.42,13.51], [-0.00,-0.03,-0.04], [-16.33,8.92,-6.77], [0.00,-0.02,-0.02]]), + (298, [[-323.00,-11.30,56.10], [39.10,49.20,-8.90], [1.34,14.37,13.48], [-0.01,-0.02,-0.02], [18.66,-0.68,6.41], [0.00,-0.01,-0.01]]), + (299, [[-277.50,6.40,49.70], [95.70,-13.00,0.00], [1.31,14.34,13.47], [-0.01,-0.02,-0.01], [-2.43,-13.25,14.39], [0.00,-0.01,-0.01]]), + (300, [[-191.40,-10.90,80.50], [62.80,-7.70,9.50], [1.31,14.33,13.44], [-0.00,-0.02,-0.02], [-2.20,-13.19,14.45], [0.00,-0.01,-0.01]]), + (301, [[-133.30,24.30,81.00], [42.20,67.00,0.00], [1.31,14.31,13.43], [-0.00,-0.02,-0.01], [18.18,3.68,6.51], [0.00,-0.01,-0.01]]), + (302, [[-125.40,67.10,93.50], [-20.50,21.20,-1.40], [1.31,14.30,13.40], [-0.00,-0.01,-0.01], [4.25,15.50,-11.28], [0.00,-0.01,-0.01]]), + (303, [[-181.30,58.00,64.50], [-62.10,-31.80,-29.80], [1.31,14.28,13.40], [-0.00,-0.02,-0.02], [10.08,15.61,-6.29], [0.00,-0.01,-0.01]]), + (304, [[-295.90,96.80,39.60], [-106.30,-114.70,-51.10], [1.31,14.24,13.36], [-0.00,-0.04,-0.03], [4.76,18.63,-3.64], [0.00,-0.02,-0.02]]), + (305, [[-170.50,62.70,-13.20], [-26.90,-123.60,24.00], [1.31,14.19,13.33], [-0.01,-0.04,-0.04], [-13.05,13.98,-3.83], [0.00,-0.02,-0.02]]), + (306, [[-274.30,42.90,28.40], [-12.60,-108.50,-11.40], [1.30,14.17,13.29], [-0.01,-0.04,-0.04], [-9.87,16.73,1.27], [0.00,-0.02,-0.02]]), + (307, [[-142.90,-22.50,18.30], [11.70,9.50,57.30], [1.30,14.12,13.25], [1.17,-1.58,1.19], [-8.50,1.10,17.40], [1.23,-1.65,1.27]]), + (308, [[-150.90,-36.10,84.20], [-5.30,-48.90,32.20], [3.19,11.59,15.20], [0.04,-0.08,0.03], [-18.85,4.45,0.74], [0.05,-0.07,0.04]]), + (309, [[-135.30,-105.30,94.80], [-3.20,-32.60,55.90], [1.30,14.07,13.22], [5.63,-11.05,0.16], [-19.00,-0.37,3.62], [5.94,-11.65,0.17]]), + (310, [[-138.40,-135.90,107.80], [4.80,-33.70,-0.70], [11.60,-5.52,14.45], [5.06,-12.37,-7.66], [-13.46,-9.01,10.56], [5.34,-13.05,-8.09]]), + (311, [[-150.80,-112.60,40.60], [1.40,115.30,8.10], [6.11,-5.43,-17.49], [-8.73,-1.10,-16.85], [-17.15,-5.91,-6.62], [-9.22,-1.17,-17.79]]), + (312, [[-176.80,19.30,-24.60], [67.20,241.30,-20.60], [-11.23,-9.02,-12.79], [-5.04,-2.23,0.97], [-15.85,-5.85,9.23], [-5.32,-2.36,1.00]]), + (313, [[-276.70,70.90,-69.10], [-51.90,-162.20,10.10], [-3.56,-10.26,-15.83], [2.84,-0.45,-1.11], [12.65,-14.44,0.32], [3.00,-0.48,-1.18]]), + (314, [[-221.20,2.30,-47.30], [-165.70,-117.10,-0.90], [-3.56,-10.24,-15.80], [0.01,0.02,0.03], [1.81,-18.01,6.26], [0.00,0.01,0.02]]), + (315, [[-283.70,-70.80,-59.10], [66.20,-75.00,17.60], [-3.55,-10.22,-15.76], [0.01,0.02,0.03], [15.04,7.81,-8.85], [0.00,0.01,0.02]]), + (316, [[-200.90,-32.00,-51.70], [94.90,36.10,50.70], [-3.55,-10.20,-15.74], [7.54,1.13,2.34], [-11.52,7.36,-13.32], [8.01,1.20,2.48]]), + (317, [[-114.90,21.00,-43.50], [88.80,141.00,123.30], [14.13,-7.58,-10.28], [10.12,6.89,4.80], [-4.72,9.27,-15.96], [10.75,7.32,5.08]]), + (318, [[-154.40,135.80,-62.60], [-78.30,-1.00,-2.30], [16.98,6.86,-5.05], [-4.73,11.66,5.50], [17.17,-5.33,-6.15], [-5.02,12.40,5.84]]), + (319, [[-274.80,136.50,7.90], [22.10,45.90,70.80], [3.58,18.49,2.00], [-5.93,5.11,3.12], [-10.85,8.85,12.76], [-6.30,5.46,3.32]]), + (320, [[-141.60,114.90,31.30], [60.30,66.50,26.50], [3.58,18.43,2.00], [-0.01,-0.03,-0.00], [6.50,11.07,13.86], [0.00,-0.02,0.00]]), + (321, [[-108.40,101.20,30.10], [11.30,-64.60,-17.80], [3.57,18.42,2.00], [5.73,-9.33,0.72], [0.02,15.31,11.02], [6.12,-9.95,0.76]]), + (322, [[-117.50,36.30,28.10], [-11.80,-88.50,4.40], [17.84,-4.74,3.78], [7.09,-9.12,-1.91], [-3.85,-1.13,18.41], [7.57,-9.72,-2.04]]), + (323, [[-123.00,-16.90,76.90], [-5.40,-40.50,20.40], [18.61,-0.28,-2.79], [-0.21,4.61,-0.38], [2.98,10.82,15.11], [-0.21,4.92,-0.40]]), + (324, [[-83.50,-94.80,124.40], [-5.30,-37.10,-69.10], [16.96,5.85,5.55], [-0.96,3.46,4.71], [3.12,-10.39,15.33], [-1.00,3.70,5.04]]), + (325, [[-114.60,-3.80,-22.00], [-48.40,-89.30,-74.40], [16.90,5.83,5.53], [0.13,-7.07,-4.33], [4.87,2.00,17.95], [0.15,-7.57,-4.63]]), + (326, [[-106.10,-89.80,24.00], [-40.70,-98.90,-72.10], [17.17,-6.96,-2.28], [0.23,-2.61,-5.35], [-2.51,-11.23,14.69], [0.26,-2.79,-5.73]]), + (327, [[-134.60,-44.80,-44.70], [-45.50,-59.20,-129.40], [17.42,-0.71,-6.58], [-4.55,4.11,-6.56], [1.78,-17.35,6.53], [-4.87,4.41,-7.04]]), + (328, [[-152.20,-122.40,-0.90], [-138.70,-24.00,-10.70], [6.30,2.05,-17.37], [-2.19,-5.54,0.63], [8.24,-16.66,-0.54], [-2.34,-5.95,0.67]]), + (329, [[-215.00,-66.50,-51.90], [-95.40,-77.80,7.50], [12.21,-12.81,-5.56], [4.44,-4.77,7.49], [5.60,-2.49,17.52], [4.78,-5.13,8.04]]), + (330, [[-281.50,-141.60,-97.10], [-33.10,-74.40,-0.80], [16.28,-8.80,-0.52], [2.14,2.15,2.68], [-0.19,-1.68,18.43], [2.32,2.30,2.88]]), + (331, [[-142.90,-169.80,-24.70], [57.10,22.50,62.40], [16.22,-8.78,-0.52], [-0.05,0.02,0.00], [11.32,13.95,-4.23], [-0.03,0.02,0.00]]), + (332, [[-114.90,-94.60,56.00], [-22.70,-27.90,103.30], [16.18,-8.75,-0.52], [-0.04,0.02,0.00], [8.74,15.58,4.42], [-0.03,0.01,0.00]]), + (333, [[-165.80,-210.20,55.70], [-82.80,8.90,-63.60], [16.14,-8.73,-0.52], [-0.04,0.02,0.00], [5.07,-11.32,13.52], [-0.03,0.01,0.00]]), + (334, [[-221.80,-171.30,-25.00], [-110.60,-77.10,-27.50], [16.10,-8.71,-0.52], [-7.05,1.07,-6.62], [4.94,0.82,17.61], [-7.61,1.16,-7.17]]), + (335, [[-212.40,-201.20,82.90], [136.90,5.40,26.70], [-1.57,-6.04,-17.16], [1.17,-0.16,1.14], [-4.47,16.34,-6.83], [1.28,-0.18,1.23]]), + (336, [[-187.10,-132.60,25.20], [-87.20,10.40,-111.30], [16.02,-8.66,-0.52], [9.16,4.06,10.76], [-0.64,-13.63,12.06], [9.93,4.39,11.65]]), + (337, [[-324.00,-192.70,-37.00], [-25.10,-36.30,21.20], [16.40,5.65,5.36], [0.10,4.80,1.97], [-1.16,17.46,4.81], [0.13,5.20,2.14]]), + (338, [[-280.20,-208.50,37.40], [-89.00,-10.60,119.10], [16.36,5.65,5.36], [-10.49,2.92,-7.65], [-1.38,16.69,-6.91], [-11.39,3.18,-8.31]]), + (339, [[-271.90,-187.90,119.40], [42.70,34.80,6.60], [-6.81,12.13,-11.55], [-5.42,1.49,-5.96], [-7.93,8.70,13.73], [-5.88,1.63,-6.48]]), + (340, [[-252.20,-147.10,107.10], [22.70,45.10,-4.00], [-4.50,11.45,-13.24], [2.55,1.22,0.64], [-6.75,14.49,8.41], [2.78,1.34,0.69]]), + (341, [[-216.60,-117.80,95.70], [40.30,-19.20,-0.50], [-1.03,15.03,-9.94], [9.63,-2.95,8.59], [-2.14,12.12,13.20], [10.48,-3.21,9.35]]), + (342, [[-210.30,-154.50,112.40], [-20.60,-33.90,26.20], [16.29,5.62,5.33], [9.65,-5.25,8.52], [-3.37,17.07,4.70], [10.51,-5.71,9.27]]), + (343, [[-241.10,-217.80,103.30], [-99.30,-50.40,-38.80], [16.26,5.60,5.33], [-2.89,1.23,-6.88], [14.59,6.76,8.10], [-3.14,1.34,-7.50]]), + (344, [[-262.00,-235.10,20.00], [83.30,-4.40,-126.20], [8.59,8.91,-13.03], [-0.53,0.21,-1.21], [16.26,-0.43,-7.64], [-0.57,0.23,-1.31]]), + (345, [[-341.30,-228.90,-31.50], [21.90,106.10,-95.20], [16.20,5.59,5.30], [3.58,-1.58,8.69], [8.06,-9.23,-13.09], [3.93,-1.72,9.48]]), + (346, [[-223.00,-253.50,-46.00], [3.40,60.90,-83.80], [16.15,5.57,5.28], [0.66,-1.98,-3.36], [7.60,-13.50,-8.93], [0.74,-2.16,-3.66]]), + (347, [[-309.60,-169.80,-81.10], [21.90,106.10,-95.20], [17.66,1.21,-2.13], [-7.72,-0.17,-9.71], [-0.02,-7.68,-16.09], [-8.44,-0.18,-10.64]]), + (348, [[-209.50,-219.10,-37.80], [53.10,-46.50,-77.10], [-1.88,5.45,-16.82], [-6.57,1.42,-4.92], [16.09,5.92,-4.73], [-7.20,1.56,-5.40]]), + (349, [[-173.60,-172.20,-85.40], [-26.90,37.00,-15.30], [-1.88,5.43,-16.79], [3.86,-5.85,4.16], [-17.03,-0.68,-4.94], [4.24,-6.42,4.55]]), + (350, [[-291.30,-84.30,-106.00], [97.00,135.70,42.80], [10.76,-13.65,-3.25], [6.72,-8.15,5.15], [-2.27,0.16,-17.54], [7.39,-8.96,5.63]]), + (351, [[-120.90,-148.90,-48.40], [39.70,69.50,-18.40], [12.13,-10.71,-6.95], [0.44,1.01,-1.23], [-9.07,-0.74,-15.07], [0.50,1.10,-1.36]]), + (352, [[-144.10,-35.10,-76.70], [-46.20,4.30,-3.90], [12.10,-10.68,-6.92], [-0.03,0.02,0.02], [10.79,-9.03,10.52], [-0.02,0.02,0.01]]), + (353, [[-190.90,-106.20,-108.70], [-85.30,10.90,-25.60], [12.07,-10.66,-6.92], [-0.03,0.02,0.01], [6.38,-11.33,11.75], [-0.02,0.01,0.01]]), + (354, [[-285.70,-73.50,-145.80], [-88.80,-66.70,-0.90], [12.05,-10.64,-6.89], [-0.03,0.03,0.02], [6.61,-3.69,15.76], [-0.02,0.02,0.01]]), + (355, [[-321.80,-178.80,-111.70], [-31.80,-89.20,89.10], [12.02,-10.61,-6.88], [-0.02,0.02,0.01], [12.07,6.81,10.58], [-0.02,0.01,0.01]]), + (356, [[-371.60,-176.40,-124.40], [19.20,94.50,-4.50], [12.00,-10.59,-6.87], [-1.15,5.43,-2.83], [-8.74,-6.69,-13.49], [-1.26,6.01,-3.14]]), + (357, [[-321.80,-83.50,-118.80], [-75.90,112.20,-24.80], [8.97,3.79,-14.39], [-7.87,9.63,-2.48], [-11.44,-8.95,-9.53], [-8.72,10.67,-2.75]]), + (358, [[-395.50,-163.20,-123.30], [-53.40,-89.20,1.10], [-6.47,10.77,-11.94], [1.54,4.94,6.19], [13.23,-1.02,-11.15], [1.72,5.48,6.85]]), + (359, [[-473.40,-148.90,-123.50], [-56.10,65.20,-46.90], [7.85,15.32,-1.62], [8.17,-9.27,2.34], [2.54,-0.37,-17.10], [9.07,-10.30,2.58]]), + (360, [[-429.70,-106.40,-120.50], [163.60,-61.70,-10.20], [11.90,-10.51,-6.81], [-2.78,-9.61,-6.54], [15.99,0.31,-6.50], [-3.09,-10.68,-7.28]]), + (361, [[-402.50,-38.30,-145.20], [-67.70,81.20,4.50], [0.25,-3.70,-16.83], [-6.38,6.43,-3.19], [-10.37,-13.61,2.01], [-7.10,7.14,-3.56]]), + (362, [[-461.90,-56.90,-150.00], [-80.10,-50.60,3.70], [-4.07,3.87,-16.26], [-5.47,3.23,2.15], [7.90,-14.29,-5.42], [-6.09,3.59,2.38]]), + (363, [[-522.70,-134.30,-113.60], [-48.30,6.50,89.20], [-13.08,1.57,-11.01], [-0.45,2.83,1.70], [-0.50,-16.92,-2.84], [-0.50,3.16,1.88]]), + (364, [[-492.60,-30.90,-110.50], [-4.70,62.60,70.10], [-4.57,10.62,-12.64], [3.44,3.64,-0.64], [-16.20,-5.46,0.93], [3.83,4.07,-0.73]]), + (365, [[-562.40,-79.20,-83.10], [-57.30,18.40,43.90], [-4.56,10.60,-12.61], [0.01,-0.02,0.03], [-8.36,-12.71,-7.79], [0.01,-0.02,0.02]]), + (366, [[-607.00,13.50,-78.80], [37.30,101.70,-7.80], [-4.55,10.57,-12.58], [0.01,-0.03,0.03], [-7.84,13.29,7.24], [0.01,-0.02,0.02]]), + (367, [[-511.10,40.20,-112.70], [103.50,-93.30,-48.20], [-4.54,10.54,-12.55], [0.11,-3.57,-1.75], [7.34,13.94,6.40], [0.12,-3.99,-1.97]]), + (368, [[-523.20,-9.50,-122.50], [-147.00,5.30,22.40], [-4.34,3.49,-16.04], [-0.01,-3.23,-1.48], [-3.07,-16.44,-2.99], [-0.01,-3.61,-1.67]]), + (369, [[-588.70,-24.10,-95.80], [34.00,-42.60,1.70], [-4.54,2.91,-16.07], [0.65,0.95,0.15], [8.97,14.26,-1.90], [0.72,1.07,0.16]]), + (370, [[-532.30,-72.30,-120.30], [111.50,-25.50,-41.10], [-2.90,5.60,-15.71], [1.57,2.29,0.53], [6.54,15.08,4.03], [1.76,2.57,0.59]]), + (371, [[-460.90,-12.40,-123.40], [176.70,55.60,45.00], [-0.94,8.08,-14.80], [0.80,1.00,0.37], [-8.09,12.91,7.28], [0.90,1.13,0.40]]), + (372, [[-427.40,65.30,-95.70], [-43.60,32.50,-16.00], [-1.12,7.82,-14.89], [0.27,0.90,0.56], [-13.67,-5.66,-8.07], [0.30,1.02,0.62]]), + (373, [[-471.40,54.70,-118.00], [-79.10,-33.90,8.90], [-0.57,9.50,-13.88], [-0.62,1.29,1.01], [8.69,-10.93,-9.39], [-0.70,1.46,1.13]]), + (374, [[-580.40,127.50,-99.50], [11.00,31.00,79.80], [-4.48,10.41,-12.37], [1.47,0.43,0.17], [-15.12,-5.54,-4.71], [1.66,0.50,0.18]]), + (375, [[-556.80,144.60,-36.30], [82.20,-21.40,6.30], [0.24,10.67,-12.91], [0.42,0.00,-0.03], [-0.83,13.33,10.11], [0.47,0.02,-0.04]]), + (376, [[-519.60,126.70,-112.70], [103.30,-10.80,-25.10], [-4.46,10.37,-12.34], [-2.19,-0.16,0.28], [1.29,13.22,10.15], [-2.48,-0.17,0.31]]), + (377, [[-425.90,145.30,-95.20], [0.10,5.40,86.10], [-4.45,10.34,-12.31], [0.01,-0.03,0.03], [-11.10,-5.16,-11.33], [0.01,-0.02,0.02]]), + (378, [[-512.40,124.30,-46.70], [-26.40,-6.80,-45.50], [-4.44,10.31,-12.28], [0.01,-0.02,0.03], [4.74,-3.75,-15.50], [0.01,-0.01,0.02]]), + (379, [[-476.90,99.10,-97.70], [61.40,-4.20,-24.70], [-4.43,10.30,-12.24], [0.01,-0.02,0.03], [4.42,13.01,9.33], [0.01,-0.01,0.02]]), + (380, [[-371.40,119.00,-116.30], [47.50,67.00,21.40], [-4.42,10.27,-12.22], [3.72,1.74,2.21], [-10.80,7.73,9.88], [4.22,1.99,2.49]]), + (381, [[-341.60,157.90,-39.40], [-130.40,-15.20,-17.30], [4.12,14.31,-7.18], [0.70,2.51,4.56], [7.38,-7.06,-12.99], [0.79,2.87,5.16]]), + (382, [[-401.40,155.50,-49.20], [-44.00,17.80,118.30], [-0.25,16.40,-1.90], [-2.23,0.58,5.83], [-15.69,-0.81,-5.06], [-2.54,0.67,6.62]]), + (383, [[-326.70,144.80,-18.40], [68.80,-24.00,-65.20], [-0.24,15.08,6.61], [0.05,-0.90,-4.01], [2.61,-2.46,16.07], [0.06,-1.01,-4.56]]), + (384, [[-264.80,135.60,-54.60], [15.70,44.40,54.40], [-0.14,14.29,-8.13], [3.05,-0.30,-4.66], [-15.24,3.30,5.20], [3.48,-0.33,-5.31]]), + (385, [[-311.00,161.60,22.30], [30.30,-19.60,79.00], [7.38,14.50,-2.12], [2.95,0.10,1.93], [-13.62,8.04,4.34], [3.37,0.13,2.19]]), + (386, [[-216.70,146.00,34.60], [48.10,-13.40,2.20], [6.52,14.51,-3.81], [-0.36,-0.13,-1.13], [2.52,3.35,15.82], [-0.41,-0.13,-1.29]]), + (387, [[-127.20,99.80,74.20], [48.10,-23.70,1.30], [6.59,14.19,-4.66], [3.97,-5.53,2.44], [1.29,4.55,15.62], [4.55,-6.30,2.78]]), + (388, [[-31.50,35.80,58.00], [9.60,-94.20,34.00], [16.09,1.23,2.18], [-4.96,-6.31,9.74], [-2.35,4.18,15.56], [-5.67,-7.21,11.15]]), + (389, [[-93.20,47.90,78.70], [-40.40,4.30,-4.70], [0.43,-2.16,16.10], [-13.30,3.09,-2.34], [3.91,15.60,2.37], [-15.22,3.54,-2.68]]), + (390, [[-83.60,41.80,21.70], [-25.40,95.30,-36.30], [-14.30,7.55,-1.39], [1.19,7.30,-7.96], [-1.27,14.38,7.41], [1.37,8.37,-9.11]]), + (391, [[-94.90,120.00,-16.70], [54.70,18.00,-1.30], [7.93,14.11,0.46], [13.15,-4.37,2.41], [11.79,3.11,10.66], [15.08,-5.02,2.76]]), + (392, [[-6.00,8.70,44.40], [-86.70,-73.70,-3.60], [9.84,-11.82,4.85], [1.39,-7.11,-5.37], [-3.52,3.38,15.38], [1.61,-8.16,-6.18]]), + (393, [[-69.50,67.10,-5.30], [-28.20,-6.40,-92.20], [11.21,-7.89,-8.41], [-1.75,10.80,-4.15], [-8.51,-13.50,-1.99], [-2.01,12.43,-4.77]]), + (394, [[-80.80,-39.40,-67.40], [124.60,-54.30,39.80], [4.96,15.06,-2.40], [-6.39,8.82,4.76], [-5.15,4.31,14.56], [-7.36,10.17,5.48]]), + (395, [[-47.50,28.90,-23.70], [59.80,-55.90,69.30], [-3.12,15.47,2.61], [6.16,-4.72,4.76], [-15.89,0.77,1.75], [7.12,-5.43,5.49]]), + (396, [[-37.50,-11.90,-20.60], [-26.30,-38.40,68.20], [11.68,7.11,8.26], [7.91,-7.09,-3.25], [-9.65,12.38,3.01], [9.13,-8.18,-3.75]]), + (397, [[-36.80,-10.90,27.50], [-1.60,7.40,38.00], [15.41,-0.75,-4.09], [1.34,-2.85,-4.47], [0.16,14.03,-7.61], [1.56,-3.28,-5.16]]), + (398, [[-42.70,-8.00,62.70], [-6.50,1.70,7.10], [15.40,-0.75,-4.08], [-0.01,0.00,0.01], [8.70,6.15,-11.87], [-0.01,0.00,0.00]]), + (399, [[-63.30,1.20,96.30], [-26.00,27.20,0.00], [15.39,-0.74,-4.07], [-0.01,0.00,0.00], [4.77,-10.89,-10.61], [-0.01,0.00,0.00]]), + (400, [[-78.00,27.60,100.90], [37.30,13.80,0.20], [15.37,-0.74,-4.07], [-8.40,-4.20,4.36], [11.85,8.81,-5.96], [-9.71,-4.86,5.05]]), + (401, [[-31.50,35.20,105.20], [15.60,-22.20,3.00], [-7.10,-12.01,7.62], [-11.72,-1.75,3.45], [-1.14,-10.45,-11.93], [-13.57,-2.02,3.99]]), + (402, [[-34.50,-1.20,104.80], [-10.90,-26.50,-24.40], [-13.35,-6.68,5.45], [4.66,-0.01,-4.41], [-9.62,6.68,-10.73], [5.39,-0.02,-5.10]]), + (403, [[-5.70,4.10,69.80], [22.60,26.50,-0.50], [7.22,-13.73,-3.36], [11.49,4.26,-3.48], [-6.46,-2.27,-14.31], [13.31,4.94,-4.03]]), + (404, [[-8.00,34.90,79.80], [-9.00,30.20,23.80], [15.31,-0.74,-4.06], [3.58,5.76,-0.31], [-1.18,3.33,-15.46], [4.16,6.67,-0.35]]), + (405, [[-24.40,59.80,98.70], [-18.30,17.30,14.10], [15.30,-0.74,-4.05], [-1.58,4.17,-0.52], [5.62,-2.37,-14.63], [-1.83,4.84,-0.61]]), + (406, [[-52.80,83.20,117.00], [-19.40,32.60,10.00], [11.40,9.59,-5.36], [-1.64,-2.45,7.05], [-7.37,1.06,-13.96], [-1.90,-2.84,8.18]]), + (407, [[-33.10,94.80,102.90], [22.10,-6.20,-30.40], [11.18,-4.03,10.43], [0.95,-7.69,3.13], [-5.60,-14.79,0.42], [1.10,-8.91,3.63]]), + (408, [[-19.60,67.80,71.00], [-12.00,23.60,-71.10], [14.18,-5.72,-3.98], [-0.41,5.00,-8.19], [-6.55,-14.01,-3.24], [-0.47,5.81,-9.51]]), + (409, [[-69.80,126.80,91.50], [-61.80,12.70,9.10], [7.64,13.03,-4.51], [1.21,0.41,0.04], [2.52,-4.38,-14.93], [1.42,0.48,0.04]]), + (410, [[-121.30,169.50,92.00], [-11.10,37.00,0.00], [15.20,-0.73,-4.03], [1.04,-10.30,0.16], [-2.39,-6.01,-14.35], [1.22,-11.98,0.19]]), + (411, [[-114.50,225.50,92.00], [69.10,44.90,0.00], [10.70,-10.76,-4.10], [-8.87,-5.78,-0.28], [0.37,5.13,-14.86], [-10.32,-6.73,-0.33]]), + (412, [[-65.20,213.40,92.00], [33.20,-32.20,0.00], [-4.64,-14.27,-4.64], [-9.41,1.68,-1.87], [7.96,-1.26,-13.48], [-10.96,1.95,-2.18]]), + (413, [[-41.70,168.20,81.00], [8.20,-39.50,-1.80], [-11.15,-7.27,-8.30], [-1.36,1.33,-1.36], [8.85,-2.92,-12.62], [-1.58,1.55,-1.59]]), + (414, [[-32.20,130.30,62.30], [24.30,-54.00,-19.60], [-8.60,-10.28,-8.12], [1.34,-1.11,-0.38], [6.96,-1.16,-14.00], [1.56,-1.30,-0.45]]), + (415, [[13.30,68.90,25.90], [74.40,51.70,-56.50], [-9.28,-7.79,-9.90], [6.57,-0.10,0.78], [-12.40,9.38,1.71], [7.67,-0.13,0.90]]), + (416, [[-52.20,119.90,-39.10], [-64.10,-49.60,36.30], [9.14,-11.37,-5.48], [7.36,2.12,-1.37], [9.51,1.17,12.30], [8.61,2.47,-1.62]]), + (417, [[0.60,40.90,-6.30], [-35.10,-73.30,-52.20], [8.63,-3.53,-12.44], [-8.63,0.31,2.35], [5.24,-13.94,4.44], [-10.11,0.35,2.75]]), + (418, [[-93.60,68.70,-44.60], [-75.00,91.80,-77.60], [-11.00,-10.92,0.23], [-8.60,-3.22,5.56], [-5.10,5.26,13.66], [-10.08,-3.79,6.52]]), + (419, [[-10.30,30.20,-41.90], [25.00,-66.20,-30.80], [-10.97,-10.89,0.23], [8.19,6.85,5.89], [-2.70,-0.59,-15.21], [9.62,8.03,6.92]]), + (420, [[-50.40,-34.50,-84.60], [-46.00,102.90,-35.50], [6.96,4.09,13.14], [6.94,5.55,5.15], [13.88,0.32,-6.72], [8.16,6.52,6.07]]), + (421, [[-41.40,32.40,-58.90], [-91.30,85.20,-56.10], [6.80,3.44,13.37], [-2.72,1.28,0.04], [14.99,1.22,-3.30], [-3.20,1.52,0.06]]), + (422, [[-114.30,-19.20,-124.30], [-81.00,8.40,9.10], [-0.47,7.88,13.17], [0.59,-0.71,0.09], [-2.23,13.25,-7.43], [0.71,-0.83,0.13]]), + (423, [[-129.50,59.30,-86.40], [-83.60,13.00,50.80], [6.56,2.89,13.54], [2.54,-3.98,0.65], [-1.22,15.08,-2.38], [3.00,-4.70,0.79]]), + (424, [[-193.40,-50.20,-121.30], [-158.00,10.70,45.10], [3.30,-1.08,14.87], [-2.63,2.52,-0.11], [0.46,15.22,1.05], [-3.10,2.98,-0.11]]), + (425, [[-260.70,9.90,-99.50], [-72.10,-15.50,-24.10], [0.44,6.55,13.74], [-1.24,1.76,-0.01], [4.85,13.83,-4.13], [-1.46,2.09,0.01]]), + (426, [[-339.40,-58.30,-138.90], [-98.20,0.40,-23.00], [0.64,2.26,15.01], [-1.75,1.21,-0.89], [4.50,14.44,-1.28], [-2.08,1.44,-1.04]]), + (427, [[-392.70,8.10,-127.60], [58.00,12.90,-44.30], [-3.35,8.68,11.96], [-0.09,0.88,-0.16], [0.81,-8.79,12.31], [-0.11,1.05,-0.17]]), + (428, [[-318.60,-12.70,-117.30], [82.30,72.00,33.30], [-0.09,5.02,14.26], [0.82,-1.67,0.99], [12.74,-5.73,5.79], [0.97,-1.97,1.19]]), + (429, [[-400.20,75.30,-134.70], [185.90,159.10,45.20], [-3.30,6.20,13.33], [-0.07,1.98,-1.16], [10.32,-8.05,7.46], [-0.09,2.36,-1.36]]), + (430, [[-297.10,32.20,-114.40], [170.70,159.00,13.00], [-0.44,9.53,11.61], [-1.28,1.68,-1.81], [12.34,-3.86,7.64], [-1.53,2.01,-2.14]]), + (431, [[-183.70,12.90,-89.70], [13.00,150.40,-5.30], [-6.15,10.11,9.18], [-3.94,-4.23,-0.25], [10.28,8.60,6.67], [-4.71,-5.05,-0.28]]), + (432, [[-336.80,87.50,-103.70], [-17.50,86.10,36.10], [-9.24,-1.63,11.58], [4.82,0.55,1.73], [10.27,2.82,10.43], [5.77,0.68,2.09]]), + (433, [[-251.90,87.50,-90.80], [85.40,-108.30,36.10], [1.48,6.38,13.35], [2.95,-0.08,1.37], [-12.10,-7.18,4.81], [3.53,-0.09,1.66]]), + (434, [[-181.50,101.00,-68.40], [88.50,-70.20,49.50], [-1.14,-0.38,14.79], [-1.06,-4.88,0.18], [-4.44,-14.11,1.21], [-1.27,-5.85,0.23]]), + (435, [[-170.30,54.60,-111.80], [73.70,-24.10,-48.10], [-1.11,-5.01,13.90], [-2.34,5.28,-2.64], [-11.88,-8.82,-0.69], [-2.81,6.35,-3.16]]), + (436, [[-123.20,76.70,-98.70], [73.80,14.70,83.70], [-6.08,9.98,9.07], [-4.11,1.60,-5.47], [-3.58,-9.93,10.36], [-4.95,1.91,-6.57]]), + (437, [[-53.70,112.30,-68.10], [-112.20,97.90,113.50], [-10.47,-10.40,0.23], [-1.90,-8.86,-3.85], [5.83,-5.70,12.30], [-2.30,-10.67,-4.63]]), + (438, [[-42.10,136.80,15.40], [139.60,-1.80,110.30], [-10.45,-10.37,0.22], [2.10,-1.42,-0.53], [0.19,-6.57,-13.17], [2.52,-1.73,-0.64]]), + (439, [[8.20,95.10,34.30], [-24.80,-1.90,92.70], [-6.19,-13.30,-0.86], [0.32,0.74,3.30], [12.59,-6.22,4.32], [0.37,0.88,3.99]]), + (440, [[16.90,122.10,92.60], [26.30,5.60,42.10], [-8.88,-9.49,6.81], [-1.66,0.65,-1.50], [8.76,-11.07,-4.01], [-2.01,0.77,-1.81]]), + (441, [[25.30,149.50,92.30], [-11.10,35.90,0.00], [-10.40,-10.33,0.22], [-0.75,-0.41,-3.28], [2.21,-6.43,12.99], [-0.91,-0.50,-3.96]]), + (442, [[-9.30,181.40,93.40], [-17.10,39.40,0.00], [-10.39,-10.31,0.22], [0.35,9.47,-2.05], [2.32,-4.80,13.63], [0.42,11.45,-2.48]]), + (443, [[-3.30,218.30,94.20], [39.10,16.20,0.00], [-9.65,10.16,-4.20], [8.92,8.72,-0.98], [-6.26,1.96,13.08], [10.79,10.55,-1.19]]), + (444, [[33.30,192.20,83.10], [42.50,-69.90,-17.10], [12.42,7.57,-1.31], [12.06,-2.03,2.94], [2.78,-2.09,14.19], [14.60,-2.45,3.56]]), + (445, [[29.00,113.80,73.30], [13.20,-7.90,-43.20], [13.13,5.61,2.93], [0.73,-5.94,-0.50], [4.80,-13.22,3.84], [0.89,-7.19,-0.61]]), + (446, [[53.50,137.40,54.40], [22.90,17.80,6.30], [14.05,-3.81,-0.14], [0.39,-1.17,-2.28], [7.30,8.20,-9.56], [0.48,-1.41,-2.77]]), + (447, [[57.60,178.10,62.90], [-9.40,32.20,-3.10], [14.04,2.98,-2.35], [-0.01,2.18,-0.71], [-1.74,-2.76,-14.18], [-0.01,2.65,-0.87]]), + (448, [[40.10,195.20,59.60], [-3.40,25.80,-0.90], [14.03,2.98,-2.35], [-0.01,-0.00,0.00], [-2.38,0.39,-14.33], [-0.01,0.00,0.00]]), + (449, [[57.30,231.00,78.90], [-15.50,11.50,19.40], [14.02,2.98,-2.35], [-0.01,-0.00,0.00], [1.64,5.09,-13.50], [-0.01,0.00,0.00]]), + (450, [[34.30,245.80,93.80], [-46.90,3.20,0.00], [14.00,2.98,-2.34], [-0.01,-0.00,0.00], [13.58,-3.28,-3.92], [-0.01,0.00,0.00]]), + (451, [[5.80,255.40,92.60], [2.30,2.40,34.80], [13.99,2.98,-2.34], [-4.14,-6.59,-1.04], [-3.20,14.00,-1.97], [-5.03,-8.01,-1.27]]), + (452, [[37.80,263.40,105.50], [25.30,1.40,0.00], [3.92,-13.05,-4.88], [-9.58,-6.24,-0.76], [2.92,5.06,-13.25], [-11.64,-7.58,-0.92]]), + (453, [[72.90,262.00,95.30], [27.10,-36.00,-29.30], [-8.26,-11.16,-4.04], [-3.75,0.11,0.48], [-0.60,2.85,-14.17], [-4.56,0.13,0.57]]), + (454, [[74.30,240.00,41.90], [65.30,-11.40,-10.10], [0.07,-13.89,-3.97], [7.15,-0.12,0.45], [1.53,3.34,-13.97], [8.71,-0.16,0.54]]), + (455, [[104.20,247.50,91.20], [23.80,44.00,5.50], [8.34,-11.39,-3.00], [2.79,12.36,2.88], [-4.37,-3.22,-13.36], [3.41,15.07,3.51]]), + (456, [[105.20,286.30,78.80], [-59.10,14.70,15.40], [7.77,11.94,2.14], [-4.20,11.14,0.08], [1.32,2.98,-14.03], [-5.12,13.58,0.10]]), + (457, [[79.00,257.00,53.90], [-35.60,-5.00,-14.30], [-1.64,13.96,-3.05], [-5.03,0.93,-0.98], [4.80,-2.31,-13.37], [-6.14,1.14,-1.19]]), + (458, [[20.00,252.70,43.90], [-73.70,-16.00,-8.60], [-3.37,13.95,0.50], [-4.01,-3.06,-0.71], [1.21,0.81,-14.29], [-4.90,-3.72,-0.87]]), + (459, [[-18.80,195.30,54.90], [-24.50,-54.20,-37.40], [-11.67,5.99,-5.79], [-3.78,-3.64,-2.86], [6.77,2.24,-12.45], [-4.63,-4.44,-3.50]]), + (460, [[-85.50,167.30,15.40], [-18.50,-23.90,-52.20], [-11.65,5.98,-5.77], [5.22,-1.93,-3.52], [5.56,5.86,-11.81], [6.38,-2.36,-4.33]]), + (461, [[-9.90,178.40,10.90], [70.50,-60.80,38.30], [0.74,1.40,-14.19], [3.58,-3.04,-3.48], [4.04,13.68,-0.74], [4.38,-3.72,-4.28]]), + (462, [[40.80,131.00,22.30], [93.00,82.10,-75.60], [-3.57,-1.06,-13.75], [-0.17,-2.60,0.37], [-5.60,13.08,-0.88], [-0.21,-3.20,0.44]]), + (463, [[15.50,223.00,15.30], [66.30,73.50,-18.10], [1.15,-4.77,-13.34], [5.85,-2.68,3.02], [-10.81,8.34,-3.93], [7.19,-3.30,3.69]]), + (464, [[84.50,187.60,6.70], [63.20,-22.90,74.10], [9.72,-7.39,-7.21], [1.95,3.39,0.57], [8.70,11.18,-0.61], [2.40,4.17,0.68]]), + (465, [[81.80,195.00,99.00], [85.20,-17.50,-8.30], [4.96,3.89,-12.66], [-5.95,3.42,-2.24], [8.04,10.82,4.29], [-7.33,4.21,-2.77]]), + (466, [[144.30,215.80,88.40], [56.60,35.60,-14.80], [-3.43,2.97,-13.36], [-6.00,-0.83,0.66], [-4.99,12.62,3.89], [-7.40,-1.02,0.80]]), + (467, [[178.40,287.40,86.20], [6.50,74.90,-2.80], [-8.76,1.95,-10.85], [-2.09,-5.60,3.23], [-10.59,2.84,8.83], [-2.58,-6.92,3.98]]), + (468, [[160.50,350.90,83.50], [-55.40,54.50,2.60], [-8.76,-9.20,-6.04], [4.12,-6.89,3.11], [-3.63,-4.88,12.68], [5.08,-8.53,3.83]]), + (469, [[79.50,372.50,92.00], [-94.70,-10.00,12.80], [2.10,-13.31,-3.93], [8.18,5.30,-0.77], [3.37,-3.46,13.17], [10.12,6.55,-0.96]]), + (470, [[56.20,296.40,44.30], [5.10,-77.10,-40.60], [10.08,4.95,-8.35], [-0.89,8.18,-2.63], [9.68,-4.29,9.15], [-1.10,10.13,-3.27]]), + (471, [[86.50,241.90,24.50], [53.00,-52.30,0.20], [3.03,8.68,-10.52], [-3.05,-2.57,-2.05], [4.54,10.28,8.30], [-3.77,-3.18,-2.56]]), + (472, [[152.10,205.80,56.00], [63.60,-8.30,10.00], [3.75,-2.52,-13.19], [-0.12,-2.70,-1.03], [3.99,13.25,-1.69], [-0.15,-3.35,-1.29]]), + (473, [[198.40,215.10,56.00], [38.20,22.50,-1.40], [3.11,-0.98,-13.53], [-0.74,1.84,-0.19], [-4.66,12.88,-2.50], [-0.92,2.29,-0.25]]), + (474, [[231.60,243.60,55.70], [23.70,41.90,-1.20], [2.03,1.74,-13.65], [-0.06,0.95,0.02], [-10.43,9.15,-0.98], [-0.08,1.18,0.02]]), + (475, [[254.20,308.60,53.70], [-36.30,58.90,0.00], [3.59,0.22,-13.41], [1.44,-1.14,0.41], [-10.53,-8.47,-3.17], [1.80,-1.42,0.49]]), + (476, [[201.60,339.10,45.30], [-53.50,14.40,-12.40], [5.39,-0.96,-12.74], [1.75,-3.67,9.37], [-1.05,-13.82,0.09], [2.19,-4.57,11.67]]), + (477, [[225.60,364.90,17.70], [84.00,-17.10,-36.30], [7.68,-8.22,8.07], [-1.74,-1.93,11.58], [0.09,-11.24,-8.08], [-2.17,-2.41,14.45]]), + (478, [[262.20,310.80,24.60], [19.90,-60.50,3.10], [0.53,-4.56,13.03], [-3.49,2.51,2.39], [-10.55,-8.90,-0.68], [-4.35,3.12,3.00]]), + (479, [[266.70,240.60,17.50], [-54.80,-92.30,1.00], [-0.35,-2.40,13.58], [-0.74,1.97,0.30], [-12.86,4.89,0.94], [-0.93,2.46,0.39]]), + (480, [[191.50,210.20,17.50], [-54.20,-18.80,19.40], [-1.21,0.07,13.70], [0.91,2.69,-0.23], [-9.15,10.19,1.31], [1.14,3.36,-0.27]]), + (481, [[126.50,239.40,20.10], [-85.50,-4.10,-17.80], [1.56,3.82,13.10], [1.41,1.92,-0.33], [4.42,12.70,-2.76], [1.77,2.40,-0.39]]), + (482, [[27.70,256.90,-12.00], [25.60,34.70,43.20], [1.53,3.79,13.06], [-0.00,-0.01,-0.03], [9.79,2.46,9.24], [0.00,-0.01,-0.02]]), + (483, [[83.20,288.30,-1.00], [33.20,-4.80,-3.70], [1.53,3.78,13.04], [-0.00,-0.01,-0.03], [-1.89,-12.93,3.99], [0.00,-0.01,-0.02]]), + (484, [[213.40,266.00,3.10], [68.30,112.60,23.20], [1.54,3.79,12.99], [-0.00,-0.01,-0.03], [13.46,-1.13,1.71], [0.00,-0.01,-0.02]]), + (485, [[188.20,299.90,26.40], [-48.40,-18.80,4.40], [1.54,3.76,12.97], [-0.00,-0.01,-0.02], [-3.42,12.78,-3.08], [0.00,-0.00,-0.01]]), + (486, [[130.20,290.80,30.50], [-44.60,71.50,28.90], [1.54,3.76,12.95], [-0.01,-0.01,-0.02], [5.93,12.16,-1.02], [0.00,-0.00,-0.01]]), + (487, [[136.70,339.40,47.80], [-100.80,75.50,26.60], [1.53,3.75,12.93], [-0.01,-0.01,-0.03], [3.93,12.60,-3.07], [0.00,-0.01,-0.02]]), + (488, [[47.80,248.50,21.60], [-98.10,56.50,2.30], [1.53,3.74,12.88], [-0.00,-0.01,-0.04], [5.65,11.60,-3.99], [0.00,-0.01,-0.02]]), + (489, [[59.30,327.60,28.10], [34.80,103.20,-11.30], [1.52,3.73,12.85], [-0.00,-0.01,-0.03], [13.35,-1.71,-0.52], [0.00,-0.01,-0.02]]), + (490, [[158.50,381.30,13.00], [145.50,-5.80,-42.40], [1.52,3.72,12.81], [-0.01,-0.01,-0.04], [-1.62,-12.62,4.27], [0.00,-0.01,-0.03]]), + (491, [[240.70,304.70,-6.30], [49.30,-67.70,-27.10], [1.50,3.70,12.77], [-0.01,-0.01,-0.03], [-12.00,-3.05,5.07], [0.00,-0.01,-0.02]]), + (492, [[240.40,234.90,-17.20], [-74.10,-88.50,16.10], [1.51,3.71,12.74], [-0.00,-0.01,-0.03], [-8.90,9.83,-1.49], [0.00,-0.01,-0.02]]), + (493, [[173.00,289.90,-12.50], [56.50,158.10,0.10], [1.51,3.69,12.71], [-0.00,-0.01,-0.04], [13.31,-0.52,-0.18], [0.00,-0.01,-0.02]]), + (494, [[109.50,348.10,-9.70], [-74.10,-88.50,16.10], [1.51,3.69,12.67], [-0.01,-0.01,-0.02], [-8.85,9.78,-1.48], [0.00,-0.00,-0.01]]), + (495, [[88.40,320.90,-6.10], [-71.10,-68.40,21.40], [1.50,3.67,12.66], [-0.01,-0.01,-0.01], [-8.75,9.82,-1.75], [0.00,-0.00,-0.01]]), + (496, [[61.80,280.20,-37.60], [69.10,-114.80,-49.00], [1.50,3.67,12.64], [-0.00,-0.01,-0.03], [-12.10,-1.34,5.24], [0.00,-0.00,-0.02]]), + (497, [[132.90,264.70,-28.90], [-44.70,-165.90,-57.30], [1.48,3.66,12.61], [-0.00,-0.01,-0.04], [-8.48,9.70,2.90], [0.00,-0.01,-0.02]]), + (498, [[147.20,179.70,61.30], [91.20,-36.60,30.40], [1.49,3.66,12.56], [-0.01,-0.01,-0.04], [-2.24,-12.03,4.87], [0.00,-0.01,-0.02]]), + (499, [[238.20,177.20,65.00], [18.30,-82.80,-18.10], [1.47,3.65,12.53], [-6.46,-1.97,-8.08], [-12.42,2.57,3.39], [-8.32,-2.53,-10.38]]), + (500, [[197.80,161.40,50.30], [67.60,35.60,-126.70], [-12.26,-0.53,-4.63], [0.94,-2.52,-10.53], [-2.37,12.18,4.22], [1.21,-3.24,-13.56]]), + (501, [[254.20,183.80,49.30], [-11.80,23.50,62.10], [4.62,-2.23,-12.04], [10.29,-1.14,3.54], [0.07,-2.27,-12.88], [13.26,-1.47,4.56]]), + (502, [[277.70,254.80,52.00], [-1.10,48.50,-21.40], [12.21,-3.24,3.31], [0.61,0.19,-0.28], [1.81,-9.01,-9.27], [0.80,0.24,-0.38]]), + (503, [[291.40,209.50,13.10], [-39.30,-47.20,-6.60], [6.85,-1.93,-10.90], [-3.43,0.14,-6.40], [9.23,-6.36,6.65], [-4.42,0.18,-8.27]]), + (504, [[227.20,207.90,6.30], [-93.70,-69.70,-8.90], [4.07,-2.87,-12.01], [0.12,0.05,0.07], [7.43,-9.54,4.76], [0.16,0.06,0.08]]), + (505, [[186.40,164.40,16.90], [-71.70,-61.20,-10.00], [6.83,-1.92,-10.86], [1.27,0.44,0.54], [8.91,-7.14,6.16], [1.65,0.57,0.68]]), + (506, [[118.40,159.70,1.30], [-74.40,26.40,-38.50], [6.81,-1.92,-10.84], [-0.02,0.00,0.03], [-2.76,-12.65,0.27], [-0.01,0.00,0.02]]), + (507, [[42.70,245.00,-45.30], [77.70,116.50,19.30], [6.79,-1.92,-10.80], [-0.03,0.01,0.04], [-8.26,7.43,-6.56], [-0.02,0.00,0.03]]), + (508, [[159.90,180.50,-31.40], [106.20,76.60,20.20], [6.76,-1.90,-10.75], [-0.03,0.01,0.04], [-3.78,11.20,-5.02], [-0.02,0.00,0.03]]), + (509, [[134.10,292.30,-47.10], [34.50,97.60,13.80], [6.73,-1.90,-10.73], [-0.02,0.01,0.03], [-10.09,3.53,-7.05], [-0.01,0.00,0.02]]), + (510, [[193.30,275.10,-46.30], [23.80,-61.70,26.10], [6.72,-1.89,-10.69], [-3.56,1.74,-0.59], [9.96,6.08,5.19], [-4.64,2.27,-0.79]]), + (511, [[190.90,187.00,-52.20], [66.50,-39.30,3.60], [-2.38,2.55,-12.25], [-3.82,1.31,-0.79], [2.74,12.42,0.81], [-5.00,1.72,-1.05]]), + (512, [[254.20,247.30,-47.60], [-23.50,92.50,19.80], [-1.93,0.97,-12.52], [0.99,-1.69,-0.13], [-11.80,-4.51,1.36], [1.29,-2.21,-0.20]]), + (513, [[228.40,321.30,-41.20], [52.70,188.20,-7.70], [-0.13,-1.39,-12.60], [3.62,-1.19,0.81], [-12.42,2.55,-0.21], [4.76,-1.57,1.05]]), + (514, [[176.60,339.50,-38.20], [-78.70,16.00,21.50], [6.66,-1.86,-10.59], [2.47,-0.17,0.74], [7.34,-10.12,-1.95], [3.25,-0.23,0.96]]), + (515, [[119.00,367.30,-29.70], [-127.00,18.70,4.70], [6.64,-1.87,-10.58], [-0.02,0.00,0.03], [5.68,-11.26,0.62], [-0.01,0.00,0.02]]), + (516, [[91.40,252.30,-63.20], [23.10,-112.20,118.60], [6.62,-1.87,-10.53], [-0.03,0.01,0.04], [7.75,9.89,0.38], [-0.02,0.00,0.03]]), + (517, [[175.10,162.40,-53.90], [-54.80,-66.80,32.70], [6.59,-1.86,-10.49], [-0.03,0.01,0.04], [11.97,0.65,3.64], [-0.02,0.00,0.03]]), + (518, [[70.80,203.50,-65.80], [-102.40,-41.90,-13.50], [6.57,-1.85,-10.45], [-0.02,0.01,0.03], [7.44,-8.87,4.67], [-0.01,0.00,0.02]]), + (519, [[52.30,140.20,-39.60], [-180.50,-24.10,75.00], [6.56,-1.83,-10.42], [-0.01,0.01,0.02], [10.92,-5.86,-1.23], [-0.01,0.00,0.01]]), + (520, [[6.80,106.50,-47.40], [-171.30,31.80,-4.10], [6.54,-1.84,-10.42], [-0.02,0.00,0.02], [4.47,-11.58,0.76], [-0.01,0.00,0.02]]), + (521, [[27.90,191.60,-30.80], [-96.90,52.70,-49.30], [6.53,-1.84,-10.38], [-0.02,0.00,0.03], [-3.83,-11.78,-0.64], [-0.01,0.00,0.02]]), + (522, [[-17.90,115.60,-73.10], [-104.10,42.30,14.10], [6.50,-1.84,-10.34], [-0.02,0.01,0.04], [3.67,-11.67,-1.73], [-0.01,0.00,0.02]]), + (523, [[1.90,223.30,-37.40], [44.00,82.00,-9.10], [6.48,-1.83,-10.30], [-0.02,0.01,0.03], [-8.06,6.38,-6.78], [-0.01,0.00,0.02]]), + (524, [[33.20,282.60,-58.50], [-23.00,67.10,-26.70], [6.46,-1.82,-10.28], [0.79,3.52,4.91], [-9.76,-5.35,-5.20], [1.08,4.71,6.57]]), + (525, [[67.80,358.20,-24.30], [-2.30,0.30,54.60], [8.70,7.96,3.32], [1.46,2.72,1.91], [-8.05,8.86,2.62], [1.97,3.65,2.54]]), + (526, [[40.70,358.70,43.40], [-22.60,47.20,59.80], [10.07,6.17,-3.14], [-2.81,1.16,1.68], [-6.06,5.75,-8.92], [-3.76,1.57,2.26]]), + (527, [[29.20,413.00,41.50], [-60.50,10.90,19.00], [2.71,10.25,6.04], [-2.85,2.07,3.48], [-2.92,6.65,-9.81], [-3.83,2.79,4.68]]), + (528, [[-26.50,361.80,43.10], [-56.30,17.20,1.60], [4.26,10.71,3.91], [2.65,-1.03,-4.10], [1.65,3.61,-11.51], [3.58,-1.38,-5.52]]), + (529, [[-23.40,393.00,43.00], [-7.70,31.40,-0.90], [8.20,8.68,-2.31], [-0.97,0.74,-1.25], [-3.55,5.57,-10.21], [-1.31,1.01,-1.68]]), + (530, [[-36.60,415.60,41.80], [-25.50,17.70,1.00], [3.39,11.66,-0.43], [-4.02,1.55,1.19], [-3.78,1.95,-11.38], [-5.42,2.09,1.60]]), + (531, [[-70.00,421.50,45.40], [-30.80,-9.50,1.40], [-1.42,12.05,0.40], [-5.91,-4.42,2.80], [1.42,0.95,-12.01], [-7.98,-5.96,3.78]]), + (532, [[-90.30,401.60,44.50], [-15.10,-33.40,-0.70], [-10.42,1.99,5.88], [-2.95,-8.68,2.68], [-6.30,0.47,-10.36], [-3.98,-11.72,3.63]]), + (533, [[-91.80,361.20,44.50], [35.10,-38.10,-18.40], [-5.87,-8.91,5.73], [6.01,-6.11,-1.81], [-6.62,-2.05,-9.93], [8.12,-8.26,-2.44]]), + (534, [[-38.80,367.10,17.80], [33.30,56.60,-27.60], [5.34,-10.83,0.53], [6.11,6.76,-2.78], [-6.72,-7.33,-6.87], [8.27,9.14,-3.76]]), + (535, [[-55.20,436.50,11.50], [-50.10,54.50,-0.10], [8.19,8.83,-0.65], [0.24,8.59,-0.86], [-1.11,0.26,-12.00], [0.34,11.63,-1.17]]), + (536, [[-121.40,460.30,17.10], [-86.80,60.90,-1.80], [6.07,10.28,-1.54], [0.90,-2.49,-1.08], [-1.49,-0.82,-11.91], [1.24,-3.38,-1.46]]), + (537, [[-164.50,536.10,-17.30], [-9.90,55.20,-8.50], [11.44,1.36,-3.37], [8.03,-12.39,-1.98], [-3.05,-2.47,-11.34], [10.93,-16.81,-2.68]]) + ] ), + 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-5', + 'identifierRanges': '1-536', + 'name': get_smallintestine_term('small intestine')[0], + 'ontId': get_smallintestine_term('small intestine')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-17', 'name': get_smallintestine_term('duodenum')[0], 'ontId': get_smallintestine_term('duodenum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '6-82', + 'identifierRanges': '18-235', 'name': get_smallintestine_term('jejunum')[0], 'ontId': get_smallintestine_term('jejunum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '83-150', + 'identifierRanges': '236-536', 'name': get_smallintestine_term('ileum')[0], 'ontId': get_smallintestine_term('ileum')[1] }] - }), - - 'Mouse 1' : ScaffoldPackage(MeshType_1d_path1, { - 'scaffoldSettings' : { - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Coordinate dimensions' : 3, - 'Length' : 1.0, - 'Number of elements' : 45 - }, - 'meshEdits' : exnode_string_from_nodeset_field_parameters( + }) + + elif "Mouse 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "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" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ - (1, [ [ -2.30, 18.50, -4.40 ], [ -4.20, -0.80, 3.70 ], [ 0.00, 0.60, 0.00 ], [ 0.00, 0.11, 0.00 ], [ -0.33, 0.01, -0.50 ], [ 0.00, 0.00, 0.50 ] ] ), - (2, [ [ -8.60, 16.30, -0.40 ], [ -7.10, -2.70, 1.60 ], [ 0.00, 0.73, 0.00 ], [ 0.00, 0.14, 0.00 ], [ 0.08, 0.09, -0.72 ], [ 0.00, 0.00, 0.50 ] ] ), - (3, [ [ -18.30, 12.60, -1.50 ], [ -6.40, -1.70, -3.80 ], [ 0.00, 0.90, 0.00 ], [ 0.00, 0.13, 0.00 ], [ 0.61, 0.04, -0.65 ], [ 0.00, 0.00, 0.50 ] ] ), - (4, [ [ -15.60, 13.70, -6.10 ], [ 7.00, 2.10, -1.80 ], [ 0.00, 1.00, 0.00 ], [ 0.00, 0.05, 0.00 ], [ 0.50, 0.08, 0.86 ], [ 0.00, 0.00, 0.50 ] ] ), - (5, [ [ -9.30, 14.80, -4.90 ], [ 4.70, 0.70, 1.80 ], [ 0.00, 1.00, 0.00 ], [ 0.00, 0.00, 0.00 ], [ -0.23, 0.02, 0.97 ], [ 0.00, 0.00, 0.50 ] ] ), - (6, [ [ -3.90, 15.70, -3.00 ], [ 4.30, 0.70, 2.00 ], [ 0.00, 1.00, 0.00 ], [ 0.17, -1.19, 0.09 ], [ -0.29, 0.02, 0.96 ], [ 0.00, 0.00, 0.50 ] ] ), - (7, [ [ -3.40, 13.40, -2.80 ], [ -4.10, -0.70, -1.70 ], [ 0.28, -0.95, 0.14 ], [ 0.03, -1.11, 0.04 ], [ -0.23, 0.05, 0.97 ], [ 0.00, 0.00, 0.50 ] ] ), - (8, [ [ -7.60, 12.40, -4.60 ], [ -3.70, -0.80, -0.90 ], [ 0.00, -1.00, 0.05 ], [ -0.14, -0.02, -0.04 ], [ -0.43, 0.01, 0.90 ], [ 0.00, 0.00, 0.50 ] ] ), - (9, [ [ -11.60, 11.60, -5.70 ], [ -4.20, -0.70, -0.20 ], [ 0.00, -1.00, 0.05 ], [ 0.09, 0.01, -0.08 ], [ -0.21, 0.03, 0.98 ], [ 0.00, 0.00, 0.50 ] ] ), - (10, [ [ -16.50, 11.70, -3.90 ], [ -1.00, 0.20, 5.80 ], [ 0.21, -0.97, -0.14 ], [ -0.04, 0.05, -0.25 ], [ 0.98, 0.17, -0.04 ], [ 0.00, 0.00, 0.50 ] ] ), - (11, [ [ -12.50, 11.70, -1.40 ], [ 3.60, 0.10, 0.60 ], [ -0.06, -0.89, -0.45 ], [ -0.31, 0.12, -0.21 ], [ -0.02, 0.43, -0.90 ], [ 0.00, 0.00, 0.50 ] ] ), - (12, [ [ -6.80, 11.80, -0.60 ], [ 2.90, 0.00, 0.70 ], [ -0.42, -0.72, -0.54 ], [ -0.16, 1.09, 0.46 ], [ -0.35, 0.43, -0.83 ], [ 0.00, 0.00, 0.50 ] ] ), - (13, [ [ -6.40, 9.80, -1.60 ], [ -2.90, -0.30, -1.40 ], [ -0.48, 0.85, 0.21 ], [ 0.07, 0.85, 0.47 ], [ 0.12, 0.37, -0.92 ], [ 0.00, 0.00, 0.50 ] ] ), - (14, [ [ -9.50, 9.50, -2.90 ], [ -4.60, 0.00, -1.80 ], [ -0.26, 0.89, 0.37 ], [ 0.21, 0.05, 0.07 ], [ 0.22, 0.44, -0.87 ], [ 0.00, 0.00, 0.50 ] ] ), - (15, [ [ -14.30, 9.40, -4.60 ], [ -3.40, 0.10, -1.60 ], [ -0.06, 0.95, 0.30 ], [ 0.14, 0.05, -0.18 ], [ 0.46, 0.29, -0.84 ], [ 0.00, 0.00, 0.50 ] ] ), - (16, [ [ -19.00, 9.40, -2.90 ], [ 0.30, 0.20, 6.70 ], [ 0.00, 1.00, 0.00 ], [ 0.17, -0.03, 0.03 ], [ -1.00, 0.00, 0.07 ], [ 0.00, 0.00, 0.50 ] ] ), - (17, [ [ -14.50, 9.70, 0.20 ], [ 3.60, -1.20, 1.00 ], [ 0.28, 0.89, 0.36 ], [ 0.37, -0.41, 0.31 ], [ -0.26, -0.29, 0.92 ], [ 0.00, 0.00, 0.50 ] ] ), - (18, [ [ -12.60, 7.70, 0.70 ], [ 0.60, -2.70, 0.20 ], [ 0.69, 0.32, 0.65 ], [ 0.15, -0.68, 0.19 ], [ -0.68, 0.03, 0.73 ], [ 0.00, 0.00, 0.50 ] ] ), - (19, [ [ -13.10, 3.80, 0.30 ], [ -4.00, -3.60, -1.50 ], [ 0.47, -0.52, 0.71 ], [ -0.73, -0.40, -0.16 ], [ -0.46, 0.51, 0.73 ], [ 0.00, 0.00, 0.50 ] ] ), - (20, [ [ -15.20, 5.10, -0.80 ], [ 6.00, 6.90, 1.80 ], [ -0.87, -0.39, 0.29 ], [ -0.53, 0.27, 0.04 ], [ -0.22, -0.94, 0.24 ], [ 0.00, 0.00, 0.50 ] ] ), - (21, [ [ -17.30, 6.90, -1.00 ], [ -2.50, 0.00, -0.40 ], [ -0.69, 0.00, 0.73 ], [ -0.05, -0.05, -0.12 ], [ -0.55, 0.83, -0.09 ], [ 0.00, 0.00, 0.50 ] ] ), - (22, [ [ -19.90, 6.80, -2.50 ], [ -1.50, -1.10, -3.40 ], [ -0.91, -0.35, 0.20 ], [ 0.18, -0.33, -0.70 ], [ -0.48, 0.80, -0.36 ], [ 0.00, 0.00, 0.50 ] ] ), - (23, [ [ -17.20, 6.30, -5.10 ], [ 4.00, 0.80, -1.30 ], [ -0.20, -0.64, -0.74 ], [ 0.52, -0.04, -0.62 ], [ -0.41, 0.74, -0.54 ], [ 0.00, 0.00, 0.50 ] ] ), - (24, [ [ -12.20, 7.80, -6.80 ], [ 4.80, 1.70, -0.30 ], [ 0.06, -0.35, -0.93 ], [ 0.24, 0.14, -0.07 ], [ -0.34, 0.87, -0.35 ], [ 0.00, 0.00, 0.50 ] ] ), - (25, [ [ -7.90, 9.60, -6.50 ], [ 3.70, 1.70, 0.70 ], [ 0.28, -0.34, -0.90 ], [ -0.23, 0.13, 0.01 ], [ -0.35, 0.84, -0.42 ], [ 0.00, 0.00, 0.50 ] ] ), - (26, [ [ -3.80, 10.30, -5.50 ], [ 3.80, -2.70, -0.10 ], [ -0.39, -0.09, -0.92 ], [ -0.22, 0.47, 0.06 ], [ 0.33, 0.90, -0.29 ], [ 0.00, 0.00, 0.50 ] ] ), - (27, [ [ -5.30, 7.60, -6.40 ], [ -3.50, -1.00, -1.30 ], [ -0.21, 0.58, -0.79 ], [ -0.10, 0.22, 0.09 ], [ 0.12, -0.72, -0.68 ], [ 0.00, 0.00, 0.50 ] ] ), - (28, [ [ -9.00, 6.40, -7.30 ], [ -3.20, -1.30, 1.90 ], [ -0.60, 0.33, -0.73 ], [ -0.33, -0.33, 0.51 ], [ 0.06, -0.89, -0.46 ], [ 0.00, 0.00, 0.50 ] ] ), - (29, [ [ -11.60, 4.00, -2.00 ], [ 5.60, -0.20, 4.30 ], [ -0.82, -0.14, 0.55 ], [ 0.58, -0.22, 0.77 ], [ -0.18, -0.93, -0.32 ], [ 0.00, 0.00, 0.50 ] ] ), - (30, [ [ -5.90, 5.00, -3.10 ], [ 4.10, 1.20, -1.60 ], [ 0.46, -0.14, 0.88 ], [ -0.22, -0.22, -0.11 ], [ 0.25, -0.93, -0.27 ], [ 0.00, 0.00, 0.50 ] ] ), - (31, [ [ -2.50, 6.00, -3.80 ], [ 3.60, 0.70, 3.20 ], [ -0.71, -0.50, 0.50 ], [ -0.65, 0.12, -0.73 ], [ 0.20, -0.87, -0.44 ], [ 0.00, 0.00, 0.50 ] ] ), - (32, [ [ -4.10, 3.20, -0.40 ], [ -3.50, -1.70, 2.60 ], [ -0.65, 0.26, -0.71 ], [ 0.19, 0.53, -0.71 ], [ 0.12, -0.89, -0.43 ], [ 0.00, 0.00, 0.50 ] ] ), - (33, [ [ -9.70, 1.70, 2.30 ], [ -7.90, -1.00, 1.00 ], [ -0.30, 0.51, -0.81 ], [ 0.69, 0.07, 0.25 ], [ -0.09, -0.85, -0.52 ], [ 0.00, 0.00, 0.50 ] ] ), - (34, [ [ -19.00, 0.60, -0.40 ], [ 0.20, 3.70, -6.80 ], [ 0.96, 0.29, 0.00 ], [ 0.12, -0.28, 0.90 ], [ 0.26, -0.76, -0.59 ], [ 0.00, 0.00, 0.50 ] ] ), - (35, [ [ -13.90, 2.30, -5.80 ], [ 4.40, 0.60, -1.10 ], [ 0.20, -0.04, 0.98 ], [ -0.57, -0.13, 0.44 ], [ 0.08, -1.00, -0.06 ], [ 0.00, 0.00, 0.50 ] ] ), - (36, [ [ -7.70, 1.20, -4.60 ], [ 3.90, -3.40, 1.50 ], [ -0.22, 0.00, 0.98 ], [ -0.31, 0.34, -0.17 ], [ -0.54, -0.84, -0.11 ], [ 0.00, 0.00, 0.50 ] ] ), - (37, [ [ -4.80, -4.00, -1.30 ], [ -4.20, -3.30, 3.10 ], [ -0.40, 0.67, 0.62 ], [ 0.01, 0.39, -0.20 ], [ -0.82, 0.10, -0.56 ], [ 0.00, 0.00, 0.50 ] ] ), - (38, [ [ -10.90, -6.10, -0.60 ], [ -5.30, -1.20, -0.90 ], [ -0.21, 0.81, 0.55 ], [ 0.05, 0.11, -0.14 ], [ 0.07, 0.58, -0.81 ], [ 0.00, 0.00, 0.50 ] ] ), - (39, [ [ -19.90, -6.40, -5.50 ], [ -0.30, 1.70, -10.50 ], [ -0.39, 0.87, 0.30 ], [ 0.06, 0.09, -0.23 ], [ 0.91, 0.37, 0.19 ], [ 0.00, 0.00, 0.50 ] ] ), - (40, [ [ -10.70, -3.20, -8.80 ], [ 7.80, 0.40, 0.10 ], [ -0.09, 0.99, 0.09 ], [ -0.32, -0.44, -0.23 ], [ -0.05, -0.10, 0.99 ], [ 0.00, 0.00, 0.50 ] ] ), - (41, [ [ -1.20, -1.90, -7.30 ], [ 0.80, 8.10, 2.50 ], [ -0.99, 0.03, -0.16 ], [ 0.29, -0.98, -0.16 ], [ -0.17, -0.38, 0.91 ], [ 0.00, 0.00, 0.50 ] ] ), - (42, [ [ -6.30, 0.50, -8.10 ], [ -9.80, -1.20, 0.50 ], [ 0.10, -0.96, -0.25 ], [ 0.58, -0.56, -0.12 ], [ 0.08, -0.25, 0.97 ], [ 0.00, 0.00, 0.50 ] ] ), - (43, [ [ -16.00, -0.70, -7.40 ], [ -7.60, 1.20, 1.50 ], [ -0.05, -0.91, -0.41 ], [ -0.62, 0.61, 0.13 ], [ 0.28, -0.43, 0.86 ], [ 0.00, 0.00, 0.50 ] ] ), - (44, [ [ -20.50, 2.30, -6.10 ], [ 3.50, 7.20, -2.90 ], [ -0.99, 0.09, -0.09 ], [ -0.21, 0.77, -0.11 ], [ -0.17, 0.12, 0.98 ], [ 0.00, 0.00, 0.50 ] ] ), - (45, [ [ -11.40, 2.60, -10.10 ], [ 10.40, 1.50, -0.20 ], [ -0.08, 0.51, -0.86 ], [ 0.49, 0.10, -0.38 ], [ -0.10, 0.85, 0.51 ], [ 0.00, 0.00, 0.50 ] ] ), - (46, [ [ -3.80, 4.20, -7.30 ], [ 3.50, 0.90, 2.70 ], [ 0.07, 0.36, -0.93 ], [ -0.19, -0.40, 0.24 ], [ -0.73, 0.68, 0.01 ], [ 0.00, 0.00, 0.50 ] ] ) ] ), + (1, [[-2.30,18.50,-4.40], [-4.20,-0.80,3.70], [0.00,0.70,0.00], [0.00,0.11,0.00], [-0.39,0.01,-0.58], [0.00,0.00,0.50]]), + (2, [[-8.60,16.30,-0.40], [-7.10,-2.70,1.60], [0.00,0.83,0.00], [0.00,0.14,0.00], [0.09,0.10,-0.82], [0.00,0.00,0.50]]), + (3, [[-18.30,12.60,-1.50], [-6.40,-1.70,-3.80], [0.00,1.00,0.00], [0.00,0.13,0.00], [0.68,0.04,-0.72], [0.00,0.00,0.50]]), + (4, [[-15.60,13.70,-6.10], [7.00,2.10,-1.80], [0.00,1.10,0.00], [0.00,0.05,0.00], [0.55,0.09,0.95], [0.00,0.00,0.50]]), + (5, [[-9.30,14.80,-4.90], [4.70,0.70,1.80], [0.00,1.10,0.00], [0.00,0.00,0.00], [-0.25,0.02,1.07], [0.00,0.00,0.50]]), + (6, [[-3.90,15.70,-3.00], [4.30,0.70,2.00], [0.00,1.10,0.00], [0.17,-1.19,0.09], [-0.32,0.02,1.06], [0.00,0.00,0.50]]), + (7, [[-3.40,13.40,-2.80], [-4.10,-0.70,-1.70], [0.31,-1.04,0.15], [0.03,-1.11,0.04], [-0.25,0.06,1.07], [0.00,0.00,0.50]]), + (8, [[-7.60,12.40,-4.60], [-3.70,-0.80,-0.90], [0.00,-1.10,0.05], [-0.14,-0.02,-0.04], [-0.47,0.01,0.99], [0.00,0.00,0.50]]), + (9, [[-11.60,11.60,-5.70], [-4.20,-0.70,-0.20], [0.00,-1.10,0.05], [0.09,0.01,-0.08], [-0.23,0.03,1.08], [0.00,0.00,0.50]]), + (10, [[-16.50,11.70,-3.90], [-1.00,0.20,5.80], [0.23,-1.07,-0.15], [-0.04,0.05,-0.25], [1.08,0.19,-0.04], [0.00,0.00,0.50]]), + (11, [[-12.50,11.70,-1.40], [3.60,0.10,0.60], [-0.07,-0.98,-0.50], [-0.31,0.12,-0.21], [-0.02,0.47,-0.99], [0.00,0.00,0.50]]), + (12, [[-6.80,11.80,-0.60], [2.90,0.00,0.70], [-0.46,-0.79,-0.59], [-0.16,1.09,0.46], [-0.39,0.47,-0.91], [0.00,0.00,0.50]]), + (13, [[-6.40,9.80,-1.60], [-2.90,-0.30,-1.40], [-0.53,0.94,0.23], [0.07,0.85,0.47], [0.13,0.41,-1.01], [0.00,0.00,0.50]]), + (14, [[-9.50,9.50,-2.90], [-4.60,0.00,-1.80], [-0.29,0.98,0.41], [0.21,0.05,0.07], [0.24,0.48,-0.96], [0.00,0.00,0.50]]), + (15, [[-14.30,9.40,-4.60], [-3.40,0.10,-1.60], [-0.07,1.05,0.33], [0.14,0.05,-0.18], [0.51,0.32,-0.92], [0.00,0.00,0.50]]), + (16, [[-19.00,9.40,-2.90], [0.30,0.20,6.70], [0.00,1.10,0.00], [0.17,-0.03,0.03], [-1.10,0.00,0.08], [0.00,0.00,0.50]]), + (17, [[-14.50,9.70,0.20], [3.60,-1.20,1.00], [0.31,0.98,0.40], [0.37,-0.41,0.31], [-0.29,-0.32,1.01], [0.00,0.00,0.50]]), + (18, [[-12.60,7.70,0.70], [0.60,-2.70,0.20], [0.76,0.35,0.71], [0.15,-0.68,0.19], [-0.75,0.03,0.80], [0.00,0.00,0.50]]), + (19, [[-13.10,3.80,0.30], [-4.00,-3.60,-1.50], [0.52,-0.57,0.78], [-0.73,-0.40,-0.16], [-0.51,0.56,0.80], [0.00,0.00,0.50]]), + (20, [[-15.20,5.10,-0.80], [6.00,6.90,1.80], [-0.96,-0.43,0.32], [-0.53,0.27,0.04], [-0.24,-1.03,0.26], [0.00,0.00,0.50]]), + (21, [[-17.30,6.90,-1.00], [-2.50,0.00,-0.40], [-0.76,0.00,0.80], [-0.05,-0.05,-0.12], [-0.61,0.91,-0.10], [0.00,0.00,0.50]]), + (22, [[-19.90,6.80,-2.50], [-1.50,-1.10,-3.40], [-1.00,-0.39,0.22], [0.18,-0.33,-0.70], [-0.53,0.88,-0.40], [0.00,0.00,0.50]]), + (23, [[-17.20,6.30,-5.10], [4.00,0.80,-1.30], [-0.22,-0.70,-0.81], [0.52,-0.04,-0.62], [-0.45,0.81,-0.59], [0.00,0.00,0.50]]), + (24, [[-12.20,7.80,-6.80], [4.80,1.70,-0.30], [0.07,-0.39,-1.02], [0.24,0.14,-0.07], [-0.37,0.96,-0.39], [0.00,0.00,0.50]]), + (25, [[-7.90,9.60,-6.50], [3.70,1.70,0.70], [0.31,-0.37,-0.99], [-0.23,0.13,0.01], [-0.38,0.92,-0.46], [0.00,0.00,0.50]]), + (26, [[-3.80,10.30,-5.50], [3.80,-2.70,-0.10], [-0.43,-0.10,-1.01], [-0.22,0.47,0.06], [0.36,0.99,-0.32], [0.00,0.00,0.50]]), + (27, [[-5.30,7.60,-6.40], [-3.50,-1.00,-1.30], [-0.23,0.64,-0.87], [-0.10,0.22,0.09], [0.13,-0.79,-0.75], [0.00,0.00,0.50]]), + (28, [[-9.00,6.40,-7.30], [-3.20,-1.30,1.90], [-0.66,0.36,-0.80], [-0.33,-0.33,0.51], [0.07,-0.98,-0.51], [0.00,0.00,0.50]]), + (29, [[-11.60,4.00,-2.00], [5.60,-0.20,4.30], [-0.90,-0.15,0.61], [0.58,-0.22,0.77], [-0.20,-1.02,-0.35], [0.00,0.00,0.50]]), + (30, [[-5.90,5.00,-3.10], [4.10,1.20,-1.60], [0.51,-0.15,0.97], [-0.22,-0.22,-0.11], [0.27,-1.02,-0.30], [0.00,0.00,0.50]]), + (31, [[-2.50,6.00,-3.80], [3.60,0.70,3.20], [-0.78,-0.55,0.55], [-0.65,0.12,-0.73], [0.22,-0.96,-0.48], [0.00,0.00,0.50]]), + (32, [[-4.10,3.20,-0.40], [-3.50,-1.70,2.60], [-0.72,0.29,-0.78], [0.19,0.53,-0.71], [0.13,-0.98,-0.47], [0.00,0.00,0.50]]), + (33, [[-9.70,1.70,2.30], [-7.90,-1.00,1.00], [-0.33,0.56,-0.89], [0.69,0.07,0.25], [-0.10,-0.93,-0.57], [0.00,0.00,0.50]]), + (34, [[-19.00,0.60,-0.40], [0.20,3.70,-6.80], [1.06,0.32,0.00], [0.12,-0.28,0.90], [0.29,-0.84,-0.65], [0.00,0.00,0.50]]), + (35, [[-13.90,2.30,-5.80], [4.40,0.60,-1.10], [0.22,-0.04,1.08], [-0.57,-0.13,0.44], [0.09,-1.10,-0.07], [0.00,0.00,0.50]]), + (36, [[-7.70,1.20,-4.60], [3.90,-3.40,1.50], [-0.24,0.00,1.08], [-0.31,0.34,-0.17], [-0.59,-0.92,-0.12], [0.00,0.00,0.50]]), + (37, [[-4.80,-4.00,-1.30], [-4.20,-3.30,3.10], [-0.44,0.74,0.68], [0.01,0.39,-0.20], [-0.90,0.11,-0.62], [0.00,0.00,0.50]]), + (38, [[-10.90,-6.10,-0.60], [-5.30,-1.20,-0.90], [-0.23,0.89,0.60], [0.05,0.11,-0.14], [0.08,0.64,-0.89], [0.00,0.00,0.50]]), + (39, [[-19.90,-6.40,-5.50], [-0.30,1.70,-10.50], [-0.43,0.96,0.33], [0.06,0.09,-0.23], [1.00,0.41,0.21], [0.00,0.00,0.50]]), + (40, [[-10.70,-3.20,-8.80], [7.80,0.40,0.10], [-0.10,1.09,0.10], [-0.32,-0.44,-0.23], [-0.06,-0.11,1.09], [0.00,0.00,0.50]]), + (41, [[-1.20,-1.90,-7.30], [0.80,8.10,2.50], [-1.09,0.03,-0.18], [0.29,-0.98,-0.16], [-0.19,-0.42,1.00], [0.00,0.00,0.50]]), + (42, [[-6.30,0.50,-8.10], [-9.80,-1.20,0.50], [0.11,-1.06,-0.28], [0.58,-0.56,-0.12], [0.09,-0.27,1.07], [0.00,0.00,0.50]]), + (43, [[-16.00,-0.70,-7.40], [-7.60,1.20,1.50], [-0.06,-1.00,-0.45], [-0.62,0.61,0.13], [0.31,-0.47,0.95], [0.00,0.00,0.50]]), + (44, [[-20.50,2.30,-6.10], [3.50,7.20,-2.90], [-1.09,0.10,-0.10], [-0.21,0.77,-0.11], [-0.19,0.13,1.08], [0.00,0.00,0.50]]), + (45, [[-11.40,2.60,-10.10], [10.40,1.50,-0.20], [-0.09,0.56,-0.95], [0.49,0.10,-0.38], [-0.11,0.94,0.56], [0.00,0.00,0.50]]), + (46, [[-3.80,4.20,-7.30], [3.50,0.90,2.70], [0.08,0.40,-1.02], [-0.19,-0.40,0.24], [-0.80,0.75,0.01], [0.00,0.00,0.50]]) + ] ), 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-45', + 'name': get_smallintestine_term('small intestine')[0], + 'ontId': get_smallintestine_term('small intestine')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -869,8 +906,17 @@ class MeshType_3d_smallintestine1(Scaffold_base): 'name': get_smallintestine_term('ileum')[0], 'ontId': get_smallintestine_term('ileum')[1] }] - } ) - } + }) + + +class MeshType_3d_smallintestine1(Scaffold_base): + ''' + Generates a 3-D small intestine mesh with variable numbers + of elements around, along the central line, and through wall. + The small intestine is created by a function that generates + a small intestine segment and uses tubemesh to map the segment + along a central line profile. + ''' @staticmethod def getName(): @@ -886,19 +932,13 @@ def getParameterSetNames(): @classmethod def getDefaultOptions(cls, parameterSetName='Default'): - if 'Cattle 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Cattle 1'] - elif 'Mouse 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Mouse 1'] - else: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 1'] options = { - 'Central path': copy.deepcopy(centralPathOption), + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), 'Number of segments': 80, - 'Number of elements around': 8, + 'Number of elements around': 12, 'Number of elements along segment': 3, - 'Number of elements through wall': 4, - 'Wall thickness': 0.45, + 'Number of elements through wall': 1, + 'Wall thickness': 3.0, 'Mucosa relative thickness': 0.55, 'Submucosa relative thickness': 0.15, 'Circular muscle layer relative thickness': 0.25, @@ -911,10 +951,12 @@ def getDefaultOptions(cls, parameterSetName='Default'): 'Refine number of elements through wall': 1 } if 'Cattle 1' in parameterSetName: - options['Number of segments'] = 300 + options['Number of segments'] = 400 + options['Number of elements around'] = 8 options['Wall thickness'] = 2.0 elif 'Mouse 1' in parameterSetName: options['Number of segments'] = 100 + options['Number of elements around'] = 8 options['Wall thickness'] = 0.1 return options @@ -922,7 +964,7 @@ def getDefaultOptions(cls, parameterSetName='Default'): @staticmethod def getOrderedOptionNames(): return [ - 'Central path', + 'Network layout', 'Number of segments', 'Number of elements around', 'Number of elements along segment', @@ -941,14 +983,14 @@ def getOrderedOptionNames(): @classmethod def getOptionValidScaffoldTypes(cls, optionName): - if optionName == 'Central path': - return [ MeshType_1d_path1 ] + if optionName == 'Network layout': + return [ MeshType_1d_network_layout1 ] return [] @classmethod def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): - if optionName == 'Central path': - return list(cls.centralPathDefaultScaffoldPackages.keys()) + if optionName == 'Network layout': + return cls.getParameterSetNames() assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() @@ -964,16 +1006,16 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() - if optionName == 'Central path': + if optionName == 'Network layout': if not parameterSetName: - parameterSetName = list(cls.centralPathDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.centralPathDefaultScaffoldPackages[parameterSetName]) + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' @classmethod def checkOptions(cls, options): - if not options['Central path'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Central path'): - options['Central path'] = cls.getOptionScaffoldPackage('Central path', MeshType_1d_path1) + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) for key in [ 'Number of segments', 'Number of elements around', @@ -996,250 +1038,15 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ - centralPath = options['Central path'] - segmentCount = options['Number of segments'] - elementsCountAround = options['Number of elements around'] - elementsCountAlongSegment = options['Number of elements along segment'] - elementsCountThroughWall = options['Number of elements through wall'] - wallThickness = options['Wall thickness'] - mucosaRelThickness = options['Mucosa relative thickness'] - submucosaRelThickness = options['Submucosa relative thickness'] - circularRelThickness = options['Circular muscle layer relative thickness'] - longitudinalRelThickness = options['Longitudinal muscle layer relative thickness'] - useCrossDerivatives = options['Use cross derivatives'] - useCubicHermiteThroughWall = not(options['Use linear through wall']) - elementsCountAlong = int(elementsCountAlongSegment*segmentCount) - startPhase = 0.0 - - # Small intestine coordinates - lengthToDiameterRatio = 200 - wallThicknessToDiameterRatio = 0.15 - relativeThicknessListSmallIntestineCoordinates = [1.0 / elementsCountThroughWall - for n3 in range(elementsCountThroughWall)] - - firstNodeIdentifier = 1 - firstElementIdentifier = 1 - - # Central path - tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) - tmpFieldmodule = tmpRegion.getFieldmodule() - tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') - smallIntestineTermsAlong = [None, 'duodenum', 'jejunum', 'ileum'] - arcLengthOfGroupsAlong = [] - - for termName in smallIntestineTermsAlong: - tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None - tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes - - cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( - tmpNodeset, tmpCoordinates, - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, - Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, - Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) - arcLength = 0.0 - for e in range(len(cxGroup) - 1): - arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], - cxGroup[e + 1], cd1Group[e + 1]) - arcLengthOfGroupsAlong.append(arcLength) - - if not termName: - cx = cxGroup - cd1 = cd1Group - cd2 = cd2Group - cd3 = cd3Group - cd12 = cd12Group - cd13 = cd13Group - - del tmpNodeset - del tmpGroup - - del tmpCoordinates - del tmpNodes - del tmpFieldmodule - del tmpRegion - - # find arclength of colon - length = 0.0 - elementsCountIn = len(cx) - 1 - sd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, fixAllDirections = True, - magnitudeScalingMode = interp.DerivativeScalingMode.HARMONIC_MEAN) - - for e in range(elementsCountIn): - arcLength = interp.getCubicHermiteArcLength(cx[e], sd1[e], cx[e + 1], sd1[e + 1]) - # print(e+1, arcLength) - length += arcLength - segmentLength = length / segmentCount - elementAlongLength = length / elementsCountAlong - # print('Length = ', length) - - # Sample central path - sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlongSegment*segmentCount) - sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) - - innerRadiusListCP = [vector.magnitude(c) for c in cd2] - dInnerRadiusListCP = [] - for n in range(len(innerRadiusListCP) - 1): - dInnerRadiusListCP.append(innerRadiusListCP[n + 1] - innerRadiusListCP[n]) - dInnerRadiusListCP.append(innerRadiusListCP[-1] - innerRadiusListCP[-2]) - innerRadiusList, dInnerRadiusList = interp.interpolateSampleCubicHermite( - innerRadiusListCP, dInnerRadiusListCP, se, sxi, ssf) - - centralPathLength = arcLengthOfGroupsAlong[0] - elementAlongLength = centralPathLength / elementsCountAlong - - elementsCountAlongGroups = [] - groupLength = 0.0 - e = 0 - elementsCount = 1 - length = elementAlongLength - for i in range(1, len(smallIntestineTermsAlong)): - groupLength += arcLengthOfGroupsAlong[i] - if e == elementsCountAlong - 2: - elementsCount += 1 - elementsCountAlongGroups.append(elementsCount) - else: - while length < groupLength: - elementsCount += 1 - e += 1 - length += elementAlongLength - - # check which end is grouplength closer to - distToUpperEnd = abs(length - groupLength) - distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) - if distToLowerEnd < distToUpperEnd: - elementsCount -= 1 - elementsCountAlongGroups.append(elementsCount) - e -= 1 - length -= elementAlongLength - else: - elementsCountAlongGroups.append(elementsCount) - elementsCount = 0 - - # Groups along small intestine - smallintestineGroup = AnnotationGroup(region, get_smallintestine_term("small intestine")) - duodenumGroup = AnnotationGroup(region, get_smallintestine_term("duodenum")) - jejunumGroup = AnnotationGroup(region, get_smallintestine_term("jejunum")) - ileumGroup = AnnotationGroup(region, get_smallintestine_term("ileum")) - - annotationGroupAlong = [[smallintestineGroup, duodenumGroup], - [smallintestineGroup, jejunumGroup], - [smallintestineGroup, ileumGroup]] - - annotationGroupsAlong = [] - for i in range(len(elementsCountAlongGroups)): - elementsCount = elementsCountAlongGroups[i] - for n in range(elementsCount): - annotationGroupsAlong.append(annotationGroupAlong[i]) - - annotationGroupsAround = [] - for i in range(elementsCountAround): - annotationGroupsAround.append([ ]) - - # Groups through wall - longitudinalMuscleGroup = AnnotationGroup(region, - get_smallintestine_term( - "longitudinal muscle layer of small intestine")) - circularMuscleGroup = AnnotationGroup(region, - get_smallintestine_term("circular muscle layer of small intestine")) - submucosaGroup = AnnotationGroup(region, get_smallintestine_term("submucosa of small intestine")) - mucosaGroup = AnnotationGroup(region, get_smallintestine_term("mucosa of small intestine")) - - if elementsCountThroughWall == 1: - relativeThicknessList = [1.0] - annotationGroupsThroughWall = [[]] - else: - relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, - circularRelThickness, longitudinalRelThickness] - annotationGroupsThroughWall = [[mucosaGroup], [submucosaGroup], - [circularMuscleGroup], [longitudinalMuscleGroup]] - - xExtrude = [] - d1Extrude = [] - d2Extrude = [] - d3UnitExtrude = [] - - # Create object - smallIntestineSegmentTubeMeshInnerPoints = CylindricalSegmentTubeMeshInnerPoints( - elementsCountAround, elementsCountAlongSegment, segmentLength, - wallThickness, innerRadiusList, startPhase) - - for nSegment in range(segmentCount): - # Create inner points - xInner, d1Inner, d2Inner, transitElementList, segmentAxis, radiusAlongSegmentList = \ - smallIntestineSegmentTubeMeshInnerPoints.getCylindricalSegmentTubeMeshInnerPoints(nSegment) - - # Project reference point for warping onto central path - start = nSegment*elementsCountAlongSegment - end = (nSegment + 1)*elementsCountAlongSegment + 1 - sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ - tubemesh.getPlaneProjectionOnCentralPath(xInner, elementsCountAround, elementsCountAlongSegment, - segmentLength, sx[start:end], sd1[start:end], sd2[start:end], - sd12[start:end]) - - # Warp segment points - xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = tubemesh.warpSegmentPoints( - xInner, d1Inner, d2Inner, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, - elementsCountAround, elementsCountAlongSegment, zRefList) - - # Store points along length - xExtrude = xExtrude + (xWarpedList if nSegment == 0 else xWarpedList[elementsCountAround:]) - d1Extrude = d1Extrude + (d1WarpedList if nSegment == 0 else d1WarpedList[elementsCountAround:]) - - # Smooth d2 for nodes between segments and recalculate d3 - if nSegment == 0: - d2Extrude = d2Extrude + (d2WarpedList[:-elementsCountAround]) - d3UnitExtrude = d3UnitExtrude + (d3WarpedUnitList[:-elementsCountAround]) - else: - xSecondFace = xWarpedList[elementsCountAround:elementsCountAround*2] - d2SecondFace = d2WarpedList[elementsCountAround:elementsCountAround*2] - for n1 in range(elementsCountAround): - nx = [xLastTwoFaces[n1], xLastTwoFaces[n1 + elementsCountAround], xSecondFace[n1]] - nd2 = [d2LastTwoFaces[n1], d2LastTwoFaces[n1 + elementsCountAround], d2SecondFace[n1]] - d2 = interp.smoothCubicHermiteDerivativesLine(nx, nd2, fixStartDerivative = True, - fixEndDerivative = True)[1] - d2Extrude.append(d2) - d3Unit = vector.normalise(vector.crossproduct3(vector.normalise(d1LastTwoFaces[n1 + elementsCountAround]), - vector.normalise(d2))) - d3UnitExtrude.append(d3Unit) - d2Extrude = d2Extrude + \ - (d2WarpedList[elementsCountAround:-elementsCountAround] if nSegment < segmentCount - 1 else - d2WarpedList[elementsCountAround:]) - d3UnitExtrude = d3UnitExtrude + \ - (d3WarpedUnitList[elementsCountAround:-elementsCountAround] if nSegment < segmentCount - 1 else - d3WarpedUnitList[elementsCountAround:]) - xLastTwoFaces = xWarpedList[-elementsCountAround*2:] - d1LastTwoFaces = d1WarpedList[-elementsCountAround*2:] - d2LastTwoFaces = d2WarpedList[-elementsCountAround*2:] - - # Create coordinates and derivatives - xList, d1List, d2List, d3List, curvatureList = tubemesh.extrudeSurfaceCoordinates(xExtrude, d1Extrude, - d2Extrude, d3UnitExtrude, [wallThickness]*(elementsCountAlong+1), relativeThicknessList, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, transitElementList, outward=True) - - flatWidthList, xiList = smallIntestineSegmentTubeMeshInnerPoints.getFlatWidthAndXiList() - - # Create flat coordinates - xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates( - xiList, flatWidthList, length, wallThickness, relativeThicknessList, elementsCountAround, - elementsCountAlong, elementsCountThroughWall, transitElementList) + nextNodeIdentifier = 1 + nextElementIdentifier = 1 + smallIntestineTermsAlong = ['small intestine', 'duodenum', 'jejunum', 'ileum'] + geometricNetworkLayout = options['Network layout'] + geometricNetworkLayout = SmallIntestineNetworkLayout(region, geometricNetworkLayout, smallIntestineTermsAlong) - # Create small intestine coordinates - xSmallIntestine, d1SmallIntestine, d2SmallIntestine = \ - tubemesh.createOrganCoordinates(xiList, relativeThicknessListSmallIntestineCoordinates, - lengthToDiameterRatio, wallThicknessToDiameterRatio, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, - transitElementList) - - # Create nodes and elements - nextNodeIdentifier, nextElementIdentifier, annotationGroups = tubemesh.createNodesAndElements( - region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, - xSmallIntestine, d1SmallIntestine, d2SmallIntestine, "small intestine coordinates", - elementsCountAround, elementsCountAlong, elementsCountThroughWall, - annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, useCubicHermiteThroughWall, useCrossDerivatives, - closedProximalEnd=False) + annotationGroups, nextNodeIdentifier, nextElementIdentifier = \ + createSmallIntestineMesh3d(region, options, geometricNetworkLayout, nextNodeIdentifier, + nextElementIdentifier, flatCoordinates=True, materialCoordinates=True)[0:3] return annotationGroups, None @@ -1295,3 +1102,328 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): "luminal surface of duodenum")) duodenumLuminal.getMeshGroup(mesh2d).addElementsConditional(is_duodenumLuminal) +def createSmallIntestineMesh3d(region, options, networkLayout, nextNodeIdentifier, nextElementIdentifier, + flatCoordinates=False, materialCoordinates=False, nodeIdProximal=[], + xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[], arclengthCPProximal=0.0): + """ + Generates a small intestine scaffold in the region using a network layout and parameter options. + :param region: Region to create elements in. + :param options: Parameter options for small intestine scaffold. + :param networkLayout: Network layout describing path of small intestine. + :param nextNodeIdentifier: Next node identifier to use. + :param nextElementIdentifier: Next element identifier to use. + :param flatCoordinates: Create flat coordinates if True. + :param nodeIdProximal, xProximal, d1Proximal, d2Proximal, d3Proximal: Identifier, coordinates and derivatives of + nodes to use on proximal end of small intestine. + :param arclengthCPProximal: Arc length of network layout in the element leading up to the start of the small + intestine. + :param materialCoordinates: Create material coordinates if True. + :return annotationGroups, nextNodeIdentifier, nextElementIdentifier, nodesIdDistal, xDistal, d1Distal, d2Distal, + d3Distal, xNext, d2Next + """ + segmentCount = options['Number of segments'] + elementsCountAround = options['Number of elements around'] + elementsCountAlongSegment = options['Number of elements along segment'] + elementsCountThroughWall = options['Number of elements through wall'] + wallThickness = options['Wall thickness'] + mucosaRelThickness = options['Mucosa relative thickness'] + submucosaRelThickness = options['Submucosa relative thickness'] + circularRelThickness = options['Circular muscle layer relative thickness'] + longitudinalRelThickness = options['Longitudinal muscle layer relative thickness'] + useCrossDerivatives = options['Use cross derivatives'] + useCubicHermiteThroughWall = not(options['Use linear through wall']) + elementsCountAlong = int(elementsCountAlongSegment*segmentCount) + startPhase = 0.0 + + # Small intestine coordinates + lengthToDiameterRatio = 200 + wallThicknessToDiameterRatio = 0.15 + relativeThicknessListSmallIntestineCoordinates = [1.0 / elementsCountThroughWall + for n3 in range(elementsCountThroughWall)] + + smallIntestineTermsAlong = ['small intestine', 'duodenum', 'jejunum', 'ileum'] + + networkLayoutLength = networkLayout.arcLengthOfGroupsAlong[0] + cx = networkLayout.cxGroups[0] + cd1 = networkLayout.cd1Groups[0] + cd2 = networkLayout.cd2Groups[0] + cd12 = networkLayout.cd12Groups[0] + arcLengthOfGroupsAlong = networkLayout.arcLengthOfGroupsAlong + + # find arclength of colon + length = 0.0 + elementsCountIn = len(cx) - 1 + sd1 = interp.smoothCubicHermiteDerivativesLine(cx, cd1, fixAllDirections = True, + magnitudeScalingMode = interp.DerivativeScalingMode.HARMONIC_MEAN) + + for e in range(elementsCountIn): + arcLength = interp.getCubicHermiteArcLength(cx[e], sd1[e], cx[e + 1], sd1[e + 1]) + # print(e+1, arcLength) + length += arcLength + segmentLength = length / segmentCount + elementAlongLength = length / elementsCountAlong + # print('Length = ', length) + + # Sample network layout + startLength = 0.0 + lengthFraction = 1.0 + if xProximal: + startLength = arclengthCPProximal + lengthFraction = 0.5 + sx, sd1, se, sxi, ssf = interp.sampleCubicHermiteCurves(cx, cd1, elementsCountAlongSegment*segmentCount, + addLengthStart=0.5*startLength, + lengthFractionStart=lengthFraction) + sd2, sd12 = interp.interpolateSampleCubicHermite(cd2, cd12, se, sxi, ssf) + + outerRadiusListCP = [vector.magnitude(c) for c in cd2] + dOuterRadiusListCP = [] + for n in range(len(outerRadiusListCP) - 1): + dOuterRadiusListCP.append(outerRadiusListCP[n + 1] - outerRadiusListCP[n]) + dOuterRadiusListCP.append(outerRadiusListCP[-1] - outerRadiusListCP[-2]) + outerRadiusList, dOuterRadiusList = interp.interpolateSampleCubicHermite( + outerRadiusListCP, dOuterRadiusListCP, se, sxi, ssf) + + elementAlongLength = networkLayoutLength / elementsCountAlong + + elementsCountAlongGroups = [] + groupLength = 0.0 + e = 0 + elementsCount = 1 + length = elementAlongLength + for i in range(1, len(smallIntestineTermsAlong)): + groupLength += arcLengthOfGroupsAlong[i] + if e == elementsCountAlong - 2: + elementsCount += 1 + elementsCountAlongGroups.append(elementsCount) + else: + while length < groupLength: + elementsCount += 1 + e += 1 + length += elementAlongLength + + # check which end is grouplength closer to + distToUpperEnd = abs(length - groupLength) + distToLowerEnd = abs(groupLength - (length - elementsCountAlong)) + if distToLowerEnd < distToUpperEnd: + elementsCount -= 1 + elementsCountAlongGroups.append(elementsCount) + e -= 1 + length -= elementAlongLength + else: + elementsCountAlongGroups.append(elementsCount) + elementsCount = 0 + + # Groups along small intestine + smallintestineGroup = AnnotationGroup(region, get_smallintestine_term("small intestine")) + duodenumGroup = AnnotationGroup(region, get_smallintestine_term("duodenum")) + jejunumGroup = AnnotationGroup(region, get_smallintestine_term("jejunum")) + ileumGroup = AnnotationGroup(region, get_smallintestine_term("ileum")) + + annotationGroupAlong = [[smallintestineGroup, duodenumGroup], + [smallintestineGroup, jejunumGroup], + [smallintestineGroup, ileumGroup]] + + annotationGroupsAlong = [] + for i in range(len(elementsCountAlongGroups)): + elementsCount = elementsCountAlongGroups[i] + for n in range(elementsCount): + annotationGroupsAlong.append(annotationGroupAlong[i]) + + annotationGroupsAround = [] + for i in range(elementsCountAround): + annotationGroupsAround.append([ ]) + + # Groups through wall + longitudinalMuscleGroup = AnnotationGroup(region, + get_smallintestine_term( + "longitudinal muscle layer of small intestine")) + circularMuscleGroup = AnnotationGroup(region, + get_smallintestine_term("circular muscle layer of small intestine")) + submucosaGroup = AnnotationGroup(region, get_smallintestine_term("submucosa of small intestine")) + mucosaGroup = AnnotationGroup(region, get_smallintestine_term("mucosa of small intestine")) + + if elementsCountThroughWall == 1: + relativeThicknessList = [1.0] + annotationGroupsThroughWall = [[]] + else: + relativeThicknessList = [mucosaRelThickness, submucosaRelThickness, + circularRelThickness, longitudinalRelThickness] + annotationGroupsThroughWall = [[mucosaGroup], [submucosaGroup], + [circularMuscleGroup], [longitudinalMuscleGroup]] + + xExtrude = [] + d1Extrude = [] + d2Extrude = [] + d3UnitExtrude = [] + + # Create object + smallIntestineSegmentTubeMeshOuterPoints = CylindricalSegmentTubeMeshOuterPoints( + elementsCountAround, elementsCountAlongSegment, segmentLength, + wallThickness, outerRadiusList, startPhase) + + for nSegment in range(segmentCount): + # Create outer points + xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, radiusAlongSegmentList = \ + smallIntestineSegmentTubeMeshOuterPoints.getCylindricalSegmentTubeMeshOuterPoints(nSegment) + + # Project reference point for warping onto network layout + start = nSegment*elementsCountAlongSegment + end = (nSegment + 1)*elementsCountAlongSegment + 1 + sxRefList, sd1RefList, sd2ProjectedListRef, zRefList = \ + tubemesh.getPlaneProjectionOnCentralPath(xOuter, elementsCountAround, elementsCountAlongSegment, + segmentLength, sx[start:end], sd1[start:end], sd2[start:end], + sd12[start:end]) + + # Warp segment points + xWarpedList, d1WarpedList, d2WarpedList, d3WarpedUnitList = tubemesh.warpSegmentPoints( + xOuter, d1Outer, d2Outer, segmentAxis, sxRefList, sd1RefList, sd2ProjectedListRef, + elementsCountAround, elementsCountAlongSegment, zRefList) + + # Store points along length + xExtrude = xExtrude + (xWarpedList if nSegment == 0 else xWarpedList[elementsCountAround:]) + d1Extrude = d1Extrude + (d1WarpedList if nSegment == 0 else d1WarpedList[elementsCountAround:]) + + # Smooth d2 for nodes between segments and recalculate d3 + if nSegment == 0: + d2Extrude = d2Extrude + (d2WarpedList[:-elementsCountAround]) + d3UnitExtrude = d3UnitExtrude + (d3WarpedUnitList[:-elementsCountAround]) + else: + xSecondFace = xWarpedList[elementsCountAround:elementsCountAround*2] + d2SecondFace = d2WarpedList[elementsCountAround:elementsCountAround*2] + for n1 in range(elementsCountAround): + nx = [xLastTwoFaces[n1], xLastTwoFaces[n1 + elementsCountAround], xSecondFace[n1]] + nd2 = [d2LastTwoFaces[n1], d2LastTwoFaces[n1 + elementsCountAround], d2SecondFace[n1]] + d2 = interp.smoothCubicHermiteDerivativesLine(nx, nd2, fixStartDerivative = True, + fixEndDerivative = True)[1] + d2Extrude.append(d2) + d3Unit = \ + vector.normalise(vector.crossproduct3(vector.normalise(d1LastTwoFaces[n1 + elementsCountAround]), + vector.normalise(d2))) + d3UnitExtrude.append(d3Unit) + d2Extrude = d2Extrude + \ + (d2WarpedList[elementsCountAround:-elementsCountAround] if nSegment < segmentCount - 1 else + d2WarpedList[elementsCountAround:]) + d3UnitExtrude = d3UnitExtrude + \ + (d3WarpedUnitList[elementsCountAround:-elementsCountAround] if nSegment < segmentCount - 1 + else d3WarpedUnitList[elementsCountAround:]) + xLastTwoFaces = xWarpedList[-elementsCountAround*2:] + d1LastTwoFaces = d1WarpedList[-elementsCountAround*2:] + d2LastTwoFaces = d2WarpedList[-elementsCountAround*2:] + + # Create coordinates and derivatives + xList, d1List, d2List, d3List, curvatureList, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal = \ + tubemesh.extrudeSurfaceCoordinates(xExtrude, d1Extrude, d2Extrude, d3UnitExtrude, + [wallThickness]*(elementsCountAlong+1), relativeThicknessList, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + transitElementList, outward=False, xProximal=xProximal, + d1Proximal=d1Proximal, d2Proximal=d2Proximal, d3Proximal=d3Proximal) + + flatWidthList, xiList = smallIntestineSegmentTubeMeshOuterPoints.getFlatWidthAndXiList() + + # Create flat coordinates + if flatCoordinates: + xFlat, d1Flat, d2Flat = tubemesh.createFlatCoordinates( + xiList, flatWidthList, length, wallThickness, relativeThicknessList, elementsCountAround, + elementsCountAlong, elementsCountThroughWall, transitElementList) + else: + xFlat = d1Flat = d2Flat = [] + + # Create small intestine coordinates + if materialCoordinates: + xSmallIntestine, d1SmallIntestine, d2SmallIntestine = \ + tubemesh.createOrganCoordinates(xiList, relativeThicknessListSmallIntestineCoordinates, + lengthToDiameterRatio, wallThicknessToDiameterRatio, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + transitElementList) + else: + xSmallIntestine = d1SmallIntestine = d2SmallIntestine = [] + + # Create nodes and elements + nextNodeIdentifier, nextElementIdentifier, annotationGroups, nodesIdDistal = \ + tubemesh.createNodesAndElements(region, xList, d1List, d2List, d3List, xFlat, d1Flat, d2Flat, xSmallIntestine, + d1SmallIntestine, d2SmallIntestine, "small intestine coordinates", + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, + nextNodeIdentifier, nextElementIdentifier, useCubicHermiteThroughWall, + useCrossDerivatives, closedProximalEnd=False, localIdxDistal=localIdxDistal, + nodeIdProximal=nodeIdProximal) + + xNext = [] + d2Next = [] + for n3 in range(elementsCountThroughWall + 1): + xNextAround = [] + d2NextAround = [] + for n1 in range(elementsCountAround): + n = elementsCountAround * (elementsCountThroughWall + 1) + elementsCountAround * n3 + n1 + xNextAround.append(xList[n]) + d2NextAround.append(d2List[n]) + xNext.append(xNextAround) + d2Next.append(d2NextAround) + + return annotationGroups, nextNodeIdentifier, nextElementIdentifier, nodesIdDistal, xDistal, d1Distal, d2Distal, \ + d3Distal, xNext, d2Next + +class SmallIntestineNetworkLayout: + """ + Generates sampled network layout for small intestine scaffold. + """ + def __init__(self, region, networkLayout, termsAlong=[None]): + """ + :param region: Zinc region to define model in. + :param networkLayout: Network layout subscaffold from meshtype_1d_network_layout1 + :param termsAlong: Annotation terms along length of network layout + """ + # Extract length of each group along small intestine from network layout + cxGroups = [] + cd1Groups = [] + cd2Groups = [] + cd3Groups = [] + cd12Groups = [] + cd13Groups = [] + + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + tmpFieldmodule = tmpRegion.getFieldmodule() + tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + arcLengthOfGroupsAlong = [] + + for termName in termsAlong: + tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None + tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) + + arcLength = 0.0 + for e in range(len(cxGroup) - 1): + arcLength += interp.getCubicHermiteArcLength(cxGroup[e], cd1Group[e], + cxGroup[e + 1], cd1Group[e + 1]) + arcLengthOfGroupsAlong.append(arcLength) + + if termName == "small intestine": + cxGroups.append(cxGroup) + cd1Groups.append(cd1Group) + cd2Groups.append(cd2Group) + cd3Groups.append(cd3Group) + cd12Groups.append(cd12Group) + cd13Groups.append(cd13Group) + + del tmpNodeset + del tmpGroup + + del tmpCoordinates + del tmpNodes + del tmpFieldmodule + del tmpRegion + + self.arcLengthOfGroupsAlong = arcLengthOfGroupsAlong + self.cxGroups = cxGroups + self.cd1Groups = cd1Groups + self.cd2Groups = cd2Groups + self.cd3Groups = cd3Groups + self.cd12Groups = cd12Groups + self.cd13Groups = cd13Groups diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_stomach1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_stomach1.py index f1d1101e..8afc63a9 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_stomach1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_stomach1.py @@ -22,8 +22,8 @@ from scaffoldmaker.annotation.esophagus_terms import get_esophagus_term from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term from scaffoldmaker.annotation.stomach_terms import get_stomach_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 -from scaffoldmaker.meshtypes.meshtype_3d_ostium1 import MeshType_3d_ostium1, generateOstiumMesh +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 +from scaffoldmaker.meshtypes.meshtype_3d_ostium2 import generateOstiumMesh from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base from scaffoldmaker.scaffoldpackage import ScaffoldPackage from scaffoldmaker.utils import interpolation as interp @@ -32,296 +32,280 @@ from scaffoldmaker.utils.annulusmesh import createAnnulusMesh3d from scaffoldmaker.utils.eftfactory_bicubichermitelinear import eftfactory_bicubichermitelinear from scaffoldmaker.utils.eftfactory_tricubichermite import eftfactory_tricubichermite -from scaffoldmaker.utils.eft_utils import setEftScaleFactorIds, remapEftNodeValueLabel, remapEftNodeValueLabelsVersion +from scaffoldmaker.utils.eft_utils import setEftScaleFactorIds, remapEftNodeValueLabel from scaffoldmaker.utils.geometry import sampleEllipsePoints from scaffoldmaker.utils.tracksurface import TrackSurface from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters, \ - mesh_destroy_elements_and_nodes_by_identifiers, get_nodeset_path_field_parameters + mesh_destroy_elements_and_nodes_by_identifiers, get_nodeset_path_ordered_field_parameters, \ + get_nodeset_path_field_parameters - -class MeshType_3d_stomach1(Scaffold_base): - """ - Generates a 3-D stomach mesh with variable numbers of elements around the esophagus and duodenum, - along the central line, and through wall. The stomach is created using a central path as the longitudinal axis - of the stomach. D2 of the central path points to the greater curvature of the stomach and magnitude of D2 and D3 - are the radii of the stomach in the respective direction. - """ - centralPathDefaultScaffoldPackages = { - 'Human 1': ScaffoldPackage(MeshType_1d_path1, { +def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName): + assert parameterSetName in cls.getParameterSetNames() # make sure parameter set is in list of parameters of parent scaffold + if parameterSetName in ("Default", "Human 1"): + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 12 + "Structure": "1-2-3.2, 4-5-6-7-8-3-9-10-11-12-13-14-15" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[0.49,0.06,0.00], [-0.03,-0.00,-0.00], [0.01,-0.04,0.00], [0.02,-0.14,0.00], [0.00,0.00,0.04], [0.00,0.00,0.13]]), - (2, [[0.45,0.05,-0.00], [-0.06,-0.01,-0.00], [0.03,-0.17,0.00], [0.02,-0.12,0.00], [0.00,0.00,0.17], [0.00,0.00,0.13]]), - (3, [[0.38,0.04,0.00], [-0.08,-0.02,0.00], [0.04,-0.27,0.00], [0.01,-0.10,0.00], [0.00,0.00,0.29], [0.00,0.00,0.11]]), - (4, [[0.28,0.02,0.00], [-0.11,-0.02,0.00], [0.05,-0.36,0.00], [0.00,-0.07,0.00], [0.00,0.00,0.38], [0.00,0.00,0.07]]), - (5, [[0.16,0.01,0.00], [-0.14,-0.01,0.00], [0.04,-0.40,0.00], [-0.03,-0.02,0.00], [0.00,0.00,0.42], [0.00,0.00,0.03]]), - (6, [[0.00,0.00,0.00], [-0.20,0.00,0.00], [-0.01,-0.40,0.00], [-0.06,0.01,0.00], [0.00,0.00,0.43], [0.00,0.00,0.01]]), - (7, [[-0.23,0.02,0.00], [-0.23,0.05,0.00], [-0.09,-0.37,0.00], [-0.08,0.05,0.00], [0.00,0.00,0.44], [0.00,0.00,-0.01]]), - (8, [[-0.45,0.10,0.00], [-0.20,0.12,0.00], [-0.18,-0.29,0.00], [-0.06,0.11,0.00], [0.00,0.00,0.41], [0.00,0.00,-0.05]]), - (9, [[-0.61,0.26,0.00], [-0.15,0.20,0.00], [-0.22,-0.16,0.00], [-0.02,0.13,0.00], [0.00,0.00,0.34], [0.00,0.00,-0.09]]), - (10, [[-0.73,0.50,0.00], [-0.04,0.23,0.00], [-0.21,-0.04,0.00], [0.04,0.09,0.00], [0.00,0.00,0.23], [0.00,0.00,-0.07]]), - (11, [[-0.71,0.69,0.00], [0.05,0.17,0.00], [-0.14,0.03,0.00], [0.06,0.05,-0.00], [0.00,0.00,0.18], [0.00,0.00,-0.06]]), - (12, [[-0.64,0.83,0.00], [0.10,0.14,0.00], [-0.08,0.06,0.00], [0.03,0.03,-0.00], [0.00,0.00,0.11], [0.00,0.00,-0.03]]), - (13, [[-0.51,0.97,0.00], [0.16,0.14,0.00], [-0.08,0.09,0.00], [-0.03,0.03,0.00], [0.00,0.00,0.13], [0.00,0.00,0.07]]) + (1, [[0.000,0.560,0.000], [0.000,-0.070,0.000], [0.060,0.000,0.000], [0.170,0.120,-0.000], [0.000,0.000,0.060], [0.000,0.000,0.110]]), + (2, [[0.000,0.390,0.000], [0.000,-0.280,0.000], [0.130,0.000,0.000], [0.020,-0.120,-0.000], [0.000,0.000,0.130], [0.000,0.000,0.170]]), + (3, [[0.000,0.000,0.000], [[-0.200,0.000,0.000],[0.000,-0.490,0.000]], [[0.000,-0.400,0.000],[0.130,0.000,0.000]], [[-0.060,0.010,0.000],[-0.010,-0.400,0.000]], [[0.000,0.000,0.430],[0.000,0.000,0.130]], [[0.000,0.000,0.010],[0.000,0.000,0.010]]]), + (4, [[0.490,0.060,0.000], [-0.030,-0.000,-0.000], [0.010,-0.040,0.000], [0.020,-0.140,0.000], [0.000,0.000,0.040], [0.000,0.000,0.130]]), + (5, [[0.450,0.050,-0.000], [-0.060,-0.010,-0.000], [0.030,-0.170,0.000], [0.020,-0.120,0.000], [0.000,0.000,0.170], [0.000,0.000,0.130]]), + (6, [[0.380,0.040,0.000], [-0.080,-0.020,0.000], [0.040,-0.270,0.000], [0.010,-0.100,0.000], [0.000,0.000,0.290], [0.000,0.000,0.110]]), + (7, [[0.280,0.020,0.000], [-0.110,-0.020,0.000], [0.050,-0.360,0.000], [0.000,-0.070,0.000], [0.000,0.000,0.380], [0.000,0.000,0.070]]), + (8, [[0.160,0.010,0.000], [-0.140,-0.010,0.000], [0.040,-0.400,0.000], [-0.030,-0.020,0.000], [0.000,0.000,0.420], [0.000,0.000,0.030]]), + (9, [[-0.230,0.020,0.000], [-0.230,0.050,0.000], [-0.090,-0.370,0.000], [-0.080,0.050,0.000], [0.000,0.000,0.440], [0.000,0.000,-0.010]]), + (10, [[-0.450,0.100,0.000], [-0.200,0.120,0.000], [-0.180,-0.290,0.000], [-0.060,0.110,0.000], [0.000,0.000,0.410], [0.000,0.000,-0.050]]), + (11, [[-0.610,0.260,0.000], [-0.150,0.200,0.000], [-0.220,-0.160,0.000], [-0.020,0.130,0.000], [0.000,0.000,0.340], [0.000,0.000,-0.090]]), + (12, [[-0.730,0.500,0.000], [-0.040,0.230,0.000], [-0.210,-0.040,0.000], [0.040,0.090,0.000], [0.000,0.000,0.230], [0.000,0.000,-0.070]]), + (13, [[-0.710,0.690,0.000], [0.050,0.170,0.000], [-0.140,0.030,0.000], [0.060,0.050,-0.000], [0.000,0.000,0.180], [0.000,0.000,-0.060]]), + (14, [[-0.640,0.830,0.000], [0.100,0.140,0.000], [-0.080,0.060,0.000], [0.030,0.030,-0.000], [0.000,0.000,0.110], [0.000,0.000,-0.030]]), + (15, [[-0.510,0.970,0.000], [0.160,0.140,0.000], [-0.080,0.090,0.000], [-0.030,0.030,0.000], [0.000,0.000,0.130], [0.000,0.000,0.070]]) ]), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-5', + 'identifierRanges': '1-14', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-7', 'name': get_stomach_term('fundus of stomach')[0], 'ontId': get_stomach_term('fundus of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '6-8', + 'identifierRanges': '8-10', 'name': get_stomach_term('body of stomach')[0], 'ontId': get_stomach_term('body of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '9-10', + 'identifierRanges': '11-12', 'name': get_stomach_term('pyloric antrum')[0], 'ontId': get_stomach_term('pyloric antrum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '11', + 'identifierRanges': '13', 'name': get_stomach_term('pyloric canal')[0], 'ontId': get_stomach_term('pyloric canal')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '12', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] + 'identifierRanges': '14', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] }] - }), - 'Human 2': ScaffoldPackage(MeshType_1d_path1, { - 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 12 + }) + elif "Human 2" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3.2, 4-5-6-7-3-8-9-10-11-12-13-14-15" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[61.590,-101.050,1152.900], [0.442,-2.863,-3.864], [11.300,-0.230,1.460], [15.701,-3.029,2.832], [-0.850,-7.440,5.420], [-5.756,-22.456,14.946]]), - (2, [[61.990,-104.310,1148.310], [0.358,-3.656,-5.314], [24.170,-2.490,3.340], [10.039,-1.491,0.928], [-4.920,-25.060,16.910], [-2.384,-12.784,8.034]]), - (3, [[62.280,-108.340,1142.260], [0.251,-4.603,-7.040], [30.560,-2.990,3.040], [5.720,-0.448,-0.071], [-5.130,-31.610,20.490], [-0.206,-5.098,2.599]]), - (4, [[62.470,-113.500,1134.220], [0.315,-6.148,-9.733], [35.400,-3.370,3.270], [4.541,-0.488,0.325], [-5.330,-34.800,21.800], [-0.383,-3.012,1.219]]), - (5, [[62.940,-120.610,1122.780], [0.448,-8.598,-13.993], [39.520,-4.010,3.730], [3.189,-0.587,-0.295], [-5.970,-37.560,22.890], [-0.099,-1.218,0.549]]), - (6, [[63.320,-130.670,1106.220], [-0.184,-10.489,-16.967], [41.370,-4.520,2.350], [0.495,-2.468,-4.032], [-5.290,-36.560,22.660], [0.257,0.762,0.246]]), - (7, [[62.540,-141.560,1088.910], [-4.623,-11.401,-18.639], [40.430,-9.060,-4.490], [-4.947,-4.939,-8.800], [-5.480,-36.050,23.410], [0.770,0.606,1.053]]), - (8, [[53.670,-152.880,1069.820], [-15.955,-9.817,-16.265], [30.765,-14.468,-15.598], [-14.187,-3.408,-7.577], [-3.580,-35.330,24.820], [2.031,4.346,-1.238]]), - (9, [[32.230,-159.890,1058.560], [-22.295,-4.560,-7.466], [11.809,-15.766,-19.452], [-15.401,0.331,-0.624], [-1.410,-27.160,20.790], [1.197,8.617,-5.083]]), - (10, [[10.360,-162.050,1054.830], [-21.098,1.023,-0.272], [-0.460,-14.000,-17.230], [-8.754,2.830,4.764], [-1.070,-18.150,14.780], [-1.003,7.491,-3.260]]), - (11, [[-8.740,-158.280,1057.630], [-17.280,7.584,3.006], [-6.110,-10.230,-10.220], [-2.634,4.430,6.290], [-3.260,-12.000,13.950], [-1.380,7.085,-2.660]]), - (12, [[-23.259,-147.625,1060.642], [-11.148,12.211,0.633], [-5.944,-5.188,-4.599], [-0.696,3.015,1.714], [-3.887,-4.046,9.590], [-2.080,5.832,-2.463]]), - (13, [[-30.740,-135.240,1059.320], [-3.618,11.918,-3.109], [-7.329,-3.791,-6.004], [-2.074,-0.221,-4.524], [-7.127,0.091,8.642], [-4.400,2.442,0.567]]) + (1, [[11.750,-111.874,1127.887], [7.636,-5.715,-7.930], [5.678,1.265,4.556], [-8.397,13.092,24.878], [-0.708,-3.530,1.862], [-0.807,-7.995,7.596]]), + (2, [[23.789,-117.922,1120.040], [26.354,-6.724,-6.404], [4.223,6.205,10.864], [10.037,1.800,8.968], [-1.192,-11.215,6.869], [-2.926,-13.889,10.204]]), + (3, [[63.704,-120.094,1123.374], [[0.500,-9.138,-13.405],[50.106,1.267,11.056]], [[37.742,-3.477,3.778],[-2.509,7.605,10.499]], [[3.190,-0.590,-0.290],[3.190,-0.590,-0.290]], [[-5.452,-34.121,23.056],[-1.379,-10.790,7.486]], [[-0.100,-1.220,0.550],[-0.100,-1.220,0.550]]]), + (4, [[61.247,-99.931,1152.681], [0.346,-2.728,-3.873], [11.320,-0.365,1.269], [15.701,-3.029,2.832], [-0.653,-5.931,4.119], [-5.756,-22.456,14.946]]), + (5, [[61.743,-103.510,1147.760], [0.413,-3.592,-5.311], [24.159,-2.387,3.493], [10.039,-1.491,0.928], [-2.982,-15.339,10.142], [-2.384,-12.784,8.034]]), + (6, [[62.381,-107.527,1141.785], [0.249,-4.737,-7.073], [30.559,-2.973,3.067], [5.720,-0.448,-0.071], [-3.839,-23.420,15.550], [-0.206,-5.098,2.599]]), + (7, [[62.800,-113.150,1133.665], [0.116,-6.546,-9.651], [35.408,-3.630,2.888], [4.541,-0.488,0.325], [-4.677,-29.659,20.061], [-0.383,-3.012,1.219]]), + (8, [[64.339,-131.197,1107.233], [0.086,-11.682,-16.915], [39.201,-3.705,2.758], [0.490,-2.470,-4.030], [-5.108,-35.712,24.638], [0.260,0.760,0.250]]), + (9, [[62.912,-143.954,1088.811], [-5.216,-12.408,-17.967], [34.623,-8.161,-4.415], [-4.950,-4.940,-8.800], [-4.917,-34.532,25.275], [0.770,0.610,1.050]]), + (10, [[53.361,-155.397,1072.006], [-15.833,-9.775,-15.486], [25.117,-13.916,-16.896], [-14.190,-3.410,-7.580], [-2.355,-30.712,21.794], [2.030,4.350,-1.240]]), + (11, [[32.110,-162.230,1059.680], [-22.173,-3.681,-8.142], [10.067,-16.126,-20.126], [-15.400,0.330,-0.620], [-2.559,-23.629,17.653], [1.200,8.620,-5.080]]), + (12, [[10.560,-162.970,1055.650], [-20.956,2.164,-0.908], [-0.696,-13.976,-17.241], [-8.750,2.830,4.760], [-2.502,-18.048,14.732], [-1.000,7.490,-3.260]]), + (13, [[-8.740,-158.280,1057.630], [-17.269,8.027,2.588], [-6.253,-10.164,-10.200], [-2.630,4.430,6.290], [-3.442,-11.913,13.981], [-1.380,7.080,-2.660]]), + (14, [[-23.260,-147.620,1060.640], [-11.787,11.369,1.720], [-5.807,-5.321,-4.621], [-0.700,3.020,1.710], [-3.207,-4.764,9.515], [-2.080,5.830,-2.460]]), + (15, [[-32.281,-136.261,1061.249], [-6.125,11.114,-0.493], [-5.735,-3.374,-4.823], [-2.070,-0.220,-4.520], [-4.630,-2.238,7.071], [-4.400,2.440,0.570]]) ]), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-4', - 'name': get_stomach_term('fundus of stomach')[0], - 'ontId': get_stomach_term('fundus of stomach')[1] + 'identifierRanges': '1-14', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '5-8', - 'name': get_stomach_term('body of stomach')[0], - 'ontId': get_stomach_term('body of stomach')[1] + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '9-10', - 'name': get_stomach_term('pyloric antrum')[0], - 'ontId': get_stomach_term('pyloric antrum')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '11', - 'name': get_stomach_term('pyloric canal')[0], - 'ontId': get_stomach_term('pyloric canal')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '12', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] - }] - }), - 'Mouse 1': ScaffoldPackage(MeshType_1d_path1, { - 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 11 - }, - 'meshEdits': exnode_string_from_nodeset_field_parameters( - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[0.540,0.710,0.000], [-0.005,-0.065,0.000], [0.080,-0.010,0.000], [0.098,-0.016,0.000], [0.000,0.000,0.040], [0.000,0.000,0.124]]), - (2, [[0.530,0.630,0.000], [-0.015,-0.095,0.000], [0.170,-0.030,0.000], [0.082,-0.024,0.000], [0.000,0.000,0.160], [0.000,0.000,0.116]]), - (3, [[0.510,0.520,0.000], [-0.029,-0.135,0.000], [0.240,-0.060,0.000], [0.066,-0.042,0.000], [0.000,0.000,0.270], [0.000,0.000,0.098]]), - (4, [[0.470,0.360,0.000], [-0.055,-0.161,0.000], [0.300,-0.120,0.000], [0.026,-0.089,0.000], [0.000,0.000,0.350], [0.000,0.000,0.056]]), - (5, [[0.400,0.200,0.000], [-0.107,-0.145,0.000], [0.290,-0.240,0.000], [-0.054,-0.110,0.000], [0.000,0.000,0.380], [0.000,0.000,0.020]]), - (6, [[0.260,0.080,0.000], [-0.202,-0.111,0.000], [0.190,-0.340,0.000], [-0.132,-0.084,0.000], [0.000,0.000,0.390], [0.000,0.000,0.002]]), - (7, [[0.000,0.000,0.000], [-0.288,-0.009,0.000], [0.010,-0.400,0.000], [-0.194,0.007,0.000], [0.000,0.000,0.380], [0.000,0.000,-0.015]]), - (8, [[-0.290,0.070,0.000], [-0.237,0.128,0.000], [-0.200,-0.320,0.000], [-0.109,0.097,0.000], [0.000,0.000,0.360], [0.000,0.000,-0.031]]), - (9, [[-0.460,0.230,0.000], [-0.099,0.191,0.000], [-0.230,-0.210,0.000], [0.020,0.121,0.000], [0.000,0.000,0.320], [0.000,0.000,-0.079]]), - (10, [[-0.486,0.419,0.000], [-0.008,0.167,0.000], [-0.170,-0.080,0.000], [0.069,0.087,0.000], [0.000,0.000,0.210], [0.000,0.000,-0.109]]), - (11, [[-0.480,0.560,0.000], [-0.012,0.142,0.000], [-0.094,-0.025,0.000], [0.030,0.020,0.000], [0.000,0.000,0.102], [0.000,0.000,-0.046]]), - (12, [[-0.510,0.700,0.000], [-0.048,0.137,0.000], [-0.110,-0.040,0.000], [-0.062,-0.050,0.000], [0.000,0.000,0.120], [0.000,0.000,0.082]]) - ]), - - 'userAnnotationGroups': [ - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '1-6', + 'identifierRanges': '3-6', 'name': get_stomach_term('fundus of stomach')[0], 'ontId': get_stomach_term('fundus of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '7-8', + 'identifierRanges': '7-10', 'name': get_stomach_term('body of stomach')[0], 'ontId': get_stomach_term('body of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '9', + 'identifierRanges': '11-12', 'name': get_stomach_term('pyloric antrum')[0], 'ontId': get_stomach_term('pyloric antrum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '10', + 'identifierRanges': '13', 'name': get_stomach_term('pyloric canal')[0], 'ontId': get_stomach_term('pyloric canal')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '11', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] + 'identifierRanges': '14', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] }] - }), - 'Pig 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif "Mouse 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 10 + "Structure": "1-2-3.2, 4-5-6-7-8-9-3-10-11-12-13-14" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[0.44,0.01,0.00], [-0.01,-0.00,0.00], [0.01,-0.05,0.00], [-0.01,-0.09,0.00], [0.00,0.00,0.08], [0.00,0.00,0.06]]), - (2, [[0.42,0.01,0.00], [-0.05,-0.01,0.00], [-0.00,-0.15,0.00], [-0.00,-0.10,0.00], [0.00,0.00,0.15], [0.00,0.00,0.08]]), - (3, [[0.33,0.00,0.00], [-0.11,-0.00,0.00], [0.00,-0.28,0.00], [-0.00,-0.13,0.00], [0.00,0.00,0.28], [0.00,0.00,0.12]]), - (4, [[0.19,0.00,0.00], [-0.17,-0.01,0.00], [0.01,-0.39,0.00], [-0.02,-0.08,0.00], [0.00,0.00,0.38], [0.00,0.00,0.07]]), - (5, [[0.00,0.00,0.00], [-0.21,0.00,0.00], [-0.03,-0.43,0.00], [-0.02,-0.02,0.00], [0.00,0.00,0.40], [0.00,0.00,0.01]]), - (6, [[-0.22,0.01,0.00], [-0.25,0.03,0.00], [-0.03,-0.43,0.00], [-0.05,0.03,0.00], [0.00,0.00,0.40], [0.00,0.00,-0.01]]), - (7, [[-0.50,0.05,0.00], [-0.26,0.12,0.00], [-0.16,-0.36,0.00], [-0.12,0.14,0.00], [0.00,0.00,0.37], [0.00,0.00,-0.05]]), - (8, [[-0.70,0.24,0.00], [-0.11,0.27,0.00], [-0.28,-0.16,0.00], [-0.05,0.21,0.00], [0.00,0.00,0.31], [0.00,0.00,-0.09]]), - (9, [[-0.70,0.52,0.00], [0.12,0.26,0.00], [-0.27,0.05,0.00], [0.10,0.09,0.00], [0.00,0.00,0.18], [0.00,0.00,-0.11]]), - (10, [[-0.50,0.70,0.00], [0.14,0.19,0.00], [-0.09,0.03,0.00], [0.08,-0.02,0.00], [0.00,0.00,0.09], [0.00,0.00,-0.04]]), - (11, [[-0.41,0.88,0.00], [0.03,0.16,0.00], [-0.09,0.01,0.00], [-0.08,-0.03,0.00], [0.00,0.00,0.09], [0.00,0.00,0.04]]) + (1, [[-0.047,0.617,-0.000], [0.043,-0.123,0.000], [0.065,0.011,0.000], [0.098,-0.016,0.000], [0.000,0.000,0.066], [0.000,0.000,0.124]]), + (2, [[-0.010,0.400,-0.000], [0.030,-0.309,0.000], [0.109,0.019,0.000], [0.082,-0.024,0.000], [0.000,-0.000,0.110], [0.000,0.000,0.116]]), + (3, [[0.000,0.000,0.000], [[-0.288,-0.009,0.000],[-0.010,-0.490,0.000]], [[0.010,-0.400,0.000],[0.109,0.019,0.000]], [[-0.194,0.007,0.000],[-0.194,0.007,0.000]], [[0.000,0.000,0.380],[0.000,-0.000,0.110]], [[0.000,0.000,-0.015],[0.000,0.000,-0.015]]]), + (4, [[0.540,0.710,0.000], [-0.005,-0.065,0.000], [0.080,-0.010,0.000], [0.098,-0.016,0.000], [0.000,0.000,0.040], [0.000,0.000,0.124]]), + (5, [[0.530,0.630,0.000], [-0.015,-0.095,0.000], [0.170,-0.030,0.000], [0.082,-0.024,0.000], [0.000,0.000,0.160], [0.000,0.000,0.116]]), + (6, [[0.510,0.520,0.000], [-0.029,-0.135,0.000], [0.240,-0.060,0.000], [0.066,-0.042,0.000], [0.000,0.000,0.270], [0.000,0.000,0.098]]), + (7, [[0.470,0.360,0.000], [-0.055,-0.161,0.000], [0.300,-0.120,0.000], [0.026,-0.089,0.000], [0.000,0.000,0.350], [0.000,0.000,0.056]]), + (8, [[0.400,0.200,0.000], [-0.107,-0.145,0.000], [0.290,-0.240,0.000], [-0.054,-0.110,0.000], [0.000,0.000,0.380], [0.000,0.000,0.020]]), + (9, [[0.260,0.080,0.000], [-0.202,-0.111,0.000], [0.190,-0.340,0.000], [-0.132,-0.084,0.000], [0.000,0.000,0.390], [0.000,0.000,0.002]]), + (10, [[-0.290,0.070,0.000], [-0.237,0.128,0.000], [-0.200,-0.320,0.000], [-0.109,0.097,0.000], [0.000,0.000,0.360], [0.000,0.000,-0.031]]), + (11, [[-0.460,0.230,0.000], [-0.099,0.191,0.000], [-0.230,-0.210,0.000], [0.020,0.121,0.000], [0.000,0.000,0.320], [0.000,0.000,-0.079]]), + (12, [[-0.486,0.419,0.000], [-0.008,0.167,0.000], [-0.170,-0.080,0.000], [0.069,0.087,0.000], [0.000,0.000,0.210], [0.000,0.000,-0.109]]), + (13, [[-0.480,0.560,0.000], [-0.012,0.142,0.000], [-0.094,-0.025,0.000], [0.030,0.020,0.000], [0.000,0.000,0.102], [0.000,0.000,-0.046]]), + (14, [[-0.510,0.700,0.000], [-0.048,0.137,0.000], [-0.110,-0.040,0.000], [-0.062,-0.050,0.000], [0.000,0.000,0.120], [0.000,0.000,0.082]]) ]), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-4', + 'identifierRanges': '1-13', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-8', 'name': get_stomach_term('fundus of stomach')[0], 'ontId': get_stomach_term('fundus of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '5-7', + 'identifierRanges': '9-10', 'name': get_stomach_term('body of stomach')[0], 'ontId': get_stomach_term('body of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '8', + 'identifierRanges': '11', 'name': get_stomach_term('pyloric antrum')[0], 'ontId': get_stomach_term('pyloric antrum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '9', + 'identifierRanges': '12', 'name': get_stomach_term('pyloric canal')[0], 'ontId': get_stomach_term('pyloric canal')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '10', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] + 'identifierRanges': '13', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] }] - }), - 'Rat 1': ScaffoldPackage(MeshType_1d_path1, { + }) + elif "Pig 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 12 + "Structure": "1-2-3.2, 4-5-6-7-3-8-9-10-11-12-13" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[0.601,0.602,0.000], [-0.027,-0.056,0.000], [0.077,-0.036,0.000], [0.122,-0.056,0.000], [0.000,0.000,0.080], [0.000,0.000,0.076]]), - (2, [[0.564,0.524,0.000], [-0.047,-0.100,-0.000], [0.189,-0.097,0.000], [0.101,-0.066,0.000], [0.000,0.000,0.160], [0.000,0.000,0.084]]), - (3, [[0.507,0.402,0.000], [-0.071,-0.139,-0.000], [0.273,-0.171,0.000], [0.062,-0.070,-0.000], [0.000,0.000,0.250], [0.000,0.000,0.073]]), - (4, [[0.420,0.248,0.000], [-0.097,-0.137,-0.000], [0.307,-0.237,0.000], [-0.011,-0.067,-0.000], [0.000,0.000,0.300], [0.000,0.000,0.039]]), - (5, [[0.315,0.129,0.000], [-0.125,-0.109,-0.000], [0.256,-0.304,0.000], [-0.080,-0.076,0.000], [0.000,0.000,0.330], [0.000,0.000,0.030]]), - (6, [[0.171,0.034,0.000], [-0.161,-0.066,0.000], [0.144,-0.389,0.000], [-0.125,-0.058,0.000], [0.000,0.000,0.360], [0.000,0.000,0.015]]), - (7, [[0.000,0.000,0.000], [-0.200,0.002,0.000], [0.005,-0.420,0.000], [-0.156,0.003,0.000], [0.000,0.000,0.360], [0.000,0.000,-0.009]]), - (8, [[-0.218,0.048,0.000], [-0.208,0.094,0.000], [-0.173,-0.374,0.000], [-0.152,0.079,0.000], [0.000,0.000,0.340], [0.000,0.000,-0.015]]), - (9, [[-0.404,0.184,0.000], [-0.142,0.162,0.000], [-0.299,-0.260,0.000], [-0.044,0.113,0.000], [0.000,0.000,0.330], [0.000,0.000,-0.025]]), - (10, [[-0.497,0.356,0.000], [-0.049,0.209,0.000], [-0.255,-0.188,0.000], [0.077,0.107,0.000], [0.000,0.000,0.290], [0.000,0.000,-0.111]]), - (11, [[-0.490,0.587,0.000], [-0.018,0.189,-0.000], [-0.152,-0.045,0.000], [0.069,0.049,0.000], [0.000,0.000,0.120], [0.000,0.000,-0.073]]), - (12, [[-0.523,0.730,0.000], [-0.032,0.116,0.000], [-0.111,-0.036,0.000], [0.003,-0.002,0.000], [0.000,0.000,0.120], [0.000,0.000,0.018]]), - (13, [[-0.552,0.820,0.000], [-0.026,0.063,0.000], [-0.132,-0.045,0.000], [-0.045,-0.016,0.000], [0.000,0.000,0.150], [0.000,0.000,0.042]]) + (1, [[0.040,0.550,0.000], [0.000,-0.040,-0.000], [0.055,-0.007,0.000], [-0.010,-0.090,0.000], [0.000,0.000,0.0554], [0.000,0.000,0.060]]), + (2, [[0.030,0.430,0.000], [-0.020,-0.270,-0.000], [0.118,-0.005,-0.000], [-0.000,-0.100,0.000], [-0.000,0.000,0.118], [0.000,0.000,0.080]]), + (3, [[0.000,0.000,0.000], [[-0.210,0.000,0.000],[-0.040,-0.590,-0.000]], [[0.000,-0.431,0.000],[0.118,-0.005,-0.000]], [[-0.020,-0.020,0.000],[-0.020,-0.020,0.000]], [[0.000,0.000,0.400],[-0.000,0.000,0.118]], [[0.000,0.000,0.010],[0.000,0.000,0.010]]]), + (4, [[0.440,0.010,0.000], [-0.010,-0.000,0.000], [0.010,-0.050,0.000], [-0.010,-0.090,0.000], [0.000,0.000,0.080], [0.000,0.000,0.060]]), + (5, [[0.420,0.010,0.000], [-0.050,-0.010,0.000], [-0.000,-0.150,0.000], [-0.000,-0.100,0.000], [0.000,0.000,0.150], [0.000,0.000,0.080]]), + (6, [[0.330,0.000,0.000], [-0.110,-0.000,0.000], [0.000,-0.280,0.000], [-0.000,-0.130,0.000], [0.000,0.000,0.280], [0.000,0.000,0.120]]), + (7, [[0.190,0.000,0.000], [-0.170,-0.010,0.000], [0.010,-0.390,0.000], [-0.020,-0.080,0.000], [0.000,0.000,0.380], [0.000,0.000,0.070]]), + (8, [[-0.220,0.010,0.000], [-0.250,0.030,0.000], [-0.030,-0.430,0.000], [-0.050,0.030,0.000], [0.000,0.000,0.400], [0.000,0.000,-0.010]]), + (9, [[-0.500,0.050,0.000], [-0.260,0.120,0.000], [-0.160,-0.360,0.000], [-0.120,0.140,0.000], [0.000,0.000,0.370], [0.000,0.000,-0.050]]), + (10, [[-0.700,0.240,0.000], [-0.110,0.270,0.000], [-0.280,-0.160,0.000], [-0.050,0.210,0.000], [0.000,0.000,0.310], [0.000,0.000,-0.090]]), + (11, [[-0.700,0.520,0.000], [0.120,0.260,0.000], [-0.270,0.050,0.000], [0.100,0.090,0.000], [0.000,0.000,0.180], [0.000,0.000,-0.110]]), + (12, [[-0.500,0.700,0.000], [0.140,0.190,0.000], [-0.090,0.030,0.000], [0.080,-0.020,0.000], [0.000,0.000,0.090], [0.000,0.000,-0.040]]), + (13, [[-0.410,0.880,0.000], [0.030,0.160,0.000], [-0.090,0.010,0.000], [-0.080,-0.030,0.000], [0.000,0.000,0.090], [0.000,0.000,0.040]]) ]), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-6', + 'identifierRanges': '1-12', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-6', 'name': get_stomach_term('fundus of stomach')[0], 'ontId': get_stomach_term('fundus of stomach')[1] }, @@ -350,265 +334,220 @@ class MeshType_3d_stomach1(Scaffold_base): '_AnnotationGroup': True, 'dimension': 1, 'identifierRanges': '12', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] }] - }), - 'Material': ScaffoldPackage(MeshType_1d_path1, { + }) + elif "Rat 1" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3.2, 4-5-6-7-8-9-3-10-11-12-13-14-15" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[-0.011,0.636,0.000], [0.012,-0.116,0.000], [0.057,0.000,0.000], [0.122,-0.056,0.000], [-0.000,0.000,0.057], [0.000,0.000,0.076]]), + (2, [[-0.001,0.419,-0.000], [0.008,-0.318,0.000], [0.108,0.000,0.000], [0.101,-0.066,0.000], [0.000,0.000,0.108], [0.000,0.000,0.084]]), + (3, [[0.000,0.000,0.000], [[-0.200,0.002,0.000],[-0.006,-0.520,0.000]], [[0.005,-0.420,0.000],[0.108,0.000,0.000]], [[-0.156,0.003,0.000],[-0.156,0.003,0.000]], [[0.000,0.000,0.360],[0.000,0.000,0.108]], [[0.000,0.000,-0.009],[0.000,0.000,-0.009]]]), + (4, [[0.601,0.602,0.000], [-0.027,-0.056,0.000], [0.077,-0.036,0.000], [0.122,-0.056,0.000], [0.000,0.000,0.080], [0.000,0.000,0.076]]), + (5, [[0.564,0.524,0.000], [-0.047,-0.100,-0.000], [0.189,-0.097,0.000], [0.101,-0.066,0.000], [0.000,0.000,0.160], [0.000,0.000,0.084]]), + (6, [[0.507,0.402,0.000], [-0.071,-0.139,-0.000], [0.273,-0.171,0.000], [0.062,-0.070,-0.000], [0.000,0.000,0.250], [0.000,0.000,0.073]]), + (7, [[0.420,0.248,0.000], [-0.097,-0.137,-0.000], [0.307,-0.237,0.000], [-0.011,-0.067,-0.000], [0.000,0.000,0.300], [0.000,0.000,0.039]]), + (8, [[0.315,0.129,0.000], [-0.125,-0.109,-0.000], [0.256,-0.304,0.000], [-0.080,-0.076,0.000], [0.000,0.000,0.330], [0.000,0.000,0.030]]), + (9, [[0.171,0.034,0.000], [-0.161,-0.066,0.000], [0.144,-0.389,0.000], [-0.125,-0.058,0.000], [0.000,0.000,0.360], [0.000,0.000,0.015]]), + (10, [[-0.218,0.048,0.000], [-0.208,0.094,0.000], [-0.173,-0.374,0.000], [-0.152,0.079,0.000], [0.000,0.000,0.340], [0.000,0.000,-0.015]]), + (11, [[-0.404,0.184,0.000], [-0.142,0.162,0.000], [-0.299,-0.260,0.000], [-0.044,0.113,0.000], [0.000,0.000,0.330], [0.000,0.000,-0.025]]), + (12, [[-0.497,0.356,0.000], [-0.049,0.209,0.000], [-0.255,-0.188,0.000], [0.077,0.107,0.000], [0.000,0.000,0.290], [0.000,0.000,-0.111]]), + (13, [[-0.490,0.587,0.000], [-0.018,0.189,-0.000], [-0.152,-0.045,0.000], [0.069,0.049,0.000], [0.000,0.000,0.120], [0.000,0.000,-0.073]]), + (14, [[-0.523,0.730,0.000], [-0.032,0.116,0.000], [-0.111,-0.036,0.000], [0.003,-0.002,0.000], [0.000,0.000,0.120], [0.000,0.000,0.018]]), + (15, [[-0.552,0.820,0.000], [-0.026,0.063,0.000], [-0.132,-0.045,0.000], [-0.045,-0.016,0.000], [0.000,0.000,0.150], [0.000,0.000,0.042]]) + ]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-14', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-8', + 'name': get_stomach_term('fundus of stomach')[0], + 'ontId': get_stomach_term('fundus of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '9-11', + 'name': get_stomach_term('body of stomach')[0], + 'ontId': get_stomach_term('body of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '12', + 'name': get_stomach_term('pyloric antrum')[0], + 'ontId': get_stomach_term('pyloric antrum')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '13', + 'name': get_stomach_term('pyloric canal')[0], + 'ontId': get_stomach_term('pyloric canal')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '14', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] + }] + }) + elif "Material" in parameterSetName: + return ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 15 + "Structure": "1-2-3.2, 4-5-6-7-8-9-3-10-11-12-13-14-15-16-17-18" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [[0.700,0.000,0.000], [-0.020,0.000,0.000], [0.000,-0.050,0.000], [0.000,-0.100,0.000], [0.000,0.000,0.050], [0.000,0.000,0.100]]), - (2, [[0.680,0.000,0.000], [-0.050,0.000,0.000], [0.000,-0.150,0.000], [0.000,-0.110,0.000], [0.000,0.000,0.150], [0.000,0.000,0.110]]), - (3, [[0.600,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.290,0.000], [0.000,-0.130,0.000], [0.000,0.000,0.290], [0.000,0.000,0.130]]), - (4, [[0.490,0.000,0.000], [-0.130,0.000,0.000], [0.000,-0.400,0.000], [0.000,-0.100,0.000], [0.000,0.000,0.400], [0.000,0.000,0.100]]), - (5, [[0.350,0.000,0.000], [-0.160,0.000,0.000], [0.000,-0.480,0.000], [0.000,-0.050,0.000], [0.000,0.000,0.480], [0.000,0.000,0.050]]), - (6, [[0.180,0.000,0.000], [-0.170,0.000,0.000], [0.000,-0.500,0.000], [0.000,-0.010,0.000], [0.000,0.000,0.500], [0.000,0.000,0.010]]), - (7, [[0.000,0.000,0.000], [-0.190,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), - (8, [[-0.200,0.000,0.000], [-0.200,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), - (9, [[-0.400,0.000,0.000], [-0.200,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), - (10, [[-0.600,0.000,0.000], [-0.180,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), - (11, [[-0.750,0.000,0.000], [-0.150,0.000,0.000], [0.000,-0.440,0.000], [0.000,0.100,0.000], [0.000,0.000,0.440], [0.000,0.000,-0.100]]), - (12, [[-0.900,0.000,0.000], [-0.120,0.000,0.000], [0.000,-0.310,0.000], [0.000,0.120,0.000], [0.000,0.000,0.310], [0.000,0.000,-0.120]]), - (13, [[-1.000,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), - (14, [[-1.100,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), - (15, [[-1.200,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), - (16, [[-1.300,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]) + (1, [[0.000,0.800,0.000], [0.000,-0.200,0.000], [0.080,-0.000,0.000], [0.000,-0.100,0.000], [0.000,0.000,0.080], [0.000,0.000,0.100]]), + (2, [[0.000,0.500,0.000], [0.000,-0.400,0.000], [0.150,0.000,0.000], [0.000,-0.110,0.000], [0.000,0.000,0.150], [0.000,0.000,0.110]]), + (3, [[0.000,0.000,0.000], [[-0.190,0.000,0.000],[0.000,-0.600,0.000]], [[0.000,-0.500,0.000], [0.210,0.000,0.000]], [[0.000,0.000,0.000],[0.000,0.000,0.000]], [[0.000,0.000,0.500],[0.000,0.000,0.200]], [[0.000,0.000,0.000],[0.000,0.000,0.000]]]), + (4, [[0.700,0.000,0.000], [-0.020,0.000,0.000], [0.000,-0.050,0.000], [0.000,-0.100,0.000], [0.000,0.000,0.050], [0.000,0.000,0.100]]), + (5, [[0.680,0.000,0.000], [-0.050,0.000,0.000], [0.000,-0.150,0.000], [0.000,-0.110,0.000], [0.000,0.000,0.150], [0.000,0.000,0.110]]), + (6, [[0.600,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.290,0.000], [0.000,-0.130,0.000], [0.000,0.000,0.290], [0.000,0.000,0.130]]), + (7, [[0.490,0.000,0.000], [-0.130,0.000,0.000], [0.000,-0.400,0.000], [0.000,-0.100,0.000], [0.000,0.000,0.400], [0.000,0.000,0.100]]), + (8, [[0.350,0.000,0.000], [-0.160,0.000,0.000], [0.000,-0.480,0.000], [0.000,-0.050,0.000], [0.000,0.000,0.480], [0.000,0.000,0.050]]), + (9, [[0.180,0.000,0.000], [-0.170,0.000,0.000], [0.000,-0.500,0.000], [0.000,-0.010,0.000], [0.000,0.000,0.500], [0.000,0.000,0.010]]), + (10, [[-0.200,0.000,0.000], [-0.200,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), + (11, [[-0.400,0.000,0.000], [-0.200,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), + (12, [[-0.600,0.000,0.000], [-0.180,0.000,0.000], [0.000,-0.500,0.000], [0.000,0.000,0.000], [0.000,0.000,0.500], [0.000,0.000,0.000]]), + (13, [[-0.750,0.000,0.000], [-0.150,0.000,0.000], [0.000,-0.440,0.000], [0.000,0.100,0.000], [0.000,0.000,0.440], [0.000,0.000,-0.100]]), + (14, [[-0.900,0.000,0.000], [-0.120,0.000,0.000], [0.000,-0.310,0.000], [0.000,0.120,0.000], [0.000,0.000,0.310], [0.000,0.000,-0.120]]), + (15, [[-1.000,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), + (16, [[-1.100,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), + (17, [[-1.200,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]), + (18, [[-1.300,0.000,0.000], [-0.100,0.000,0.000], [0.000,-0.200,0.000], [0.000,0.000,0.000], [0.000,0.000,0.200], [0.000,0.000,0.000]]) ]), 'userAnnotationGroups': [ { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '1-6', + 'identifierRanges': '1-17', + 'name': get_stomach_term('stomach')[0], + 'ontId': get_stomach_term('stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-2', + 'name': get_stomach_term('esophagus part of stomach')[0], + 'ontId': get_stomach_term('esophagus part of stomach')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3-8', 'name': get_stomach_term('fundus of stomach')[0], 'ontId': get_stomach_term('fundus of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '7-9', + 'identifierRanges': '9-11', 'name': get_stomach_term('body of stomach')[0], 'ontId': get_stomach_term('body of stomach')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '10-11', + 'identifierRanges': '12-13', 'name': get_stomach_term('pyloric antrum')[0], 'ontId': get_stomach_term('pyloric antrum')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '12-13', + 'identifierRanges': '14-15', 'name': get_stomach_term('pyloric canal')[0], 'ontId': get_stomach_term('pyloric canal')[1] }, { '_AnnotationGroup': True, 'dimension': 1, - 'identifierRanges': '14-15', - 'name': get_smallintestine_term('duodenum')[0], - 'ontId': get_smallintestine_term('duodenum')[1] + 'identifierRanges': '16-17', + 'name': get_stomach_term('duodenum part of stomach')[0], + 'ontId': get_stomach_term('duodenum part of stomach')[1] }] - }), - } + }) - ostiumDefaultScaffoldPackages = { - 'Human 1': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, +def getDefaultOstiumSettings(): + """ + Generate list of default options for ostium. + """ + options = { 'Number of elements around ostium': 8, 'Number of elements along': 3, 'Number of elements through wall': 4, - 'Unit scale': 0.0105, - 'Outlet': False, - 'Ostium diameter': 25.0, - 'Ostium length': 15.0, - 'Ostium wall thickness': 5.0, - 'Ostium wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, - 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 5.0, - 'Vessel wall thickness': 3.0, - 'Vessel wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, - 'Use linear through vessel wall': True, - 'Use cross derivatives': False, - 'Refine': False, - 'Refine number of elements around': 4, - 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - 'Human 2': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, - 'Number of elements along': 3, - 'Number of elements through wall': 1, - 'Unit scale': 0.0105 * 101, + 'Unit scale': 1.0, 'Outlet': False, - 'Ostium diameter': 25.0, - 'Ostium length': 15.0, - 'Ostium wall thickness': 5.0, + 'Ostium wall thickness': 0.0525, 'Ostium wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 5.0, - 'Vessel wall thickness': 3.0, + 'Vessel wall thickness': 0.0315, 'Vessel wall relative thicknesses': [0.55, 0.15, 0.25, 0.05], - 'Vessel angle 1 degrees': -40.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': -60.0, - 'Use linear through vessel wall': True, - 'Use cross derivatives': False, - 'Refine': False, - 'Refine number of elements around': 4, - 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - 'Mouse 1': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, - 'Number of elements along': 3, - 'Number of elements through wall': 4, - 'Unit scale': 0.147, - 'Outlet': False, - 'Ostium diameter': 1.5, - 'Ostium length': 1.5, - 'Ostium wall thickness': 0.35, - 'Ostium wall relative thicknesses': [0.75, 0.05, 0.15, 0.05], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, - 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 0.5, - 'Vessel wall thickness': 0.2, - 'Vessel wall relative thicknesses': [0.75, 0.05, 0.15, 0.05], - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, - 'Use linear through vessel wall': True, - 'Use cross derivatives': False, - 'Refine': False, - 'Refine number of elements around': 4, - 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - 'Pig 1': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, - 'Number of elements along': 3, - 'Number of elements through wall': 4, - 'Unit scale': 0.0118, - 'Outlet': False, - 'Ostium diameter': 20.0, - 'Ostium length': 10.0, - 'Ostium wall thickness': 5.0, - 'Ostium wall relative thicknesses': [0.47, 0.1, 0.33, 0.1], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, - 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 3.0, - 'Vessel wall thickness': 3.0, - 'Vessel wall relative thicknesses': [0.47, 0.1, 0.33, 0.1], - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, 'Use linear through vessel wall': True, 'Use cross derivatives': False, 'Refine': False, 'Refine number of elements around': 4, 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - 'Rat 1': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, - 'Number of elements along': 3, - 'Number of elements through wall': 4, - 'Unit scale': 0.043, - 'Outlet': False, - 'Ostium diameter': 5.0, - 'Ostium length': 5.0, - 'Ostium wall thickness': 0.5, - 'Ostium wall relative thicknesses': [0.65, 0.12, 0.18, 0.05], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, - 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 2.0, - 'Vessel wall thickness': 0.3, - 'Vessel wall relative thicknesses': [0.65, 0.12, 0.18, 0.05], - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, - 'Use linear through vessel wall': True, - 'Use cross derivatives': False, - 'Refine': False, - 'Refine number of elements around': 4, - 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - 'Material': ScaffoldPackage(MeshType_3d_ostium1, { - 'scaffoldSettings': { - 'Number of vessels': 1, - 'Number of elements across common': 2, - 'Number of elements around ostium': 8, - 'Number of elements along': 3, - 'Number of elements through wall': 4, - 'Unit scale': 1.0, - 'Outlet': False, - 'Ostium diameter': 0.3, - 'Ostium length': 0.3, - 'Ostium wall thickness': 0.05, - 'Ostium wall relative thicknesses': [0.25, 0.25, 0.25, 0.25], - 'Ostium inter-vessel distance': 0.0, - 'Ostium inter-vessel height': 0.0, - 'Use linear through ostium wall': True, - 'Vessel end length factor': 1.0, - 'Vessel inner diameter': 0.1, - 'Vessel wall thickness': 0.03, - 'Vessel wall relative thicknesses': [0.25, 0.25, 0.25, 0.25], - 'Vessel angle 1 degrees': 0.0, - 'Vessel angle 1 spread degrees': 0.0, - 'Vessel angle 2 degrees': 0.0, - 'Use linear through vessel wall': True, - 'Use cross derivatives': False, - 'Refine': False, - 'Refine number of elements around': 4, - 'Refine number of elements along': 4, - 'Refine number of elements through wall': 1 - }, - }), - } + 'Refine number of elements through wall': 1} + + return options + +def updateOstiumOptions(options, ostiumOptions): + """ + Update ostium sub-scaffold options which depend on parent options. + """ + ostiumOptions['Number of elements around ostium'] = options['Number of elements around esophagus'] + ostiumOptions['Ostium wall thickness'] = options['Wall thickness'] + ostiumOptions['Vessel wall thickness'] = options['Esophagus wall thickness'] + elementsCountThroughWall = options['Number of elements through wall'] + ostiumOptions['Number of elements through wall'] = elementsCountThroughWall + ostiumOptions['Use linear through ostium wall'] = options['Use linear through wall'] + ostiumOptions['Use linear through vessel wall'] = options['Use linear through wall'] + if elementsCountThroughWall == 1: + ostiumOptions['Ostium wall relative thicknesses'] = [1.0] + ostiumOptions['Vessel wall relative thicknesses'] = [1.0] + else: + mucosaRelThickness = options['Mucosa relative thickness'] + submucosaRelThickness = options['Submucosa relative thickness'] + circularRelThickness = options['Circular muscle layer relative thickness'] + longRelThickness = options['Longitudinal muscle layer relative thickness'] + relThicknesses = [mucosaRelThickness, submucosaRelThickness, circularRelThickness, longRelThickness] + ostiumOptions['Ostium wall relative thicknesses'] = relThicknesses + ostiumOptions['Vessel wall relative thicknesses'] = relThicknesses + + return ostiumOptions + + +class MeshType_3d_stomach1(Scaffold_base): + """ + Generates a 3-D stomach mesh with variable numbers of elements around the esophagus and duodenum, + along the central line, and through wall. The stomach is created using a network layout as the longitudinal axis + of the stomach. D2 of the network layout points to the greater curvature of the stomach and magnitude of D2 and D3 + are the radii of the stomach in the respective direction. + """ @staticmethod def getName(): @@ -627,38 +566,19 @@ def getParameterSetNames(): @classmethod def getDefaultOptions(cls, parameterSetName='Default'): - if 'Human 2' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 2'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Human 2'] - elif 'Mouse 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Mouse 1'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Mouse 1'] - elif 'Pig 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Pig 1'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Pig 1'] - elif 'Rat 1' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Rat 1'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Rat 1'] - elif 'Material' in parameterSetName: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Material'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Material'] - else: - centralPathOption = cls.centralPathDefaultScaffoldPackages['Human 1'] - ostiumOption = cls.ostiumDefaultScaffoldPackages['Human 1'] - options = { - 'Central path': copy.deepcopy(centralPathOption), + 'Network layout': getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName), 'Number of elements around esophagus': 8, 'Number of elements around duodenum': 16, 'Number of elements along': 14, 'Number of elements through wall': 4, 'Wall thickness': 0.0525, + 'Esophagus wall thickness': 0.0315, 'Mucosa relative thickness': 0.55, 'Submucosa relative thickness': 0.15, 'Circular muscle layer relative thickness': 0.25, 'Longitudinal muscle layer relative thickness': 0.05, 'Limiting ridge': False, - 'Gastro-esophageal junction': copy.deepcopy(ostiumOption), 'Use linear through wall': True, 'Refine': False, 'Refine number of elements surface': 4, @@ -666,10 +586,13 @@ def getDefaultOptions(cls, parameterSetName='Default'): 'Refine number of elements through wall': 1 } if 'Human 2' in parameterSetName: + options['Number of elements around duodenum'] = 12 options['Number of elements through wall'] = 1 - options['Wall thickness'] = 0.0525 * 101 + options['Wall thickness'] = 3.0 + options['Esophagus wall thickness'] = 3.0 elif 'Mouse 1' in parameterSetName: options['Wall thickness'] = 0.05145 + options['Esophagus wall thickness'] = 0.01029 options['Mucosa relative thickness'] = 0.75 options['Submucosa relative thickness'] = 0.05 options['Circular muscle layer relative thickness'] = 0.15 @@ -677,6 +600,7 @@ def getDefaultOptions(cls, parameterSetName='Default'): options['Limiting ridge'] = True elif 'Pig 1' in parameterSetName: options['Wall thickness'] = 0.059 + options['Esophagus wall thickness'] = 0.0354 options['Mucosa relative thickness'] = 0.47 options['Submucosa relative thickness'] = 0.1 options['Circular muscle layer relative thickness'] = 0.33 @@ -684,6 +608,7 @@ def getDefaultOptions(cls, parameterSetName='Default'): options['Limiting ridge'] = False elif 'Rat 1' in parameterSetName: options['Wall thickness'] = 0.0215 + options['Esophagus wall thickness'] = 0.0129 options['Mucosa relative thickness'] = 0.65 options['Submucosa relative thickness'] = 0.12 options['Circular muscle layer relative thickness'] = 0.18 @@ -691,30 +616,30 @@ def getDefaultOptions(cls, parameterSetName='Default'): options['Limiting ridge'] = True elif 'Material' in parameterSetName: options['Wall thickness'] = 0.05 + options['Esophagus wall thickness'] = 0.03 options['Mucosa relative thickness'] = 0.25 options['Submucosa relative thickness'] = 0.25 options['Circular muscle layer relative thickness'] = 0.25 options['Longitudinal muscle layer relative thickness'] = 0.25 options['Limiting ridge'] = False - cls.updateSubScaffoldOptions(options) return options @staticmethod def getOrderedOptionNames(): return [ - 'Central path', + 'Network layout', 'Number of elements around esophagus', 'Number of elements around duodenum', 'Number of elements along', 'Number of elements through wall', 'Wall thickness', + 'Esophagus wall thickness', 'Mucosa relative thickness', 'Submucosa relative thickness', 'Circular muscle layer relative thickness', 'Longitudinal muscle layer relative thickness', 'Limiting ridge', - 'Gastro-esophageal junction', 'Use linear through wall', 'Refine', 'Refine number of elements surface', @@ -723,18 +648,14 @@ def getOrderedOptionNames(): @classmethod def getOptionValidScaffoldTypes(cls, optionName): - if optionName == 'Central path': - return [MeshType_1d_path1] - if optionName == 'Gastro-esophageal junction': - return [MeshType_3d_ostium1] + if optionName == 'Network layout': + return [MeshType_1d_network_layout1] return [] @classmethod def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType): - if optionName == 'Central path': - return list(cls.centralPathDefaultScaffoldPackages.keys()) - if optionName == 'Gastro-esophageal junction': - return list(cls.ostiumDefaultScaffoldPackages.keys()) + if optionName == 'Network layout': + return cls.getParameterSetNames() assert scaffoldType in cls.getOptionValidScaffoldTypes(optionName), \ cls.__name__ + '.getOptionScaffoldTypeParameterSetNames. ' + \ 'Invalid option \'' + optionName + '\' scaffold type ' + scaffoldType.getName() @@ -750,24 +671,16 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non assert parameterSetName in cls.getOptionScaffoldTypeParameterSetNames(optionName, scaffoldType), \ 'Invalid parameter set ' + str(parameterSetName) + ' for scaffold ' + str(scaffoldType.getName()) + \ ' in option ' + str(optionName) + ' of scaffold ' + cls.getName() - if optionName == 'Central path': - if not parameterSetName: - parameterSetName = list(cls.centralPathDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.centralPathDefaultScaffoldPackages[parameterSetName]) - if optionName == 'Gastro-esophageal junction': + if optionName == 'Network layout': if not parameterSetName: - parameterSetName = list(cls.ostiumDefaultScaffoldPackages.keys())[0] - return copy.deepcopy(cls.ostiumDefaultScaffoldPackages[parameterSetName]) + parameterSetName = "Default" + return getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName) assert False, cls.__name__ + '.getOptionScaffoldPackage: Option ' + optionName + ' is not a scaffold' @classmethod def checkOptions(cls, options): - if not options['Central path'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Central path'): - options['Central path'] = cls.getOptionScaffoldPackage('Central path', MeshType_1d_path1) - if not options['Gastro-esophageal junction'].getScaffoldType() in cls.getOptionValidScaffoldTypes( - 'Gastro-esophageal junction'): - options['Gastro-esophageal junction'] = cls.getOptionScaffoldPackage('Gastro-esophageal junction', - MeshType_3d_ostium1) + if not options['Network layout'].getScaffoldType() in cls.getOptionValidScaffoldTypes('Network layout'): + options['Network layout'] = cls.getOptionScaffoldPackage('Network layout', MeshType_1d_network_layout1) if options['Number of elements around esophagus'] < 8: options['Number of elements around esophagus'] = 8 if options['Number of elements around duodenum'] < 12: @@ -787,32 +700,6 @@ def checkOptions(cls, options): if options[key] < 1: options[key] = 1 - cls.updateSubScaffoldOptions(options) - - @classmethod - def updateSubScaffoldOptions(cls, options): - """ - Update ostium sub-scaffold options which depend on parent options. - """ - ostiumOptions = options['Gastro-esophageal junction'] - ostiumSettings = ostiumOptions.getScaffoldSettings() - ostiumSettings['Number of elements around ostium'] = options['Number of elements around esophagus'] - wallThickness = options['Wall thickness'] / ostiumSettings['Unit scale'] - ostiumSettings['Ostium wall thickness'] = wallThickness - elementsCountThroughWall = options['Number of elements through wall'] - ostiumSettings['Number of elements through wall'] = elementsCountThroughWall - if elementsCountThroughWall == 1: - ostiumSettings['Ostium wall relative thicknesses'] = [1.0] - ostiumSettings['Vessel wall relative thicknesses'] = [1.0] - else: - mucosaRelThickness = options['Mucosa relative thickness'] - submucosaRelThickness = options['Submucosa relative thickness'] - circularRelThickness = options['Circular muscle layer relative thickness'] - longRelThickness = options['Longitudinal muscle layer relative thickness'] - relThicknesses = [mucosaRelThickness, submucosaRelThickness, circularRelThickness, longRelThickness] - ostiumSettings['Ostium wall relative thicknesses'] = relThicknesses - ostiumSettings['Vessel wall relative thicknesses'] = relThicknesses - @classmethod def generateBaseMesh(cls, region, options): """ @@ -821,27 +708,27 @@ def generateBaseMesh(cls, region, options): :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup, None """ - cls.updateSubScaffoldOptions(options) - geometricCentralPath = options['Central path'] - materialCentralPath = cls.centralPathDefaultScaffoldPackages['Material'] + + geometricNetworkLayout = options['Network layout'] + materialNetworkLayout = getDefaultNetworkLayoutScaffoldPackage(cls, 'Material') limitingRidge = options['Limiting ridge'] elementsCountThroughWall = options['Number of elements through wall'] allAnnotationGroups = [] - stomachTermsAlong = [None, 'fundus of stomach', 'body of stomach', - 'pyloric antrum', 'pyloric canal', 'duodenum'] + stomachTermsAlong = ['stomach', 'fundus of stomach', 'body of stomach', + 'pyloric antrum', 'pyloric canal', 'duodenum part of stomach', 'esophagus part of stomach'] # Geometric coordinates fm = region.getFieldmodule() coordinates = find_or_create_field_coordinates(fm) - geometricCentralPath = StomachCentralPath(region, geometricCentralPath, stomachTermsAlong) + geometricNetworkLayout = StomachNetworkLayout(region, geometricNetworkLayout, stomachTermsAlong) allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier, elementsAlongGroups = \ createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, - allAnnotationGroups, centralPath=geometricCentralPath, - options=options, nodeIdentifier=1, elementIdentifier=1) + allAnnotationGroups, networkLayout=geometricNetworkLayout, + options=options, nodeIdentifier=1, elementIdentifier=1)[0:4] # Material coordinates stomach_coordinates = find_or_create_field_coordinates(fm, name="stomach coordinates") @@ -851,14 +738,14 @@ def generateBaseMesh(cls, region, options): with ChangeManager(tmp_fm): tmp_stomach_coordinates = find_or_create_field_coordinates(tmp_fm, name="stomach coordinates") - materialCentralPath = StomachCentralPath(tmp_region, materialCentralPath, stomachTermsAlong) + materialNetworkLayout = StomachNetworkLayout(tmp_region, materialNetworkLayout, stomachTermsAlong) allAnnotationGroupsMaterial, nextNodeIdentifier, nextElementIdentifier = \ createStomachMesh3d(tmp_region, tmp_fm, tmp_stomach_coordinates, stomachTermsAlong, allAnnotationGroupsMaterial, - centralPath=materialCentralPath, options=options, nodeIdentifier=1, + networkLayout=materialNetworkLayout, options=options, nodeIdentifier=1, elementIdentifier=1, elementsAlongSections=elementsAlongGroups, - materialCoordinates=True)[:-1] + materialCoordinates=True)[:3] # Write two coordinates sir = tmp_region.createStreaminformationRegion() @@ -917,6 +804,7 @@ def generateBaseMesh(cls, region, options): return allAnnotationGroups, None + @classmethod def refineMesh(cls, meshrefinement, options): """ @@ -1205,17 +1093,19 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): annotationGroups.remove(nearLCGroup) -class StomachCentralPath: +class StomachNetworkLayout: """ - Generates sampled central path for stomach scaffold. + Generates sampled network layout for stomach scaffold. """ - def __init__(self, region, centralPath, stomachTermsAlong=[None]): + def __init__(self, region, networkLayout, stomachTermsAlong=[None], esoSegmentIdx=0, stomachSegmentIdx=[1,2]): """ :param region: Zinc region needed to create path region to define path in. - :param centralPath: Central path subscaffold from meshtype_1d_path1 + :param networkLayout: Network layout subscaffold from meshtype_1d_network_layout1 :param stomachTermsAlong: Annotation terms along length of stomach + :param esoSegmentIdx: Segment index of esophagus branch. + :param stomachSegmentIdx: Segment index of the body of stomach. """ - # Extract length of each group along stomach from central path + # Extract length of each group along stomach from network layout arcLengthOfGroupsAlong = [] cxGroups = [] cd1Groups = [] @@ -1224,21 +1114,93 @@ def __init__(self, region, centralPath, stomachTermsAlong=[None]): cd12Groups = [] cd13Groups = [] - self._path_region = region.createRegion() - centralPath.generate(self._path_region) - tmpFieldmodule = self._path_region.getFieldmodule() + tmpRegion = region.createRegion() + networkLayout.generate(tmpRegion) + pathNetworkMesh = networkLayout.getConstructionObject() + tmpFieldmodule = tmpRegion.getFieldmodule() tmpNodes = tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) tmpCoordinates = tmpFieldmodule.findFieldByName('coordinates') + networkSegments = pathNetworkMesh.getNetworkSegments() + + cxGroup = [] + cd1Group = [] + cd2Group = [] + cd3Group = [] + cd12Group = [] + cd13Group = [] + stomachNodes = [] + esoNodes = [] + esoVersions = [] + lowerStomachNodes = [] + lowerStomachVersions = [] for termName in stomachTermsAlong: tmpGroup = tmpFieldmodule.findFieldByName(termName).castGroup() if termName else None tmpNodeset = tmpGroup.getNodesetGroup(tmpNodes) if tmpGroup else tmpNodes - cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = get_nodeset_path_field_parameters( - tmpNodeset, tmpCoordinates, - [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, - Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, - Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) + if termName == "stomach": + nodeiterator = tmpNodeset.createNodeiterator() + node = nodeiterator.next() + while node.isValid(): + stomachNodes.append(node.getIdentifier()) + node = nodeiterator.next() + + for i in range(len(networkSegments[stomachSegmentIdx[1]].getNodeIdentifiers())): + if networkSegments[stomachSegmentIdx[1]].getNodeIdentifiers()[i] in stomachNodes: + lowerStomachNodes.append(networkSegments[stomachSegmentIdx[1]].getNodeIdentifiers()[i]) + lowerStomachVersions.append(networkSegments[stomachSegmentIdx[1]].getNodeVersions()[i]) + + for i in range(2): + cx, cd1, cd2, cd3, cd12, cd13 = get_nodeset_path_ordered_field_parameters( + tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3], + (lowerStomachNodes if i else networkSegments[stomachSegmentIdx[0]].getNodeIdentifiers()), + (lowerStomachVersions if i else networkSegments[stomachSegmentIdx[0]].getNodeVersions())) + + cxGroup += cx[(1 if i else 0):] + cd1Group += cd1[(1 if i else 0):] + cd2Group += cd2[(1 if i else 0):] + cd3Group += cd3[(1 if i else 0):] + cd12Group += cd12[(1 if i else 0):] + cd13Group += cd13[(1 if i else 0):] + + if i == 0: + xbranchpt = cx[-1] + d2branchpt = cd2[-1] + d3branchpt = cd3[-1] + arcLengthToBranchPt = 0.0 + for n in range(len(cx) - 1): + arcLengthToBranchPt += interp.getCubicHermiteArcLength(cx[n], cd1[n], cx[n + 1], cd1[n + 1]) + + elif termName == "esophagus part of stomach": + for i in range(len(networkSegments[esoSegmentIdx].getNodeIdentifiers())): + if networkSegments[esoSegmentIdx].getNodeIdentifiers()[i] in stomachNodes: + esoNodes.append(networkSegments[esoSegmentIdx].getNodeIdentifiers()[i]) + esoVersions.append(networkSegments[esoSegmentIdx].getNodeVersions()[i]) + + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = \ + get_nodeset_path_ordered_field_parameters(tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3], + esoNodes, esoVersions) + + elif termName == "fundus of stomach": + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = \ + get_nodeset_path_ordered_field_parameters(tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3], + networkSegments[1].getNodeIdentifiers(), + networkSegments[1].getNodeVersions()) + else: + cxGroup, cd1Group, cd2Group, cd3Group, cd12Group, cd13Group = \ + get_nodeset_path_field_parameters(tmpNodeset, tmpCoordinates, + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, + Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D_DS3, + Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D2_DS1DS3]) arcLength = 0.0 for e in range(len(cxGroup) - 1): @@ -1266,6 +1228,10 @@ def __init__(self, region, centralPath, stomachTermsAlong=[None]): self.cd3Groups = cd3Groups self.cd12Groups = cd12Groups self.cd13Groups = cd13Groups + self.xBranchPt = xbranchpt + self.d2BranchPt = d2branchpt + self.d3BranchPt = d3branchpt + self.arcLengthToBranchPt = arcLengthToBranchPt def findCurvatureAroundLoop(nx, nd, radialVectors): @@ -1309,22 +1275,27 @@ def findCurvatureAlongLine(nx, nd, radialVectors): return curvature -def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotationGroups, centralPath, options, - nodeIdentifier, elementIdentifier, elementsAlongSections = [], materialCoordinates=False): +def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotationGroups, networkLayout, options, + nodeIdentifier, elementIdentifier, elementsAlongSections = [], + materialCoordinates=False, nodeIdProximalEso=[], xProximalEso=[], d1ProximalEso=[], + d2ProximalEso=[], d3ProximalEso=[]): """ - Generates a stomach scaffold in the region using a central path and parameter options. + Generates a stomach scaffold in the region using a network layout and parameter options. :param region: Region to create elements in. :param fm: Zinc fieldModule to create elements in. :param coordinates: Coordinate field to define nodes and elements. :param stomachTermsAlong: Annotation terms along length of stomach. :param allAnnotationGroups: List of annotation groups. - :param centralPath: Central path through the axis of the stomach scaffold. + :param networkLayout: Network layout through the axis of the stomach scaffold. :param options: Parameter options for stomach scaffold. :param nodeIdentifier: First node identifier. :param elementIdentifier: First element identifier. :param elementsAlongSections: Number of elements along each section. :param materialCoordinates: Create material coordinates if True. - :return allAnnotationGroups, elementsAlongSections + :param nodeIdProximalEso, xProximalEso, d1ProximalEso, d2ProximalEso, d3ProximalEso: Identifier, coordinates and + derivatives of nodes to use at the start of esophagus section joining to the stomach. + :return allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier, elementsAlongSections, nodeIdxDistal, + xDistal, d1Distal, d2Distal, d3Distal, arclengthDuodenumCP, xPrev, d2Prev """ elementsCountAroundEso = options['Number of elements around esophagus'] elementsCountAroundDuod = options['Number of elements around duodenum'] @@ -1337,17 +1308,19 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio useCrossDerivatives = False useCubicHermiteThroughWall = not (options['Use linear through wall']) - GEJOptions = options['Gastro-esophageal junction'] - GEJSettings = GEJOptions.getScaffoldSettings() + ostiumOptions = getDefaultOstiumSettings() + GEJSettings = updateOstiumOptions(options, ostiumOptions) elementsAlongEsophagus = GEJSettings['Number of elements along'] elementsThroughEsophagusWall = GEJSettings['Number of elements through wall'] - ostiumDiameter = GEJSettings['Ostium diameter'] + ostiumRadius = vector.magnitude(networkLayout.cd2Groups[-1][1]) limitingRidge = options['Limiting ridge'] wallThickness = options['Wall thickness'] + GEJSettings['Use linear through ostium wall'] = options['Use linear through wall'] + GEJSettings['Use linear through vessel wall'] = options['Use linear through wall'] elementsCountAcrossCardia = 1 cardiaDiameterFactor = 1.4 # scale to ostium diameter - sf = (cardiaDiameterFactor - 1) * ostiumDiameter * 0.5 * GEJSettings['Unit scale'] + sf = (cardiaDiameterFactor - 1) * ostiumRadius elementsAroundHalfEso = int(elementsCountAroundEso * 0.5) elementsAroundQuarterEso = int(elementsCountAroundEso * 0.25) @@ -1367,26 +1340,16 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio relThicknesses = [1.0] unitScale = GEJSettings['Unit scale'] - ostiumLength = GEJSettings['Ostium length'] ostiumWallThickness = GEJSettings['Ostium wall thickness'] ostiumWallRelThicknesses = GEJSettings['Ostium wall relative thicknesses'] - vesselInnerDiameter = GEJSettings['Vessel inner diameter'] vesselWallThickness = GEJSettings['Vessel wall thickness'] vesselWallRelThicknesses = GEJSettings['Vessel wall relative thicknesses'] - vesselAngle1 = GEJSettings['Vessel angle 1 degrees'] - vesselAngle2 = GEJSettings['Vessel angle 2 degrees'] GEJSettings['Unit scale'] = 1.0 - GEJSettings['Ostium diameter'] = 0.3 - GEJSettings['Ostium length'] = 0.3 GEJSettings['Ostium wall thickness'] = wallThickness GEJSettings['Ostium wall relative thicknesses'] = relThicknesses - GEJSettings['Vessel inner diameter'] = 0.1 GEJSettings['Vessel wall thickness'] = wallThickness * 0.6 GEJSettings['Vessel wall relative thicknesses'] = relThicknesses - sf = (cardiaDiameterFactor - 1) * GEJSettings['Ostium diameter'] * 0.5 - GEJSettings['Vessel angle 1 degrees'] = 0.0 - GEJSettings['Vessel angle 2 degrees'] = 0.0 nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) nodetemplate = nodes.createNodetemplate() @@ -1408,14 +1371,15 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio # Create annotation groups for stomach sections arcLengthRatioForGroupsFromFundusApex = [] - arcLengthOfGroupsAlong = centralPath.arcLengthOfGroupsAlong - stomachCentralPathLength = arcLengthOfGroupsAlong[0] + arcLengthOfGroupsAlong = networkLayout.arcLengthOfGroupsAlong + stomachNetworkLayoutLength = arcLengthOfGroupsAlong[0] - for i in range(1, len(stomachTermsAlong)): - arcLengthRatio = arcLengthOfGroupsAlong[i] / stomachCentralPathLength + for i in range(1, len(stomachTermsAlong) - 1): + arcLengthRatio = arcLengthOfGroupsAlong[i] / stomachNetworkLayoutLength arcLengthRatioForGroupsFromFundusApex.append(arcLengthRatio) stomachGroup = AnnotationGroup(region, get_stomach_term("stomach")) + smallIntestineGroup = AnnotationGroup(region, get_smallintestine_term("small intestine")) fundusGroup = AnnotationGroup(region, get_stomach_term("fundus of stomach")) bodyGroup = AnnotationGroup(region, get_stomach_term("body of stomach")) antrumGroup = AnnotationGroup(region, get_stomach_term("pyloric antrum")) @@ -1426,7 +1390,7 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio [stomachGroup, bodyGroup], [stomachGroup, antrumGroup], [stomachGroup, pylorusGroup], - [stomachGroup, duodenumGroup]] + [smallIntestineGroup, duodenumGroup]] longitudinalMuscleGroup = AnnotationGroup(region, get_stomach_term("longitudinal muscle layer of stomach")) circularMuscleGroup = AnnotationGroup(region, get_stomach_term("circular muscle layer of stomach")) @@ -1441,7 +1405,7 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio [circularMuscleGroup], [longitudinalMuscleGroup]] - # Break central path into elements allocation to each group + # Break network layout into elements allocation to each group cxSections = [] cd1Sections = [] cd2Sections = [] @@ -1457,13 +1421,13 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio targetLengthTS = 0.025 - for i in (list(range(1, len(stomachTermsAlong) - 1)) + [0]): # start from body, go back to fundus - cxGroup = centralPath.cxGroups[i + 1] - cd1Group = centralPath.cd1Groups[i + 1] - cd2Group = centralPath.cd2Groups[i + 1] - cd3Group = centralPath.cd3Groups[i + 1] - cd12Group = centralPath.cd12Groups[i + 1] - cd13Group = centralPath.cd13Groups[i + 1] + for i in (list(range(1, len(stomachTermsAlong) - 2)) + [0]): # start from body, go back to fundus + cxGroup = networkLayout.cxGroups[i + 1] + cd1Group = networkLayout.cd1Groups[i + 1] + cd2Group = networkLayout.cd2Groups[i + 1] + cd3Group = networkLayout.cd3Groups[i + 1] + cd12Group = networkLayout.cd12Groups[i + 1] + cd13Group = networkLayout.cd13Groups[i + 1] # for n2 in range(len(cxGroup)): # node = nodes.createNode(nodeIdentifier, nodetemplate) @@ -1474,7 +1438,7 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio # coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, cd3Group[n2]) # nodeIdentifier += 1 - if materialCoordinates and i == len(stomachTermsAlong) - 1: + if materialCoordinates and i == len(stomachTermsAlong) - 2: for n in range(len(cxGroup)): cd12Group[n] = zero cd13Group[n] = zero @@ -1632,11 +1596,60 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio # Visualise track surface # nodeIdentifier, elementIdentifier = trackSurfaceStomach.generateMesh(region) - # Set up gastro-esophageal junction with midpoint aligned to fundus-body junction + # Set up gastro-esophageal junction with network layout + cxEso = networkLayout.cxGroups[-1] + cd1Eso = networkLayout.cd1Groups[-1] + cd2Eso = networkLayout.cd2Groups[-1] + cd3Eso = networkLayout.cd3Groups[-1] + cd12Eso = networkLayout.cd12Groups[-1] + + # Find centre position + # track along esophagus path and since cxEso[1] could be above or below the track surface, we check both side to + # determine direction to track. At each point, find the nearest position and take the diff between nearest point + # to the point in line, keep tracking till diff is close to zero. + + xTol = 1.0E-6 + arcStart = 0.0 + arcEnd = networkLayout.arcLengthOfGroupsAlong[-1] + nearestPosition = trackSurfaceStomach.findNearestPosition(cxEso[0]) + xNearestStart = trackSurfaceStomach.evaluateCoordinates(nearestPosition, derivatives=False) + distStart = vector.magnitude([cxEso[0][c] - xNearestStart[c] for c in range(3)]) + nearestPosition = trackSurfaceStomach.findNearestPosition(cxEso[-1]) + xNearestEnd = trackSurfaceStomach.evaluateCoordinates(nearestPosition, derivatives=False) + distEnd = vector.magnitude([cxEso[-1][c] - xNearestEnd[c] for c in range(3)]) + + for iter in range(100): + arcDistance = (arcStart + arcEnd) * 0.5 + x, d1 = interp.getCubicHermiteCurvesPointAtArcDistance(cxEso, cd1Eso, arcDistance)[0:2] + nearestPosition = trackSurfaceStomach.findNearestPosition(x) + xNearest = trackSurfaceStomach.evaluateCoordinates(nearestPosition, derivatives=False) + dist = vector.magnitude([x[c] - xNearest[c] for c in range(3)]) + + if abs(distStart - distEnd) > xTol: + if distStart < distEnd: + arcEnd = arcDistance + distEnd = dist + else: + arcStart = arcDistance + distStart = dist + + else: + xCentre, d1Centre, d2Centre = trackSurfaceStomach.evaluateCoordinates(nearestPosition, derivatives=True) + normAxis = vector.normalise([-d for d in d1]) + eIdx = interp.getNearestPointIndex(cxEso, xCentre) - 1 + arcLenghtSum = 0.0 + for e in range(eIdx): + arcLenghtSum += interp.getCubicHermiteArcLength(cxEso[e], cd1Eso[e], + cxEso[e + 1], cd1Eso[e + 1]) + xi = (arcDistance - arcLenghtSum) / \ + interp.getCubicHermiteArcLength(cxEso[eIdx], cd1Eso[eIdx], cxEso[eIdx + 1], cd1Eso[eIdx + 1]) + d2Centre = interp.interpolateCubicHermite(cd2Eso[eIdx], cd12Eso[eIdx], cd2Eso[eIdx + 1], + cd12Eso[eIdx + 1], xi) + break + if iter > 98: + print('Search for ileum entry centre - Max iters reached:', iter) + GEJSettings['Number of elements around ostium'] = elementsCountAroundEso - GEJPosition = trackSurfaceStomach.findNearestPosition(xGEJ) - xCentre, d1Centre, d2Centre = trackSurfaceStomach.evaluateCoordinates(GEJPosition, derivatives=True) - axis1 = d1Centre esophagusGroup = AnnotationGroup(region, get_esophagus_term("esophagus")) esophagusMeshGroup = esophagusGroup.getMeshGroup(mesh) @@ -1663,10 +1676,24 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio allAnnotationGroups += [esophagusMucosaGroup, esophagusSubmucosaGroup, esophagusCircularGroup, esophagusLongitudinalGroup] + xPath = [cxEso[0], xCentre] + d1Path = [cd1Eso[0], [-d for d in normAxis]] + ostiumLength = interp.computeCubicHermiteArcLength(xPath[0], d1Path[0], xPath[1], d1Path[1], + rescaleDerivatives=True) + d1Path[1] = vector.setMagnitude(d1Path[1], ostiumLength*0.1) + d2Path = [cd2Eso[0], d2Centre] + d3Path = [cd3Eso[0], vector.setMagnitude([-d for d in d1Centre], vector.magnitude(d2Centre))] + d12Path = [cd2Eso[0], [0.0, 0.0, 0.0]] + d13Path = [cd3Eso[0], [0.0, 0.0, 0.0]] + + networkLayoutEso = CustomNetworkLayout(xPath, d1Path, d2Path, d3Path, d12Path, d13Path) + nextNodeIdentifier, nextElementIdentifier, (o1_x, o1_d1, o1_d2, o1_d3, o1_NodeId, o1_Positions) = \ - generateOstiumMesh(region, GEJSettings, trackSurfaceStomach, GEJPosition, axis1, - nodeIdentifier, elementIdentifier, - vesselMeshGroups=[[stomachMeshGroup, esophagusMeshGroup, abdominalEsoMeshGroup]], + generateOstiumMesh(region, GEJSettings, trackSurfaceStomach, networkLayoutEso, + nodeIdentifier, elementIdentifier, nodeIdProximal=nodeIdProximalEso, + xProximal=xProximalEso, d1Proximal=d1ProximalEso, d2Proximal=d2ProximalEso, + d3Proximal=d3ProximalEso, + vesselMeshGroups=[[esophagusMeshGroup, abdominalEsoMeshGroup]], ostiumMeshGroups=[stomachMeshGroup, esophagogastricJunctionMeshGroup], wallAnnotationGroups=ostiumWallAnnotationGroups, coordinates=coordinates) @@ -1676,15 +1703,10 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio if materialCoordinates: GEJSettings['Unit scale'] = unitScale - GEJSettings['Ostium diameter'] = ostiumDiameter - GEJSettings['Ostium length'] = ostiumLength GEJSettings['Ostium wall thickness'] = ostiumWallThickness GEJSettings['Ostium wall relative thicknesses'] = ostiumWallRelThicknesses - GEJSettings['Vessel inner diameter'] = vesselInnerDiameter GEJSettings['Vessel wall thickness'] = vesselWallThickness GEJSettings['Vessel wall relative thicknesses'] = vesselWallRelThicknesses - GEJSettings['Vessel angle 1 degrees'] = vesselAngle1 - GEJSettings['Vessel angle 2 degrees'] = vesselAngle2 # Create location of annulus xAnnulusOuter = [[] for x in range(elementsCountAroundEso)] @@ -1747,7 +1769,8 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio minElementsInSections = [4, 3, 2, 2, 1] excessElements = elementsCountAlong - sum(minElementsInSections) - diff = [quarterLengthSections[c] - targetLengthPerElement * minElementsInSections[c] for c in range(len(minElementsInSections))] + diff = [quarterLengthSections[c] - targetLengthPerElement * minElementsInSections[c] + for c in range(len(minElementsInSections))] for i in range(excessElements): maxIdx = max(range(len(diff)), key=diff.__getitem__) minElementsInSections[maxIdx] += 1 @@ -1755,6 +1778,7 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio elementsAlongSections = minElementsInSections totalElementsAlong = sum(elementsAlongSections) + arclengthDuodenumCP = arcLengthOfGroupsAlong[5]/elementsAlongSections[-1] xSampledAlong = [[] for n1 in range(elementsCountAroundDuod)] d1SampledAlong = [[] for n1 in range(elementsCountAroundDuod)] @@ -1816,7 +1840,8 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio nxR, nd1R, nd2R, nd3R = \ trackSurfaceStomach.resampleHermiteCurvePointsSmooth( nx, nd1, nd2, nd3, proportions, derivativeMagnitudeEnd= - vector.magnitude(d1EllipseAroundAll[sectionIdx[1]][elementsAroundQuarterDuod + elementsAroundHalfDuod]))[0:-1] + vector.magnitude( + d1EllipseAroundAll[sectionIdx[1]][elementsAroundQuarterDuod + elementsAroundHalfDuod]))[0:-1] for n in range(len(nxR)): xEllipseAroundAll[sectionIdx[1]][elementsAroundHalfDuod + 1 + n] = nxR[n] @@ -2281,6 +2306,14 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio nodeIdx = stomachStartNode idxMat = [] + xDistal = [] + d1Distal = [] + d2Distal = [] + d3Distal = [] + xPrev = [] + d2Prev = [] + nodeIdxDistal = [] + if elementsCountThroughWall > 1: thicknessProportionsUI = [0.0, mucosaRelThickness, submucosaRelThickness, circularRelThickness, longitudinalRelThickness, longitudinalRelThickness] @@ -2298,6 +2331,12 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio for n3 in range(elementsCountThroughWall + 1): xi3 = xi3List[n3] if elementsCountThroughWall > 1 else 1.0 / elementsCountThroughWall * n3 idxAround = [] + xDistalAround = [] + d1DistalAround = [] + d2DistalAround = [] + d3DistalAround = [] + nodeIdxDistalAround = [] + for n1 in range(len(xSampledAroundAlong[n2])): # Coordinates norm = vector.normalise(d3SampledAroundAlong[n2][n1]) @@ -2322,9 +2361,27 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio for c in norm] d3List.append(d3) + if n2 >= len(xSampledAroundAlong) - 2: + xDistalAround.append(x) + d1DistalAround.append(d1) + d2DistalAround.append(d2) + d3DistalAround.append(d3) + nodeIdxDistalAround.append(nodeIdx) + idxAround.append(nodeIdx) nodeIdx += 1 idxThroughWall.append(idxAround) + + if n2 == len(xSampledAroundAlong) - 2: + xPrev.append(xDistalAround) + d2Prev.append(d2DistalAround) + + if n2 == len(xSampledAroundAlong) - 1: + xDistal.append(xDistalAround) + d1Distal.append(d1DistalAround) + d2Distal.append(d2DistalAround) + d3Distal.append(d3DistalAround) + nodeIdxDistal.append(nodeIdxDistalAround) idxMat.append(idxThroughWall) nodeIdxGC = [] @@ -2561,7 +2618,9 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio elementtemplate1 = elementtemplateX # print(elementIdentifier) # 166 - elif (elementsAroundQuarterEso - 2) > 0 and annulusFundusOpenRingIdx <= e2 < annulusFundusOpenRingIdx + 2.0 * (elementsAroundQuarterEso - 2): + elif (elementsAroundQuarterEso - 2) > 0 and \ + annulusFundusOpenRingIdx <= e2 < annulusFundusOpenRingIdx + \ + 2.0 * (elementsAroundQuarterEso - 2): if e1 == elementsAroundHalfDuod - 2: scaleFactors = [-1.0] eft1 = eftfactory.createEftNoCrossDerivatives() @@ -2812,4 +2871,18 @@ def createStomachMesh3d(region, fm, coordinates, stomachTermsAlong, allAnnotatio element = elementIter.next() allAnnotationGroups.append(nearLCGroup) - return allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier, elementsAlongSections + return allAnnotationGroups, nextNodeIdentifier, nextElementIdentifier, elementsAlongSections, nodeIdxDistal, \ + xDistal, d1Distal, d2Distal, d3Distal, arclengthDuodenumCP, xPrev, d2Prev + + +class CustomNetworkLayout: + """ + Generates sampled network layout for part of network layout. + """ + def __init__(self, cx, cd1, cd2, cd3, cd12, cd13): + self.cxPath = cx + self.cd1Path = cd1 + self.cd2Path = cd2 + self.cd3Path = cd3 + self.cd12Path = cd12 + self.cd13Path = cd13 diff --git a/src/scaffoldmaker/scaffolds.py b/src/scaffoldmaker/scaffolds.py index 10fb2d48..fac184c6 100644 --- a/src/scaffoldmaker/scaffolds.py +++ b/src/scaffoldmaker/scaffolds.py @@ -23,6 +23,7 @@ from scaffoldmaker.meshtypes.meshtype_3d_colon1 import MeshType_3d_colon1 from scaffoldmaker.meshtypes.meshtype_3d_colonsegment1 import MeshType_3d_colonsegment1 from scaffoldmaker.meshtypes.meshtype_3d_esophagus1 import MeshType_3d_esophagus1 +from scaffoldmaker.meshtypes.meshtype_3d_gastrointestinaltract1 import MeshType_3d_gastrointestinaltract1 from scaffoldmaker.meshtypes.meshtype_3d_heart1 import MeshType_3d_heart1 from scaffoldmaker.meshtypes.meshtype_3d_heart2 import MeshType_3d_heart2 from scaffoldmaker.meshtypes.meshtype_3d_heartarterialroot1 import MeshType_3d_heartarterialroot1 @@ -39,6 +40,7 @@ from scaffoldmaker.meshtypes.meshtype_3d_lung2 import MeshType_3d_lung2 from scaffoldmaker.meshtypes.meshtype_3d_musclefusiform1 import MeshType_3d_musclefusiform1 from scaffoldmaker.meshtypes.meshtype_3d_ostium1 import MeshType_3d_ostium1 +from scaffoldmaker.meshtypes.meshtype_3d_ostium2 import MeshType_3d_ostium2 from scaffoldmaker.meshtypes.meshtype_3d_smallintestine1 import MeshType_3d_smallintestine1 from scaffoldmaker.meshtypes.meshtype_3d_solidcylinder1 import MeshType_3d_solidcylinder1 from scaffoldmaker.meshtypes.meshtype_3d_solidsphere1 import MeshType_3d_solidsphere1 @@ -80,6 +82,7 @@ def __init__(self): MeshType_3d_colon1, MeshType_3d_colonsegment1, MeshType_3d_esophagus1, + MeshType_3d_gastrointestinaltract1, MeshType_3d_heart1, MeshType_3d_heart2, MeshType_3d_heartarterialroot1, @@ -96,6 +99,7 @@ def __init__(self): MeshType_3d_lung2, MeshType_3d_musclefusiform1, MeshType_3d_ostium1, + MeshType_3d_ostium2, MeshType_3d_smallintestine1, MeshType_3d_solidcylinder1, MeshType_3d_solidsphere1, diff --git a/src/scaffoldmaker/utils/interpolation.py b/src/scaffoldmaker/utils/interpolation.py index b319fd48..967426dd 100644 --- a/src/scaffoldmaker/utils/interpolation.py +++ b/src/scaffoldmaker/utils/interpolation.py @@ -1473,3 +1473,29 @@ def getNearestLocationBetweenCurves(nx, nd1, ox, od1, nLoop=False, oLoop=False, print('getNearestLocationBetweenCurves did not converge: Reached max iterations', it + 1, 'closeness in xi', mag_dxi) return location, otherLocation, False + +def getCurvaturesAlongCurve(cx, cd, radialVectors, loop=False): + """ + Calculate curvatures for points lying along a curve. + :param cx: coordinates on curve + :param cd: derivative of coordinates on curve + :param radialVectors: radial direction, assumed normal to curve tangent at coordinate + :param loop: True if curve is a closed loop + :return: curvatures along coordinates on curve + """ + curvatures = [] + cCount = len(cx) + for c in range(cCount): + kappa = None + if (c > 0) or loop: + cm = c - 1 + kappa = getCubicHermiteCurvature(cx[cm], cd[cm], cx[c], cd[c], radialVectors[c], 1.0) + if (c < (cCount - 1)) or loop: + cp = c + 1 - cCount + kappap = getCubicHermiteCurvature(cx[c], cd[c], cx[cp], cd[cp], radialVectors[c], 0.0) + if kappa is None: + kappa = kappap + else: + kappa = 0.5 * (kappa + kappap) + curvatures.append(kappa) + return curvatures diff --git a/src/scaffoldmaker/utils/tubemesh.py b/src/scaffoldmaker/utils/tubemesh.py index b1c4c493..e8e356dd 100644 --- a/src/scaffoldmaker/utils/tubemesh.py +++ b/src/scaffoldmaker/utils/tubemesh.py @@ -243,9 +243,9 @@ def warpSegmentPoints(xList, d1List, d2List, segmentAxis, sx, sd1, sd2, elements return xWarpedList, d1WarpedList, d2WarpedListFinal, d3WarpedUnitList -def extrudeSurfaceCoordinates(xSurf, d1Surf, d2Surf, d3Surf, - wallThicknessList, relativeThicknessList, elementsCountAround, - elementsCountAlong, elementsCountThroughWall, transitElementList, outward=True): +def extrudeSurfaceCoordinates(xSurf, d1Surf, d2Surf, d3Surf, wallThicknessList, relativeThicknessList, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, transitElementList, + outward=True, xProximal=[], d1Proximal=[], d2Proximal=[], d3Proximal=[]): """ Generates extruded coordinates using coordinates and derivatives of a surface. :param xSurf: Coordinates on surface @@ -260,6 +260,7 @@ def extrudeSurfaceCoordinates(xSurf, d1Surf, d2Surf, d3Surf, :param transitElementList: stores true if element around is a transition element that is between a big and a small element. :param outward: Set to True to generate coordinates from inner to outer surface. + :param xProximal, d1Proximal, d2Proximal, d3Proximal: coordinates and derivatives of nodes to use on proximal end. return nodes and derivatives for mesh, and curvature along extruded surface. """ @@ -271,6 +272,12 @@ def extrudeSurfaceCoordinates(xSurf, d1Surf, d2Surf, d3Surf, d1List = [] d2List = [] d3List = [] + count = 0 + localIdxDistal = [] + xDistal = [] + d1Distal = [] + d2Distal = [] + d3Distal = [] if relativeThicknessList: xi3 = 0.0 @@ -324,35 +331,64 @@ def extrudeSurfaceCoordinates(xSurf, d1Surf, d2Surf, d3Surf, for n3 in range(elementsCountThroughWall + 1): xi3 = xi3List[n3] if relativeThicknessList else 1.0/elementsCountThroughWall * n3 + xDistalAround = [] + d1DistalAround = [] + d2DistalAround = [] + d3DistalAround = [] + localIdxDistalAround = [] + for n1 in range(elementsCountAround): - n = n2*elementsCountAround + n1 - norm = d3Surf[n] - surfx = xSurf[n] - extrudedx = xExtrudedSurf[n] - # x - dWall = [wallThickness * c for c in norm] - if outward: - x = interp.interpolateCubicHermite(surfx, dWall, extrudedx, dWall, xi3) + if n2 == 0 and xProximal: + xList.append(xProximal[n3][n1]) + d1List.append(d1Proximal[n3][n1]) + d2List.append(d2Proximal[n3][n1]) + d3List.append(d3Proximal[n3][n1]) + n = n2 * elementsCountAround + n1 + curvatureList.append(curvatureAlong[n]) else: - x = interp.interpolateCubicHermite(extrudedx, dWall, surfx, dWall, xi3) - xList.append(x) - - # dx_ds1 - factor = 1.0 - wallOutwardDisplacement * (xi3 if outward else (1.0 - xi3)) * curvatureAroundSurf[n] - d1 = [factor*c for c in d1Surf[n]] - d1List.append(d1) - - # dx_ds2 - factor = 1.0 - wallOutwardDisplacement * (xi3 if outward else (1.0 - xi3)) * curvatureAlong[n] - d2 = [factor * c for c in d2Surf[n]] - d2List.append(d2) - curvatureList.append(curvatureAlong[n]) - - # dx_ds3 - d3 = [c * wallThickness * (relativeThicknessList[n3] if relativeThicknessList else 1.0/elementsCountThroughWall) for c in norm] - d3List.append(d3) - - return xList, d1List, d2List, d3List, curvatureList + n = n2*elementsCountAround + n1 + norm = d3Surf[n] + surfx = xSurf[n] + extrudedx = xExtrudedSurf[n] + # x + dWall = [wallThickness * c for c in norm] + if outward: + x = interp.interpolateCubicHermite(surfx, dWall, extrudedx, dWall, xi3) + else: + x = interp.interpolateCubicHermite(extrudedx, dWall, surfx, dWall, xi3) + xList.append(x) + + # dx_ds1 + factor = 1.0 - wallOutwardDisplacement * (xi3 if outward else (1.0 - xi3)) * curvatureAroundSurf[n] + d1 = [factor*c for c in d1Surf[n]] + d1List.append(d1) + + # dx_ds2 + factor = 1.0 - wallOutwardDisplacement * (xi3 if outward else (1.0 - xi3)) * curvatureAlong[n] + d2 = [factor * c for c in d2Surf[n]] + d2List.append(d2) + curvatureList.append(curvatureAlong[n]) + + # dx_ds3 + d3 = [c * wallThickness * (relativeThicknessList[n3] if relativeThicknessList else 1.0/elementsCountThroughWall) for c in norm] + d3List.append(d3) + + if n2 == elementsCountAlong: + xDistalAround.append(x) + d1DistalAround.append(d1) + d2DistalAround.append(d2) + d3DistalAround.append(d3) + localIdxDistalAround.append(count) + count += 1 + + if n2 == elementsCountAlong: + xDistal.append(xDistalAround) + d1Distal.append(d1DistalAround) + d2Distal.append(d2DistalAround) + d3Distal.append(d3DistalAround) + localIdxDistal.append(localIdxDistalAround) + + return xList, d1List, d2List, d3List, curvatureList, localIdxDistal, xDistal, d1Distal, d2Distal, d3Distal def createFlatCoordinates(xiList, lengthAroundList, totalLengthAlong, wallThickness, relativeThicknessList, elementsCountAround, elementsCountAlong, elementsCountThroughWall, transitElementList): @@ -485,7 +521,7 @@ def createNodesAndElements(region, elementsCountAround, elementsCountAlong, elementsCountThroughWall, annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd): + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd, localIdxDistal=[], nodeIdProximal=[]): """ Create nodes and elements for the coordinates and flat coordinates fields. :param x, d1, d2, d3: coordinates and derivatives of coordinates field. @@ -499,16 +535,23 @@ def createNodesAndElements(region, :param annotationGroupsAround: Annotation groups of elements around. :param annotationGroupsAlong: Annotation groups of elements along. :param annotationGroupsThroughWall: Annotation groups of elements through wall. - :param firstNodeIdentifier, firstElementIdentifier: first node and - element identifier to use. + :param firstNodeIdentifier, firstElementIdentifier: first node and element identifier to use. :param useCubicHermiteThroughWall: use linear when false :param useCrossDerivatives: use cross derivatives when true - :return nodeIdentifier, elementIdentifier, allAnnotationGroups + :param closedProximalEnd: Proximal end of tube is closed if true + :param localIdxDistal: local node identifiers for nodes on distal end of the tube. + :param nodeIdProximal: Node identifiers for nodes to use on proximal end of the tube. + :return nodeIdentifier, elementIdentifier, allAnnotationGroups, nodesDistal """ nodeIdentifier = firstNodeIdentifier elementIdentifier = firstElementIdentifier + startNode = firstNodeIdentifier zero = [ 0.0, 0.0, 0.0 ] + nodesDistal = [] + + for i in range(len(localIdxDistal)): + nodesDistal.append([firstNodeIdentifier + c for c in localIdxDistal[i]]) fm = region.getFieldmodule() fm.beginChange() @@ -622,7 +665,19 @@ def createNodesAndElements(region, # Create nodes # Coordinates field - for n in range(len(x)): + if nodeIdProximal: + proximalNodesOffset = len(nodeIdProximal) * len(nodeIdProximal[0]) + nodeList = [] + newNodeList = [] + + if nodeIdProximal: + for n3 in range(len(nodeIdProximal)): + for n1 in range(len(nodeIdProximal[n3])): + nodeList.append(nodeIdentifier) + newNodeList.append(nodeIdProximal[n3][n1]) + nodeIdentifier = nodeIdentifier + 1 + + for n in range(proximalNodesOffset if nodeIdProximal else 0, len(x)): node = nodes.createNode(nodeIdentifier, nodetemplate) cache.setNode(node) coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, x[n]) @@ -709,9 +764,9 @@ def createNodesAndElements(region, eftApex = eftfactory.createEftShellPoleBottom(va * 100, vb * 100) elementtemplateApex.defineField(coordinates, -1, eftApex) element = mesh.createElement(elementIdentifier, elementtemplateApex) - bni1 = e3 + 1 - bni2 = elementsCountThroughWall + 1 + elementsCountAround*e3 + e1 + 1 - bni3 = elementsCountThroughWall + 1 + elementsCountAround*e3 + (e1 + 1) % elementsCountAround + 1 + bni1 = e3 + 1 + startNode - 1 + bni2 = elementsCountThroughWall + 1 + elementsCountAround*e3 + e1 + 1 + startNode - 1 + bni3 = elementsCountThroughWall + 1 + elementsCountAround*e3 + (e1 + 1) % elementsCountAround + 1 + startNode - 1 nodeIdentifiers = [bni1, bni2, bni3, bni1 + 1, bni2 + elementsCountAround, bni3 + elementsCountAround] element.setNodesByIdentifier(eftApex, nodeIdentifiers) onOpening = e1 > elementsCountAround - 2 @@ -790,6 +845,13 @@ def createNodesAndElements(region, bni21 = e2 * now + (e3 + 1) * elementsCountAround + e1 + 1 bni22 = e2 * now + (e3 + 1) * elementsCountAround + (e1 + 1) % elementsCountAround + 1 nodeIdentifiers = [bni11, bni12, bni11 + now, bni12 + now, bni21, bni22, bni21 + now, bni22 + now] + nodeIdentifiers = [startNode - 1 + c for c in nodeIdentifiers] + if e2 == 0 and nodeIdProximal: + for m in range(len(nodeIdentifiers)): + if nodeIdentifiers[m] in nodeList: + idx = nodeList.index(nodeIdentifiers[m]) + nodeIdentifiers[m] = newNodeList[idx] + onOpening = e1 > elementsCountAround - 2 element = mesh.createElement(elementIdentifier, elementtemplate) element.setNodesByIdentifier(eft, nodeIdentifiers) @@ -811,34 +873,34 @@ def createNodesAndElements(region, fm.endChange() - return nodeIdentifier, elementIdentifier, allAnnotationGroups + return nodeIdentifier, elementIdentifier, allAnnotationGroups, nodesDistal -class CylindricalSegmentTubeMeshInnerPoints: +class CylindricalSegmentTubeMeshOuterPoints: """ - Generates inner profile of a cylindrical segment for use by tubemesh. + Generates outer profile of a cylindrical segment for use by tubemesh. """ def __init__(self, elementsCountAround, elementsCountAlongSegment, - segmentLength, wallThickness, innerRadiusList, startPhase): + segmentLength, wallThickness, outerRadiusList, startPhase): self._elementsCountAround = elementsCountAround self._elementsCountAlongSegment = elementsCountAlongSegment self._segmentLength = segmentLength self._wallThickness = wallThickness - self._innerRadiusList = innerRadiusList + self._outerRadiusList = outerRadiusList self._xiList = [] self._flatWidthList = [] self._startPhase = startPhase - def getCylindricalSegmentTubeMeshInnerPoints(self, nSegment): + def getCylindricalSegmentTubeMeshOuterPoints(self, nSegment): elementAlongStartIdx = nSegment * self._elementsCountAlongSegment elementAlongEndIdx = (nSegment + 1) * self._elementsCountAlongSegment - xInner, d1Inner, d2Inner, transitElementList, xiSegment, flatWidthSegment, segmentAxis, radiusAlongSegmentList \ - = getCylindricalSegmentInnerPoints(self._elementsCountAround, self._elementsCountAlongSegment, + xOuter, d1Outer, d2Outer, transitElementList, xiSegment, flatWidthSegment, segmentAxis, radiusAlongSegmentList \ + = getCylindricalSegmentOuterPoints(self._elementsCountAround, self._elementsCountAlongSegment, self._segmentLength, self._wallThickness, - self._innerRadiusList[elementAlongStartIdx: elementAlongEndIdx + 1], + self._outerRadiusList[elementAlongStartIdx: elementAlongEndIdx + 1], self._startPhase) startIdx = 0 if nSegment == 0 else 1 @@ -848,12 +910,12 @@ def getCylindricalSegmentTubeMeshInnerPoints(self, nSegment): flatWidth = flatWidthSegment[startIdx:self._elementsCountAlongSegment + 1] self._flatWidthList += flatWidth - return xInner, d1Inner, d2Inner, transitElementList, segmentAxis, radiusAlongSegmentList + return xOuter, d1Outer, d2Outer, transitElementList, segmentAxis, radiusAlongSegmentList def getFlatWidthAndXiList(self): return self._flatWidthList, self._xiList -def getCylindricalSegmentInnerPoints(elementsCountAround, elementsCountAlongSegment, segmentLength, +def getCylindricalSegmentOuterPoints(elementsCountAround, elementsCountAlongSegment, segmentLength, wallThickness, radiusList, startPhase): """ Generates a 3-D cylindrical segment mesh with variable numbers of elements @@ -862,7 +924,7 @@ def getCylindricalSegmentInnerPoints(elementsCountAround, elementsCountAlongSegm :param elementsCountAlongSegment: Number of elements along cylindrical segment. :param segmentLength: Length of a cylindrical segment. :param wallThickness: Thickness of wall. - :param radiusList: Inner radius at elements along tube length. + :param radiusList: Outer radius at elements along tube length. :param startPhase: Phase at start. :return coordinates, derivatives on inner surface of a cylindrical segment. :return transitElementList: stores true if element around is an element that diff --git a/tests/test_cecum.py b/tests/test_cecum.py index fa7812a4..578e127e 100644 --- a/tests/test_cecum.py +++ b/tests/test_cecum.py @@ -6,6 +6,9 @@ from cmlibs.zinc.element import Element from cmlibs.zinc.field import Field from cmlibs.zinc.result import RESULT_OK +from scaffoldmaker.annotation.annotationgroup import getAnnotationGroupForTerm +from scaffoldmaker.annotation.cecum_terms import get_cecum_term +from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term from scaffoldmaker.meshtypes.meshtype_3d_cecum1 import MeshType_3d_cecum1 from scaffoldmaker.utils.zinc_utils import createFaceMeshGroupExteriorOnFace @@ -19,58 +22,50 @@ def test_cecum1(self): Test creation of cecum scaffold. """ parameterSetNames = MeshType_3d_cecum1.getParameterSetNames() - self.assertEqual(parameterSetNames, ["Default", "Pig 1"]) - options = MeshType_3d_cecum1.getDefaultOptions("Pig 1") - self.assertEqual(30, len(options)) - self.assertEqual(5, options.get("Number of segments")) + self.assertEqual(parameterSetNames, ["Default", "Human 1", "Human 2", "Pig 1"]) + options = MeshType_3d_cecum1.getDefaultOptions("Human 2") + + networkLayout = options.get("Network layout") + networkLayoutSettings = networkLayout.getScaffoldSettings() + self.assertEqual("1-2-3.2, 4-3-5", networkLayoutSettings["Structure"]) + + self.assertEqual(29, len(options)) + self.assertEqual(1, options.get("Number of segments")) self.assertEqual(2, options.get("Number of elements around tenia coli")) - self.assertEqual(8, options.get("Number of elements along segment")) + self.assertEqual(12, options.get("Number of elements along segment")) self.assertEqual(1, options.get("Number of elements through wall")) - self.assertEqual(35.0, options.get("Start inner radius")) - self.assertEqual(3.0, options.get("Start inner radius derivative")) - self.assertEqual(38.0, options.get("End inner radius")) - self.assertEqual(3.0, options.get("End inner radius derivative")) - self.assertEqual(0.5, options.get("Corner inner radius factor")) - self.assertEqual(0.25, options.get("Haustrum inner radius factor")) - self.assertEqual(4.0, options.get("Segment length mid derivative factor")) + self.assertEqual(0.536, options.get("Corner outer radius factor")) + self.assertEqual(0.464, options.get("Haustrum outer radius factor")) + self.assertEqual(3.0, options.get("Segment length mid derivative factor")) self.assertEqual(3, options.get("Number of tenia coli")) - self.assertEqual(5.0, options.get("Start tenia coli width")) + self.assertEqual(10.0, options.get("Start tenia coli width")) self.assertEqual(0.0, options.get("End tenia coli width derivative")) - self.assertEqual(2.0, options.get("Wall thickness")) - ostiumOptions = options['Ileocecal junction'] - ostiumSettings = ostiumOptions.getScaffoldSettings() - self.assertEqual(1, ostiumSettings.get("Number of vessels")) - self.assertEqual(8, ostiumSettings.get("Number of elements around ostium")) - self.assertEqual(1, ostiumSettings.get("Number of elements through wall")) - self.assertEqual(20.0, ostiumSettings.get("Ostium diameter")) - self.assertEqual(10.0, ostiumSettings.get("Vessel inner diameter")) - self.assertEqual(60, options.get("Ileocecal junction angular position degrees")) - self.assertEqual(0.5, options.get("Ileocecal junction position along factor")) + self.assertEqual(1.6, options.get("Wall thickness")) context = Context("Test") region = context.getDefaultRegion() self.assertTrue(region.isValid()) annotationGroups = MeshType_3d_cecum1.generateBaseMesh(region, options)[0] - self.assertEqual(2, len(annotationGroups)) + self.assertEqual(7, len(annotationGroups)) fieldmodule = region.getFieldmodule() self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) mesh3d = fieldmodule.findMeshByDimension(3) - self.assertEqual(1492, mesh3d.getSize()) + self.assertEqual(460, mesh3d.getSize()) mesh2d = fieldmodule.findMeshByDimension(2) - self.assertEqual(5617, mesh2d.getSize()) + self.assertEqual(1738, mesh2d.getSize()) mesh1d = fieldmodule.findMeshByDimension(1) - self.assertEqual(6767, mesh1d.getSize()) + self.assertEqual(2102, mesh1d.getSize()) nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - self.assertEqual(2642, nodes.getSize()) + self.assertEqual(824, nodes.getSize()) datapoints = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_DATAPOINTS) self.assertEqual(0, datapoints.getSize()) coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) - assertAlmostEqualList(self, minimums, [-49.01658984455258, -46.89686037622053, -2.343256155753525], 1.0E-6) - assertAlmostEqualList(self, maximums, [42.18085849205387, 54.90211871346987, 180.0], 1.0E-6) + assertAlmostEqualList(self, minimums, [-112.4222871639696, -146.3433620526202, 852.5876977230726], 1.0E-6) + assertAlmostEqualList(self, maximums, [-54.14347619948218, -77.56, 899.9973429272325], 1.0E-6) with ChangeManager(fieldmodule): one = fieldmodule.createFieldConstant(1.0) @@ -82,10 +77,26 @@ def test_cecum1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 65905.04907630144, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 8554.513081780715, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 127866.92887366761, delta=1.0E-6) + self.assertAlmostEqual(volume, 13809.9960233912, delta=1.0E-6) + + # check some annotationGroups: + expectedSizes3d = { + "caecum": 460, + "ileum": 24, + "ileocecal junction": 12 + } + + for name in expectedSizes3d: + if name == "caecum": + term = get_cecum_term(name) + else: + term = get_smallintestine_term(name) + group = getAnnotationGroupForTerm(annotationGroups, term) + size = group.getMeshGroup(mesh3d).getSize() + self.assertEqual(expectedSizes3d[name], size, name) if __name__ == "__main__": diff --git a/tests/test_colon.py b/tests/test_colon.py index 7640c071..00ddd0b6 100644 --- a/tests/test_colon.py +++ b/tests/test_colon.py @@ -9,7 +9,7 @@ from cmlibs.zinc.node import Node from cmlibs.zinc.result import RESULT_OK from scaffoldmaker.annotation.colon_terms import get_colon_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 from scaffoldmaker.meshtypes.meshtype_3d_colon1 import MeshType_3d_colon1 from scaffoldmaker.meshtypes.meshtype_3d_colonsegment1 import MeshType_3d_colonsegment1 from scaffoldmaker.scaffoldpackage import ScaffoldPackage @@ -29,50 +29,53 @@ def test_colon1(self): self.assertEqual(parameterSetNames, ["Default", "Cattle 1", "Human 1", "Human 2", "Human 3", "Mouse 1", "Mouse 2", "Pig 1"]) - centralPathDefaultScaffoldPackages = { - 'Test line': ScaffoldPackage(MeshType_1d_path1, { - 'scaffoldSettings': { - 'Coordinate dimensions': 3, - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Length': 1.0, - 'Number of elements': 3 + testNetworkLayout = ScaffoldPackage(MeshType_1d_network_layout1, { + 'scaffoldSettings': { + "Structure": "1-2-3-4" + }, + 'meshEdits': exnode_string_from_nodeset_field_parameters( + [Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, + Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ + (1, [[0.00, 0.00, 0.00], [-50.70, 178.20, 0.00], [-37.97, -9.49, -18.98], [-6.86, -11.39, -2.36], [-18.61, -3.98, 39.12], [-14.00, -1.00, -12.00]]), + (2, [[-47.40, 188.60, 0.00], [-19.30, 177.10, 0.00], [-35.79, -6.51, -13.01], [11.23, 17.36, 14.31], [-12.66, -3.99, 36.28], [-4.00, 19.00, 22.00]]), + (3, [[-4.40, 396.50, 0.00], [206.00, 40.10, 0.00], [-13.89, 27.78, 11.11], [13.54, -1.87, 21.51], [-6.05, -12.50, 29.93], [-6.00, 0.00, 51.00]]), + (4, [[130.00, 384.10, 0.00], [130.80, -40.50, 0.00], [-5.35, 4.28, 31.06], [5.83, -8.41, 8.86], [-15.28, -27.78, 2.51], [0.00, 1.00, 24.00]])]), + + 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-3', + 'name': get_colon_term('colon')[0], + 'ontId': get_colon_term('colon')[1] }, - 'meshEdits': exnode_string_from_nodeset_field_parameters( - [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3], [ - (1, [ [ 0.00, 0.00, 0.00 ], [ -50.70, 178.20, 0.00 ], [ -37.97, -9.49, -18.98 ], [ -6.86, -11.39, -2.36 ], [ -18.61, -3.98, 39.12 ], [ -14.00, -1.00, -12.00] ] ), - (2, [ [ -47.40, 188.60, 0.00 ], [ -19.30, 177.10, 0.00 ], [ -35.79, -6.51, -13.01 ], [ 11.23, 17.36, 14.31 ], [ -12.66, -3.99, 36.28 ], [ -4.00, 19.00, 22.00] ] ), - (3, [ [ -4.40, 396.50, 0.00 ], [ 206.00, 40.10, 0.00 ], [ -13.89, 27.78, 11.11 ], [ 13.54, -1.87, 21.51 ], [ -6.05, -12.50, 29.93 ], [ -6.00, 0.00, 51.00] ] ), - (4, [ [ 130.00, 384.10, 0.00 ], [ 130.80, -40.50, 0.00 ], [ -5.35, 4.28, 31.06 ], [ 5.83, -8.41, 8.86 ], [ -15.28, -27.78, 2.51 ], [ 0.00, 1.00, 24.00] ] ) ] ), - - 'userAnnotationGroups': [ - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '1', - 'name': get_colon_term('ascending colon')[0], - 'ontId': get_colon_term('ascending colon')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '2', - 'name': get_colon_term('transverse colon')[0], - 'ontId': get_colon_term('transverse colon')[1] - }, - { - '_AnnotationGroup': True, - 'dimension': 1, - 'identifierRanges': '3', - 'name': get_colon_term('descending colon')[0], - 'ontId': get_colon_term('descending colon')[1] - }] - }) - } - centralPathOption = centralPathDefaultScaffoldPackages['Test line'] + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1', + 'name': get_colon_term('ascending colon')[0], + 'ontId': get_colon_term('ascending colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '2', + 'name': get_colon_term('transverse colon')[0], + 'ontId': get_colon_term('transverse colon')[1] + }, + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '3', + 'name': get_colon_term('descending colon')[0], + 'ontId': get_colon_term('descending colon')[1] + }] + }) + segmentProfileOption = ScaffoldPackage(MeshType_3d_colonsegment1, defaultParameterSetName='Human 1') options = { - 'Central path': copy.deepcopy(centralPathOption), + 'Base parameter set': 'Human 1', + 'Network layout': testNetworkLayout, 'Segment profile': segmentProfileOption, 'Number of segments': 3, 'Start phase': 0.0, @@ -80,18 +83,19 @@ def test_colon1(self): 'Proximal-transverse tenia coli width': 6.0, 'Transverse-distal tenia coli width': 5.0, 'Distal tenia coli width': 5.0, + 'Use linear through wall': True, 'Refine': False, 'Refine number of elements around': 1, 'Refine number of elements along': 1, 'Refine number of elements through wall': 1 } - self.assertEqual(12, len(options)) - centralPath = options['Central path'] + self.assertEqual(14, len(options)) + networkLayout = options['Network layout'] segmentProfile = options.get("Segment profile") segmentSettings = segmentProfile.getScaffoldSettings() self.assertEqual(8, segmentSettings.get("Number of elements around haustrum")) - self.assertEqual(0.5, segmentSettings.get("Corner inner radius factor")) - self.assertEqual(0.5, segmentSettings.get("Haustrum inner radius factor")) + self.assertEqual(0.536, segmentSettings.get("Corner outer radius factor")) + self.assertEqual(0.464, segmentSettings.get("Haustrum outer radius factor")) self.assertEqual(0.5, segmentSettings.get("Segment length end derivative factor")) self.assertEqual(3, segmentSettings.get("Number of tenia coli")) self.assertEqual(0.6, segmentSettings.get("Tenia coli thickness")) @@ -106,7 +110,7 @@ def test_colon1(self): self.assertTrue(region.isValid()) tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) + networkLayout.generate(tmpRegion) tmpFieldmodule = tmpRegion.getFieldmodule() cx = get_nodeset_path_field_parameters( tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES), @@ -140,19 +144,19 @@ def test_colon1(self): coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) - assertAlmostEqualList(self, minimums, [-102.55487309988112, -11.951736893846785, -63.16829934203756], 1.0E-6) - assertAlmostEqualList(self, maximums, [139.2604050120047, 450.61008758758777, 52.71048326055835], 1.0E-6) + assertAlmostEqualList(self, minimums, [-100.08668914502144, -11.342531039430702, -60.09737764484168], 1.0E-6) + assertAlmostEqualList(self, maximums, [138.56897619597683, 447.93686761958236, 50.13111447364834], 1.0E-6) flatCoordinates = fieldmodule.findFieldByName("flat coordinates").castFiniteElement() self.assertTrue(flatCoordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(flatCoordinates, nodes) assertAlmostEqualList(self, minimums, [0.0, 0.0, 0.0], 1.0E-6) - assertAlmostEqualList(self, maximums, [397.9905020852475, 561.3383898388232, 2.2], 1.0E-6) + assertAlmostEqualList(self, maximums, [377.06179507784395, 561.3383898388232, 2.2], 1.0E-6) colonCoordinates = fieldmodule.findFieldByName("colon coordinates").castFiniteElement() minimums, maximums = evaluateFieldNodesetRange(colonCoordinates, nodes) - assertAlmostEqualList(self, minimums, [-0.599793206103745, 0.0, -0.6], 1.0E-4) - assertAlmostEqualList(self, maximums, [0.599793206103745, 24.0, 0.625], 1.0E-4) + assertAlmostEqualList(self, minimums, [-0.599920500334689, 0.0, -0.6], 1.0E-4) + assertAlmostEqualList(self, maximums, [0.599920500334689, 24.0, 0.625], 1.0E-4) with ChangeManager(fieldmodule): one = fieldmodule.createFieldConstant(1.0) @@ -164,10 +168,10 @@ def test_colon1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 174749.05868939584, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 164285.41543554227, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 314670.65237072564, delta=1.0E-6) + self.assertAlmostEqual(volume, 294925.4567043401, delta=1.0E-6) def test_mousecolon1(self): """ @@ -203,13 +207,13 @@ def test_mousecolon1(self): fieldcache = fieldmodule.createFieldcache() result, flatSurfaceArea = flatSurfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(flatSurfaceArea, 651.2624843023726, delta=1.0E-6) + self.assertAlmostEqual(flatSurfaceArea, 650.8919830877059, delta=1.0E-6) result, colonSurfaceArea = colonSurfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(colonSurfaceArea, 90.45789313556386, delta=1.0E-6) + self.assertAlmostEqual(colonSurfaceArea, 90.45785287687968, delta=1.0E-6) result, colonVolume = colonVolumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(colonVolume, 8.290058800222006, delta=1.0E-6) + self.assertAlmostEqual(colonVolume, 8.290050554292705, delta=1.0E-6) if __name__ == "__main__": diff --git a/tests/test_colonsegment.py b/tests/test_colonsegment.py index 55f58781..7ae5a525 100644 --- a/tests/test_colonsegment.py +++ b/tests/test_colonsegment.py @@ -21,20 +21,20 @@ def test_humancolonsegment1(self): parameterSetNames = MeshType_3d_colonsegment1.getParameterSetNames() self.assertEqual(parameterSetNames, ["Default", "Cattle 1", "Human 1", "Human 2", "Mouse 1", "Pig 1"]) options = MeshType_3d_colonsegment1.getDefaultOptions("Human 1") - self.assertEqual(31, len(options)) + self.assertEqual(32, len(options)) self.assertEqual(0.0, options.get("Start phase")) self.assertEqual(2, options.get("Number of elements around tenia coli")) self.assertEqual(4, options.get("Number of elements along segment")) self.assertEqual(4, options.get("Number of elements through wall")) - self.assertEqual(43.5, options.get("Start inner radius")) - self.assertEqual(0.0, options.get("Start inner radius derivative")) - self.assertEqual(33.0, options.get("End inner radius")) - self.assertEqual(0.0, options.get("End inner radius derivative")) + self.assertEqual(None, options.get("Start inner radius")) + self.assertEqual(None, options.get("Start inner radius derivative")) + self.assertEqual(None, options.get("End inner radius")) + self.assertEqual(None, options.get("End inner radius derivative")) self.assertEqual(3.0, options.get("Segment length mid derivative factor")) self.assertEqual(50.0, options.get("Segment length")) self.assertEqual(3, options.get("Number of tenia coli")) - self.assertEqual(10.0, options.get("Start tenia coli width")) - self.assertEqual(0.0, options.get("End tenia coli width derivative")) + self.assertEqual(11.1, options.get("Start tenia coli width")) + self.assertEqual(0.4, options.get("End tenia coli width derivative")) self.assertEqual(1.6, options.get("Wall thickness")) context = Context("Test") @@ -59,14 +59,14 @@ def test_humancolonsegment1(self): coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) - assertAlmostEqualList(self, minimums, [-2.172286248499807e-15, -58.95670186936737, -55.54662267827035], 1.0E-6) - assertAlmostEqualList(self, maximums, [50.0, 50.52621132610023, 55.54662267827035], 1.0E-6) + assertAlmostEqualList(self, minimums, [-2.172286248499807e-15, -59.07417787753859, -55.60850335002243], 1.0E-6) + assertAlmostEqualList(self, maximums, [50.0, 50.60638395601446, 55.60850335002243], 1.0E-6) flatCoordinates = fieldmodule.findFieldByName("flat coordinates").castFiniteElement() self.assertTrue(flatCoordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(flatCoordinates, nodes) assertAlmostEqualList(self, minimums, [0.0, 0.0, 0.0], 1.0E-6) - assertAlmostEqualList(self, maximums, [397.2736607240895, 50.0, 2.2], 1.0E-6) + assertAlmostEqualList(self, maximums, [392.25861666443416, 50.0, 2.2], 1.0E-6) with ChangeManager(fieldmodule): one = fieldmodule.createFieldConstant(1.0) @@ -78,10 +78,10 @@ def test_humancolonsegment1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 21032.6788157990, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 20870.63159749863, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 39836.60239335828, delta=1.0E-6) + self.assertAlmostEqual(volume, 39988.68541401406, delta=1.0E-6) def test_mousecolonsegment1(self): """ @@ -114,10 +114,10 @@ def test_mousecolonsegment1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 468.17062489996886, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 467.98576432245915, delta=1.0E-6) result, flatSurfaceArea = flatSurfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(flatSurfaceArea, surfaceArea, delta=1.0E-3) + self.assertAlmostEqual(flatSurfaceArea, 467.98905126160287, delta=1.0E-3) if __name__ == "__main__": diff --git a/tests/test_esophagus.py b/tests/test_esophagus.py index b3d43748..2ee82bdf 100644 --- a/tests/test_esophagus.py +++ b/tests/test_esophagus.py @@ -29,8 +29,8 @@ def test_esophagus1(self): self.assertEqual(15, len(options)) self.assertEqual(8, options.get("Number of elements around")) self.assertEqual(20, options.get("Number of elements along")) - self.assertEqual(4, options.get("Number of elements through wall")) - self.assertEqual(3.2, options.get("Wall thickness")) + self.assertEqual(1, options.get("Number of elements through wall")) + self.assertEqual(1.2, options.get("Wall thickness")) self.assertEqual(0.35, options.get("Mucosa relative thickness")) self.assertEqual(0.15, options.get("Submucosa relative thickness")) self.assertEqual(0.25, options.get("Circular muscle layer relative thickness")) @@ -40,32 +40,32 @@ def test_esophagus1(self): region = context.getDefaultRegion() self.assertTrue(region.isValid()) annotationGroups = scaffold.generateBaseMesh(region, options)[0] - self.assertEqual(12, len(annotationGroups)) + self.assertEqual(8, len(annotationGroups)) fieldmodule = region.getFieldmodule() self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) mesh3d = fieldmodule.findMeshByDimension(3) - self.assertEqual(640, mesh3d.getSize()) + self.assertEqual(160, mesh3d.getSize()) mesh2d = fieldmodule.findMeshByDimension(2) - self.assertEqual(2112, mesh2d.getSize()) + self.assertEqual(648, mesh2d.getSize()) mesh1d = fieldmodule.findMeshByDimension(1) - self.assertEqual(2312, mesh1d.getSize()) + self.assertEqual(824, mesh1d.getSize()) nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - self.assertEqual(844, nodes.getSize()) + self.assertEqual(340, nodes.getSize()) datapoints = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_DATAPOINTS) self.assertEqual(0, datapoints.getSize()) coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) - assertAlmostEqualList(self, minimums, [-11.461359765715862, -117.02328007059768, 1124.746516933097], 1.0E-6) - assertAlmostEqualList(self, maximums, [14.41809738372959, -62.10186570804781, 1403.745932596971], 1.0E-6) + assertAlmostEqualList(self, minimums, [-8.645606404075409, -115.4469482741834, 1123.3296869517246], 1.0E-6) + assertAlmostEqualList(self, maximums, [17.428066853931824, -63.05159903323634, 1403.9055789269714], 1.0E-6) flatCoordinates = fieldmodule.findFieldByName("flat coordinates").castFiniteElement() self.assertTrue(flatCoordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(flatCoordinates, nodes) - assertAlmostEqualList(self, minimums, [0.0, 0.0, 0.0], 1.0E-6) - assertAlmostEqualList(self, maximums, [31.765221935414147, 287.8507353356311, 3.2], 1.0E-6) + assertAlmostEqualList(self, minimums, [-2.023676644962851, 0.0, 0.0], 1.0E-6) + assertAlmostEqualList(self, maximums, [38.56398979676183, 289.9673186862639, 1.2], 1.0E-6) esophagusCoordinates = fieldmodule.findFieldByName("esophagus coordinates").castFiniteElement() minimums, maximums = evaluateFieldNodesetRange(esophagusCoordinates, nodes) @@ -82,21 +82,17 @@ def test_esophagus1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 13952.301236699395, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 12544.147466204333, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 35523.4403218177, delta=1.0E-6) + self.assertAlmostEqual(volume, 13787.433711373638, delta=1.0E-6) # check some annotationGroups: expectedSizes3d = { - "abdominal part of esophagus": 96, - "cervical part of esophagus": 160, - "esophagus": 640, - "esophagus mucosa": 160, - "esophagus smooth muscle circular layer": 160, - "esophagus smooth muscle longitudinal layer": 160, - "submucosa of esophagus": 160, - "thoracic part of esophagus": 384 + "abdominal part of esophagus": 24, + "cervical part of esophagus": 40, + "esophagus": 160, + "thoracic part of esophagus": 96 } for name in expectedSizes3d: group = getAnnotationGroupForTerm(annotationGroups, get_esophagus_term(name)) @@ -113,7 +109,7 @@ def test_esophagus1(self): for annotationGroup in removeAnnotationGroups: annotationGroups.remove(annotationGroup) - self.assertEqual(12, len(annotationGroups)) + self.assertEqual(8, len(annotationGroups)) refineRegion = region.createRegion() refineFieldmodule = refineRegion.getFieldmodule() @@ -132,16 +128,16 @@ def test_esophagus1(self): for annotation in annotationGroups: if annotation not in oldAnnotationGroups: annotationGroup.addSubelements() - self.assertEqual(14, len(annotationGroups)) + self.assertEqual(10, len(annotationGroups)) # mesh3d = refineFieldmodule.findMeshByDimension(3) - self.assertEqual(40960, mesh3d.getSize()) + self.assertEqual(10240, mesh3d.getSize()) mesh2d = refineFieldmodule.findMeshByDimension(2) - self.assertEqual(125952, mesh2d.getSize()) + self.assertEqual(33408, mesh2d.getSize()) mesh1d = refineFieldmodule.findMeshByDimension(1) - self.assertEqual(129056, mesh1d.getSize()) + self.assertEqual(36128, mesh1d.getSize()) nodes = refineFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - self.assertEqual(44068, nodes.getSize()) + self.assertEqual(12964, nodes.getSize()) datapoints = refineFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_DATAPOINTS) self.assertEqual(0, datapoints.getSize()) @@ -166,7 +162,7 @@ def test_esophagus1(self): self.assertTrue(node.isValid()) cache.setNode(node) element, xi = markerLocation.evaluateMeshLocation(cache, 3) - self.assertEqual(40509, element.getIdentifier()) + self.assertEqual(9789, element.getIdentifier()) assertAlmostEqualList(self, xi, [0.0, 1.0, 1.0], 1.0E-10) if __name__ == "__main__": diff --git a/tests/test_gastrointestinaltract1.py b/tests/test_gastrointestinaltract1.py new file mode 100644 index 00000000..442360f8 --- /dev/null +++ b/tests/test_gastrointestinaltract1.py @@ -0,0 +1,155 @@ +import unittest +from testutils import assertAlmostEqualList + +from cmlibs.zinc.context import Context +from cmlibs.zinc.element import Element +from cmlibs.zinc.field import Field +from cmlibs.utils.zinc.finiteelement import evaluateFieldNodesetRange +from cmlibs.utils.zinc.general import ChangeManager +from cmlibs.zinc.result import RESULT_OK +from scaffoldmaker.annotation.annotationgroup import getAnnotationGroupForTerm +from scaffoldmaker.annotation.cecum_terms import get_cecum_term +from scaffoldmaker.annotation.colon_terms import get_colon_term +from scaffoldmaker.annotation.esophagus_terms import get_esophagus_term +from scaffoldmaker.annotation.stomach_terms import get_stomach_term +from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term +from scaffoldmaker.meshtypes.meshtype_3d_gastrointestinaltract1 import MeshType_3d_gastrointestinaltract1 +from scaffoldmaker.utils.meshrefinement import MeshRefinement +from scaffoldmaker.utils.zinc_utils import createFaceMeshGroupExteriorOnFace + + +class GastrointestinalTractScaffoldTestCase(unittest.TestCase): + + def test_gastrointestinaltract1(self): + """ + Test creation of gastrointestinal tract scaffold. + """ + scaffold = MeshType_3d_gastrointestinaltract1 + parameterSetNames = scaffold.getParameterSetNames() + self.assertEqual(parameterSetNames, ['Default', 'Human 1']) + options = scaffold.getDefaultOptions("Default") + self.assertEqual(10, len(options)) + networkLayoutOptions = options['Network layout'] + networkLayoutSettings = networkLayoutOptions.getScaffoldSettings() + self.assertEqual("1-2-3-4-5-6-7.2, 8-9-10-11-7-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-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-76-77-78-79-80-81-82-83-84-85-86-87-88-89-90-91-92-93-94-" + "95-96-97-98-99-100-101-102-103-104-105-106-107-108-109-110-111-112-113-114-115-116-117-118-" + "119-120-121-122-123-124-125-126-127-128-129-130-131-132-133-134-135-136-137-138-139-140-141-" + "142-143-144-145-146-147-148-149-150-151-152-153-154-155-156-157-158-159-160-161-162-163-164-" + "165-166-167-168-169-170-171-172.2, 173-172-174-175-176-177-178-179-180-181-182-183-184-185-" + "186-187-188-189-190-191-192-193-194-195-196-197-198-199-200-201-202-203-204-205-206-207-208-" + "209-210-211-212-213-214-215-216-217-218-219-220-221-222", + networkLayoutSettings.get("Structure")) + esoOptions = options['Esophagus'] + esoSettings = esoOptions.getScaffoldSettings() + self.assertEqual(8, esoSettings['Number of elements around']) + self.assertEqual(1, esoSettings['Number of elements through wall']) + stomachOptions = options['Stomach'] + stomachSettings = stomachOptions.getScaffoldSettings() + self.assertEqual(8, stomachSettings['Number of elements around esophagus']) + self.assertEqual(12, stomachSettings['Number of elements around duodenum']) + self.assertEqual(14, stomachSettings['Number of elements along']) + self.assertEqual(1, stomachSettings['Number of elements through wall']) + self.assertEqual(3.0, stomachSettings['Wall thickness']) + smallIntestineOptions = options['Small intestine'] + smallIntestineSettings = smallIntestineOptions.getScaffoldSettings() + self.assertEqual(80, smallIntestineSettings['Number of segments']) + self.assertEqual(12, smallIntestineSettings['Number of elements around']) + self.assertEqual(3, smallIntestineSettings['Number of elements along segment']) + self.assertEqual(1, smallIntestineSettings['Number of elements through wall']) + self.assertEqual(3, smallIntestineSettings['Wall thickness']) + cecumOptions = options['Cecum'] + cecumSettings = cecumOptions.getScaffoldSettings() + self.assertEqual(1, cecumSettings['Number of segments']) + self.assertEqual(8, cecumSettings['Number of elements around haustrum']) + self.assertEqual(12, cecumSettings['Number of elements along segment']) + self.assertEqual(1, cecumSettings['Number of elements through wall']) + self.assertEqual(1.6, cecumSettings['Wall thickness']) + colonOptions = options['Colon'] + colonSettings = colonOptions.getScaffoldSettings() + self.assertEqual(33, colonSettings['Number of segments']) + self.assertEqual(True, options['Use linear through wall']) + self.assertEqual(False, options['Refine']) + self.assertEqual(4, options['Refine number of elements surface']) + self.assertEqual(1, options['Refine number of elements through wall']) + + context = Context("Test") + region = context.getDefaultRegion() + self.assertTrue(region.isValid()) + annotationGroups = scaffold.generateMesh(region, options)[0] + self.assertEqual(30, len(annotationGroups)) + + fieldmodule = region.getFieldmodule() + self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) + mesh3d = fieldmodule.findMeshByDimension(3) + self.assertEqual(8448, mesh3d.getSize()) + mesh2d = fieldmodule.findMeshByDimension(2) + self.assertEqual(32494, mesh2d.getSize()) + mesh1d = fieldmodule.findMeshByDimension(1) + self.assertEqual(39642, mesh1d.getSize()) + nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + self.assertEqual(15600, nodes.getSize()) + datapoints = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_DATAPOINTS) + self.assertEqual(0, datapoints.getSize()) + + # check coordinates range + coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() + self.assertTrue(coordinates.isValid()) + minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) + assertAlmostEqualList(self, minimums, [-123.4289535529459, -190.90949289431342, 799.4386433354306], 1.0E-6) + assertAlmostEqualList(self, maximums, [124.21567892707846, -33.094490024089325, 1403.9055789269714], 1.0E-6) + + with ChangeManager(fieldmodule): + one = fieldmodule.createFieldConstant(1.0) + faceMeshGroup = createFaceMeshGroupExteriorOnFace(fieldmodule, Element.FACE_TYPE_XI3_1) + surfaceAreaField = fieldmodule.createFieldMeshIntegral(one, coordinates, faceMeshGroup) + surfaceAreaField.setNumbersOfPoints(4) + volumeField = fieldmodule.createFieldMeshIntegral(one, coordinates, mesh3d) + volumeField.setNumbersOfPoints(3) + fieldcache = fieldmodule.createFieldcache() + result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) + self.assertEqual(result, RESULT_OK) + self.assertAlmostEqual(surfaceArea, 280350.6462177311, delta=1.0E-6) + result, volume = volumeField.evaluateReal(fieldcache, 1) + self.assertEqual(result, RESULT_OK) + self.assertAlmostEqual(volume, 598505.4701647629, delta=1.0E-6) + + # check some annotationGroups: + expectedSizes3d = { + "esophagus": 184, + "stomach": 168, + "small intestine": 2916, + "caecum": 460, + "colon": 4752 + } + for name in expectedSizes3d: + if name == "esophagus": + term = get_esophagus_term(name) + elif name == ("stomach"): + term = get_stomach_term(name) + elif name == ("small intestine"): + term = get_smallintestine_term(name) + elif name == ("caecum"): + term = get_cecum_term(name) + elif name == ("colon"): + term = get_colon_term(name) + group = getAnnotationGroupForTerm(annotationGroups, term) + size = group.getMeshGroup(mesh3d).getSize() + self.assertEqual(expectedSizes3d[name], size, name) + + # refine 8x8x8 and check result + refineRegion = region.createRegion() + refineFieldmodule = refineRegion.getFieldmodule() + options['Refine number of elements surface'] = 2 + options['Refine number of elements through wall'] = 1 + meshrefinement = MeshRefinement(region, refineRegion, []) + scaffold.refineMesh(meshrefinement, options) + + refineFieldmodule.defineAllFaces() + mesh3d = refineFieldmodule.findMeshByDimension(3) + self.assertEqual(33792, mesh3d.getSize()) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_general.py b/tests/test_general.py index 3ce3668b..7c4ea984 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -447,7 +447,7 @@ def test_deletion(self): # delete element ranges for body annotationGroups = scaffoldPackage.getAnnotationGroups() - self.assertEqual(73, len(annotationGroups)) + self.assertEqual(74, len(annotationGroups)) scaffoldPackage.deleteElementsInRanges(region, [[313, 496]]) self.assertEqual(824, mesh3d.getSize()) element = mesh3d.findElementByIdentifier(400) @@ -468,7 +468,7 @@ def test_deletion(self): # check that bob is deleted annotationGroups = scaffoldPackage.getAnnotationGroups() - self.assertEqual(70, len(annotationGroups)) + self.assertEqual(71, len(annotationGroups)) bob = scaffoldPackage.findAnnotationGroupByName('bob') self.assertNotIn(bob, annotationGroups) node = nodes.findNodeByIdentifier(bobNodeIdentifier) diff --git a/tests/test_smallintestine.py b/tests/test_smallintestine.py index 0eee9d40..cfdc069b 100644 --- a/tests/test_smallintestine.py +++ b/tests/test_smallintestine.py @@ -9,7 +9,7 @@ from cmlibs.zinc.node import Node from cmlibs.zinc.result import RESULT_OK from scaffoldmaker.annotation.smallintestine_terms import get_smallintestine_term -from scaffoldmaker.meshtypes.meshtype_1d_path1 import MeshType_1d_path1 +from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1 from scaffoldmaker.meshtypes.meshtype_3d_smallintestine1 import MeshType_3d_smallintestine1 from scaffoldmaker.scaffoldpackage import ScaffoldPackage from scaffoldmaker.utils.zinc_utils import createFaceMeshGroupExteriorOnFace, \ @@ -25,14 +25,9 @@ def test_smallintestine1(self): """ parameterSetNames = MeshType_3d_smallintestine1.getParameterSetNames() self.assertEqual(parameterSetNames, ["Default", "Cattle 1", "Human 1", "Mouse 1"]) - centralPathDefaultScaffoldPackages = { - 'Test line': ScaffoldPackage(MeshType_1d_path1, { + testNetworkLayout = ScaffoldPackage(MeshType_1d_network_layout1, { 'scaffoldSettings': { - 'D2 derivatives': True, - 'D3 derivatives': True, - 'Coordinate dimensions': 3, - 'Length': 1.0, - 'Number of elements': 3 + "Structure": "1-2-3-4" }, 'meshEdits': exnode_string_from_nodeset_field_parameters( [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1, Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2, Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3 ], [ @@ -42,6 +37,13 @@ def test_smallintestine1(self): (4, [ [ -15.60, 13.70, -6.10 ], [ 7.00, 2.10, -1.80 ], [ 0.00, 1.00, 0.00 ], [ 0.00, 0.05, 0.00 ], [ 0.50, 0.08, 0.86 ], [ 0.00, 0.00, 0.50 ] ] ) ] ), 'userAnnotationGroups': [ + { + '_AnnotationGroup': True, + 'dimension': 1, + 'identifierRanges': '1-3', + 'name': get_smallintestine_term('small intestine')[0], + 'ontId': get_smallintestine_term('small intestine')[1] + }, { '_AnnotationGroup': True, 'dimension': 1, @@ -64,17 +66,16 @@ def test_smallintestine1(self): 'ontId': get_smallintestine_term('ileum')[1] }] }) - } - centralPathOption = centralPathDefaultScaffoldPackages['Test line'] + options = MeshType_3d_smallintestine1.getDefaultOptions("Mouse 1") - options['Central path'] = copy.deepcopy(centralPathOption) + options['Network layout'] = testNetworkLayout options['Number of segments'] = 3 self.assertEqual(16, len(options)) - centralPath = options['Central path'] + networkLayout = options['Network layout'] self.assertEqual(3, options.get("Number of segments")) self.assertEqual(8, options.get("Number of elements around")) self.assertEqual(3, options.get("Number of elements along segment")) - self.assertEqual(4, options.get("Number of elements through wall")) + self.assertEqual(1, options.get("Number of elements through wall")) self.assertEqual(None, options.get("Duodenum length")) self.assertEqual(None, options.get("Jejunum-ileum inner radius")) self.assertEqual(0.1, options.get("Wall thickness")) @@ -84,7 +85,7 @@ def test_smallintestine1(self): self.assertTrue(region.isValid()) tmpRegion = region.createRegion() - centralPath.generate(tmpRegion) + networkLayout.generate(tmpRegion) tmpFieldmodule = tmpRegion.getFieldmodule() cx = get_nodeset_path_field_parameters( tmpFieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES), @@ -97,26 +98,26 @@ def test_smallintestine1(self): del tmpRegion annotationGroups = MeshType_3d_smallintestine1.generateBaseMesh(region, options)[0] - self.assertEqual(8, len(annotationGroups)) + self.assertEqual(4, len(annotationGroups)) fieldmodule = region.getFieldmodule() self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) mesh3d = fieldmodule.findMeshByDimension(3) - self.assertEqual(288, mesh3d.getSize()) + self.assertEqual(72, mesh3d.getSize()) mesh2d = fieldmodule.findMeshByDimension(2) - self.assertEqual(968, mesh2d.getSize()) + self.assertEqual(296, mesh2d.getSize()) mesh1d = fieldmodule.findMeshByDimension(1) - self.assertEqual(1080, mesh1d.getSize()) + self.assertEqual(384, mesh1d.getSize()) nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) - self.assertEqual(400, nodes.getSize()) + self.assertEqual(160, nodes.getSize()) datapoints = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_DATAPOINTS) self.assertEqual(0, datapoints.getSize()) coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) minimums, maximums = evaluateFieldNodesetRange(coordinates, nodes) - assertAlmostEqualList(self, minimums, [-20.053209723800897, 11.40926084082289, -7.165067989112036], 1.0E-6) - assertAlmostEqualList(self, maximums, [-1.8359517172713313, 19.193196743341623, 0.7249488391024033], 1.0E-6) + assertAlmostEqualList(self, minimums, [-19.956658197690174, 11.509153871441058, -7.068492932596849], 1.0E-6) + assertAlmostEqualList(self, maximums, [-1.9033816741586018, 19.093964008729433, 0.6249529551386831], 1.0E-6) flatCoordinates = fieldmodule.findFieldByName("flat coordinates").castFiniteElement() self.assertTrue(flatCoordinates.isValid()) @@ -142,10 +143,10 @@ def test_smallintestine1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 143.8501823770281, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 127.90324495617577, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 13.608455265457282, delta=1.0E-6) + self.assertAlmostEqual(volume, 12.011251644596864, delta=1.0E-6) result, flatSurfaceArea = flatSurfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) self.assertAlmostEqual(flatSurfaceArea, 144.42091907104523, delta=1.0E-3) diff --git a/tests/test_stomach.py b/tests/test_stomach.py index bc0d0ebe..de11e342 100644 --- a/tests/test_stomach.py +++ b/tests/test_stomach.py @@ -33,25 +33,12 @@ def test_stomach1(self): self.assertEqual(14, options.get("Number of elements along")) self.assertEqual(0.0215, options.get("Wall thickness")) self.assertEqual(True, options.get("Limiting ridge")) - ostiumOptions = options['Gastro-esophageal junction'] - ostiumSettings = ostiumOptions.getScaffoldSettings() - self.assertEqual(1, ostiumSettings.get("Number of vessels")) - self.assertEqual(8, ostiumSettings.get("Number of elements around ostium")) - self.assertEqual(4, ostiumSettings.get("Number of elements through wall")) - self.assertEqual(5.0, ostiumSettings.get("Ostium diameter")) - self.assertEqual(5.0, ostiumSettings.get("Ostium length")) - self.assertEqual(0.5, ostiumSettings.get("Ostium wall thickness")) - self.assertEqual([0.65, 0.12, 0.18, 0.05], ostiumSettings.get("Ostium wall relative thicknesses")) - self.assertEqual(2.0, ostiumSettings.get("Vessel inner diameter")) - self.assertEqual(0.3, ostiumSettings.get("Vessel wall thickness")) - self.assertEqual([0.65, 0.12, 0.18, 0.05], ostiumSettings.get("Vessel wall relative thicknesses")) - self.assertEqual(0.0, ostiumSettings.get("Vessel angle 1 degrees")) context = Context("Test") region = context.getDefaultRegion() self.assertTrue(region.isValid()) annotationGroups = scaffold.generateBaseMesh(region, options)[0] - self.assertEqual(41, len(annotationGroups)) + self.assertEqual(42, len(annotationGroups)) fieldmodule = region.getFieldmodule() self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) @@ -87,10 +74,10 @@ def test_stomach1(self): fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(surfaceArea, 4.090555451373093, delta=1.0E-6) + self.assertAlmostEqual(surfaceArea, 4.092273543567514, delta=1.0E-6) result, volume = volumeField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) - self.assertAlmostEqual(volume, 0.05785162283992282, delta=1.0E-6) + self.assertAlmostEqual(volume, 0.05789368036003227, delta=1.0E-6) # check some annotationGroups: expectedSizes3d = { @@ -101,7 +88,7 @@ def test_stomach1(self): "pyloric antrum": 128, "pyloric canal": 128, "duodenum": 64, - "stomach": 906 + "stomach": 778 } for name in expectedSizes3d: @@ -125,7 +112,7 @@ def test_stomach1(self): for annotationGroup in removeAnnotationGroups: annotationGroups.remove(annotationGroup) - self.assertEqual(41, len(annotationGroups)) + self.assertEqual(42, len(annotationGroups)) refineRegion = region.createRegion() refineFieldmodule = refineRegion.getFieldmodule() @@ -144,7 +131,7 @@ def test_stomach1(self): for annotation in annotationGroups: if annotation not in oldAnnotationGroups: annotationGroup.addSubelements() - self.assertEqual(75, len(annotationGroups)) + self.assertEqual(76, len(annotationGroups)) # mesh3d = refineFieldmodule.findMeshByDimension(3) self.assertEqual(57984, mesh3d.getSize())