Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
58 changes: 29 additions & 29 deletions bin/meshroom_batch
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ general_group.add_argument(
default=os.environ.get('MESHROOM_DEFAULT_PIPELINE', 'photogrammetry'),
help='Template pipeline among those listed or a Meshroom file containing a custom pipeline '
'to run on input images:\n' +
'\n'.join([' - ' + p for p in meshroom.core.pipelineTemplates]) +
'\nRequirements: the graph must contain at least one CameraInit node, and at least '
'one Publish node if --output is set.',
'\n'.join([' - ' + p for p in meshroom.core.pipelineTemplates]) +
'\nRequirements: the graph must contain one CameraInit node, and at least '
'one CopyFiles node if --output is set.',
)

general_group.add_argument(
'-o', '--output', metavar='FOLDER PUBLISH_INSTANCE=FOLDER',
'-o', '--output', metavar='FOLDER COPYFILES_INSTANCE=FOLDER',
type=str, required=False, nargs='*',
help='Output folder where results should be copied to. '
'If the output folder is provided without specifiying the instance of a Publish node, '
'all the Publish nodes in the scene will be set with the same ouput folder value. '
'If the output folder is provided without specifiying the instance of a CopyFiles node, '
'all the CopyFiles nodes in the scene will be set with the same ouput folder value. '
'If not set, results will have to be retrieved directly from the cache folder.')

general_group.add_argument(
Expand Down Expand Up @@ -151,10 +151,10 @@ with meshroom.core.graph.GraphModification(graph):
loweredPipelineTemplates = {k.lower(): v for k, v in meshroom.core.pipelineTemplates.items()}
if args.pipeline.lower() in loweredPipelineTemplates:
graph.initFromTemplate(loweredPipelineTemplates[args.pipeline.lower()],
publishOutputs=True if args.output else False)
copyOutputs=True if args.output else False)
else:
# custom pipeline
graph.initFromTemplate(args.pipeline, publishOutputs=True if args.output else False)
graph.initFromTemplate(args.pipeline, copyOutputs=True if args.output else False)

def parseInputs(inputs, uniqueInitNode):
"""Utility method for parsing the input and inputRecursive arguments."""
Expand Down Expand Up @@ -218,46 +218,46 @@ with meshroom.core.graph.GraphModification(graph):
graph.setVerbose(args.verbose)

if args.output:
# The output folders for Publish nodes can be set as follows:
# The output folders for CopyFiles nodes can be set as follows:
# - for each node, the output folder is specified following the
# "Publish_name=/output/folder/path" convention.
# - a path is provided without specifying which Publish node should be set with it:
# all the Publish nodes will be set with it.
# - some Publish nodes have their path specified, and another path is provided
# without specifying a node: all Publish nodes with dedicated will have their own
# "CopyFiles_name=/output/folder/path" convention.
# - a path is provided without specifying which CopyFiles node should be set with it:
# all the CopyFiles nodes will be set with it.
# - some CopyFiles nodes have their path specified, and another path is provided
# without specifying a node: all CopyFiles nodes with dedicated will have their own
# output folders set, and those which have not been specified will be set with the
# other path.
# - some Publish nodes have their output folder specified while others do not: all
# - some CopyFiles nodes have their output folder specified while others do not: all
# the nodes with specified folders will use the provided values, and those without
# any will be set with the output folder of the first specified Publish node.
# any will be set with the output folder of the first specified CopyFiles node.
# - several output folders are provided without specifying any node: the last one will
# be used to set all the Publish nodes' output folders.
# be used to set all the CopyFiles nodes' output folders.

# Check that there is at least one Publish node
publishNodes = graph.nodesOfType('Publish')
if len(publishNodes) == 0:
# Check that there is at least one CopyFiles node
copyNodes = graph.nodesOfType('CopyFiles')
if len(copyNodes) == 0:
raise RuntimeError('meshroom_batch requires a pipeline graph with at least ' +
'one Publish node, none found.')
'one CopyFiles node, none found.')

reExtract = re.compile(r'(\w+)=(.*)') # NodeName=value
globalPublishPath = ""
globalCopyPath = ''
for p in args.output:
result = reExtract.match(p)
if not result: # If the argument is only a path, set it for the global path
globalPublishPath = p
globalCopyPath = p
continue

node, value = result.groups()
for i, n in enumerate(publishNodes): # Find the correct Publish node in the list
for i, n in enumerate(copyNodes): # Find the correct CopyFiles node in the list
if n.name == node: # If found, set the value, and remove it from the list
n.output.value = value
publishNodes.pop(i)
if globalPublishPath == "": # Fallback in case some nodes would have no path
globalPublishPath = value
copyNodes.pop(i)
if globalCopyPath == '': # Fallback in case some nodes would have no path
globalCopyPath = value
break

for n in publishNodes: # Set the remaining Publish nodes with the global path
n.output.value = globalPublishPath
for n in copyNodes: # Set the remaining CopyPath nodes with the global path
n.output.value = globalCopyPath
else:
print(f'No output set, results will be available in the cache folder: "{graph.cacheDir}"')

