Skip to content

Commit

Permalink
Merge pull request #262 from oneway1225/tubenetwork_solid_core
Browse files Browse the repository at this point in the history
Add solid core to tubenetwork mesh
  • Loading branch information
rchristie authored Aug 22, 2024
2 parents ebd9b82 + 678f488 commit da31a25
Show file tree
Hide file tree
Showing 9 changed files with 2,878 additions and 211 deletions.
2 changes: 2 additions & 0 deletions src/scaffoldmaker/annotation/body_terms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
( "core", "" ),
( "non core", "" ),
( "core boundary", "" ),
( "arm", "UBERON:0001460"),
( "leg", "UBERON:0000978")
]

def get_body_term(name : str):
Expand Down
132 changes: 114 additions & 18 deletions src/scaffoldmaker/meshtypes/meshtype_3d_tubenetwork1.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,87 @@
"""
Generates a 3-D Hermite bifurcating tube network.
Generates a 3-D Hermite bifurcating tube network (with optional solid core).
"""
from scaffoldmaker.meshtypes.meshtype_1d_network_layout1 import MeshType_1d_network_layout1
from scaffoldmaker.meshtypes.scaffold_base import Scaffold_base
from scaffoldmaker.scaffoldpackage import ScaffoldPackage
from scaffoldmaker.utils.tubenetworkmesh import TubeNetworkMeshBuilder, TubeNetworkMeshGenerateData


def calculateElementsCountAcrossMinor(cls, options):
# Calculate elementsCountAcrosMinor
elementsCountAcrossMinor = int(((options["Elements count around"] - 4) / 4 -
(options['Number of elements across core major'] / 2)) * 2 + 6)

return elementsCountAcrossMinor

def setParametersToDefault(cls, options):
options["Elements count around"] = 8
options["Number of elements across core major"] = 4
options["Number of elements across core transition"] = 1

return options

def checkCoreParameters(cls, options, dependentChanges=False):
# Check elements count around are ok
if options["Elements count around"] < 8:
dependentChanges = True
options = setParametersToDefault(cls, options)
if options["Elements count around"] % 4:
options["Elements count around"] += 4 - options["Elements count around"] % 4

# Check elements count across major are ok
if options['Number of elements across core major'] < 4:
options['Number of elements across core major'] = 4
if options['Number of elements across core major'] % 2:
options['Number of elements across core major'] += 1

# Check elements count across transition
if options['Number of elements across core transition'] < 1:
options['Number of elements across core transition'] = 1

# Calculate elementsCountAcrossMinor based on the current set of elementsCountAround and elementsCountAcrossMajor
elementsCountAcrossMinor = calculateElementsCountAcrossMinor(cls, options)

# Rcrit check
Rcrit = max(
min(options['Number of elements across core major'] - 4, elementsCountAcrossMinor - 4) // 2 + 1, 0)
if Rcrit < options['Number of elements across core transition']:
dependentChanges = True
options['Number of elements across core transition'] = Rcrit

# Number of elements around sanity check
eM = options["Number of elements across core major"]
em = elementsCountAcrossMinor
eC = (eM - 1) * (em - 1) - ((eM - 3) * (em - 3))
if options["Elements count around"] != eC:
dependentChanges = True
# Reset parameter values
setParametersToDefault(cls, options)

annotationElementsCountsAround = options["Annotation elements counts around"]
if len(annotationElementsCountsAround) == 0:
options["Annotation elements count around"] = [0]
else:
for i in range(len(annotationElementsCountsAround)):
if annotationElementsCountsAround[i] <= 0:
annotationElementsCountsAround[i] = 0
elif annotationElementsCountsAround[i] < 4:
annotationElementsCountsAround[i] = 4

if options["Use linear through wall"]:
dependentChanges = True
options["Use linear through wall"] = False

return options, dependentChanges


class MeshType_3d_tubenetwork1(Scaffold_base):
"""
Generates a 3-D hermite tube network, with linear or cubic basis through wall.
Number of elements generated are primarily controlled by "elements count around" and "elements count across major".
The elements count around parameter determines the number of elements around a circular rim.
The elements count across major determines the number of elements across the major axis of an ellipse (y-axis in the scaffold).
The number of elements across minor axis (z-axis) is calculated internally based on the two elements count parameters.
"""

@classmethod
Expand All @@ -31,7 +103,11 @@ def getDefaultOptions(cls, parameterSetName="Default"):
"Annotation elements counts around": [0],
"Target element density along longest segment": 4.0,
"Use linear through wall": False,
"Show trim surfaces": False
"Show trim surfaces": False,
"Core": False,
'Number of elements across core major': 4,
'Number of elements across core transition': 1,
"Annotation elements counts across major": [0]
}
return options

