diff --git a/src/scaffoldmaker/annotation/bladder_terms.py b/src/scaffoldmaker/annotation/bladder_terms.py index 29e90616..9b08c5f1 100644 --- a/src/scaffoldmaker/annotation/bladder_terms.py +++ b/src/scaffoldmaker/annotation/bladder_terms.py @@ -4,19 +4,39 @@ # convention: preferred name, preferred id, followed by any other ids and alternative names bladder_terms = [ - ("urinary bladder", "UBERON:0001255", "FMA:15900"), - ("neck of urinary bladder", "UBERON:0001258", "FMA:15912"), - ("Dome of the Bladder", "ILX:0738433"), - ("serosa of urinary bladder", "UBERON:0001260"), ("bladder lumen", "UBERON:0009958"), - ("serosa of body of urinary bladder", "ILX:0739276"), + ("dome of the bladder", "ILX:0738433"), + ("dorsal part of bladder lumen", "None"), + ("dorsal part of lumen of body of urinary bladder", "ILX:0739250"), + ("dorsal part of lumen of neck of urinary bladder", "ILX:0739255"), + ("dorsal part of lumen of urethra", "ILX:0739260"), + ("dorsal part of bladder", "None"), + ("dorsal part of urethra", "ILX:0739258"), + ("dorsal part of serosa of body of urinary bladder", "ILX:0739278"), + ("dorsal part of serosa of neck of urinary bladder", "ILX:0739280"), + ("dorsal part of serosa of urethra", "ILX:0739283"), + ("dorsal part of serosa of urinary bladder", "ILX:0739248"), ("lumen of body of urinary bladder", "ILX:0739252"), - ("serosa of neck of urinary bladder", "ILX:0739277"), ("lumen of neck of urinary bladder", "ILX:0739256"), - ("urethra", "UBERON:0000057", "ILX:0733022"), - ("lumen of urethra", "ILX:0736762"), + ("lumen of urethra", "UBERON:0010390", "ILX:0736762"), + ("neck of urinary bladder", "UBERON:0001258", "FMA:15912"), + ("serosa of body of urinary bladder", "ILX:0739276"), + ("serosa of neck of urinary bladder", "ILX:0739277"), ("serosa of urethra", "ILX:0739282"), - ("ureter", "UBERON:0000056", "ILX:0728080") + ("serosa of urinary bladder", "UBERON:0001260"), + ("ureter", "UBERON:0000056", "ILX:0728080"), + ("urethra", "UBERON:0000057", "ILX:0733022"), + ("urinary bladder", "UBERON:0001255", "FMA:15900"), + ("ventral part of bladder lumen", "None"), + ("ventral part of lumen of body of urinary bladder", "ILX:0739251"), + ("ventral part of lumen of neck of urinary bladder", "ILX:0739257"), + ("ventral part of lumen of urethra", "ILX:0739261"), + ("ventral part of serosa of body of urinary bladder", "ILX:0739279"), + ("ventral part of serosa of neck of urinary bladder", "ILX:0739281"), + ("ventral part of serosa of urethra", "ILX:0739306"), + ("ventral part of serosa of urinary bladder", "ILX:0739249"), + ("ventral part of bladder", "None"), + ("ventral part of urethra", "ILX:0739259") ] def get_bladder_term(name : str): diff --git a/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py b/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py index 12a0a5bc..041f97e9 100644 --- a/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py +++ b/src/scaffoldmaker/meshtypes/meshtype_3d_bladderurethra1.py @@ -21,6 +21,7 @@ from scaffoldmaker.utils.interpolation import smoothCubicHermiteDerivativesLine from scaffoldmaker.utils.tracksurface import TrackSurface, TrackSurfacePosition, calculate_surface_axes from scaffoldmaker.utils.zinc_utils import exnodeStringFromNodeValues, mesh_destroy_elements_and_nodes_by_identifiers +from opencmiss.utils.zinc.field import findOrCreateFieldGroup, findOrCreateFieldNodeGroup, findOrCreateFieldStoredMeshLocation, findOrCreateFieldStoredString from opencmiss.zinc.element import Element from opencmiss.zinc.field import Field from opencmiss.zinc.node import Node @@ -301,11 +302,13 @@ def checkOptions(cls, options): 'Refine number of elements through wall']: if options[key] < 1: options[key] = 1 + if options['Number of elements around'] % 2 != 0: + options['Number of elements around'] += 1 if options['Number of elements through wall'] > 1: if options['Include ureter']: options['Number of elements through wall'] = 1 - if options['Ureter position around'] < 0.1: - options['Ureter position around'] = 0.1 + if options['Ureter position around'] < 0.5: + options['Ureter position around'] = 0.5 # ureters are on the dorsal part of the bladder elif options['Ureter position around'] > 0.9: options['Ureter position around'] = 0.9 if options['Ureter position down'] < 0.15: @@ -367,6 +370,19 @@ def generateBaseMesh(cls, region, options): nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) mesh = fm.findMeshByDimension(3) + # Annotation fiducial point + 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() + markerTemplateInternal = nodes.createNodetemplate() + markerTemplateInternal.defineField(markerName) + markerTemplateInternal.defineField(markerLocation) + + cache = fm.createFieldcache() + # Central path # Bladder part tmpRegion = region.createRegion() @@ -651,49 +667,6 @@ def generateBaseMesh(cls, region, options): elementsCountAlongBody = round(ureterPositionDown * elementsCountAlongBladder - 1) elementsCountAlongNeck = elementsCountAlongBladder - elementsCountAlongBody - # Create annotation groups for bladder and urethra - bodyGroup = AnnotationGroup(region, get_bladder_term("Dome of the Bladder")) - neckGroup = AnnotationGroup(region, get_bladder_term("neck of urinary bladder")) - bladderGroup = AnnotationGroup(region, get_bladder_term("urinary bladder")) - urethraGroup = AnnotationGroup(region, get_bladder_term("urethra")) - ureterGroup = AnnotationGroup(region, get_bladder_term("ureter")) - if includeUrethra: - elementsCountAlongGroups = [elementsCountAlongBody, elementsCountAlongNeck, elementsCountAlongUrethra] - annotationGroupAlong = [[bladderGroup, bodyGroup], [bladderGroup, neckGroup], [urethraGroup]] - else: - elementsCountAlongGroups = [elementsCountAlongBody, elementsCountAlongNeck] - annotationGroupAlong = [[bladderGroup, bodyGroup], [bladderGroup, neckGroup]] - - 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([]) - - annotationGroupsThroughWall = [] - for i in range(elementsCountThroughWall): - annotationGroupsThroughWall.append([]) - - neckMeshGroup = neckGroup. getMeshGroup(mesh) - bodyMeshGroup = bodyGroup.getMeshGroup(mesh) - urinaryBladderMeshGroup = bladderGroup.getMeshGroup(mesh) - urethraMeshGroup = urethraGroup. getMeshGroup(mesh) - ureterMeshGroup = ureterGroup. getMeshGroup(mesh) - - # Create nodes and elements - nextNodeIdentifier, nextElementIdentifier, annotationGroups = tubemesh.createNodesAndElements( - region, xFinal, d1Final, d2Final, d3Final, xFlat, d1Flat, d2Flat, xTexture, d1Texture, d2Texture, - elementsCountAround, elementsCountAlong, elementsCountThroughWall, - annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, - firstNodeIdentifier, firstElementIdentifier, - useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True) - - annotationGroups.append(ureterGroup) - # Define outer layer of the bladder to create the trackSurface on it outerNodes_x = [] outerNodes_d1 = [] @@ -722,6 +695,14 @@ def generateBaseMesh(cls, region, options): ureter1Position = trackSurfaceUreter1.createPositionProportion(ureterPositionAround, ureterPositionDown) ureterElementPositionAround = ureter1Position.e1 ureterElementPositionDown = ureter1Position.e2 + elementToDeleteStartIdx1 = elementsCountThroughWall * elementsCountAround * (ureterElementPositionDown - (0 if ureter1Position.xi2 > 0.5 else 1)) \ + + ureterElementPositionAround + (1 if ureter1Position.xi1 > 0.5 else 0) + + elementIndex = elementToDeleteStartIdx1 - elementsCountAround * ureterElementPositionDown + if ureterElementPositionAround > (elementsCountAround / 4): + elementsCountVentral1 = (elementsCountAround // 4) + else: + elementsCountVentral1 = elementIndex - 1 # Create trackSurface at the outer layer of the bladder for ureter 2 nodesOnTrackSurface2_x = [] @@ -738,17 +719,108 @@ def generateBaseMesh(cls, region, options): trackSurfaceUreter2 = TrackSurface(elementsCount1, elementsCount2, nodesOnTrackSurface2_x, nodesOnTrackSurface2_d1, nodesOnTrackSurface2_d2) - ureter2Position = TrackSurfacePosition(elementsCountAround//2 - ureterElementPositionAround + (-1 if ureter1Position.xi1 > 0 else 0), + ureter2Position = TrackSurfacePosition(elementsCountAround // 2 - ureterElementPositionAround + (-1 if ureter1Position.xi1 > 0 else 0), ureterElementPositionDown, (1 - ureter1Position.xi1) if ureter1Position.xi1 > 0 else ureter1Position.xi1, ureter1Position.xi2) - bladderMeshGroup = [neckMeshGroup, urinaryBladderMeshGroup] + else: + elementsCountVentral1 = elementsCountAround // 4 + + # Create annotation groups for bladder and urethra + bodyGroup = AnnotationGroup(region, get_bladder_term("dome of the bladder")) + neckGroup = AnnotationGroup(region, get_bladder_term("neck of urinary bladder")) + bladderGroup = AnnotationGroup(region, get_bladder_term("urinary bladder")) + urethraGroup = AnnotationGroup(region, get_bladder_term("urethra")) + ureterGroup = AnnotationGroup(region, get_bladder_term("ureter")) + if includeUrethra: + elementsCountAlongGroups = [elementsCountAlongBody, elementsCountAlongNeck, elementsCountAlongUrethra] + annotationGroupAlong = [[bladderGroup, bodyGroup], [bladderGroup, neckGroup], [urethraGroup]] + else: + elementsCountAlongGroups = [elementsCountAlongBody, elementsCountAlongNeck] + annotationGroupAlong = [[bladderGroup, bodyGroup], [bladderGroup, neckGroup]] + + 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([]) + + annotationGroupsThroughWall = [] + for i in range(elementsCountThroughWall): + annotationGroupsThroughWall.append([]) + + neckMeshGroup = neckGroup. getMeshGroup(mesh) + bodyMeshGroup = bodyGroup.getMeshGroup(mesh) + urinaryBladderMeshGroup = bladderGroup.getMeshGroup(mesh) + urethraMeshGroup = urethraGroup. getMeshGroup(mesh) + ureterMeshGroup = ureterGroup. getMeshGroup(mesh) + + # Create nodes and elements + nextNodeIdentifier, nextElementIdentifier, annotationGroups = tubemesh.createNodesAndElements( + region, xFinal, d1Final, d2Final, d3Final, xFlat, d1Flat, d2Flat, xTexture, d1Texture, d2Texture, + elementsCountAround, elementsCountAlong, elementsCountThroughWall, + annotationGroupsAround, annotationGroupsAlong, annotationGroupsThroughWall, + firstNodeIdentifier, firstElementIdentifier, + useCubicHermiteThroughWall, useCrossDerivatives, closedProximalEnd=True) + + if includeUreter: + annotationGroups.append(ureterGroup) + + # Create annotation groups for dorsal and ventral parts of the bladder and urethra + bladderDorsalGroup = AnnotationGroup(region, get_bladder_term("dorsal part of bladder")) + bladderVentralGroup = AnnotationGroup(region, get_bladder_term("ventral part of bladder")) + dorsalBladderMeshGroup = bladderDorsalGroup.getMeshGroup(mesh) + ventralBladderMeshGroup = bladderVentralGroup.getMeshGroup(mesh) + if includeUrethra: + urethraDorsalGroup = AnnotationGroup(region, get_bladder_term("dorsal part of urethra")) + urethraVentralGroup = AnnotationGroup(region, get_bladder_term("ventral part of urethra")) + dorsalUrethraMeshGroup = urethraDorsalGroup.getMeshGroup(mesh) + ventralUrethraMeshGroup = urethraVentralGroup.getMeshGroup(mesh) + + for e2 in range(elementsCountAlong): + for e3 in range(elementsCountThroughWall): + for e1 in range(elementsCountAround): + elementIdx = e3 * elementsCountAround + e2 * elementsCountThroughWall * elementsCountAround + e1 + 1 + if e1 < elementsCountVentral1 or e1 > elementsCountAround - elementsCountVentral1 - 1: + element = mesh.findElementByIdentifier(elementIdx) + if e2 < elementsCountAlongBladder: + ventralBladderMeshGroup.addElement(element) + else: + ventralUrethraMeshGroup.addElement(element) + else: + element = mesh.findElementByIdentifier(elementIdx) + if e2 < elementsCountAlongBladder: + dorsalBladderMeshGroup.addElement(element) + else: + dorsalUrethraMeshGroup.addElement(element) + + annotationGroups.append(bladderDorsalGroup) + annotationGroups.append(bladderVentralGroup) + if includeUrethra: + annotationGroups.append(urethraDorsalGroup) + annotationGroups.append(urethraVentralGroup) + + if includeUreter: + bladderMeshGroup = [neckMeshGroup, urinaryBladderMeshGroup, dorsalBladderMeshGroup] generateUreterInlets(region, nodes, mesh, ureterDefaultOptions, elementsCountAround, elementsCountThroughWall, elementsCountAroundUreter, trackSurfaceUreter1, ureter1Position, trackSurfaceUreter2, ureter2Position, ureterElementPositionDown, ureterElementPositionAround, xFinal, d1Final, d2Final, nextNodeIdentifier, nextElementIdentifier, elementsCountUreterRadial, ureterMeshGroup, bladderMeshGroup) + # Apex annotation point + nodeIdentifier = nextNodeIdentifier + idx = 1 + element1 = mesh.findElementByIdentifier(idx) + markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal) + cache.setNode(markerPoint) + markerName.assignString(cache, 'Apex of urinary bladder') + markerLocation.assignMeshLocation(cache, element1, [0.0, 0.0, 1.0]) + fm.endChange() return annotationGroups @@ -779,9 +851,11 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): ''' # Create 2d surface mesh groups fm = region.getFieldmodule() - bodyGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("Dome of the Bladder")) + bodyGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("dome of the bladder")) neckGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("neck of urinary bladder")) urinaryBladderGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("urinary bladder")) + bladderVentralGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("ventral part of bladder")) + bladderDorsalGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("dorsal part of bladder")) mesh2d = fm.findMeshByDimension(2) @@ -801,6 +875,14 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): is_urinaryBladder_serosa = fm.createFieldAnd(is_urinaryBladder, is_exterior_face_xi3_1) is_urinaryBladder_lumen = fm.createFieldAnd(is_urinaryBladder, is_exterior_face_xi3_0) + is_dorsal_bladder = bladderDorsalGroup.getFieldElementGroup(mesh2d) + is_ventral_bladder = bladderVentralGroup.getFieldElementGroup(mesh2d) + + serosaOfUrinaryBladder = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("serosa of urinary bladder")) + serosaOfUrinaryBladder.getMeshGroup(mesh2d).addElementsConditional(is_urinaryBladder_serosa) + lumenOfUrinaryBladder = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("bladder lumen")) + lumenOfUrinaryBladder.getMeshGroup(mesh2d).addElementsConditional(is_urinaryBladder_lumen) + serosaOfBody = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("serosa of body of urinary bladder")) serosaOfBody.getMeshGroup(mesh2d).addElementsConditional(is_body_serosa) lumenOfBody = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("lumen of body of urinary bladder")) @@ -811,23 +893,87 @@ def defineFaceAnnotations(cls, region, options, annotationGroups): lumenOfNeck = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("lumen of neck of urinary bladder")) lumenOfNeck.getMeshGroup(mesh2d).addElementsConditional(is_neck_lumen) - serosaOfUrinaryBladder = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("serosa of urinary bladder")) - serosaOfUrinaryBladder.getMeshGroup(mesh2d).addElementsConditional(is_urinaryBladder_serosa) - lumenOfUrinaryBladder = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("bladder lumen")) - lumenOfUrinaryBladder.getMeshGroup(mesh2d).addElementsConditional(is_urinaryBladder_lumen) + is_bladder_serosa_dorsal = fm.createFieldAnd(is_urinaryBladder_serosa, is_dorsal_bladder) + serosaOfBladder_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of serosa of urinary bladder")) + serosaOfBladder_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_bladder_serosa_dorsal) + + is_bladder_serosa_ventral = fm.createFieldAnd(is_urinaryBladder_serosa, is_ventral_bladder) + serosaOfBladder_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of serosa of urinary bladder")) + serosaOfBladder_ventral.getMeshGroup(mesh2d).addElementsConditional(is_bladder_serosa_ventral) + + is_bladder_lumen_dorsal = fm.createFieldAnd(is_urinaryBladder_lumen, is_dorsal_bladder) + lumenOfBladder_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of bladder lumen")) + lumenOfBladder_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_bladder_lumen_dorsal) + + is_bladder_lumen_ventral = fm.createFieldAnd(is_urinaryBladder_lumen, is_ventral_bladder) + lumenOfBladder_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of bladder lumen")) + lumenOfBladder_ventral.getMeshGroup(mesh2d).addElementsConditional(is_bladder_lumen_ventral) + + is_body_serosa_dorsal = fm.createFieldAnd(is_body_serosa, is_dorsal_bladder) + serosaOfBody_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of serosa of body of urinary bladder")) + serosaOfBody_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_body_serosa_dorsal) + + is_body_serosa_ventral = fm.createFieldAnd(is_body_serosa, is_ventral_bladder) + serosaOfBody_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of serosa of body of urinary bladder")) + serosaOfBody_ventral.getMeshGroup(mesh2d).addElementsConditional(is_body_serosa_ventral) + + is_body_lumen_dorsal = fm.createFieldAnd(is_body_lumen, is_dorsal_bladder) + lumenOfBody_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of lumen of body of urinary bladder")) + lumenOfBody_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_body_lumen_dorsal) + + is_body_lumen_ventral = fm.createFieldAnd(is_body_lumen, is_ventral_bladder) + lumenOfBody_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of lumen of body of urinary bladder")) + lumenOfBody_ventral.getMeshGroup(mesh2d).addElementsConditional(is_body_lumen_ventral) + + is_neck_serosa_dorsal = fm.createFieldAnd(is_neck_serosa, is_dorsal_bladder) + serosaOfNeck_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of serosa of neck of urinary bladder")) + serosaOfNeck_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_neck_serosa_dorsal) + + is_neck_serosa_ventral = fm.createFieldAnd(is_neck_serosa, is_ventral_bladder) + serosaOfNeck_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of serosa of neck of urinary bladder")) + serosaOfNeck_ventral.getMeshGroup(mesh2d).addElementsConditional(is_neck_serosa_ventral) + + is_neck_lumen_dorsal = fm.createFieldAnd(is_neck_lumen, is_dorsal_bladder) + lumenOfNeck_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of lumen of neck of urinary bladder")) + lumenOfNeck_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_neck_lumen_dorsal) + + is_neck_lumen_ventral = fm.createFieldAnd(is_neck_lumen, is_ventral_bladder) + lumenOfNeck_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of lumen of neck of urinary bladder")) + lumenOfNeck_ventral.getMeshGroup(mesh2d).addElementsConditional(is_neck_lumen_ventral) if options['Include urethra'] == True: urethraGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("urethra")) + urethraVentralGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("ventral part of urethra")) + urethraDorsalGroup = getAnnotationGroupForTerm(annotationGroups, get_bladder_term("dorsal part of urethra")) is_urethra = urethraGroup.getFieldElementGroup(mesh2d) is_urethra_serosa = fm.createFieldAnd(is_urethra, is_exterior_face_xi3_1) is_urethra_lumen = fm.createFieldAnd(is_urethra, is_exterior_face_xi3_0) + is_dorsal_urethra = urethraDorsalGroup.getFieldElementGroup(mesh2d) + is_ventral_urethra = urethraVentralGroup.getFieldElementGroup(mesh2d) + serosaOfUrethra = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("serosa of urethra")) serosaOfUrethra.getMeshGroup(mesh2d).addElementsConditional(is_urethra_serosa) lumenOfUrethra = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("lumen of urethra")) lumenOfUrethra.getMeshGroup(mesh2d).addElementsConditional(is_urethra_lumen) + is_urethra_serosa_dorsal = fm.createFieldAnd(is_urethra_serosa, is_dorsal_urethra) + serosaOfUrethra_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of serosa of urethra")) + serosaOfUrethra_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_urethra_serosa_dorsal) + + is_urethra_serosa_ventral = fm.createFieldAnd(is_urethra_serosa, is_ventral_urethra) + serosaOfUrethra_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of serosa of urethra")) + serosaOfUrethra_ventral.getMeshGroup(mesh2d).addElementsConditional(is_urethra_serosa_ventral) + + is_urethra_lumen_dorsal = fm.createFieldAnd(is_urethra_lumen, is_dorsal_urethra) + lumenOfUrethra_dorsal = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("dorsal part of lumen of urethra")) + lumenOfUrethra_dorsal.getMeshGroup(mesh2d).addElementsConditional(is_urethra_lumen_dorsal) + + is_urethra_lumen_ventral = fm.createFieldAnd(is_urethra_lumen, is_ventral_urethra) + lumenOfUrethra_ventral = findOrCreateAnnotationGroupForTerm(annotationGroups, region, get_bladder_term("ventral part of lumen of urethra")) + lumenOfUrethra_ventral.getMeshGroup(mesh2d).addElementsConditional(is_urethra_lumen_ventral) + def generateUreterInlets(region, nodes, mesh, ureterDefaultOptions,elementsCountAround, elementsCountThroughWall, elementsCountAroundUreter, trackSurfaceUreter1, ureter1Position, trackSurfaceUreter2, ureter2Position, ureterElementPositionDown, ureterElementPositionAround,