def defineFaceAnnotations(cls, region, options, annotationGroups):
        """
        Add face annotation groups from the 1D mesh.
        :param region: Zinc region containing model.
        :param options: Dict containing options. See getDefaultOptions().
        :param annotationGroups: List of annotation groups for ventral-level elements.
        New point annotation groups are appended to this list.
        """
        # create  groups
        fm = region.getFieldmodule()
        mesh2d = fm.findMeshByDimension(2)
        is_exterior = fm.createFieldIsExterior()
        is_exterior_face_xi1 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI1_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI1_1)))
        is_exterior_face_xi2 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI2_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI2_1)))
        is_exterior_face_xi3 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI3_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI3_1)))

        # external regions
        groupNames = ['brainstem', 'midbrain', 'medulla oblongata', 'pons']
        for groupName in groupNames:
            subGroup = AnnotationGroup(region, get_brainstem_term(groupName))
            issub = subGroup.getFieldElementGroup(mesh2d)
            is_subface_ext = fm.createFieldOr(
                fm.createFieldAnd(issub, is_exterior_face_xi1),
                fm.createFieldAnd(issub, is_exterior_face_xi3))
            subFaceGroup = findOrCreateAnnotationGroupForTerm(
                annotationGroups, region,
                get_brainstem_term(groupName + ' exterior'))
            subFaceGroup.getMeshGroup(mesh2d).addElementsConditional(
                is_subface_ext)

        # brainstem interface
        groupNames = [
            'brainstem-spinal cord interface', 'thalamus-brainstem interface'
        ]
        for groupName in groupNames:
            subGroupName = 'midbrain' if groupName == 'thalamus-brainstem interface' else 'medulla oblongata'
            subGroup = AnnotationGroup(region,
                                       get_brainstem_term(subGroupName))
            issub = subGroup.getFieldElementGroup(mesh2d)
            is_subface_ext = fm.createFieldAnd(issub, is_exterior_face_xi2)
            subFaceGroup = findOrCreateAnnotationGroupForTerm(
                annotationGroups, region, get_brainstem_term(groupName))
            subFaceGroup.getMeshGroup(mesh2d).addElementsConditional(
                is_subface_ext)