Expand All @@ -44,7 +120,11 @@ def getOrderedOptionNames():
"Annotation elements counts around",
"Target element density along longest segment",
"Use linear through wall",
"Show trim surfaces"
"Show trim surfaces",
"Core",
'Number of elements across core major',
'Number of elements across core transition',
"Annotation elements counts across major"
]

@classmethod
Expand Down Expand Up @@ -82,23 +162,33 @@ def getOptionScaffoldPackage(cls, optionName, scaffoldType, parameterSetName=Non
def checkOptions(cls, options):
if not options["Network layout"].getScaffoldType() in cls.getOptionValidScaffoldTypes("Network layout"):
options["Network layout"] = cls.getOptionScaffoldPackage("Network layout", MeshType_1d_network_layout1)
elementsCountAround = options["Elements count around"]
if options["Elements count around"] < 4:
options["Elements count around"] = 4
dependentChanges = False

# Parameters specific to the core
if options["Core"] == True:
options, dependentChanges = checkCoreParameters(cls, options, dependentChanges)

# When core option is false
else:
if options["Elements count around"] < 4:
options["Elements count around"] = 4
annotationElementsCountsAround = options["Annotation elements counts around"]
if len(annotationElementsCountsAround) == 0:
options["Annotation elements count around"] = [0]
else:
for i in range(len(annotationElementsCountsAround)):
if annotationElementsCountsAround[i] <= 0:
annotationElementsCountsAround[i] = 0
elif annotationElementsCountsAround[i] < 4:
annotationElementsCountsAround[i] = 4

# Common parameters
if options["Elements count through wall"] < 1:
options["Elements count through wall"] = 1
annotationElementsCountsAround = options["Annotation elements counts around"]
if len(annotationElementsCountsAround) == 0:
options["Annotation elements count around"] = [0]
else:
for i in range(len(annotationElementsCountsAround)):
if annotationElementsCountsAround[i] <= 0:
annotationElementsCountsAround[i] = 0
elif annotationElementsCountsAround[i] < 4:
annotationElementsCountsAround[i] = 4

if options["Target element density along longest segment"] < 1.0:
options["Target element density along longest segment"] = 1.0
dependentChanges = False

return dependentChanges

@classmethod
Expand All @@ -112,15 +202,21 @@ def generateBaseMesh(cls, region, options):
layoutRegion = region.createRegion()
networkLayout = options["Network layout"]
networkLayout.generate(layoutRegion) # ask scaffold to generate to get user-edited parameters
layoutAnnotationGroups = networkLayout.getAnnotationGroups()
networkMesh = networkLayout.getConstructionObject()

tubeNetworkMeshBuilder = TubeNetworkMeshBuilder(
networkMesh,
targetElementDensityAlongLongestSegment=options["Target element density along longest segment"],
defaultElementsCountAround=options["Elements count around"],
elementsCountThroughWall=options["Elements count through wall"],
layoutAnnotationGroups=networkLayout.getAnnotationGroups(),
annotationElementsCountsAround=options["Annotation elements counts around"])
layoutAnnotationGroups=layoutAnnotationGroups,
annotationElementsCountsAround=options["Annotation elements counts around"],
defaultElementsCountAcrossMajor=options['Number of elements across core major'],
elementsCountTransition=options['Number of elements across core transition'],
annotationElementsCountsAcrossMajor=options["Annotation elements counts across major"],
isCore=options["Core"])

tubeNetworkMeshBuilder.build()
generateData = TubeNetworkMeshGenerateData(
region, 3,
Expand Down
Loading

0 comments on commit da31a25

Please sign in to comment.