From 14790d4c880248f844e2d300a752511d18eeff1a Mon Sep 17 00:00:00 2001
From: Stefan Bienert <stefan.bienert@unibas.ch>
Date: Fri, 12 Jan 2024 15:47:11 +0100
Subject: [PATCH] More fine grained software parameters

---
 convert_to_modelcif.py | 126 +++++++++++++++++++++++++++++++----------
 1 file changed, 96 insertions(+), 30 deletions(-)

diff --git a/convert_to_modelcif.py b/convert_to_modelcif.py
index 974d594..27b7894 100755
--- a/convert_to_modelcif.py
+++ b/convert_to_modelcif.py
@@ -644,24 +644,74 @@ def _cast_param(val):
 
 def _get_software_with_parameters(sw_dict, other_dict):
     """Get software with versions and parameters."""
+
     # ToDo: deal with `use_mmseqs=True`
     # ToDo: should all args go to AlphaPulldown?
+    def _assemble_params(key, known_args, swwp):
+        for mthd in known_args[key]["method_type"]:
+            for tool in known_args[key]["sw"]:
+                if mthd not in swwp[tool]:
+                    swwp[tool][mthd] = {}
+                swwp[tool][mthd][f"--{key}"] = _cast_param(val)
+
     known_args = {
-        "db_preset": ["AlphaFold"],
-        "max_template_date": ["AlphaFold"],
-        "model_preset": ["AlphaFold"],
-        "num_multimer_predictions_per_model": ["AlphaFold"],
-        "plddt_threshold": ["AlphaPulldown"],
-        "hb_allowance": ["AlphaPulldown"],
-        "threshold_clashes": ["AlphaPulldown"],
-        "job_index": ["AlphaPulldown"],
-        "use_mmseqs2": ["AlphaPulldown"],
-        "skip_existing": ["AlphaPulldown"],
-        "save_msa_files": ["AlphaPulldown"],
-        "num_predictions_per_model": ["AlphaPulldown"],
-        "benchmark": ["AlphaFold", "AlphaPulldown"],
-        "use_precomputed_msas": ["AlphaFold", "AlphaPulldown"],
-        "models_to_relax": ["AlphaFold", "AlphaPulldown"],
+        "db_preset": {"sw": ["AlphaFold"], "method_type": ["coevolution MSA"]},
+        "max_template_date": {
+            "sw": ["AlphaFold"],
+            "method_type": ["coevolution MSA"],
+        },
+        "model_preset": {
+            "sw": ["AlphaFold"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "num_multimer_predictions_per_model": {
+            "sw": ["AlphaFold"],
+            "method_type": ["modeling"],
+        },
+        "plddt_threshold": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "hb_allowance": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "threshold_clashes": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "job_index": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "use_mmseqs2": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA"],
+        },
+        "skip_existing": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "save_msa_files": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "num_predictions_per_model": {
+            "sw": ["AlphaPulldown"],
+            "method_type": ["modeling"],
+        },
+        "benchmark": {
+            "sw": ["AlphaFold", "AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "use_precomputed_msas": {
+            "sw": ["AlphaFold", "AlphaPulldown"],
+            "method_type": ["coevolution MSA", "modeling"],
+        },
+        "models_to_relax": {
+            "sw": ["AlphaFold", "AlphaPulldown"],
+            "method_type": ["modeling"],
+        },
     }
     trans_args = {
         "num_multimer_predictions_per_model": "num_predictions_per_model"
@@ -717,16 +767,10 @@ def _get_software_with_parameters(sw_dict, other_dict):
     swwp = sw_dict  # Software With Parameters
     for key, val in other_dict.items():
         if key in known_args:
-            for tool in known_args[key]:
-                if "params" not in swwp[tool]:
-                    swwp[tool]["params"] = {}
-                swwp[tool]["params"][f"--{key}"] = _cast_param(val)
+            _assemble_params(key, known_args, swwp)
             if key in trans_args:
                 key = trans_args[key]
-                for tool in known_args[key]:
-                    if "params" not in swwp[tool]:
-                        swwp[tool]["params"] = {}
-                    swwp[tool]["params"][f"--{key}"] = _cast_param(val)
+                _assemble_params(key, known_args, swwp)
         else:
             if key not in ignored_args and re.match(re_args, key) is None:
                 logging.info(f"Found unknown key in 'other': {key}")
@@ -1066,28 +1110,50 @@ def _get_protocol_steps(modelcif_json):
         for tool in sftwr:
             if tool not in step["software_group"]:
                 step["software_group"].append(tool)
-                if "params" in sftwr[tool]:
-                    step["parameter_group"].append(sftwr[tool]["params"])
+                if step["method_type"] in sftwr[tool]:
+                    step["parameter_group"].append(
+                        sftwr[tool][step["method_type"]]
+                    )
                 else:
                     step["parameter_group"].append({})
+            else:
+                pos = step["software_group"].index(tool)
+                if step["method_type"] in sftwr[tool]:
+                    params = sftwr[tool][step["method_type"]]
+                else:
+                    params = {}
+                if step["parameter_group"][pos] != params:
+                    raise RuntimeError(
+                        f"Different parameters/ values for {tool}."
+                    )
+
     protocol.append(step)
 
     # modelling step
     # ToDo: Discuss input, seem to depend on mode
     # ToDo: what about step details? Would it be nice to add the AlphaPulldown
     #       mode here?
+    m_type = "modeling"
     step = {
-        "method_type": "modeling",
+        "method_type": m_type,
         "step_name": None,
         "details": None,
         "input_data_group": ["target_sequences", "STEPTYPE$coevolution MSA"],
         "output_data_group": "model",
         "software_group": ["AlphaPulldown", "AlphaFold"],
-        "parameter_group": [
-            sftwr["AlphaPulldown"]["params"],
-            sftwr["AlphaFold"]["params"],
-        ],
+        "parameter_group": [],
     }
+    for sftwr in modelcif_json["__meta__"].values():
+        sftwr = sftwr["software"]
+        for i, tool in enumerate(["AlphaPulldown", "AlphaFold"]):
+            if i >= len(step["parameter_group"]):
+                step["parameter_group"].append(sftwr[tool][m_type])
+            else:
+                if step["parameter_group"][i] != sftwr[tool][m_type]:
+                    raise RuntimeError(
+                        f"Different parameters/ values for {tool}."
+                    )
+
     protocol.append(step)
 
     # model selection step <- ask if there is automated selection, if only
-- 
GitLab