Beispiel #2
0
    def generateBaseMesh(region, options):
        """
        Generate the base tricubic Hermite mesh. See also generateMesh().
        :param region: Zinc region to define model in. Must be empty.
        :param options: Dict containing options. See getDefaultOptions().
        :return: List of AnnotationGroup
        """

        baseParameterSetName = options['Base parameter set']
        isHuman = 'Human' in baseParameterSetName
        isRat = 'Rat' in baseParameterSetName

        centralPath = options['Central path']
        full = not options['Lower half']
        elementsCountAcrossMajor = options['Number of elements across major']
        if not full:
            elementsCountAcrossMajor //= 2
        elementsCountAcrossMinor = options['Number of elements across minor']
        elementsCountAcrossShell = options['Number of elements across shell']
        elementsCountAcrossTransition = options['Number of elements across transition']
        elementsCountAlongAbdomen = options['Number of elements in abdomen']
        elementsCountAlongHead = options['Number of elements in head']
        elementsCountAlongNeck = options['Number of elements in neck']
        elementsCountAlongThorax = options['Number of elements in thorax']
        shellRadiusProportion = options['Shell thickness proportion']
        shellProportion = 1/(1/shellRadiusProportion-1)*(elementsCountAcrossMajor/2/elementsCountAcrossShell - 1)
        discontinuity = options['Discontinuity on the core boundary']
        useCrossDerivatives = options['Use cross derivatives']

        elementsCountAlong = elementsCountAlongAbdomen + elementsCountAlongThorax + elementsCountAlongNeck + elementsCountAlongHead

        fieldmodule = region.getFieldmodule()
        coordinates = findOrCreateFieldCoordinates(fieldmodule)
        mesh = fieldmodule.findMeshByDimension(3)

        bodyGroup = AnnotationGroup(region, get_body_term("body"))
        coreGroup = AnnotationGroup(region, get_body_term("core"))
        non_coreGroup = AnnotationGroup(region, get_body_term("non core"))
        abdomenGroup = AnnotationGroup(region, get_body_term("abdomen"))
        thoraxGroup = AnnotationGroup(region, get_body_term("thorax"))
        neckGroup = AnnotationGroup(region, get_body_term("neck core"))
        headGroup = AnnotationGroup(region, get_body_term("head core"))
        annotationGroups = [bodyGroup, coreGroup, non_coreGroup, abdomenGroup, thoraxGroup, neckGroup, headGroup]

        cylinderCentralPath = CylinderCentralPath(region, centralPath, elementsCountAlong)

        cylinderShape = CylinderShape.CYLINDER_SHAPE_FULL

        base = CylinderEnds(elementsCountAcrossMajor, elementsCountAcrossMinor, elementsCountAcrossShell,
                            elementsCountAcrossTransition, shellProportion,
                            [0.0, 0.0, 0.0], cylinderCentralPath.alongAxis[0], cylinderCentralPath.majorAxis[0],
                            cylinderCentralPath.minorRadii[0])
        cylinder1 = CylinderMesh(fieldmodule, coordinates, elementsCountAlong, base,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath, useCrossDerivatives=False)

        # body coordinates
        bodyCoordinates = findOrCreateFieldCoordinates(fieldmodule, name="body coordinates")
        tmp_region = region.createRegion()
        tmp_fieldmodule = tmp_region.getFieldmodule()
        tmp_body_coordinates = findOrCreateFieldCoordinates(tmp_fieldmodule, name="body coordinates")
        tmp_cylinder = CylinderMesh(tmp_fieldmodule, tmp_body_coordinates, elementsCountAlong, base,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath, useCrossDerivatives=False)
        sir = tmp_region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemory()
        tmp_region.write(sir)
        result, buffer = srm.getBuffer()
        sir = region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemoryBuffer(buffer)
        region.read(sir)

        del srm
        del sir
        del tmp_body_coordinates
        del tmp_fieldmodule
        del tmp_region

        # Groups of different parts of the body
        is_body = fieldmodule.createFieldConstant(1)
        bodyMeshGroup = bodyGroup.getMeshGroup(mesh)
        bodyMeshGroup.addElementsConditional(is_body)

        coreMeshGroup = coreGroup.getMeshGroup(mesh)

        # core group
        e1a = elementsCountAcrossShell
        e1z = elementsCountAcrossMinor - elementsCountAcrossShell - 1
        e2a = elementsCountAcrossShell
        e2b = e2a + elementsCountAcrossTransition
        e2z = elementsCountAcrossMajor - elementsCountAcrossShell - 1
        e2y = e2z - elementsCountAcrossTransition
        e1oc = elementsCountAcrossMinor - 2*elementsCountAcrossShell - 2*elementsCountAcrossTransition
        e2oc = elementsCountAcrossMajor - 2*elementsCountAcrossShell - 2*elementsCountAcrossTransition
        e2oCore = e2oc * e1oc + 2 * elementsCountAcrossTransition * (e2oc + e1oc)
        elementsCountAround = cylinder1.getElementsCountAround()
        e2oShell = elementsCountAround * elementsCountAcrossShell
        e2o = e2oCore + e2oShell
        elementId = cylinder1.getElementIdentifiers()
        for e3 in range(elementsCountAlong):
            for e2 in range(elementsCountAcrossMajor):
                for e1 in range(elementsCountAcrossMinor):
                    coreElement = ((e2 >= e2a) and (e2 <= e2z)) and ((e1 >= e1a) and (e1 <= e1z))
                    if coreElement:
                        elementIdentifier = elementId[e3][e2][e1]
                        if elementIdentifier:
                            element = mesh.findElementByIdentifier(elementIdentifier)
                            coreMeshGroup.addElement(element)

        is_non_core = fieldmodule.createFieldNot(coreGroup.getGroup())
        non_coreMeshGroup = non_coreGroup.getMeshGroup(mesh)
        non_coreMeshGroup.addElementsConditional(is_non_core)

        abdomenMeshGroup = abdomenGroup.getMeshGroup(mesh)
        thoraxMeshGroup = thoraxGroup.getMeshGroup(mesh)
        neckMeshGroup = neckGroup.getMeshGroup(mesh)
        headMeshGroup = headGroup.getMeshGroup(mesh)
        meshGroups = [abdomenMeshGroup, thoraxMeshGroup, neckMeshGroup, headMeshGroup]

        abdomenRange = [1, elementsCountAlongAbdomen*e2o]
        thoraxRange = [abdomenRange[1]+1, abdomenRange[1]+elementsCountAlongThorax*e2o]
        neckRange = [thoraxRange[1]+1, thoraxRange[1] + elementsCountAlongNeck*e2o]
        headRange = [neckRange[1]+1, elementsCountAlong*e2o]
        groupsRanges = [abdomenRange, thoraxRange, neckRange, headRange]

        totalElements = e2o*elementsCountAlong
        for elementIdentifier in range(1, totalElements+1):
            element = mesh.findElementByIdentifier(elementIdentifier)
            if coreMeshGroup.containsElement(element):
                ri = 0
                for groupRange in groupsRanges:
                    if (elementIdentifier >= groupRange[0]) and (elementIdentifier <= groupRange[1]):
                        meshGroups[ri].addElement(element)
                        break
                    ri += 1

        if discontinuity:
            # create discontinuity in d3 on the core boundary
            nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
            elementtemplate = mesh.createElementtemplate()
            undefineNodetemplate = nodes.createNodetemplate()
            undefineNodetemplate.undefineField(coordinates)
            nodetemplate = nodes.createNodetemplate()
            fieldcache = fieldmodule.createFieldcache()
            with ChangeManager(fieldmodule):
                localNodeIndexes = [1, 2, 3, 4]
                valueLabel = Node.VALUE_LABEL_D_DS3
                for e3 in range(elementsCountAlong):
                    for e2 in range(elementsCountAcrossMajor):
                        for e1 in range(elementsCountAcrossMinor):
                            regularRowElement = (((e2 >= e2b) and (e2 <= e2y)) and ((e1 == e1a - 1) or (e1 == e1z + 1)))
                            non_coreFirstLayerElement = (e2 == e2a - 1) or regularRowElement or (e2 == e2z + 1)
                            elementIdentifier = elementId[e3][e2][e1]
                            if elementIdentifier and non_coreFirstLayerElement:
                                element = mesh.findElementByIdentifier(elementIdentifier)
                                eft = element.getElementfieldtemplate(coordinates, -1)
                                nodeIds = get_element_node_identifiers(element, eft)
                                for localNodeIndex in localNodeIndexes:
                                    node = element.getNode(eft, localNodeIndex)
                                    nodetemplate.defineFieldFromNode(coordinates, node)
                                    versionsCount = nodetemplate.getValueNumberOfVersions(coordinates, -1, valueLabel)
                                    if versionsCount == 1:
                                        fieldcache.setNode(node)
                                        result0, x = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_VALUE, 1, 3)
                                        result0, d1 = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS1, 1, 3)
                                        result0, d2 = coordinates.getNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS2, 1, 3)
                                        result0, d3 = coordinates.getNodeParameters(fieldcache, -1, valueLabel, 1, 3)
                                        result1 = node.merge(undefineNodetemplate)
                                        result2 = nodetemplate.setValueNumberOfVersions(coordinates, -1, valueLabel, 2)
                                        result3 = node.merge(nodetemplate)
                                        result4 = coordinates.setNodeParameters(fieldcache, -1, Node.VALUE_LABEL_VALUE, 1, x)
                                        result4 = coordinates.setNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS1, 1, d1)
                                        result4 = coordinates.setNodeParameters(fieldcache, -1, Node.VALUE_LABEL_D_DS2, 1, d2)
                                        result4 = coordinates.setNodeParameters(fieldcache, -1, valueLabel, 1, d3)
                                        result5 = coordinates.setNodeParameters(fieldcache, -1, valueLabel, 2, d3)
                                remapEftNodeValueLabelsVersion(eft, localNodeIndexes, [valueLabel], 2)
                                result1 = elementtemplate.defineField(coordinates, -1, eft)
                                result2 = element.merge(elementtemplate)
                                result3 = element.setNodesByIdentifier(eft, nodeIds)
        else:
            fieldcache = fieldmodule.createFieldcache()

        # Annotation fiducial point
        markerGroup = findOrCreateFieldGroup(fieldmodule, "marker")
        markerName = findOrCreateFieldStoredString(fieldmodule, name="marker_name")
        markerLocation = findOrCreateFieldStoredMeshLocation(fieldmodule, mesh, name="marker_location")
        markerBodyCoordinates = findOrCreateFieldCoordinates(fieldmodule, name="marker_body_coordinates")
        nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
        markerPoints = findOrCreateFieldNodeGroup(markerGroup, nodes).getNodesetGroup()
        markerTemplateInternal = nodes.createNodetemplate()
        markerTemplateInternal.defineField(markerName)
        markerTemplateInternal.defineField(markerLocation)
        markerTemplateInternal.defineField(markerBodyCoordinates)
        #
        middleLeft = elementsCountAcrossMinor//2
        topElem = elementsCountAcrossMajor - 1
        middleRight = middleLeft - 1
        neckFirstElem = elementsCountAlongAbdomen+elementsCountAlongThorax
        thoraxFirstElem = elementsCountAlongAbdomen
        middleDown = elementsCountAcrossMajor//2 - 1

        # organ landmarks groups
        apexOfHeart = heart_terms.get_heart_term('apex of heart')
        leftAtriumEpicardiumVenousMidpoint = heart_terms.get_heart_term('left atrium epicardium venous midpoint')
        rightAtriumEpicardiumVenousMidpoint = heart_terms.get_heart_term('right atrium epicardium venous midpoint')
        apexOfUrinaryBladder = bladder_terms.get_bladder_term('apex of urinary bladder')
        leftUreterJunctionWithBladder = bladder_terms.get_bladder_term('left ureter junction with bladder')
        rightUreterJunctionWithBladder = bladder_terms.get_bladder_term('right ureter junction with bladder')
        urethraJunctionWithBladderDorsal = bladder_terms.get_bladder_term('urethra junction of dorsal bladder neck')
        urethraJunctionWithBladderVentral = bladder_terms.get_bladder_term('urethra junction of ventral bladder neck')
        gastroesophagalJunctionOnLesserCurvature = stomach_terms.get_stomach_term('esophagogastric junction along the lesser curvature on serosa')
        limitingRidgeOnGreaterCurvature = stomach_terms.get_stomach_term('limiting ridge at the greater curvature on serosa')
        pylorusOnGreaterCurvature = stomach_terms.get_stomach_term('gastroduodenal junction along the greater curvature on serosa')
        junctionBetweenFundusAndBodyOnGreaterCurvature = stomach_terms.get_stomach_term("fundus-body junction along the greater curvature on serosa")
        apexOfLeftLung = lung_terms.get_lung_term('apex of left lung')
        ventralBaseOfLeftLung = lung_terms.get_lung_term('ventral base of left lung')
        dorsalBaseOfLeftLung = lung_terms.get_lung_term('dorsal base of left lung')
        apexOfRightLung = lung_terms.get_lung_term('apex of right lung')
        ventralBaseOfRightLung = lung_terms.get_lung_term('ventral base of right lung')
        dorsalBaseOfRightLung = lung_terms.get_lung_term('dorsal base of right lung')
        laterodorsalTipOfMiddleLobeOfRightLung = lung_terms.get_lung_term('laterodorsal tip of middle lobe of right lung')
        apexOfRightLungAccessoryLobe = lung_terms.get_lung_term('apex of right lung accessory lobe')
        ventralBaseOfRightLungAccessoryLobe = lung_terms.get_lung_term('ventral base of right lung accessory lobe')
        dorsalBaseOfRightLungAccessoryLobe = lung_terms.get_lung_term('dorsal base of right lung accessory lobe')
        medialBaseOfLeftLung = lung_terms.get_lung_term("medial base of left lung")
        medialBaseOfRightLung = lung_terms.get_lung_term("medial base of right lung")
        brainstemDorsalMidlineCaudalPoint = brainstem_terms.get_brainstem_term('brainstem dorsal midline caudal point')
        brainstemDorsalMidlineCranialPoint = brainstem_terms.get_brainstem_term('brainstem dorsal midline cranial point')
        brainstemVentralMidlineCaudalPoint = brainstem_terms.get_brainstem_term('brainstem ventral midline caudal point')
        brainstemVentralMidlineCranialPoint = brainstem_terms.get_brainstem_term('brainstem ventral midline cranial point')

        # marker coordinates. In future we want to have only one table for all species.
        if isRat:
            bodyMarkerPoints = [
                {"group": ("left hip joint", ''), "x": [0.367, 0.266, 0.477]},
                {"group": ("right hip joint", ''), "x": [-0.367, 0.266, 0.477]},
                {"group": ("left shoulder joint", ''), "x": [0.456, -0.071, 2.705]},
                {"group": ("right shoulder joint", ''), "x": [-0.456, -0.071, 2.705]},
                {"group": ("along left femur", ''), "x": [0.456, 0.07, 0.633]},
                {"group": ("along right femur", ''), "x": [-0.456, 0.07, 0.633]},
                {"group": ("along left humerus", ''), "x": [0.423, -0.173, 2.545]},
                {"group": ("along right humerus", ''), "x": [-0.423, -0.173, 2.545]},
                {"group": apexOfUrinaryBladder, "x": [-0.124, -0.383, 0.434]},
                {"group": leftUreterJunctionWithBladder, "x": [-0.111, -0.172, 0.354]},
                {"group": rightUreterJunctionWithBladder, "x": [-0.03, -0.196, 0.363]},
                {"group": urethraJunctionWithBladderDorsal, "x": [-0.03, -0.26, 0.209]},
                {"group": urethraJunctionWithBladderVentral, "x": [-0.037, -0.304, 0.203]},
                {"group": brainstemDorsalMidlineCaudalPoint, "x": [-0.032, 0.418, 2.713]},
                {"group": brainstemDorsalMidlineCranialPoint, "x": [-0.017, 0.203, 2.941]},
                {"group": brainstemVentralMidlineCaudalPoint, "x": [-0.028, 0.388, 2.72]},
                {"group": brainstemVentralMidlineCranialPoint, "x": [-0.019, 0.167, 2.95]},
                {"group": apexOfHeart, "x": [0.096, -0.128, 1.601]},
                {"group": leftAtriumEpicardiumVenousMidpoint, "x": [0.127, -0.083, 2.079]},
                {"group": rightAtriumEpicardiumVenousMidpoint, "x": [0.039, -0.082, 2.075]},
                {"group": apexOfLeftLung, "x": [0.172, -0.175, 2.337]},
                {"group": ventralBaseOfLeftLung, "x": [0.274, -0.285, 1.602]},
                {"group": dorsalBaseOfLeftLung, "x": [0.037, 0.31, 1.649]},
                {"group": apexOfRightLung, "x": [-0.086, -0.096, 2.311]},
                {"group": ventralBaseOfRightLung, "x": [0.14, -0.357, 1.662]},
                {"group": dorsalBaseOfRightLung, "x": [-0.054, 0.304, 1.667]},
                {"group": laterodorsalTipOfMiddleLobeOfRightLung, "x": [-0.258, -0.173, 2.013]},
                {"group": apexOfRightLungAccessoryLobe, "x": [0.041, -0.063, 1.965]},
                {"group": ventralBaseOfRightLungAccessoryLobe, "x": [0.143, -0.356, 1.66]},
                {"group": dorsalBaseOfRightLungAccessoryLobe, "x": [0.121, -0.067, 1.627]},
                {"group": gastroesophagalJunctionOnLesserCurvature, "x": [0.12, 0.009, 1.446]},
                {"group": limitingRidgeOnGreaterCurvature, "x": [0.318, 0.097, 1.406]},
                {"group": pylorusOnGreaterCurvature, "x": [0.08, -0.111, 1.443]},
            ]
        elif isHuman:
            bodyMarkerPoints = [
                {"group": urethraJunctionWithBladderDorsal, "x": [-0.0071, -0.2439, 0.1798]},
                {"group": urethraJunctionWithBladderVentral, "x": [-0.007, -0.2528, 0.1732]},
                {"group": leftUreterJunctionWithBladder, "x": [0.1074, 0.045, 0.1728]},
                {"group": rightUreterJunctionWithBladder, "x": [-0.1058, 0.0533, 0.1701]},
                {"group": apexOfUrinaryBladder, "x": [0.005, 0.1286, 0.1264]},
                {"group": brainstemDorsalMidlineCaudalPoint, "x": [0.0068, 0.427, 2.7389]},
                {"group": brainstemDorsalMidlineCranialPoint, "x": [0.008, -0.0231, 3.0778]},
                {"group": brainstemVentralMidlineCaudalPoint, "x": [0.0054, 0.3041, 2.7374]},
                {"group": brainstemVentralMidlineCranialPoint, "x": [0.0025, -0.2308, 3.091]},
                {"group": apexOfHeart, "x": [0.1373, -0.1855, 1.421]},
                {"group": leftAtriumEpicardiumVenousMidpoint, "x": [0.0024, 0.1452, 1.8022]},
                {"group": rightAtriumEpicardiumVenousMidpoint, "x": [-0.0464, 0.0373, 1.7491]},
                {"group": apexOfLeftLung, "x": [0.0655, -0.0873, 2.3564]},
                {"group": apexOfRightLung, "x": [-0.088, -0.0363, 2.3518]},
                {"group": laterodorsalTipOfMiddleLobeOfRightLung, "x": [-0.2838, -0.0933, 1.9962]},
                {"group": ventralBaseOfLeftLung, "x": [0.219, -0.2866, 1.4602]},
                {"group": medialBaseOfLeftLung, "x": [0.0426, -0.0201, 1.4109]},
                {"group": ventralBaseOfRightLung, "x": [-0.2302, -0.2356, 1.3926]},
                {"group": medialBaseOfRightLung, "x": [-0.0363, 0.0589, 1.3984]},
                {"group": dorsalBaseOfLeftLung, "x": [0.1544, 0.2603, 1.3691]},
                {"group": dorsalBaseOfRightLung, "x": [0.0369, -0.2524, 0.912]},
                {"group": gastroesophagalJunctionOnLesserCurvature, "x": [-0.0062, -0.3259, 0.8586]},
                {"group": pylorusOnGreaterCurvature, "x": [-0.0761, -0.3189, 0.8663]},
                {"group": junctionBetweenFundusAndBodyOnGreaterCurvature, "x": [0.1884, -0.1839, 0.9639]},
            ]

        nodeIdentifier = cylinder1._endNodeIdentifier
        findMarkerLocation = fieldmodule.createFieldFindMeshLocation(markerBodyCoordinates, bodyCoordinates, mesh)
        findMarkerLocation.setSearchMode(FieldFindMeshLocation.SEARCH_MODE_EXACT)
        for bodyMarkerPoint in bodyMarkerPoints:
            markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal)
            fieldcache.setNode(markerPoint)
            markerBodyCoordinates.assignReal(fieldcache, bodyMarkerPoint["x"])
            markerName.assignString(fieldcache, bodyMarkerPoint["group"][0])

            element, xi = findMarkerLocation.evaluateMeshLocation(fieldcache, 3)
            markerLocation.assignMeshLocation(fieldcache, element, xi)
            nodeIdentifier += 1

        return annotationGroups