Expand Down
8 changes: 4 additions & 4 deletions meshroom/core/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def load(self, filepath: PathLike):
self._deserialize(Graph._loadGraphData(filepath))
self._fileDateVersion = os.path.getmtime(filepath)

def initFromTemplate(self, filepath: PathLike, publishOutputs: bool = False):
def initFromTemplate(self, filepath: PathLike, copyOutputs: bool = False):
"""
Deserialize a template Meshroom Graph ".mg" file in place.

Expand All @@ -265,7 +265,7 @@ def initFromTemplate(self, filepath: PathLike, publishOutputs: bool = False):

Args:
filepath: The path to the Meshroom Graph file to load.
publishOutputs: (optional) Whether to keep 'Publish' nodes.
copyOutputs: (optional) Whether to keep 'CopyFiles' nodes.
"""
self._deserialize(Graph._loadGraphData(filepath))

Expand All @@ -274,9 +274,9 @@ def initFromTemplate(self, filepath: PathLike, publishOutputs: bool = False):
# node instance created by this process.
self._triggerNodeCreatedCallback(self.nodes)

if not publishOutputs:
if not copyOutputs:
with GraphModification(self):
for node in [node for node in self.nodes if node.nodeType == "Publish"]:
for node in [node for node in self.nodes if node.nodeType == "CopyFiles"]:
self.removeNode(node.name)

@staticmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,32 @@
import os


class Publish(desc.Node):
size = desc.DynamicNodeSize('inputFiles')
class CopyFiles(desc.Node):
size = desc.DynamicNodeSize("inputFiles")

category = 'Export'
documentation = '''
category = "Export"
documentation = """
This node allows to copy files into a specific folder.
'''
"""

inputs = [
desc.ListAttribute(
elementDesc=desc.File(
name="input",
label="Input",
description="File or folder to publish.",
description="File or folder to copy.",
value="",
),
name="inputFiles",
label="Input Files",
description="Input files or folders' content to publish.",
description="Input files or folders' content to copy.",
exposed=True,
group="",
),
desc.File(
name="output",
label="Output Folder",
description="Folder to publish to.",
description="Folder to copy to.",
value="",
),
desc.ChoiceParam(
Expand All @@ -51,39 +51,41 @@ def resolvedPaths(self, inputFiles, outDir):
for inputFile in inputFiles:
for f in glob.glob(inputFile.value):
if os.path.isdir(f):
paths[f] = outDir # Do not concatenate the input folder's name with the output's
# Do not concatenate the input folder's name with the output's
paths[f] = outDir
else:
paths[f] = os.path.join(outDir, os.path.basename(f))
return paths

def processChunk(self, chunk):
try:
chunk.logManager.start(chunk.node.verboseLevel.value)

if not chunk.node.inputFiles:
chunk.logger.warning('Nothing to publish')
chunk.logger.warning("No file to copy.")
return
if not chunk.node.output.value:
return

outFiles = self.resolvedPaths(chunk.node.inputFiles.value, chunk.node.output.value)

if not outFiles:
error = 'Publish: input files listed, but nothing to publish'
error = "CopyFiles: input files listed, but nothing to copy."
chunk.logger.error(error)
chunk.logger.info(f'Listed input files: {[i.value for i in chunk.node.inputFiles.value]}')
chunk.logger.info(f"Listed input files: {[i.value for i in chunk.node.inputFiles.value]}.")
raise RuntimeError(error)

if not os.path.exists(chunk.node.output.value):
os.makedirs(chunk.node.output.value)

for iFile, oFile in outFiles.items():
if os.path.isdir(iFile): # If the input is a directory, copy the directory's content
chunk.logger.info(f'Publish directory {iFile} into {oFile}')
# If the input is a directory, copy the directory's content
if os.path.isdir(iFile):
chunk.logger.info(f"CopyFiles directory {iFile} into {oFile}.")
du.copy_tree(iFile, oFile)
else:
chunk.logger.info(f'Publish file {iFile} into {oFile}')
chunk.logger.info(f"CopyFiles file {iFile} into {oFile}.")
shutil.copyfile(iFile, oFile)
chunk.logger.info('Publish end')
chunk.logger.info("CopyFiles end.")
finally:
chunk.logManager.end()
4 changes: 2 additions & 2 deletions meshroom/ui/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,10 +469,10 @@ def loadGraph(self, filepath):
self.setGraph(g)

@Slot(str, bool, result=bool)
def initFromTemplate(self, filepath, publishOutputs=False):
def initFromTemplate(self, filepath, copyOutputs=False):
graph = Graph("")
if filepath:
graph.initFromTemplate(filepath, publishOutputs=publishOutputs)
graph.initFromTemplate(filepath, copyOutputs=copyOutputs)
self.setGraph(graph)

@Slot(QUrl, result="QVariantList")
Expand Down
2 changes: 1 addition & 1 deletion meshroom/ui/qml/Application.qml
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ Page {
Action {
id: loadTemplateAction

property string tooltip: "Load a template like a regular project file (any \"Publish\" node will be displayed)"
property string tooltip: "Load a template like a regular project file (any \"CopyFiles\" node will be displayed)"
text: "Load Template"
onTriggered: {
ensureSaved(function() {
Expand Down
Loading