Custom template for QGIS Processing not working

Viewing 4 posts - 1 through 4 (of 4 total)
  • 30th April 2025 at 5:10 pm #34577

    I’m stuck. I’m trying to get Muster to work with the QGIS Processing Executor qgis_process.exe
    It runs fine when I execute the following command via the command line:
    C:\QGIS3\OSGeo4W.bat C:\QGIS3\apps\qgis-ltr\bin\qgis_process.exe run "umep:Outdoor Thermal Comfort: SOLWEIG" --distance_units=meters --area_units=m2 --ellipsoid=EPSG:7004 --SAVE_BUILD="False" --CYL="True" --INPUT_LC="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/LandCover_37FZ1_02.tif" --USE_LC_BUILD="False" --OUTPUT_LUP="False" --INPUT_CDSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/CDSM_37FZ1_02.tif" --LEAF_END="300" --ACTIVITY="80" --WEIGHT="75" --OUTPUT_SH="False" --INPUT_SVF="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/svfs_2025d.zip" --SEX="0" --OUTPUT_KUP="False" --LEAF_START="97" --INPUT_TDSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/TDSM_37FZ1_02.tif" --UTC="2" --INPUT_THEIGHT="25" --INPUT_HEIGHT="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/WallHeight_37FZ1_02.tif" --POSTURE="0" --TRANS_VEG="3" --OUTPUT_LDOWN="False" --EMIS_WALLS="0.9" --OUTPUT_TREEPLANTER="False" --ALBEDO_GROUND="0.15" --INPUT_DSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/DSM_37FZ1_02.tif" --AGE="35" --INPUT_DEM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/DEM_37FZ1_02.tif" --ABS_S="0.7" --ONLYGLOBAL="True" --INPUTMET="//host/public/projectfiles/UMEP_37FZ1/20220812_metdata_afternoon_only.txt" --INPUT_ASPECT="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/WallAspect_37FZ1_02.tif" --HEIGHT="180" --EMIS_GROUND="0.95" --SENSOR_HEIGHT="10" --INPUT_ANISO="" --OUTPUT_KDOWN="False" --ABS_L="0.95" --OUTPUT_TMRT="True" --CLO="0.9" --ALBEDO_WALLS="0.2" --CONIFER_TREES="False" --OUTPUT_DIR="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/OUTPUT"

    However if I try the same in Muster it throws an error

    [MUSTER]Spawning process C:\QGIS3\OSGeo4W.bat inside C:\QGIS3 using the following command line flags:
    [MUSTER]C:\QGIS3\apps\qgis-ltr\bin\qgis_process.exe run "umep:Outdoor Thermal Comfort: SOLWEIG" --distance_units=meters --area_units=m2 --ellipsoid=EPSG:7004 --SAVE_BUILD="False" --CYL="True" --INPUT_LC="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/LandCover_37FZ1_02.tif" --USE_LC_BUILD="False" --OUTPUT_LUP="False" --INPUT_CDSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/CDSM_37FZ1_02.tif" --LEAF_END="300" --ACTIVITY="80" --WEIGHT="75" --OUTPUT_SH="False" --INPUT_SVF="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/svfs_2025d.zip" --SEX="0" --OUTPUT_KUP="False" --LEAF_START="97" --INPUT_TDSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/TDSM_37FZ1_02.tif" --UTC="2" --INPUT_THEIGHT="25" --INPUT_HEIGHT="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/WallHeight_37FZ1_02.tif" --POSTURE="0" --TRANS_VEG="3" --OUTPUT_LDOWN="False" --EMIS_WALLS="0.9" --OUTPUT_TREEPLANTER="False" --ALBEDO_GROUND="0.15" --INPUT_DSM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/DSM_37FZ1_02.tif" --AGE="35" --INPUT_DEM="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/DEM_37FZ1_02.tif" --ABS_S="0.7" --ONLYGLOBAL="True" --INPUTMET="//host/public/projectfiles/UMEP_37FZ1/20220812_metdata_afternoon_only.txt" --INPUT_ASPECT="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/WallAspect_37FZ1_02.tif" --HEIGHT="180" --EMIS_GROUND="0.95" --SENSOR_HEIGHT="10" --INPUT_ANISO="" --OUTPUT_KDOWN="False" --ABS_L="0.95" --OUTPUT_TMRT="True" --CLO="0.9" --ALBEDO_WALLS="0.2" --CONIFER_TREES="False" --OUTPUT_DIR="//host/public/projectfiles/UMEP_37FZ1/37FZ1_02/1x1m/OUTPUT"
    
    The filename, directory name, or volume label syntax is incorrect.
    
    [MUSTER]Process terminated with exit code: 1

    This is the partial custom template I made.

    
    ''' Muster 8 Generic script template class ''' 
    
    ''' Import Muster base modules '''
    import MClientAPI
    import MTemplateAPI
    ''' Import Python base lib modules '''
    import os.path
    import re
    ''' Import Python additional lib modules '''
    import json
    
    ''' Get the template manager singleton '''
    manager = MTemplateAPI.MManager.getUniqueClass()
    
    ''' Define a new class derived from MTemplateAPI.MTemplate base class , override required methods '''
    class QgisProcTemplate(MTemplateAPI.MTemplate):
    	def __init__(self):
    		MTemplateAPI.MTemplate.__init__(self)
    		self.setID(1003)
    		self.setName("QGIS Processing")
    		self.setIconFilename("qgis.png")
    		self.setDescription("QGIS Processing Executor for algorithms with parameters in JSON file")
    		self.setTemplateLogic(MTemplateAPI.kTemplateSingleCommand)
    		self.setDefaultPriority(1)
    		self.setDefaultPools("renderfarm_simulation")
    		self.setDefaultExcludedPools("")
    		self.setMaximumLicenses(0)
    		self.setEnableAdditionalFlagsField(True)
    		
    		''' Submission form items allocation '''
    		qgisJSONfile = MTemplateAPI.MTemplateItemFile("JSONFILE","JSON file","Specifies JSON file with parameters to process","",0,1,1,"*.json*")
    		qgisAlgorithmID = MTemplateAPI.MTemplateItemCombo("QGISALGORITHM","Algorithm ID","Specify the algorithm id","UMEP: Outdoor Thermal Comfort: SOLWEIG v2022a",0,0,1)
    		qgisAlgorithmID.addItem("UMEP: Outdoor Thermal Comfort: SOLWEIG v2022a","umep:Outdoor Thermal Comfort: SOLWEIG")
    		qgisAlgorithmDistanceUnits = MTemplateAPI.MTemplateItemCombo("QGISALGORITHMDIST","Algorithm distance units","Specify the algorithm distance units","meters",0,0,1)
    		qgisAlgorithmDistanceUnits.addItem("Metres","meters")
    		qgisAlgorithmDistanceUnits.addItem("Kilometres","kilometers")
    		qgisAlgorithmDistanceUnits.addItem("Centimetres","centimeters")
    		qgisAlgorithmDistanceUnits.addItem("Millimetres","millimeters")
    		qgisAlgorithmDistanceUnits.addItem("Feet","feet")
    		qgisAlgorithmDistanceUnits.addItem("Miles","miles")
    		qgisAlgorithmDistanceUnits.addItem("Nautical miles","nauticalmiles")
    		qgisAlgorithmDistanceUnits.addItem("Yards","yards")
    		qgisAlgorithmDistanceUnits.addItem("Inches","inches")
    		qgisAlgorithmDistanceUnits.addItem("Degrees","degrees")
    		qgisAlgorithmAreaUnits = MTemplateAPI.MTemplateItemCombo("QGISALGORITHMAREA","Algorithm area units","Specify the algorithm area units","m2",0,0,1)
    		qgisAlgorithmAreaUnits.addItem("Square metres","m2")
    		qgisAlgorithmAreaUnits.addItem("Hectares","hectares")
    		qgisAlgorithmAreaUnits.addItem("Square kilometres","km2")
    		qgisAlgorithmAreaUnits.addItem("Square centimetres","cm2")
    		qgisAlgorithmAreaUnits.addItem("Square millimetres","mm2")
    		qgisAlgorithmAreaUnits.addItem("Square feet","ft2")
    		qgisAlgorithmAreaUnits.addItem("Square miles","mi2")
    		qgisAlgorithmAreaUnits.addItem("Square nautical miles","nm2")
    		qgisAlgorithmAreaUnits.addItem("Square yards","yd2")
    		qgisAlgorithmAreaUnits.addItem("Square inches","inch2")
    		qgisAlgorithmAreaUnits.addItem("Square degrees","deg2")
    		qgisAlgorithmEllipsoid = MTemplateAPI.MTemplateItemCombo("QGISALGORITHMCRS","Coordinate Reference System","Specify the Coordinate Reference System","EPSG:7004",0,0,1)
    		qgisAlgorithmEllipsoid.addItem("EPSG:7004","EPSG:7004")
    		
    		
    		self.addSubmissionItem(qgisJSONfile)
    		self.addSubmissionItem(qgisAlgorithmID)
    		self.addSubmissionItem(qgisAlgorithmDistanceUnits)
    		self.addSubmissionItem(qgisAlgorithmAreaUnits)
    		self.addSubmissionItem(qgisAlgorithmEllipsoid)
    		
    		''' items mapping to Muster default tags '''
    		self.addMapping("JSONFILE","job_file")
    			
    		''' Windows support '''
    		self.platformWindows.setPlatformEnabled(True)
    		self.platformWindows.setEnableErrorCheck(True)
    		self.platformWindows.setEnabledByDefault(True)
    		self.platformWindows.setDetectionLogic(MTemplateAPI.kProcessDirect)
    		self.platformWindows.setDetectionLogicProcessName("qgis_process.exe")
    			
    		applicationPath = MTemplateAPI.MTemplateItemFolder("QGISPROCPATH","QGIS Processing Excecutor path","Specifies the path to QGIS Processing Executor executable","C:\\\Program Files\\QGIS 3.40\\apps\\qgis-ltr\\bin",0,0,1)
    		self.platformWindows.addClientConfigurationItem(applicationPath)
    		startingFolderPath = MTemplateAPI.MTemplateItemFolder("QGISROOT","QGIS root folder","Specify the root folder QGIS processing","C:\\Program Files\\QGIS 3.40",0,0,1)
    		self.platformWindows.addClientConfigurationItem(startingFolderPath)
    		
    	''' virtual functions overrides '''
    
    	def onBuildCommandLine(self, platform, job, chunk, clientTemplatePreferences,instanceNum):
    		# iterate JSON file
    		json_file = job.attributeGetString(manager.resolveMappingToJob(self.getID(),"JSONFILE"))
    		
    		with open(json_file) as f:
    			json_data = json.load(f)
    		for entry in json_data: 
    			renderCmd = "C:\\QGIS3\\apps\\qgis-ltr\\bin\\qgis_process.exe"
    			renderCmd += " run"
    			renderCmd += " \"" + job.attributeGetString("QGISALGORITHM") + "\""
    			renderCmd += " --distance_units=" + job.attributeGetString("QGISALGORITHMDIST")
    			renderCmd += " --area_units=" + job.attributeGetString("QGISALGORITHMAREA")
    			renderCmd += " --ellipsoid=" + job.attributeGetString("QGISALGORITHMCRS")
    			parameters = entry["PARAMETERS"].items()
    			for param in parameters:
    				# cleanup single quotes
    				renderCmd += " --" + param[0] + "=\"" + param[1].replace("'","") + "\""
    			outputs = entry["OUTPUTS"].items()
    			for out in outputs:
    				renderCmd += " --" + out[0] + "=\"" + out[1] + "\""
    			
    		return renderCmd
    		
    	def onGetApplicationPath(self,job,chunk,clientTemplatePreferences,pathOut):
    		platform = MClientAPI.GetPlatform()
    		if platform == MClientAPI.kPlatformWindows:
    			pathOut.setString(clientTemplatePreferences['QGISROOT'] + "\\OSGeo4W.bat")
    		return MTemplateAPI.MTemplateError()
    		
    	def onGetApplicationStartingFolder(self,job,chunk,clientTemplatePreferences,pathOut):
    		pathOut.setString(clientTemplatePreferences['QGISROOT'])
    		return MTemplateAPI.MTemplateError()
    		
    == kept this section with the definitions for logging, warning and error checks the same as other templates ==
        
    ''' Create an instance of the template class and install it into the template manager context '''
    template = QgisProcTemplate()
    manager.installPyTemplate(template)
    • This topic was modified 1 month, 2 weeks ago by Aytaç.
    1st May 2025 at 10:32 am #34579

    An update about my findings. The slashes for the filepath in the json file seem to matter.
    If the slashes are forward, then I get this error: The filename, directory name, or volume label syntax is incorrect.
    If I change the slashes to backwards then I get in the activity log the following error:
    Chunk 1 belonging to job QGIStest(257) processed by host SRV089[1] reported the following error: Python template error: Traceback (most recent call last): File "qgis_proc.py", line 109, in onBuildCommandLine File "C:\Program Files\Virtual Vertex\Muster 9\Lib\json\__init__.py", line 264, in load parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw) File "C:\Program Files\Virtual Vertex\Muster 9\Lib\json\__init__.py", line 309, in loads return _default_decoder.decode(s) File "C:\Program Files\Virtual Vertex\Muster 9\Lib\json\decoder.py", line 352, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "C:\Program Files\Virtual Vertex\Muster 9\Lib\json\decoder.py", line 368, in raw_decode obj, end = self.scan_once(s, idx)ValueError: Invalid \escape: line 4 column 36 (char 67)

    Which makes senses. So I added extra backslash to escape the backslash and then I get the same error like with the slashes forward:

    
    [MUSTER]Spawning process C:\QGIS3\OSGeo4W.bat inside C:\QGIS3 using the following command line flags:
    [MUSTER]C:\QGIS3\apps\qgis-ltr\bin\qgis_process.exe run "umep:Outdoor Thermal Comfort: SOLWEIG" --distance_units=meters --area_units=m2 --ellipsoid=EPSG:7004 --SAVE_BUILD="False" --CYL="True" --INPUT_LC="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\LandCover_37FZ1_02.tif" --USE_LC_BUILD="False" --OUTPUT_LUP="False" --INPUT_CDSM="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\CDSM_37FZ1_02.tif" --LEAF_END="300" --ACTIVITY="80" --WEIGHT="75" --OUTPUT_SH="False" --INPUT_SVF="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\svfs_2025d.zip" --SEX="0" --OUTPUT_KUP="False" --LEAF_START="97" --INPUT_TDSM="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\TDSM_37FZ1_02.tif" --UTC="2" --INPUT_THEIGHT="25" --INPUT_HEIGHT="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\WallHeight_37FZ1_02.tif" --POSTURE="0" --TRANS_VEG="3" --OUTPUT_LDOWN="False" --EMIS_WALLS="0.9" --OUTPUT_TREEPLANTER="False" --ALBEDO_GROUND="0.15" --INPUT_DSM="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\DSM_37FZ1_02.tif" --AGE="35" --INPUT_DEM="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\DEM_37FZ1_02.tif" --ABS_S="0.7" --ONLYGLOBAL="True" --INPUTMET="\\host\public\projectfiles\UMEP_37FZ1\20220812_metdata_afternoon_only.txt" --INPUT_ASPECT="\\host\public\projectfiles\UMEP_37FZ1\37FZ1_02\1x1m\WallAspect_37FZ1_02.tif" --HEIGHT="180" --EMIS_GROUND="0.95" --SENSOR_HEIGHT="10" --INPUT_ANISO="" --OUTPUT_KDOWN="False" --ABS_L="0.95" --OUTPUT_TMRT="True" --CLO="0.9" --ALBEDO_WALLS="0.2" --CONIFER_TREES="False" --OUTPUT_DIR="\\host\public\projectfiles\UMEP_37FZ1\1x1m\OUTPUT"
    
    The filename, directory name, or volume label syntax is incorrect.
    
    [MUSTER]Process terminated with exit code: 1
    

    What is it with JSON and Python?

    2nd May 2025 at 6:12 pm #34580

    I found out that it is not related to JSON but somehow the command doesn’t work when there is a double quote around "umep:Outdoor Thermal Comfort: SOLWEIG" and I get the error like in the previous post. However, when I leave the quotes out then QGIS throws an error and Muster quits.

    
    Invalid parameter value Thermal. Parameter values must be entered after "--" e.g.
      Example:
        qgis_process run algorithm_name -- PARAM1=VALUE PARAM2=42"
    
    [MUSTER]Process terminated with exit code: 1
    

    I’m a bit lost on how to escape those quotes or escape the spaces in "umep:Outdoor Thermal Comfort: SOLWEIG"

    8th May 2025 at 9:10 am #34581

    Instead figuring out what to do in Muster I decided to change the code of the QGIS plugin and removed the spaces and semicolons in the name.

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.