Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lungs #101

Merged
merged 23 commits into from
Nov 20, 2020
Merged

Lungs #101

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
eda7f10
Added lungs meshtypes.
zekh167 Nov 13, 2020
4fc2e2f
Created regular elements for the left lung.
zekh167 Nov 13, 2020
6e8f67a
Created the back and front wedge elements.
zekh167 Nov 16, 2020
4a35705
Added different wedge element templates.
zekh167 Nov 16, 2020
e78f794
Added new wedge and tetrahedron element templates.
zekh167 Nov 17, 2020
e13480b
Created tetrahedron elements at the top.
zekh167 Nov 17, 2020
e808a18
Changed the lung meshtype name.
zekh167 Nov 17, 2020
6bb756c
Added lung terms.
zekh167 Nov 17, 2020
d531c3d
Added annotation groups and marker point.
zekh167 Nov 17, 2020
5a6d473
Changes two functions names.
zekh167 Nov 17, 2020
3cb481e
Added definition for the new element field templates.
zekh167 Nov 17, 2020
3c16be2
Minor change.
zekh167 Nov 17, 2020
a1fbe9a
Changed names.
zekh167 Nov 17, 2020
5a2c4c6
delet meshtype_3d_lungs1
zekh167 Nov 19, 2020
dfbf190
Deleted "getOptionScaffoldPackage".
zekh167 Nov 19, 2020
49fb6e9
Deleted "beginChange" and "endChange".
zekh167 Nov 19, 2020
18d0499
Renamed the apex.
zekh167 Nov 19, 2020
73d3a1c
Added new wedge and tetrahedron element templates.
zekh167 Nov 19, 2020
7982bde
Replaced new wedge element templates.
zekh167 Nov 19, 2020
337f95a
Replaced 1 function to create 4 cases of tetrahedron elements that th…
zekh167 Nov 19, 2020
0e03132
Converted eft6 and eft7 to the new one.
zekh167 Nov 19, 2020
b6e6086
Used the renamed functions.
zekh167 Nov 19, 2020
73995cc
Merged different functions and have only 3 for wedge and tetrahedron …
zekh167 Nov 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/scaffoldmaker/annotation/lung_terms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Common resource for lungs annotation terms.
"""

# convention: preferred name, preferred id, followed by any other ids and alternative names
lung_terms = [
("lung", "UBERON:0002048", "ILX:0726937"),
("left lung", "UBERON:0002168", "ILX:0733450"),
("right lung", "UBERON:0002167", "ILX:0729582"),
("upper lobe of left lung", "UBERON:0008952", "ILX:0735339"),
("lower lobe of left lung", "UBERON:0008953", "ILX:0735534"),
("upper lobe of right lung", "UBERON:0002170", "ILX:0728821"),
("middle lobe of right lung", "UBERON:0002174", "ILX:0733737"),
("lower lobe of right lung", "UBERON:0002171", "ILX:0725712"),
("right lung accessory lobe", "UBERON:0004890", "ILX:0728696")
]

def get_lung_term(name : str):
"""
Find term by matching name to any identifier held for a term.
Raise exception if name not found.
:return ( preferred name, preferred id )
"""
for term in lung_terms:
if name in term:
return ( term[0], term[1] )
raise NameError("Lung annotation term '" + name + "' not found.")
219 changes: 219 additions & 0 deletions src/scaffoldmaker/meshtypes/meshtype_3d_lung1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
'''
Generates 3D lung surface mesh.
'''

from scaffoldmaker.annotation.annotationgroup import AnnotationGroup
from scaffoldmaker.annotation.lung_terms import get_lung_term
from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base
from scaffoldmaker.utils.eftfactory_tricubichermite import eftfactory_tricubichermite
from opencmiss.utils.zinc.field import findOrCreateFieldCoordinates, findOrCreateFieldGroup, \
findOrCreateFieldNodeGroup, findOrCreateFieldStoredMeshLocation, findOrCreateFieldStoredString
from opencmiss.zinc.element import Element
from opencmiss.zinc.field import Field
from opencmiss.zinc.node import Node


class MeshType_3d_lung1(Scaffold_base):
'''
3D lung scaffold.
'''

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

@staticmethod
def getParameterSetNames():
return [
'Default',
'Mouse 1']

@classmethod
def getDefaultOptions(cls, parameterSetName='Default'):
options = {}
options['Base parameter set'] = parameterSetName

return options

@staticmethod
def getOrderedOptionNames():
optionNames = []
return optionNames

@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: annotationGroups
'''
fm = region.getFieldmodule()
coordinates = findOrCreateFieldCoordinates(fm)

nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
nodetemplate = nodes.createNodetemplate()
nodetemplate.defineField(coordinates)
nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_VALUE, 1)
nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS1, 1)
nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS2, 1)
nodetemplate.setValueNumberOfVersions(coordinates, -1, Node.VALUE_LABEL_D_DS3, 1)

mesh = fm.findMeshByDimension(3)
cache = fm.createFieldcache()

elementsCount1 = 2
elementsCount2 = 4
elementsCount3 = 4

# 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)

# Create nodes
nodeIdentifier = 1
lNodeIds = []
d1 = [0.5, 0.0, 0.0]
d2 = [0.0, 0.5, 0.0]
d3 = [0.0, 0.0, 1.0]
for n3 in range(elementsCount3 + 1):
lNodeIds.append([])
for n2 in range(elementsCount2 + 1):
lNodeIds[n3].append([])
for n1 in range(elementsCount1 + 1):
lNodeIds[n3][n2].append([])
if n3 < elementsCount3:
if (n1 == 0) and ((n2 == 0) or (n2 == elementsCount2)):
continue
else:
if (n2 == 0) or (n2 == elementsCount2) or (n1 == 0):
continue
node = nodes.createNode(nodeIdentifier, nodetemplate)
cache.setNode(node)
x = [0.5 * (n1 - 1), 0.5 * (n2 - 1), 1.0 * n3]
coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_VALUE, 1, x)
coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS1, 1, d1)
coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS2, 1, d2)
coordinates.setNodeParameters(cache, -1, Node.VALUE_LABEL_D_DS3, 1, d3)
lNodeIds[n3][n2][n1] = nodeIdentifier
nodeIdentifier += 1

# Create elements
mesh = fm.findMeshByDimension(3)
eftfactory = eftfactory_tricubichermite(mesh, None)
eftRegular = eftfactory.createEftBasic()

elementtemplateRegular = mesh.createElementtemplate()
elementtemplateRegular.setElementShapeType(Element.SHAPE_TYPE_CUBE)
elementtemplateRegular.defineField(coordinates, -1, eftRegular)

elementtemplateCustom = mesh.createElementtemplate()
elementtemplateCustom.setElementShapeType(Element.SHAPE_TYPE_CUBE)

lungGroup = AnnotationGroup(region, get_lung_term("lung"))
leftLungGroup = AnnotationGroup(region, get_lung_term("left lung"))
rightLungGroup = AnnotationGroup(region, get_lung_term("right lung"))
annotationGroups = [leftLungGroup, rightLungGroup, lungGroup]

lungMeshGroup = lungGroup.getMeshGroup(mesh)
leftLungMeshGroup = leftLungGroup.getMeshGroup(mesh)
rightLungMeshGroup = rightLungGroup.getMeshGroup(mesh)

eft1 = eftfactory.createEftWedgeCollapseXi1Quadrant([1, 5])
eft2 = eftfactory.createEftWedgeCollapseXi1Quadrant([3, 7])
eft3 = eftfactory.createEftWedgeCollapseXi2Quadrant([5, 6])
eft4 = eftfactory.createEftWedgeCollapseXi2Quadrant([7, 8])
eft5 = eftfactory.createEftWedgeCollapseXi1Quadrant([5, 7])
eft6 = eftfactory.createEftTetrahedronCollapseXi1Xi2Quadrant(8, 2)
eft7 = eftfactory.createEftTetrahedronCollapseXi1Xi2Quadrant(6, 3)

elementIdentifier = 1
for e3 in range(elementsCount3):
for e2 in range(elementsCount2):
for e1 in range(elementsCount1):
eft = eftRegular
nodeIdentifiers = [
lNodeIds[e3 ][e2][e1], lNodeIds[e3 ][e2][e1 + 1], lNodeIds[e3 ][e2 + 1][e1], lNodeIds[e3 ][e2 + 1][e1 + 1],
lNodeIds[e3 + 1][e2][e1], lNodeIds[e3 + 1][e2][e1 + 1], lNodeIds[e3 + 1][e2 + 1][e1], lNodeIds[e3 + 1][e2 + 1][e1 + 1]]
scalefactors = None
if (e3 < elementsCount3 - 1):
if (e2 == 0) and (e1 == 0):
# Back wedge elements
nodeIdentifiers.pop(4)
nodeIdentifiers.pop(0)
eft = eft1
scalefactors = [-1.0]
elif (e2 == elementsCount2 - 1) and (e1 == 0):
# Front wedge elements
nodeIdentifiers.pop(6)
nodeIdentifiers.pop(2)
eft = eft2
else:
if (e2 == 0) and (e1 == 1):
# Top back wedge elements
nodeIdentifiers.pop(5)
nodeIdentifiers.pop(4)
eft = eft3
elif (e2 == elementsCount2 - 1) and (e1 == 1):
# Top front wedge elements
nodeIdentifiers.pop(7)
nodeIdentifiers.pop(6)
eft = eft4
scalefactors = [-1.0]
elif (e2 == 1) and (e1 == 0):
# Top middle back wedge element
nodeIdentifiers.pop(6)
nodeIdentifiers.pop(4)
eft = eft5
elif (e2 == 2) and (e1 == 0):
# Top middle front wedge element
nodeIdentifiers.pop(6)
nodeIdentifiers.pop(4)
eft = eft5
if (e2 == 0) and (e1 == 0):
# Top back tetrahedron element
nodeIdentifiers.pop(6)
nodeIdentifiers.pop(5)
nodeIdentifiers.pop(4)
nodeIdentifiers.pop(0)
eft = eft6
scalefactors = [-1.0]
if (e2 == elementsCount2 - 1) and (e1 == 0):
# Top front tetrahedron element
nodeIdentifiers.pop(7)
nodeIdentifiers.pop(6)
nodeIdentifiers.pop(4)
nodeIdentifiers.pop(2)
eft = eft7
scalefactors = [-1.0]

if eft is eftRegular:
element = mesh.createElement(elementIdentifier, elementtemplateRegular)
else:
elementtemplateCustom.defineField(coordinates, -1, eft)
element = mesh.createElement(elementIdentifier, elementtemplateCustom)
element.setNodesByIdentifier(eft, nodeIdentifiers)
if scalefactors:
element.setScaleFactors(eft, scalefactors)
elementIdentifier += 1
leftLungMeshGroup.addElement(element)
lungMeshGroup.addElement(element)

# Apex annotation point
idx = elementsCount1 * elementsCount2 * (elementsCount3 - 1) + elementsCount1 * (elementsCount2 // 2)
element1 = mesh.findElementByIdentifier(idx)
markerPoint = markerPoints.createNode(nodeIdentifier, markerTemplateInternal)
nodeIdentifier += 1
cache.setNode(markerPoint)
markerName.assignString(cache, 'apex of left lung')
markerLocation.assignMeshLocation(cache, element1, [1.0, 1.0, 1.0])

return annotationGroups

2 changes: 2 additions & 0 deletions src/scaffoldmaker/scaffolds.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from scaffoldmaker.meshtypes.meshtype_3d_heartventriclesbase1 import MeshType_3d_heartventriclesbase1
from scaffoldmaker.meshtypes.meshtype_3d_heartventriclesbase2 import MeshType_3d_heartventriclesbase2
from scaffoldmaker.meshtypes.meshtype_3d_lens1 import MeshType_3d_lens1
from scaffoldmaker.meshtypes.meshtype_3d_lung1 import MeshType_3d_lung1
from scaffoldmaker.meshtypes.meshtype_3d_ostium1 import MeshType_3d_ostium1
from scaffoldmaker.meshtypes.meshtype_3d_smallintestine1 import MeshType_3d_smallintestine1
from scaffoldmaker.meshtypes.meshtype_3d_solidsphere1 import MeshType_3d_solidsphere1
Expand Down Expand Up @@ -72,6 +73,7 @@ def __init__(self):
MeshType_3d_heartventriclesbase1,
MeshType_3d_heartventriclesbase2,
MeshType_3d_lens1,
MeshType_3d_lung1,
MeshType_3d_ostium1,
MeshType_3d_smallintestine1,
MeshType_3d_solidsphere1,
Expand Down
Loading