Skip to content

Commit

Permalink
Simplify major/minor count calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
rchristie committed Sep 12, 2024
1 parent 8dd5c59 commit 15ff322
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 59 deletions.
20 changes: 9 additions & 11 deletions src/scaffoldmaker/meshtypes/meshtype_3d_tubenetwork1.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
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 (
calculateElementsCountAcrossMinor, TubeNetworkMeshBuilder, TubeNetworkMeshGenerateData)
from scaffoldmaker.utils.tubenetworkmesh import TubeNetworkMeshBuilder, TubeNetworkMeshGenerateData


class MeshType_3d_tubenetwork1(Scaffold_base):
Expand Down Expand Up @@ -202,20 +201,19 @@ def generateBaseMesh(cls, region, options):
networkMesh = networkLayout.getConstructionObject()

defaultAroundCount = options["Number of elements around"]
elementsCountTransition = options["Number of elements across core transition"]
coreTransitionCount = options["Number of elements across core transition"]
defaultCoreBoxMinorCount = options["Number of elements across core box minor"]
defaultElementsCountAcrossMajor = calculateElementsCountAcrossMinor(
defaultAroundCount, elementsCountTransition, defaultCoreBoxMinorCount + 2 * elementsCountTransition)
# implementation currently uses major count including transition
defaultCoreMajorCount = defaultAroundCount // 2 - defaultCoreBoxMinorCount + 2 * coreTransitionCount
annotationAroundCounts = options["Annotation numbers of elements around"]
annotationCoreBoxMinorCounts = options["Annotation numbers of elements across core box minor"]
annotationElementsCountsAcrossMajor = []
annotationCoreMajorCounts = []
for i in range(len(annotationCoreBoxMinorCounts)):
aroundCount = annotationAroundCounts[i] if annotationAroundCounts[i] \
else defaultAroundCount
coreBoxMinorCount = annotationCoreBoxMinorCounts[i] if annotationCoreBoxMinorCounts[i] \
else defaultCoreBoxMinorCount
annotationElementsCountsAcrossMajor.append(calculateElementsCountAcrossMinor(
aroundCount, elementsCountTransition, coreBoxMinorCount + 2 * elementsCountTransition))
annotationCoreMajorCounts.append(aroundCount // 2 - coreBoxMinorCount + 2 * coreTransitionCount)

tubeNetworkMeshBuilder = TubeNetworkMeshBuilder(
networkMesh,
Expand All @@ -224,9 +222,9 @@ def generateBaseMesh(cls, region, options):
elementsCountThroughWall=options["Number of elements through shell"],
layoutAnnotationGroups=layoutAnnotationGroups,
annotationElementsCountsAround=annotationAroundCounts,
defaultElementsCountAcrossMajor=defaultElementsCountAcrossMajor,
elementsCountTransition=elementsCountTransition,
annotationElementsCountsAcrossMajor=annotationElementsCountsAcrossMajor,
defaultElementsCountAcrossMajor=defaultCoreMajorCount,
elementsCountTransition=coreTransitionCount,
annotationElementsCountsAcrossMajor=annotationCoreMajorCounts,
isCore=options["Core"])

tubeNetworkMeshBuilder.build()
Expand Down
54 changes: 24 additions & 30 deletions src/scaffoldmaker/meshtypes/meshtype_3d_wholebody2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
from scaffoldmaker.annotation.annotationgroup import AnnotationGroup, findOrCreateAnnotationGroupForTerm, \
getAnnotationGroupForTerm
from scaffoldmaker.annotation.body_terms import get_body_term
from scaffoldmaker.utils.tubenetworkmesh import (
calculateElementsCountAcrossMinor, TubeNetworkMeshBuilder, TubeNetworkMeshGenerateData)
from scaffoldmaker.utils.tubenetworkmesh import TubeNetworkMeshBuilder, TubeNetworkMeshGenerateData
from scaffoldmaker.utils.zinc_utils import exnode_string_from_nodeset_field_parameters
from cmlibs.zinc.node import Node

Expand Down Expand Up @@ -199,7 +198,7 @@ def getDefaultNetworkLayoutScaffoldPackage(cls, parameterSetName):

class MeshType_3d_wholebody2(Scaffold_base):
"""
Generates a 3-D hermite bifurcating tube network, with linear basis through wall.
Generates a 3-D hermite bifurcating tube network with core representing the human body.
"""

@classmethod
Expand All @@ -226,7 +225,7 @@ def getDefaultOptions(cls, parameterSetName="Default"):
"Number of elements around torso": 12,
"Number of elements around arm": 8,
"Number of elements around leg": 8,
"Number of elements through wall": 1,
"Number of elements through shell": 1,
"Target element density along longest segment": 5.0,
"Show trim surfaces": False,
"Use Core": True,
Expand All @@ -246,7 +245,7 @@ def getDefaultOptions(cls, parameterSetName="Default"):
options["Number of elements around torso"] = 24
options["Number of elements around arm"] = 12
options["Number of elements around leg"] = 16
options["Number of elements through wall"] = 2
options["Number of elements through shell"] = 1
options["Target element density along longest segment"] = 10.0
options["Number of elements across core box minor"] = 4

Expand All @@ -260,7 +259,7 @@ def getOrderedOptionNames(cls):
"Number of elements around torso",
"Number of elements around arm",
"Number of elements around leg",
"Number of elements through wall",
"Number of elements through shell",
"Target element density along longest segment",
"Show trim surfaces",
"Use Core",
Expand Down Expand Up @@ -318,20 +317,16 @@ def checkOptions(cls, options):
if (minElementsCountAround is None) or (options[key] < minElementsCountAround):
minElementsCountAround = options[key]

if options["Number of elements through wall"] < 0:
options["Number of elements through wall"] = 1
if options["Number of elements through shell"] < 0:
options["Number of elements through shell"] = 1

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

if options["Number of elements across core transition"] < 1:
options["Number of elements across core transition"] = 1

elementsCountCoreTransition = options['Number of elements across core transition']
maxElementsCountCoreBoxMinor = calculateElementsCountAcrossMinor(
minElementsCountAround, elementsCountCoreTransition, 2 + 2 * elementsCountCoreTransition) \
- 2 * elementsCountCoreTransition

maxElementsCountCoreBoxMinor = minElementsCountAround // 2 - 2
for key in [
"Number of elements across core box minor"
]:
Expand Down Expand Up @@ -362,34 +357,33 @@ def generateBaseMesh(cls, region, options):
layoutAnnotationGroups = networkLayout.getAnnotationGroups()
networkMesh = networkLayout.getConstructionObject()

elementsCountCoreBoxMinor = options["Number of elements across core box minor"]
elementsCountCoreTransition = options['Number of elements across core transition']
elementsCountCoreMinor = elementsCountCoreBoxMinor + 2 * elementsCountCoreTransition
annotationElementsCountsAround = []
annotationElementsCountsAcross = []
coreBoxMinorCount = options["Number of elements across core box minor"]
coreTransitionCount = options['Number of elements across core transition']
annotationAroundCounts = []
# implementation currently uses major count including transition
annotationCoreMajorCounts = []
for layoutAnnotationGroup in layoutAnnotationGroups:
elementsCountAround = 0
elementsCountCoreMajor = 0
aroundCount = 0
coreMajorCount = 0
name = layoutAnnotationGroup.getName()
if name in ["head", "torso", "arm", "leg"]:
elementsCountAround = options["Number of elements around " + name]
elementsCountCoreMajor = calculateElementsCountAcrossMinor(
elementsCountAround, elementsCountCoreTransition, elementsCountCoreMinor)
annotationElementsCountsAround.append(elementsCountAround)
annotationElementsCountsAcross.append(elementsCountCoreMajor)
aroundCount = options["Number of elements around " + name]
coreMajorCount = aroundCount // 2 - coreBoxMinorCount + 2 * coreTransitionCount
annotationAroundCounts.append(aroundCount)
annotationCoreMajorCounts.append(coreMajorCount)

isCore = options["Use Core"]

tubeNetworkMeshBuilder = TubeNetworkMeshBuilder(
networkMesh,
targetElementDensityAlongLongestSegment=options["Target element density along longest segment"],
defaultElementsCountAround=options["Number of elements around head"],
elementsCountThroughWall=options["Number of elements through wall"],
elementsCountThroughWall=options["Number of elements through shell"],
layoutAnnotationGroups=layoutAnnotationGroups,
annotationElementsCountsAround=annotationElementsCountsAround,
defaultElementsCountAcrossMajor=annotationElementsCountsAcross[-1],
elementsCountTransition=elementsCountCoreTransition,
annotationElementsCountsAcrossMajor=annotationElementsCountsAcross,
annotationElementsCountsAround=annotationAroundCounts,
defaultElementsCountAcrossMajor=annotationCoreMajorCounts[-1],
elementsCountTransition=coreTransitionCount,
annotationElementsCountsAcrossMajor=annotationCoreMajorCounts,
isCore=isCore)

tubeNetworkMeshBuilder.build()
Expand Down
19 changes: 3 additions & 16 deletions src/scaffoldmaker/utils/tubenetworkmesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ def __init__(self, networkSegment, pathParametersList, elementsCountAround, elem
super(TubeNetworkMeshSegment, self).__init__(networkSegment, pathParametersList)
self._isCore = isCore
self._elementsCountAround = elementsCountAround
self._elementsCountAcrossMajor = elementsCountAcrossMajor
self._elementsCountAcrossMinor = calculateElementsCountAcrossMinor(
elementsCountAround, elementsCountTransition, elementsCountAcrossMajor)
self._elementsCountAcrossMajor = elementsCountAcrossMajor # includes 2 * elementsCountTransition
self._elementsCountAcrossMinor = \
self._elementsCountAround // 2 - elementsCountAcrossMajor + 4 * elementsCountTransition
self._elementsCountTransition = elementsCountTransition

# if self._isCore and self._elementsCountTransition > 1:
Expand Down Expand Up @@ -2882,16 +2882,3 @@ def resampleTubeCoordinates(rawTubeCoordinates, fixedElementsCountAlong=None,
sd1[p] = smoothCubicHermiteDerivativesLoop(sx[p], td1, fixAllDirections=True)

return sx, sd1, sd2, sd12


def calculateElementsCountAcrossMinor(elementsCountAround, elementsCountTransition, elementsCountAcrossMajor):
"""
Calculate number of elements across minor axis of shield mesh based on number around, number of radial
transition elements, and number of elements across major.
Assumes these can work together.
:param elementsCountAround: Number of elements around the circumference.
:param elementsCountTransition: Number of transition layers between the core box and the outside.
:param elementsCountAcrossMajor: Number of elements across the major axis.
:return: Number of elements across the minor axis.
"""
return elementsCountAround // 2 + 4 * elementsCountTransition - elementsCountAcrossMajor
4 changes: 2 additions & 2 deletions tests/test_wholebody2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_wholebody2_core(self):
self.assertEqual(12, options["Number of elements around torso"])
self.assertEqual(8, options["Number of elements around arm"])
self.assertEqual(8, options["Number of elements around leg"])
self.assertEqual(1, options["Number of elements through wall"])
self.assertEqual(1, options["Number of elements through shell"])
self.assertEqual(5.0, options["Target element density along longest segment"])
self.assertEqual(False, options["Show trim surfaces"])
self.assertEqual(True, options["Use Core"])
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_wholebody2_tube(self):
self.assertEqual(12, options["Number of elements around torso"])
self.assertEqual(8, options["Number of elements around arm"])
self.assertEqual(8, options["Number of elements around leg"])
self.assertEqual(1, options["Number of elements through wall"])
self.assertEqual(1, options["Number of elements through shell"])
self.assertEqual(5.0, options["Target element density along longest segment"])
self.assertEqual(False, options["Show trim surfaces"])
self.assertEqual(True, options["Use Core"])
Expand Down

0 comments on commit 15ff322

Please sign in to comment.