Skip to content

Commit 21afd05

Browse files
authored
Merge pull request #2629 from alicevision/dev/relativePaths
Add relative paths to nodes as variables
2 parents aa0943e + 2c06ea4 commit 21afd05

File tree

97 files changed

+212
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+212
-186
lines changed

meshroom/core/attribute.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,11 @@ def uid(self):
276276
# To guarantee that each output attribute receives a unique ID, we add the attribute name to it.
277277
return hashValue((self.name, self.node._uid))
278278
else:
279-
# only dependent on the hash of its value without the cache folder
280-
return hashValue(self._invalidationValue)
279+
# Only dependent on the hash of its value without the cache folder.
280+
# "/" at the end of the link is stripped to prevent having different UIDs depending on
281+
# whether the invalidation value finishes with it or not
282+
strippedInvalidationValue = self._invalidationValue.rstrip("/")
283+
return hashValue(strippedInvalidationValue)
281284
if self.isLink:
282285
linkParam = self.getLinkParam(recursive=True)
283286
return linkParam.uid()
@@ -362,7 +365,14 @@ def getEvalValue(self):
362365
Return the value. If it is a string, expressions will be evaluated.
363366
'''
364367
if isinstance(self.value, str):
365-
return Template(self.value).safe_substitute(os.environ)
368+
substituted = Template(self.value).safe_substitute(os.environ)
369+
try:
370+
varResolved = substituted.format(**self.node._cmdVars)
371+
return varResolved
372+
except (KeyError, IndexError):
373+
# Catch KeyErrors and IndexErros to be able to open files created prior to the support of
374+
# relative variables (when self.node._cmdVars was not used to evaluate expressions in the attribute)
375+
return substituted
366376
return self.value
367377

368378
def getValueStr(self, withQuotes=True):

meshroom/core/desc/node.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from inspect import getfile
2+
from pathlib import Path
13
import os
24
import psutil
35
import shlex
@@ -11,7 +13,6 @@
1113
class Node(object):
1214
"""
1315
"""
14-
internalFolder = '{cache}/{nodeType}/{uid}/'
1516
cpu = Level.NORMAL
1617
gpu = Level.NONE
1718
ram = Level.NORMAL
@@ -63,6 +64,7 @@ class Node(object):
6364
def __init__(self):
6465
super(Node, self).__init__()
6566
self.hasDynamicOutputAttribute = any(output.isDynamicValue for output in self.outputs)
67+
self.sourceCodeFolder = Path(getfile(self.__class__)).parent.resolve().as_posix()
6668

6769
def upgradeAttributeValues(self, attrValues, fromVersion):
6870
return attrValues

meshroom/core/node.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ def __init__(self, nodeType, position=None, parent=None, uid=None, **kwargs):
501501

502502
self.packageName = self.packageVersion = ""
503503
self._internalFolder = ""
504+
self._sourceCodeFolder = ""
504505

505506
self._name = None
506507
self.graph = None
@@ -757,6 +758,8 @@ def _buildAttributeCmdVars(cmdVars, name, attr):
757758

758759
""" Generate command variables using input attributes and resolved output attributes names and values. """
759760
self._cmdVars["uid"] = self._uid
761+
self._cmdVars["nodeCacheFolder"] = self.internalFolder
762+
self._cmdVars["nodeSourceCodeFolder"] = self.sourceCodeFolder
760763

761764
# Evaluate input params
762765
for name, attr in self._attributes.objects.items():
@@ -766,7 +769,11 @@ def _buildAttributeCmdVars(cmdVars, name, attr):
766769

767770
# For updating output attributes invalidation values
768771
cmdVarsNoCache = self._cmdVars.copy()
769-
cmdVarsNoCache['cache'] = ''
772+
cmdVarsNoCache["cache"] = ""
773+
774+
# Use "self._internalFolder" instead of "self.internalFolder" because we do not want it to be
775+
# resolved with the {cache} information ("self.internalFolder" resolves "self._internalFolder")
776+
cmdVarsNoCache["nodeCacheFolder"] = self._internalFolder.format(**cmdVarsNoCache)
770777

771778
# Evaluate output params
772779
for name, attr in self._attributes.objects.items():
@@ -1021,8 +1028,10 @@ def updateInternals(self, cacheDir=None):
10211028

10221029
# Update command variables / output attributes
10231030
self._cmdVars = {
1024-
'cache': cacheDir or self.graph.cacheDir,
1025-
'nodeType': self.nodeType,
1031+
"cache": cacheDir or self.graph.cacheDir,
1032+
"nodeType": self.nodeType,
1033+
"nodeCacheFolder": self._internalFolder,
1034+
"nodeSourceCodeFolder": self.sourceCodeFolder
10261035
}
10271036
self._computeUid()
10281037
self._buildCmdVars()
@@ -1039,6 +1048,10 @@ def updateInternalAttributes(self):
10391048
def internalFolder(self):
10401049
return self._internalFolder.format(**self._cmdVars)
10411050

1051+
@property
1052+
def sourceCodeFolder(self):
1053+
return self._sourceCodeFolder
1054+
10421055
def updateStatusFromCache(self):
10431056
"""
10441057
Update node status based on status file content/existence.
@@ -1440,7 +1453,8 @@ def __init__(self, nodeType, position=None, parent=None, uid=None, **kwargs):
14401453

14411454
self.packageName = self.nodeDesc.packageName
14421455
self.packageVersion = self.nodeDesc.packageVersion
1443-
self._internalFolder = self.nodeDesc.internalFolder
1456+
self._internalFolder = "{cache}/{nodeType}/{uid}"
1457+
self._sourceCodeFolder = self.nodeDesc.sourceCodeFolder
14441458

14451459
for attrDesc in self.nodeDesc.inputs:
14461460
self._attributes.add(attributeFactory(attrDesc, kwargs.get(attrDesc.name, None), isOutput=False, node=self))

meshroom/nodes/aliceVision/ApplyCalibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ class ApplyCalibration(desc.AVCommandLineNode):
4444
name="output",
4545
label="SMData",
4646
description="Path to the output SfMData file.",
47-
value=desc.Node.internalFolder + "sfmData.sfm",
47+
value="{nodeCacheFolder}/sfmData.sfm",
4848
),
4949
]

meshroom/nodes/aliceVision/CameraCalibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,6 @@ class CameraCalibration(desc.AVCommandLineNode):
124124
name="output",
125125
label="Output",
126126
description="Output filename for intrinsic [and extrinsic] parameters.",
127-
value=desc.Node.internalFolder + "/cameraCalibration.cal",
127+
value="{nodeCacheFolder}/cameraCalibration.cal",
128128
),
129129
]

meshroom/nodes/aliceVision/CameraInit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ class CameraInit(desc.AVCommandLineNode, desc.InitNode):
487487
name="output",
488488
label="SfMData",
489489
description="Output SfMData.",
490-
value=desc.Node.internalFolder + "cameraInit.sfm",
490+
value="{nodeCacheFolder}/cameraInit.sfm",
491491
),
492492
]
493493

@@ -671,7 +671,7 @@ def createViewpointsFile(self, node, additionalViews=()):
671671
"featureFolder": "",
672672
"matchingFolder": "",
673673
}
674-
node.viewpointsFile = os.path.join(node.nodeDesc.internalFolder, 'viewpoints.sfm').format(**node._cmdVars)
674+
node.viewpointsFile = os.path.join(node.internalFolder, 'viewpoints.sfm').format(**node._cmdVars)
675675
with open(node.viewpointsFile, 'w') as f:
676676
json.dump(sfmData, f, indent=4)
677677

meshroom/nodes/aliceVision/CameraLocalization.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,12 @@ class CameraLocalization(desc.AVCommandLineNode):
191191
name="outputAlembic",
192192
label="Alembic",
193193
description="Filename for the SfMData export file (where camera poses will be stored).",
194-
value=desc.Node.internalFolder + "trackedCameras.abc",
194+
value="{nodeCacheFolder}/trackedCameras.abc",
195195
),
196196
desc.File(
197197
name="outputJSON",
198198
label="JSON File",
199199
description="Filename for the localization results as .json.",
200-
value=desc.Node.internalFolder + "trackedCameras.json",
200+
value="{nodeCacheFolder}/trackedCameras.json",
201201
),
202202
]

meshroom/nodes/aliceVision/CameraRigCalibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,6 @@ class CameraRigCalibration(desc.AVCommandLineNode):
156156
name="outfile",
157157
label="Output File",
158158
description="The name of the file to store the calibration data in.",
159-
value=desc.Node.internalFolder + "cameraRigCalibration.rigCal",
159+
value="{nodeCacheFolder}/cameraRigCalibration.rigCal",
160160
),
161161
]

meshroom/nodes/aliceVision/CameraRigLocalization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ class CameraRigLocalization(desc.AVCommandLineNode):
162162
name="outputAlembic",
163163
label="Alembic",
164164
description="Filename for the SfMData export file (where camera poses will be stored).",
165-
value=desc.Node.internalFolder + "trackedcameras.abc",
165+
value="{nodeCacheFolder}/trackedcameras.abc",
166166
),
167167
]

meshroom/nodes/aliceVision/CheckerboardCalibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ class CheckerboardCalibration(desc.AVCommandLineNode):
4747
name="output",
4848
label="SfMData File",
4949
description="Path to the output SfMData file.",
50-
value=desc.Node.internalFolder + "sfmData.sfm",
50+
value="{nodeCacheFolder}/sfmData.sfm",
5151
)
5252
]

0 commit comments

Comments
 (0)