class MeshType_3d_brainstem1(Scaffold_base):
    """
    Generates a tapered cylinder for the brainstem based on
    solid cylinder mesh, with variable numbers of elements
    in major, minor and length directions. Regions of the
    brainstem are annotated.
    """

    centralPathDefaultScaffoldPackages = {
        'Brainstem 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 3.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ], [[[0.0, 0.0, 0.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 2.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 3.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 4.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 5.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 6.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 7.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]],
                        [[0.0, 0.0, 8.0], [0.0, 0.0, 1.0], [1.0, 0.0, 0.0],
                         [0.0, 0.0, 0.0], [-0.0, 1.0, 0.0], [0.0, 0.0, 0.0]]]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '2',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Cat 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 3.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [
                        # [ [0.0,1.0,-5.0], [0.0,0.0,4.5], [5.0,0.0,0.0], [1.0,0.0,0.0], [0.0,2.4,0.0], [0.0,2.2,0.0] ],
                        # [ [0.0,1.0,-0.5], [0.0,0.0,4.5], [6.0,0.0,0.0], [1.0,0.0,0.0], [0.0,4.0,0.0], [0.0,1.1,0.0] ],
                        # [ [0.0,1.0, 4.0], [0.0,0.0,4.5], [7.0,0.0,0.0], [1.0,0.0,0.0], [0.0,4.5,0.0], [0.0,0.8,0.0] ],
                        # [ [0.0,1.0, 8.5], [0.0,0.0,4.5], [8.0,0.0,0.0], [1.0,0.0,0.0], [0.0,5.5,0.0], [0.0,0.8,0.0] ],
                        # [ [0.0,1.0,13.0], [0.0,0.0,4.5], [9.0,0.0,0.0], [1.0,0.0,0.0], [0.0,6.0,0.0], [0.0,0.2,0.0] ]
                        [[0.0, 10.7, -12.3], [0.0, -3.8, 3.1], [4.8, 0.0, 0.0],
                         [-0.7, 0.0, 0.0], [-0.0, 2.2, 2.6], [0.0, 0.5, 0.1]],
                        [[0.0, 6.8, -8.8], [0.0, -4.0, 3.9], [4.5, 0.0, 0.0],
                         [0.1, 0.0, 0.0], [-0.0, 2.7, 2.7], [0.0, 0.5, 0.1]],
                        [[0.0, 2.8, -4.5], [0.0, -3.5, 4.2], [5.0, 0.0, 0.0],
                         [1.2, 0.0, 0.0], [-0.0, 3.2, 2.8], [0.0, 0.5, 0.0]],
                        [[0.0, -0.2, -0.5], [0.0, -2.8, 3.8], [6.8, 0.0, 0.0],
                         [0.8, 0.0, 0.0], [-0.0, 3.8, 2.8], [0.0, 0.6, -0.4]],
                        [[0.0, -2.8, 3.0], [0.0, -1.9, 4.1], [6.8, 0.0, 0.0],
                         [-0.6, 0.0, 0.0], [-0.0, 4.5, 2.0], [0.0, 0.3, -0.1]],
                        [[0.0, -3.8, 7.5], [0.0, -2.7, 4.6], [5.5, 0.0, 0.0],
                         [-0.2, 0.0, 0.0], [-0.0, 4.3, 2.5], [0.0, -1.0, 1.0]],
                        [[0.0, -8.2, 11.5], [0.0, -5.9, 3.2], [6.8, 0.0, 0.0],
                         [2.8, 0.0, 0.0], [-0.0, 2.3, 4.2], [0.0, -3.1, 2.4]]
                    ]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '2',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Human 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 1.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [[[0.0, 18.9, -50.7], [0.0, -3.2, 15.4], [7.8, 0.0, 0.0],
                      [0.5, 0.0, 0.0], [-0.0, 6.1, 1.3], [0.0, 0.8, 1.7]],
                     [[0.0, 14.6, -36.3], [0.0, -5.4, 13.3], [8.5, 0.0, 0.0],
                      [0.9, 0.0, 0.0], [-0.0, 7.2, 2.9], [0.0, 1.4, 1.6]],
                     [[0.0, 8.3, -24.1], [0.0, -6.4, 12.5], [9.6, 0.0, 0.0],
                      [4.4, 0.0, 0.0], [-0.0, 8.9, 4.6], [0.0, 1.3, 0.5]],
                     [[0.0, 1.8, -11.4], [0.0, -5.3, 13.3], [17.4, 0.0, 0.0],
                      [5.3, 0.0, 0.0], [-0.0, 9.8, 3.9], [0.0, 2.6, -0.2]],
                     [[0.0, -2.3, 2.4], [0.0, -3.9, 13.2], [20.2, 0.0, 0.0],
                      [-0.4, 0.0, 0.0], [-0.0, 14.1, 4.2], [0.0, 2.2, -0.5]],
                     [[0.0, -6.0, 15.0], [0.0, -2.6, 12.9], [16.8, 0.0, 0.0],
                      [-2.4, 0.0, 0.0], [-0.0, 14.4, 2.9], [0.0, 0.2, -1.9]],
                     [[0.0, -7.5, 28.0], [0.0, -0.4, 13.1], [15.3, 0.0, 0.0],
                      [-0.6, 0.0, 0.0], [-0.0, 14.5, 0.4], [0.0, 0.0, -3.1]]]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1-2',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3-4',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '5-6',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Mouse 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 1.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [([[0.0, 1.5, -3.4], [0.0, -0.1, 1.1], [1.4, 0.0, 0.0],
                       [-0.1, 0.0, 0.0], [0.0, 1.0, 0.1], [0.0, 0.1, 0.9]]),
                     ([[0.0, 1.0, -2.3], [0.0, -0.8, 1.0], [1.3, 0.0, 0.0],
                       [0.0, 0.0, 0.0], [0.0, 0.8, 0.7], [0.0, 0.0, 0.6]]),
                     ([[0.0, -0.1, -1.6], [0.0, -1.2, 0.8], [1.5, 0.0, 0.0],
                       [0.4, 0.0, 0.0], [0.0, 0.7, 1.0], [0.0, 0.1, 0.1]]),
                     ([[0.0, -1.2, -0.7], [0.0, -0.7, 1.2], [2.0, 0.0, 0.0],
                       [0.2, 0.0, 0.0], [0.0, 1.2, 0.7], [0.0, 0.1, -0.1]]),
                     ([[0.0, -1.5, 0.5], [0.0, 0.1, 1.4], [2.0, 0.0, 0.0],
                       [-0.1, 0.0, 0.0], [0.0, 1.4, -0.1], [0.0, 0.1, -0.1]]),
                     ([[0.0, -1.1, 1.9], [0.0, -0.3, 1.4], [1.6, 0.0, 0.0],
                       [-0.1, 0.0, 0.0], [0.0, 1.5, 0.3], [0.0, -0.3, 0.3]]),
                     ([[0.0, -2.1, 3.1], [0.0, -1.3, 0.8], [2.0, 0.0, 0.0],
                       [0.8, 0.0, 0.0], [0.0, 0.7, 1.2], [0.0, -0.8, 0.7]])]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1-2',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3-4',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '5-6',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Rat 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 1.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [[[0.0, 2.9, -5.4], [0.0, 0.5, 1.7], [1.9, 0.0, 0.0],
                      [-0.2, 0.0, 0.0], [0.0, 1.3, -0.4], [-0.0, 0.2, 1.3]],
                     [[0.0, 2.7, -3.5], [0.0, -0.9, 2.0], [1.8, 0.0, 0.0],
                      [0.0, 0.0, 0.0], [-0.0, 1.4, 0.6], [-0.0, 0.0, 0.8]],
                     [[0.0, 1.1, -1.8], [0.0, -1.4, 1.7], [2.0, 0.0, 0.0],
                      [0.5, 0.0, 0.0], [-0.0, 1.3, 1.1], [0.0, 0.1, 0.2]],
                     [[0.0, -0.1, -0.2], [0.0, -1.1, 1.5], [2.7, 0.0, 0.0],
                      [0.3, 0.0, 0.0], [-0.0, 1.5, 1.1], [0.0, 0.2, -0.2]],
                     [[0.0, -1.1, 1.2], [0.0, -0.7, 1.6], [2.7, 0.0, 0.0],
                      [-0.2, 0.0, 0.0], [-0.0, 1.8, 0.8], [0.0, 0.1, -0.1]],
                     [[0.0, -1.5, 3.0], [0.0, -1.1, 1.9], [2.2, 0.0, 0.0],
                      [-0.1, 0.0, 0.0], [-0.0, 1.7, 1.0], [0.0, -0.4, 0.4]],
                     [[0.0, -3.3, 4.6], [0.0, -2.4, 1.3], [2.7, 0.0, 0.0],
                      [1.1, 0.0, 0.0], [-0.0, 0.9, 1.7], [0.0, -1.2, 1.0]]]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1-2',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3-4',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '5-6',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Pig 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 1.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [([[0.0, 25.6, -29.3], [0.0, -5.4, 3.5], [4.8, 0.0, 0.0],
                       [-0.7, 0.0, 0.0], [0.0, 1.8, 2.9], [0.0, 1.1, 1.4]]),
                     ([[0.0, 19.5, -25.3], [0.0, -6.7, 4.8], [5.7, 0.0, 0.0],
                       [2.5, 0.0, 0.0], [0.0, 2.8, 4.0], [0.0, 0.8, 0.7]]),
                     ([[0.0, 12.2, -19.9], [0.0, -6.7, 5.4], [10.1, 0.0, 0.0],
                       [3.0, 0.0, 0.0], [0.0, 3.3, 4.2], [0.0, 1.5, 0.5]]),
                     ([[0.0, 6.0, -14.5], [0.0, -5.5, 6.3], [12.9, -0.2, -0.2],
                       [0.7, 0.0, 0.0], [0.1, 5.7, 4.9], [0.0, 2.0, -0.6]]),
                     ([[0.0, 1.5, -7.4], [0.0, -2.8, 7.0], [11.4, 0.0, 0.0],
                       [-0.3, 0.2, 0.0], [0.0, 7.4, 3.0], [-0.2, 2.4, -1.2]]),
                     ([[0.0, 0.1, -1.0], [0.0, -1.5, 6.9], [11.2, 0.3, 0.1],
                       [-0.5, 0.1, 0.1], [-0.3, 11.3, 2.5], [-0.1, 1.5, -0.2]
                       ]),
                     ([[0.0, -1.5, 6.6], [0.0, -2.0, 7.4], [10.3, 0.2, 0.0],
                       [-1.3, -0.2, -0.0], [-0.2, 9.4, 2.5], [0.2, -2.3, 0.9]])
                     ]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1-2',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3-4',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '5-6',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            }),
        'Sheep 1':
        ScaffoldPackage(
            MeshType_1d_path1,
            {
                'scaffoldSettings': {
                    'Coordinate dimensions': 3,
                    'D2 derivatives': True,
                    'D3 derivatives': True,
                    'Length': 1.0,
                    'Number of elements': 6
                },
                'meshEdits':
                exnodeStringFromNodeValues(  # dimensional.
                    [
                        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
                    ],
                    [([[0.0, 21.3, -33.2], [0.0, -7.5, 6.0], [4.8, 0.0, 0.0],
                       [4.8, -0.0, -0.0], [0.0, 2.8, 3.5], [0.0, 3.2, 1.3]]),
                     ([[0.0, 14.5, -26.7], [0.0, -6.1, 7.2], [8.5, -0.0, -0.0],
                       [2.6, 0.0, 0.0], [0.0, 4.9, 4.1], [-0.0, 1.1, 0.1]]),
                     ([[0.0, 9.2, -19.0], [0.0, -5.2, 7.2], [10.1, 0.0, 0.0],
                       [1.1, -0.1, -0.0], [0.0, 5.0, 3.6], [0.1, 0.4, -0.6]]),
                     ([[0.0, 4.0, -12.2], [0.0, -3.5, 7.0], [10.8, -0.2, -0.1],
                       [-0.4, 0.2, 0.0], [0.1, 5.7, 2.9], [-0.1, 0.8, -1.4]]),
                     ([[0.0, 2.1, -5.5], [0.0, -1.2, 7.6], [9.4, 0.3, 0.1],
                       [0.1, 0.2, 0.1], [-0.2, 6.6, 1.0], [-0.2, 2.2, -0.3]]),
                     ([[0.0, 1.9, 2.9], [0.0, -2.1, 8.8], [11.2, 0.2, 0.1],
                       [3.3, -0.1, -0.0], [-0.2, 10.4, 2.5], [0.1, 0.3, 2.0]]),
                     ([[0.0, -2.3, 11.4], [0.0, -6.2, 8.1], [16.2, 0.1, 0.0],
                       [6.7, -0.2, -0.0], [-0.0, 6.7, 5.1], [0.3, -7.7, 3.2]])
                     ]),
                'userAnnotationGroups': [
                    {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '1-2',
                        'name': get_brainstem_term('medulla oblongata')[0],
                        'ontId': get_brainstem_term('medulla oblongata')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '3-4',
                        'name': get_brainstem_term('pons')[0],
                        'ontId': get_brainstem_term('pons')[1]
                    }, {
                        '_AnnotationGroup': True,
                        'dimension': 1,
                        'identifierRanges': '5-6',
                        'name': get_brainstem_term('midbrain')[0],
                        'ontId': get_brainstem_term('midbrain')[1]
                    }
                ]
            })
    }

    @staticmethod
    def getName():
        return '3D Brainstem 1'

    @staticmethod
    def getParameterSetNames():
        return [
            'Default', 'Cat 1', 'Human 1', 'Mouse 1', 'Rat 1', 'Pig 1',
            'Sheep 1'
        ]

    @classmethod
    def getDefaultOptions(cls, parameterSetName='Default'):
        if parameterSetName == 'Default':
            parameterSetName = 'Human 1'

        if 'Cat 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages['Cat 1']

        if 'Human 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages[
                'Human 1']

        if 'Mouse 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages[
                'Mouse 1']

        if 'Rat 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages['Rat 1']

        if 'Pig 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages['Pig 1']

        if 'Sheep 1' in parameterSetName:
            centralPathOption = cls.centralPathDefaultScaffoldPackages[
                'Sheep 1']

        options = {
            'Base parameter set': parameterSetName,
            'Central path': copy.deepcopy(centralPathOption),
            'Number of elements across major': 6,
            'Number of elements across minor': 6,
            'Number of elements along': 8,
            'Use cross derivatives': False,
            'Refine': False,
            'Refine number of elements across major and minor': 1,
            'Refine number of elements along': 1
        }

        return options

    @staticmethod
    def getOrderedOptionNames():
        return [
            'Central path', 'Number of elements across major',
            'Number of elements across minor', 'Number of elements along',
            'Refine', 'Refine number of elements across major and minor',
            'Refine number of elements along'
        ]

    @classmethod
    def getOptionValidScaffoldTypes(cls, optionName):
        if optionName == 'Central path':
            return [MeshType_1d_path1]
        return []

    @classmethod
    def getOptionScaffoldTypeParameterSetNames(cls, optionName, scaffoldType):
        if optionName == 'Central path':
            return list(cls.centralPathDefaultScaffoldPackages.keys())
        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 == 'Central path':
            if not parameterSetName:
                parameterSetName = list(
                    cls.centralPathDefaultScaffoldPackages.keys())[0]
            return copy.deepcopy(
                cls.centralPathDefaultScaffoldPackages[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)
        dependentChanges = False
        if options['Number of elements across major'] < 4:
            options['Number of elements across major'] = 4
        if options['Number of elements across major'] % 2:
            options['Number of elements across major'] += 1
        if options['Number of elements across minor'] < 4:
            options['Number of elements across minor'] = 4
        if options['Number of elements across minor'] % 2:
            options['Number of elements across minor'] += 1
        if options['Number of elements along'] < 2:
            options['Number of elements along'] = 2
        return dependentChanges

    @classmethod
    def generateBaseMesh(cls, region, options):
        """
        Generate the base tricubic Hermite mesh. See also generateMesh().
        :param region: Zinc region to define model in. Must be empty.
        :param options: Dict containing options. See getDefaultOptions().
        :return: None
        """
        parameterSetName = options['Base parameter set']
        isCat = 'Cat 1' in parameterSetName
        isHuman = 'Human 1' in parameterSetName
        isMouse = 'Mouse 1' in parameterSetName
        isRat = 'Rat 1' in parameterSetName
        isPig = 'Pig 1' in parameterSetName
        isSheep = 'Sheep 1' in parameterSetName

        centralPath = options['Central path']
        brainstemPath = cls.centralPathDefaultScaffoldPackages['Brainstem 1']
        elementsCountAcrossMajor = options['Number of elements across major']
        elementsCountAcrossMinor = options['Number of elements across minor']
        elementsCountAlong = options['Number of elements along']

        # Cross section at Z axis
        halfBrainStem = False
        if halfBrainStem:
            elementsCountAcrossMajor //= 2
        elementsPerLayer = (
            (elementsCountAcrossMajor - 2) *
            elementsCountAcrossMinor) + (2 * (elementsCountAcrossMinor - 2))

        fm = region.getFieldmodule()
        cache = fm.createFieldcache()
        coordinates = findOrCreateFieldCoordinates(fm)
        mesh = fm.findMeshByDimension(3)

        # Annotation groups
        brainstemGroup = AnnotationGroup(region,
                                         get_brainstem_term('brainstem'))
        brainstemMeshGroup = brainstemGroup.getMeshGroup(mesh)
        midbrainGroup = AnnotationGroup(region, get_brainstem_term('midbrain'))
        midbrainMeshGroup = midbrainGroup.getMeshGroup(mesh)
        ponsGroup = AnnotationGroup(region, get_brainstem_term('pons'))
        ponsMeshGroup = ponsGroup.getMeshGroup(mesh)
        medullaGroup = AnnotationGroup(region,
                                       get_brainstem_term('medulla oblongata'))
        medullaMeshGroup = medullaGroup.getMeshGroup(mesh)
        annotationGroups = [
            brainstemGroup, midbrainGroup, ponsGroup, medullaGroup
        ]

        annotationGroupAlong = [[brainstemGroup, midbrainGroup],
                                [brainstemGroup, ponsGroup],
                                [brainstemGroup, medullaGroup]]

        # point markers
        # centralCanal = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('central canal of spinal cord'))
        # cerebralAqueduct = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('cerebral aqueduct'))
        # foramenCaecum = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('foramen caecum of medulla oblongata'))
        dorsalMidCaudalGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem dorsal midline caudal point'))
        ventralMidCaudalGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem ventral midline caudal point'))
        dorsalMidCranGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem dorsal midline cranial point'))
        ventralMidCranGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem ventral midline cranial point'))
        dorsalMidMedullaPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem dorsal midline pons-medulla junction'))
        ventralMidMedullaPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem ventral midline pons-medulla junction'))
        dorsalMidMidbrainPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem dorsal midline midbrain-pons junction'))
        ventralMidMidbrainPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem ventral midline midbrain-pons junction'))

        #######################
        # CREATE MAIN BODY MESH
        #######################
        cylinderShape = CylinderShape.CYLINDER_SHAPE_FULL if not halfBrainStem else CylinderShape.CYLINDER_SHAPE_LOWER_HALF

        # Body coordinates
        cylinderCentralPath = CylinderCentralPath(region, centralPath,
                                                  elementsCountAlong)
        base = CylinderEnds(elementsCountAcrossMajor,
                            elementsCountAcrossMinor,
                            centre=[0.0, 0.0, 0.0],
                            alongAxis=cylinderCentralPath.alongAxis[0],
                            majorAxis=cylinderCentralPath.majorAxis[0],
                            minorRadius=cylinderCentralPath.minorRadii[0])

        cylinder1 = CylinderMesh(fm,
                                 coordinates,
                                 elementsCountAlong,
                                 base,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath,
                                 useCrossDerivatives=False)

        brainstem_coordinates = findOrCreateFieldCoordinates(
            fm, name="brainstem coordinates")

        # Brain coordinates
        tmp_region = region.createRegion()
        tmp_fm = tmp_region.getFieldmodule()
        tmp_brainstem_coordinates = findOrCreateFieldCoordinates(
            tmp_fm, name="brainstem coordinates")

        cylinderCentralPath1 = CylinderCentralPath(tmp_region, brainstemPath,
                                                   elementsCountAlong)

        base1 = CylinderEnds(elementsCountAcrossMajor,
                             elementsCountAcrossMinor,
                             centre=[0.0, 0.0, 0.0],
                             alongAxis=cylinderCentralPath1.alongAxis[0],
                             majorAxis=cylinderCentralPath1.majorAxis[0],
                             minorRadius=cylinderCentralPath1.minorRadii[0])

        cylinder2 = CylinderMesh(tmp_fm,
                                 tmp_brainstem_coordinates,
                                 elementsCountAlong,
                                 base1,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath1,
                                 useCrossDerivatives=False)

        # Write two coordinates
        sir = tmp_region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemory()
        tmp_region.write(sir)
        result, buffer = srm.getBuffer()

        sir = region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemoryBuffer(buffer)
        region.read(sir)

        del srm
        del sir
        del tmp_fm
        del tmp_brainstem_coordinates
        del tmp_region

        # Annotating groups
        iRegionBoundaries = [
            int(6 * elementsCountAlong / 15),
            int(13 * elementsCountAlong / 15)
        ]
        for elementIdentifier in range(1, mesh.getSize() + 1):
            element = mesh.findElementByIdentifier(elementIdentifier)
            brainstemMeshGroup.addElement(element)
            if elementIdentifier > (iRegionBoundaries[-1] * elementsPerLayer):
                midbrainMeshGroup.addElement(element)
            elif (elementIdentifier >
                  (iRegionBoundaries[0] * elementsPerLayer)) and (
                      elementIdentifier <=
                      (iRegionBoundaries[-1] * elementsPerLayer)):
                ponsMeshGroup.addElement(element)
            else:
                medullaMeshGroup.addElement(element)

        ################
        # point markers
        ################
        pointMarkers = [
            {
                "group": dorsalMidCaudalGroup,
                "marker_brainstem_coordinates": [0.0, 1.0, 0.0]
            },
            {
                "group": ventralMidCaudalGroup,
                "marker_brainstem_coordinates": [0.0, -1.0, 0.0]
            },
            {
                "group": dorsalMidCranGroup,
                "marker_brainstem_coordinates": [0.0, 1.0, 8.0]
            },
            {
                "group": ventralMidCranGroup,
                "marker_brainstem_coordinates": [0.0, -1.0, 8.0]
            },
            {
                "group": dorsalMidMedullaPonsJunction,
                "marker_brainstem_coordinates": [0.0, 1.0, 3.0]
            },
            {
                "group": ventralMidMedullaPonsJunction,
                "marker_brainstem_coordinates": [0.0, -1.0, 3.0]
            },
            {
                "group": dorsalMidMidbrainPonsJunction,
                "marker_brainstem_coordinates": [0.0, 1.0, 6.0]
            },
            {
                "group": ventralMidMidbrainPonsJunction,
                "marker_brainstem_coordinates": [0.0, -1.0, 6.0]
            },
        ]

        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 = findOrCreateFieldNodeGroup(markerGroup,
                                                  nodes).getNodesetGroup()
        markerBrainstemCoordinates = findOrCreateFieldCoordinates(
            fm, name="marker_body_coordinates")
        markerTemplateInternal = nodes.createNodetemplate()
        markerTemplateInternal.defineField(markerName)
        markerTemplateInternal.defineField(markerLocation)
        markerTemplateInternal.defineField(markerBrainstemCoordinates)

        cache = fm.createFieldcache()

        brainstemNodesetGroup = brainstemGroup.getNodesetGroup(nodes)

        nodeIdentifier = max(1, getMaximumNodeIdentifier(nodes) + 1)
        findMarkerLocation = fm.createFieldFindMeshLocation(
            markerBrainstemCoordinates, brainstem_coordinates, mesh)
        findMarkerLocation.setSearchMode(
            FieldFindMeshLocation.SEARCH_MODE_EXACT)

        for pointMarker in pointMarkers:
            group = pointMarker["group"]
            markerPoint = markerPoints.createNode(nodeIdentifier,
                                                  markerTemplateInternal)
            cache.setNode(markerPoint)

            markerBrainstemCoordinates.assignReal(
                cache, pointMarker["marker_brainstem_coordinates"])
            markerName.assignString(cache, group.getName())

            element, xi = findMarkerLocation.evaluateMeshLocation(cache, 3)
            markerLocation.assignMeshLocation(cache, element, xi)
            group.getNodesetGroup(nodes).addNode(markerPoint)
            brainstemNodesetGroup.addNode(markerPoint)
            nodeIdentifier += 1

        return annotationGroups

    @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().
        """
        assert isinstance(meshRefinement, MeshRefinement)
        refineElementsCountAcrossMajor = options[
            'Refine number of elements across major and minor']
        refineElementsCountAlong = options['Refine number of elements along']
        meshRefinement.refineAllElementsCubeStandard3d(
            refineElementsCountAcrossMajor, refineElementsCountAlong,
            refineElementsCountAcrossMajor)

    @classmethod
    def defineFaceAnnotations(cls, region, options, annotationGroups):
        """
        Add face annotation groups from the 1D mesh.
        :param region: Zinc region containing model.
        :param options: Dict containing options. See getDefaultOptions().
        :param annotationGroups: List of annotation groups for ventral-level elements.
        New point annotation groups are appended to this list.
        """
        # create  groups
        fm = region.getFieldmodule()
        mesh2d = fm.findMeshByDimension(2)
        is_exterior = fm.createFieldIsExterior()
        is_exterior_face_xi1 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI1_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI1_1)))
        is_exterior_face_xi2 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI2_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI2_1)))
        is_exterior_face_xi3 = fm.createFieldOr(
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI3_0)),
            fm.createFieldAnd(is_exterior,
                              fm.createFieldIsOnFace(Element.FACE_TYPE_XI3_1)))

        # external regions
        groupNames = ['brainstem', 'midbrain', 'medulla oblongata', 'pons']
        for groupName in groupNames:
            subGroup = AnnotationGroup(region, get_brainstem_term(groupName))
            issub = subGroup.getFieldElementGroup(mesh2d)
            is_subface_ext = fm.createFieldOr(
                fm.createFieldAnd(issub, is_exterior_face_xi1),
                fm.createFieldAnd(issub, is_exterior_face_xi3))
            subFaceGroup = findOrCreateAnnotationGroupForTerm(
                annotationGroups, region,
                get_brainstem_term(groupName + ' exterior'))
            subFaceGroup.getMeshGroup(mesh2d).addElementsConditional(
                is_subface_ext)

        # brainstem interface
        groupNames = [
            'brainstem-spinal cord interface', 'thalamus-brainstem interface'
        ]
        for groupName in groupNames:
            subGroupName = 'midbrain' if groupName == 'thalamus-brainstem interface' else 'medulla oblongata'
            subGroup = AnnotationGroup(region,
                                       get_brainstem_term(subGroupName))
            issub = subGroup.getFieldElementGroup(mesh2d)
            is_subface_ext = fm.createFieldAnd(issub, is_exterior_face_xi2)
            subFaceGroup = findOrCreateAnnotationGroupForTerm(
                annotationGroups, region, get_brainstem_term(groupName))
            subFaceGroup.getMeshGroup(mesh2d).addElementsConditional(
                is_subface_ext)
    def generateBaseMesh(cls, region, options):
        """
        Generate the base tricubic Hermite mesh. See also generateMesh().
        :param region: Zinc region to define model in. Must be empty.
        :param options: Dict containing options. See getDefaultOptions().
        :return: None
        """
        parameterSetName = options['Base parameter set']
        isCat = 'Cat 1' in parameterSetName
        isHuman = 'Human 1' in parameterSetName
        isMouse = 'Mouse 1' in parameterSetName
        isRat = 'Rat 1' in parameterSetName
        isPig = 'Pig 1' in parameterSetName
        isSheep = 'Sheep 1' in parameterSetName

        centralPath = options['Central path']
        brainstemPath = cls.centralPathDefaultScaffoldPackages['Brainstem 1']
        elementsCountAcrossMajor = options['Number of elements across major']
        elementsCountAcrossMinor = options['Number of elements across minor']
        elementsCountAlong = options['Number of elements along']

        # Cross section at Z axis
        halfBrainStem = False
        if halfBrainStem:
            elementsCountAcrossMajor //= 2
        elementsPerLayer = (
            (elementsCountAcrossMajor - 2) *
            elementsCountAcrossMinor) + (2 * (elementsCountAcrossMinor - 2))

        fm = region.getFieldmodule()
        cache = fm.createFieldcache()
        coordinates = findOrCreateFieldCoordinates(fm)
        mesh = fm.findMeshByDimension(3)

        # Annotation groups
        brainstemGroup = AnnotationGroup(region,
                                         get_brainstem_term('brainstem'))
        brainstemMeshGroup = brainstemGroup.getMeshGroup(mesh)
        midbrainGroup = AnnotationGroup(region, get_brainstem_term('midbrain'))
        midbrainMeshGroup = midbrainGroup.getMeshGroup(mesh)
        ponsGroup = AnnotationGroup(region, get_brainstem_term('pons'))
        ponsMeshGroup = ponsGroup.getMeshGroup(mesh)
        medullaGroup = AnnotationGroup(region,
                                       get_brainstem_term('medulla oblongata'))
        medullaMeshGroup = medullaGroup.getMeshGroup(mesh)
        annotationGroups = [
            brainstemGroup, midbrainGroup, ponsGroup, medullaGroup
        ]

        annotationGroupAlong = [[brainstemGroup, midbrainGroup],
                                [brainstemGroup, ponsGroup],
                                [brainstemGroup, medullaGroup]]

        # point markers
        # centralCanal = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('central canal of spinal cord'))
        # cerebralAqueduct = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('cerebral aqueduct'))
        # foramenCaecum = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('foramen caecum of medulla oblongata'))
        dorsalMidCaudalGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem dorsal midline caudal point'))
        ventralMidCaudalGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem ventral midline caudal point'))
        dorsalMidCranGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem dorsal midline cranial point'))
        ventralMidCranGroup = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term('brainstem ventral midline cranial point'))
        dorsalMidMedullaPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem dorsal midline pons-medulla junction'))
        ventralMidMedullaPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem ventral midline pons-medulla junction'))
        dorsalMidMidbrainPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem dorsal midline midbrain-pons junction'))
        ventralMidMidbrainPonsJunction = findOrCreateAnnotationGroupForTerm(
            annotationGroups, region,
            get_brainstem_term(
                'brainstem ventral midline midbrain-pons junction'))

        #######################
        # CREATE MAIN BODY MESH
        #######################
        cylinderShape = CylinderShape.CYLINDER_SHAPE_FULL if not halfBrainStem else CylinderShape.CYLINDER_SHAPE_LOWER_HALF

        # Body coordinates
        cylinderCentralPath = CylinderCentralPath(region, centralPath,
                                                  elementsCountAlong)
        base = CylinderEnds(elementsCountAcrossMajor,
                            elementsCountAcrossMinor,
                            centre=[0.0, 0.0, 0.0],
                            alongAxis=cylinderCentralPath.alongAxis[0],
                            majorAxis=cylinderCentralPath.majorAxis[0],
                            minorRadius=cylinderCentralPath.minorRadii[0])

        cylinder1 = CylinderMesh(fm,
                                 coordinates,
                                 elementsCountAlong,
                                 base,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath,
                                 useCrossDerivatives=False)

        brainstem_coordinates = findOrCreateFieldCoordinates(
            fm, name="brainstem coordinates")

        # Brain coordinates
        tmp_region = region.createRegion()
        tmp_fm = tmp_region.getFieldmodule()
        tmp_brainstem_coordinates = findOrCreateFieldCoordinates(
            tmp_fm, name="brainstem coordinates")

        cylinderCentralPath1 = CylinderCentralPath(tmp_region, brainstemPath,
                                                   elementsCountAlong)

        base1 = CylinderEnds(elementsCountAcrossMajor,
                             elementsCountAcrossMinor,
                             centre=[0.0, 0.0, 0.0],
                             alongAxis=cylinderCentralPath1.alongAxis[0],
                             majorAxis=cylinderCentralPath1.majorAxis[0],
                             minorRadius=cylinderCentralPath1.minorRadii[0])

        cylinder2 = CylinderMesh(tmp_fm,
                                 tmp_brainstem_coordinates,
                                 elementsCountAlong,
                                 base1,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath1,
                                 useCrossDerivatives=False)

        # Write two coordinates
        sir = tmp_region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemory()
        tmp_region.write(sir)
        result, buffer = srm.getBuffer()

        sir = region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemoryBuffer(buffer)
        region.read(sir)

        del srm
        del sir
        del tmp_fm
        del tmp_brainstem_coordinates
        del tmp_region

        # Annotating groups
        iRegionBoundaries = [
            int(6 * elementsCountAlong / 15),
            int(13 * elementsCountAlong / 15)
        ]
        for elementIdentifier in range(1, mesh.getSize() + 1):
            element = mesh.findElementByIdentifier(elementIdentifier)
            brainstemMeshGroup.addElement(element)
            if elementIdentifier > (iRegionBoundaries[-1] * elementsPerLayer):
                midbrainMeshGroup.addElement(element)
            elif (elementIdentifier >
                  (iRegionBoundaries[0] * elementsPerLayer)) and (
                      elementIdentifier <=
                      (iRegionBoundaries[-1] * elementsPerLayer)):
                ponsMeshGroup.addElement(element)
            else:
                medullaMeshGroup.addElement(element)

        ################
        # point markers
        ################
        pointMarkers = [
            {
                "group": dorsalMidCaudalGroup,
                "marker_brainstem_coordinates": [0.0, 1.0, 0.0]
            },
            {
                "group": ventralMidCaudalGroup,
                "marker_brainstem_coordinates": [0.0, -1.0, 0.0]
            },
            {
                "group": dorsalMidCranGroup,
                "marker_brainstem_coordinates": [0.0, 1.0, 8.0]
            },
            {
                "group": ventralMidCranGroup,
                "marker_brainstem_coordinates": [0.0, -1.0, 8.0]
            },
            {
                "group": dorsalMidMedullaPonsJunction,
                "marker_brainstem_coordinates": [0.0, 1.0, 3.0]
            },
            {
                "group": ventralMidMedullaPonsJunction,
                "marker_brainstem_coordinates": [0.0, -1.0, 3.0]
            },
            {
                "group": dorsalMidMidbrainPonsJunction,
                "marker_brainstem_coordinates": [0.0, 1.0, 6.0]
            },
            {
                "group": ventralMidMidbrainPonsJunction,
                "marker_brainstem_coordinates": [0.0, -1.0, 6.0]
            },
        ]

        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 = findOrCreateFieldNodeGroup(markerGroup,
                                                  nodes).getNodesetGroup()
        markerBrainstemCoordinates = findOrCreateFieldCoordinates(
            fm, name="marker_body_coordinates")
        markerTemplateInternal = nodes.createNodetemplate()
        markerTemplateInternal.defineField(markerName)
        markerTemplateInternal.defineField(markerLocation)
        markerTemplateInternal.defineField(markerBrainstemCoordinates)

        cache = fm.createFieldcache()

        brainstemNodesetGroup = brainstemGroup.getNodesetGroup(nodes)

        nodeIdentifier = max(1, getMaximumNodeIdentifier(nodes) + 1)
        findMarkerLocation = fm.createFieldFindMeshLocation(
            markerBrainstemCoordinates, brainstem_coordinates, mesh)
        findMarkerLocation.setSearchMode(
            FieldFindMeshLocation.SEARCH_MODE_EXACT)

        for pointMarker in pointMarkers:
            group = pointMarker["group"]
            markerPoint = markerPoints.createNode(nodeIdentifier,
                                                  markerTemplateInternal)
            cache.setNode(markerPoint)

            markerBrainstemCoordinates.assignReal(
                cache, pointMarker["marker_brainstem_coordinates"])
            markerName.assignString(cache, group.getName())

            element, xi = findMarkerLocation.evaluateMeshLocation(cache, 3)
            markerLocation.assignMeshLocation(cache, element, xi)
            group.getNodesetGroup(nodes).addNode(markerPoint)
            brainstemNodesetGroup.addNode(markerPoint)
            nodeIdentifier += 1

        return annotationGroups
    def generateBaseMesh(cls, region, options):
        """
        Generate the base tricubic Hermite mesh. See also generateMesh().
        :param region: Zinc region to define model in. Must be empty.
        :param options: Dict containing options. See getDefaultOptions().
        :return: None
        """
        parameterSetName = options['Base parameter set']
        isCat = 'Cat 1' in parameterSetName
        isHuman = 'Human 1' in parameterSetName
        isMouse = 'Mouse 1' in parameterSetName
        isRat = 'Rat 1' in parameterSetName
        isPig = 'Pig 1' in parameterSetName
        isSheep = 'Sheep 1' in parameterSetName

        centralPath = options['Central path']
        brainstemPath = cls.centralPathDefaultScaffoldPackages['Brainstem 1']
        elementsCountAcrossMajor = options['Number of elements across major']
        elementsCountAcrossMinor = options['Number of elements across minor']
        elementsCountAlong = options['Number of elements along']

        # Cross section at Z axis
        halfBrainStem = False
        if halfBrainStem:
            elementsCountAcrossMajor //= 2
        elementsPerLayer = ((elementsCountAcrossMajor - 2) * elementsCountAcrossMinor) + (
                2 * (elementsCountAcrossMinor - 2))

        fm = region.getFieldmodule()
        cache = fm.createFieldcache()
        coordinates = findOrCreateFieldCoordinates(fm)
        mesh = fm.findMeshByDimension(3)

        # Annotation groups
        brainstemGroup = AnnotationGroup(region, get_brainstem_term('brainstem'))
        brainstemMeshGroup = brainstemGroup.getMeshGroup(mesh)
        midbrainGroup = AnnotationGroup(region, get_brainstem_term('midbrain'))
        midbrainMeshGroup = midbrainGroup.getMeshGroup(mesh)
        ponsGroup = AnnotationGroup(region, get_brainstem_term('pons'))
        ponsMeshGroup = ponsGroup.getMeshGroup(mesh)
        medullaGroup = AnnotationGroup(region, get_brainstem_term('medulla oblongata'))
        medullaMeshGroup = medullaGroup.getMeshGroup(mesh)
        annotationGroups = [brainstemGroup, midbrainGroup, ponsGroup, medullaGroup]

        annotationGroupAlong = [[brainstemGroup, midbrainGroup],
                                [brainstemGroup, ponsGroup],
                                [brainstemGroup, medullaGroup]]
        # centralCanal = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('central canal of spinal cord'))
        # cerebralAqueduct = findOrCreateAnnotationGroupForTerm(annotationGroups, region,
        #                                                        get_brainstem_term('cerebral aqueduct'))
        # foramenCaecum = findOrCreateAnnotationGroupForTerm(annotationGroups, region,

        #######################
        # CREATE MAIN BODY MESH
        #######################
        cylinderShape = CylinderShape.CYLINDER_SHAPE_FULL if not halfBrainStem else CylinderShape.CYLINDER_SHAPE_LOWER_HALF

        # brainstem coordinates
        cylinderCentralPath = CylinderCentralPath(region, centralPath, elementsCountAlong)
        base = CylinderEnds(elementsCountAcrossMajor, elementsCountAcrossMinor,
                            centre=[0.0, 0.0, 0.0],
                            alongAxis=cylinderCentralPath.alongAxis[0],
                            majorAxis=cylinderCentralPath.majorAxis[0],
                            minorRadius=cylinderCentralPath.minorRadii[0])

        cylinder1 = CylinderMesh(fm, coordinates, elementsCountAlong, base,
                                 cylinderShape=cylinderShape,
                                 cylinderCentralPath=cylinderCentralPath,
                                 useCrossDerivatives=False)

        #  workaround for old Zinc field wrapper bug: must create brainstem coordinates field before reading file
        brainstem_coordinates = findOrCreateFieldCoordinates(fm, name="brainstem coordinates")

        # generate brainstem coordinates field in temporary region
        tmp_region = region.createRegion()
        tmp_fm = tmp_region.getFieldmodule()
        with ChangeManager(tmp_fm):
            tmp_brainstem_coordinates = findOrCreateFieldCoordinates(tmp_fm, name="brainstem coordinates")

            cylinderCentralPath1 = CylinderCentralPath(tmp_region, brainstemPath, elementsCountAlong)

            base1 = CylinderEnds(elementsCountAcrossMajor, elementsCountAcrossMinor,
                                 centre=[0.0, 0.0, 0.0],
                                 alongAxis=cylinderCentralPath1.alongAxis[0],
                                 majorAxis=cylinderCentralPath1.majorAxis[0],
                                 minorRadius=cylinderCentralPath1.minorRadii[0])

            cylinder2 = CylinderMesh(tmp_fm, tmp_brainstem_coordinates, elementsCountAlong, base1,
                                     cylinderShape=cylinderShape,
                                     cylinderCentralPath=cylinderCentralPath1,
                                     useCrossDerivatives=False)

            # write to memory buffer
            sir = tmp_region.createStreaminformationRegion()
            srm = sir.createStreamresourceMemory()
            tmp_region.write(sir)
            result, buffer = srm.getBuffer()

            # read into main region
            sir = region.createStreaminformationRegion()
            srm = sir.createStreamresourceMemoryBuffer(buffer)
            region.read(sir)

            del srm
            del sir
            del tmp_brainstem_coordinates
        del tmp_fm
        del tmp_region

        # Annotating groups
        iRegionBoundaries = [int(6 * elementsCountAlong / 15), int(13 * elementsCountAlong / 15)]
        for elementIdentifier in range(1, mesh.getSize() + 1):
            element = mesh.findElementByIdentifier(elementIdentifier)
            brainstemMeshGroup.addElement(element)
            if elementIdentifier > (iRegionBoundaries[-1] * elementsPerLayer):
                midbrainMeshGroup.addElement(element)
            elif (elementIdentifier > (iRegionBoundaries[0] * elementsPerLayer)) and (
                    elementIdentifier <= (iRegionBoundaries[-1] * elementsPerLayer)):
                ponsMeshGroup.addElement(element)
            else:
                medullaMeshGroup.addElement(element)

        ################
        # point markers
        ################

        markerTermNameBrainstemCoordinatesMap = {
            'brainstem dorsal midline caudal point': [0.0, 1.0, 0.0],
            'brainstem ventral midline caudal point': [0.0, -1.0, 0.0],
            'brainstem dorsal midline cranial point': [0.0, 1.0, 8.0],
            'brainstem ventral midline cranial point': [0.0, -1.0, 8.0],
            'brainstem dorsal midline pons-medulla junction': [0.0, 1.0, 3.0],
            'brainstem ventral midline pons-medulla junction': [0.0, -1.0, 3.0],
            'brainstem dorsal midline midbrain-pons junction': [0.0, 1.0, 6.0],
            'brainstem ventral midline midbrain-pons junction': [0.0, -1.0, 6.0]
        }
        nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
        nodeIdentifier = max(1, getMaximumNodeIdentifier(nodes) + 1)
        for termName, brainstemCoordinatesValues in markerTermNameBrainstemCoordinatesMap.items():
            annotationGroup = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_brainstem_term(termName))
            annotationGroup.createMarkerNode(nodeIdentifier, brainstem_coordinates, brainstemCoordinatesValues)
            nodeIdentifier += 1

        return annotationGroups