feat(add protpardelle): Add the Protpardelle-1c cc89 protein generative model.#300
feat(add protpardelle): Add the Protpardelle-1c cc89 protein generative model.#300marcuscollins wants to merge 25 commits into
Conversation
📝 WalkthroughWalkthroughAdds a Protpardelle model wrapper, guidance and CLI integration, Pixi environments and dependencies, a packaged training configuration, availability checks, and tests. Guidance configuration and grid-search job metadata consistently use ChangesProtpardelle model integration
Guidance configuration and execution
Packaging and regression coverage
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (8)
src/sampleworks/utils/guidance_script_arguments.py (2)
619-619: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDocstring is not NumPy-style.
Only a one-line summary is provided; no
Parameterssection documentingparser. As per coding guidelines, "**/*: Always include NumPy-style docstrings for every function and class."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/utils/guidance_script_arguments.py` at line 619, The docstring on the Protpardelle guidance argument helper is missing the required NumPy-style format, so update the function docstring in guidance_script_arguments.py to document the parser parameter with a proper Parameters section and keep the one-line summary concise. Use the nearby function that adds CLI arguments for Protpardelle guidance runs as the target, and make the docstring consistent with the rest of the module’s NumPy-style documentation.Source: Coding guidelines
648-651: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueInconsistent boolean flag conventions.
--protpardelle-sidechain-modeand--protpardelle-jump-stepsuse plainstore_true(no way to explicitly disable via CLI), while--protpardelle-uniform-stepsusesBooleanOptionalAction. Consider standardizing onBooleanOptionalActionfor all protpardelle boolean flags for a consistent, explicit CLI surface.Also applies to: 658-662, 663-668
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/utils/guidance_script_arguments.py` around lines 648 - 651, The Protpardelle CLI boolean flags are inconsistent: `--protpardelle-sidechain-mode` and `--protpardelle-jump-steps` currently use `store_true`, while `--protpardelle-uniform-steps` uses `BooleanOptionalAction`. Update the argument definitions in the guidance script parser so all Protpardelle boolean options use the same boolean optional pattern, giving users explicit enable/disable forms. Keep the existing flag names and help text behavior aligned across the related parser entries.src/sampleworks/cli/guidance.py (1)
10-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a NumPy-style docstring to
main.This changed function currently has no docstring.
Proposed docstring
def main(argv: list[str] | None = None) -> int: + """Run the guidance CLI. + + Parameters + ---------- + argv + Optional command-line arguments. When ``None``, arguments are read from + the process command line. + + Returns + ------- + int + Process exit code from the guidance run. + """ config = GuidanceConfig.from_cli(argv)As per coding guidelines,
**/*: Always include NumPy-style docstrings for every function and class.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/cli/guidance.py` around lines 10 - 17, Add a NumPy-style docstring to the main function in guidance.py. Document the argv parameter and the integer return value, and keep the docstring aligned with the existing main/GuidanceConfig.from_cli/run_guidance flow so the function follows the project’s required docstring standard.Source: Coding guidelines
src/sampleworks/utils/guidance_script_utils.py (1)
184-197: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a NumPy-style docstring for
get_model_and_device.This changed docstring currently uses
Arguments:and omits a NumPy-styleReturnssection.Proposed docstring shape
- Arguments: - device_str: The device to use, e.g. "cuda:0" or "cpu". - model_checkpoint_path: The path to the model checkpoint. - model_type: The type of model to use. - config: The configuration object, usually GuidanceConfig, from which extra - model-specific settings are read, e.g. a path to a YAML config file. - model: The model to use, if provided, helps to prevent re-loading the actual weights. + Parameters + ---------- + device_str + Device to use, e.g. ``"cuda:0"`` or ``"cpu"``. + model_checkpoint_path + Path to the model checkpoint. + model_type + Type of model to use. + config + Configuration object with model-specific settings. + model + Pre-loaded model to reuse, when supported by the wrapper. + + Returns + ------- + tuple[torch.device, Any] + Selected device and constructed model wrapper.As per coding guidelines,
**/*: Always include NumPy-style docstrings for every function and class.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/utils/guidance_script_utils.py` around lines 184 - 197, The `get_model_and_device` docstring is not following the required NumPy style because it uses `Arguments:` and is missing a `Returns` section. Update the docstring in `guidance_script_utils` for `get_model_and_device` to use standard NumPy-style sections (`Parameters`, `Returns`, and any needed `Raises`), keeping the existing parameter descriptions but reformatted to match the project’s docstring conventions.Source: Coding guidelines
pyproject.toml (1)
64-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRedundant
pandasdependency-override.
pandas = "==2.3.1"is pinned both under[tool.pixi.feature.protpardelle.pypi-options.dependency-overrides](line 65) and the workspace-level[tool.pixi.pypi-options.dependency-overrides](line 187). Having the same override declared in two places invites drift if one is updated but not the other.Also applies to: 182-188
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pyproject.toml` around lines 64 - 65, The pandas override is duplicated in both the feature-level dependency-overrides block and the workspace-level dependency-overrides block, which can drift over time. Remove the redundant `pandas = "==2.3.1"` entry from one place and keep the override defined in a single authoritative location, checking the `[tool.pixi.feature.protpardelle.pypi-options.dependency-overrides]` and `[tool.pixi.pypi-options.dependency-overrides]` sections for consistency.src/sampleworks/models/protpardelle/wrapper.py (3)
134-139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing NumPy-style docstrings.
__setattr__and thedeviceproperty have no docstrings, unlike the rest of the file.
As per coding guidelines,**/*: "Always include NumPy-style docstrings for every function and class."📝 Proposed docstrings
def __setattr__(self, key, value): + """Raise if a frozen conditioning field is reassigned after construction.""" if key in self._FROZEN and getattr(self, "_initialized", False):`@property` def device(self) -> torch.device: + """torch.device: Device the wrapped model and its tensors live on.""" return self._deviceAlso applies to: 347-349
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 134 - 139, Add NumPy-style docstrings to the wrapper’s __setattr__ method and the device property so they match the rest of the module’s documentation style. Update the __setattr__ definition to include a short summary plus Parameters/Returns/Raises as appropriate, and add the same for the device property accessor (and setter if present) using the unique symbols __setattr__ and device to locate the spots.Source: Coding guidelines
55-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winModule-level file I/O at import time.
Reading and parsing the default sampling YAML happens unconditionally when this module is imported. This means every availability check in
imports.py(which importsProtpardelleWrapperjust to test importability) also pays this I/O cost, and it makes the module harder to unit-test/mock in isolation (any missing/corrupt file fails the whole import rather than a specific call).Consider lazily loading and caching these defaults (e.g., via
functools.lru_cacheon a small loader function) instead of doing it at module scope.♻️ Proposed lazy-loading refactor
-# get default model configurations from protpardelle-1c/cc89 -sampling_partial_diffusion_all_atom = files("protpardelle").joinpath( - "configs/running/sampling_partial_diffusion_allatom.yaml" -) -with open(str(sampling_partial_diffusion_all_atom), "r") as f: - DEFAULT_CONFIG = yaml.safe_load(f) - -DEFAULT_CONDITIONAL_CFG: dict[str, Any] = DEFAULT_CONFIG["sampling"]["conditional_cfg"] -DEFAULT_PARTIAL_DIFFUSION: dict[str, Any] = DEFAULT_CONFIG["sampling"]["partial_diffusion"] +@functools.lru_cache(maxsize=1) +def _load_default_sampling_config() -> dict[str, Any]: + """Lazily load and cache the default sampling config from the protpardelle package.""" + path = files("protpardelle").joinpath("configs/running/sampling_partial_diffusion_allatom.yaml") + with open(str(path), "r") as f: + return yaml.safe_load(f)["sampling"]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 55 - 62, The module-level YAML read in ProtpardelleWrapper is happening at import time, which makes import checks and tests pay unnecessary I/O and fail on missing files. Move the sampling config load out of the module scope into a small helper in wrapper.py, and cache it with a lazy mechanism such as a loader function used by the DEFAULT_CONFIG/DEFAULT_CONDITIONAL_CFG/DEFAULT_PARTIAL_DIFFUSION access path so ProtpardelleWrapper only reads the file when those defaults are actually needed.
692-714: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSelf-conditioning gate should not use a magic threshold.
self_cond_train_probis the only training-time signal here, so> 0.5will skipstruct_self_condfor any model trained with self-conditioning below that rate. Use an explicit config flag if available, or gate on the intended probability instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 692 - 714, The self-conditioning decision in the model.forward call is using a hardcoded > 0.5 threshold on self_cond_train_prob, which can incorrectly disable struct_self_cond for valid models. Update the gating logic in wrapper.py around self.model.forward to use an explicit config flag if one exists, or otherwise base the decision directly on the intended self-conditioning setting from self.model.config.train.self_cond_train_prob rather than a magic threshold.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/sampleworks/data/cc89_epoch415.yaml`:
- Around line 10-11: The bundled Protpardelle config includes developer-local
absolute paths that will ship into installs and break portability. Update the
cc89_epoch415 YAML to remove the `/scratch/users/...` style values and replace
`pdb_paths`, `full_mpnn_model_path`, `ckpt_path`, and `shapes_path` with
package-relative resource references or safe empty defaults. Use the existing
config keys in cc89_epoch415 to locate and change these defaults so the package
no longer depends on local filesystem paths.
In `@src/sampleworks/models/protpardelle/wrapper.py`:
- Line 664: The docstring/type reference for the features parameter is copied
from the wrong model type and should match the wrapper’s actual conditioning
type. Update the documentation around the relevant parameter in wrapper.py to
reference ProtpardelleConditioning instead of BoltzConditioning, keeping it
consistent with the rest of the wrapper and the associated parameter
annotations.
In `@src/sampleworks/utils/guidance_script_utils.py`:
- Around line 252-256: The `get_model_and_device(..., model=...)` reuse path is
being dropped in the `ProtpardelleWrapper` construction, so the preloaded model
is never forwarded and weights are reloaded. Update the `model_wrapper`
instantiation in the `guidance_script_utils` branch to pass through the existing
`model` argument to `ProtpardelleWrapper.__init__`, alongside the current
config, checkpoint, and device values, so the wrapper can reuse the
already-loaded model when provided.
- Around line 69-72: The Protpardelle import warning text in the guidance script
is missing a space before the environment variable name, causing the sentence to
run together and reducing readability. Update the string assembly in the
Protpardelle import warning message so the mention of the environment variable
is properly separated from the preceding word, keeping the message clear in the
Protpardelle-related import path.
---
Nitpick comments:
In `@pyproject.toml`:
- Around line 64-65: The pandas override is duplicated in both the feature-level
dependency-overrides block and the workspace-level dependency-overrides block,
which can drift over time. Remove the redundant `pandas = "==2.3.1"` entry from
one place and keep the override defined in a single authoritative location,
checking the
`[tool.pixi.feature.protpardelle.pypi-options.dependency-overrides]` and
`[tool.pixi.pypi-options.dependency-overrides]` sections for consistency.
In `@src/sampleworks/cli/guidance.py`:
- Around line 10-17: Add a NumPy-style docstring to the main function in
guidance.py. Document the argv parameter and the integer return value, and keep
the docstring aligned with the existing
main/GuidanceConfig.from_cli/run_guidance flow so the function follows the
project’s required docstring standard.
In `@src/sampleworks/models/protpardelle/wrapper.py`:
- Around line 134-139: Add NumPy-style docstrings to the wrapper’s __setattr__
method and the device property so they match the rest of the module’s
documentation style. Update the __setattr__ definition to include a short
summary plus Parameters/Returns/Raises as appropriate, and add the same for the
device property accessor (and setter if present) using the unique symbols
__setattr__ and device to locate the spots.
- Around line 55-62: The module-level YAML read in ProtpardelleWrapper is
happening at import time, which makes import checks and tests pay unnecessary
I/O and fail on missing files. Move the sampling config load out of the module
scope into a small helper in wrapper.py, and cache it with a lazy mechanism such
as a loader function used by the
DEFAULT_CONFIG/DEFAULT_CONDITIONAL_CFG/DEFAULT_PARTIAL_DIFFUSION access path so
ProtpardelleWrapper only reads the file when those defaults are actually needed.
- Around line 692-714: The self-conditioning decision in the model.forward call
is using a hardcoded > 0.5 threshold on self_cond_train_prob, which can
incorrectly disable struct_self_cond for valid models. Update the gating logic
in wrapper.py around self.model.forward to use an explicit config flag if one
exists, or otherwise base the decision directly on the intended
self-conditioning setting from self.model.config.train.self_cond_train_prob
rather than a magic threshold.
In `@src/sampleworks/utils/guidance_script_arguments.py`:
- Line 619: The docstring on the Protpardelle guidance argument helper is
missing the required NumPy-style format, so update the function docstring in
guidance_script_arguments.py to document the parser parameter with a proper
Parameters section and keep the one-line summary concise. Use the nearby
function that adds CLI arguments for Protpardelle guidance runs as the target,
and make the docstring consistent with the rest of the module’s NumPy-style
documentation.
- Around line 648-651: The Protpardelle CLI boolean flags are inconsistent:
`--protpardelle-sidechain-mode` and `--protpardelle-jump-steps` currently use
`store_true`, while `--protpardelle-uniform-steps` uses `BooleanOptionalAction`.
Update the argument definitions in the guidance script parser so all
Protpardelle boolean options use the same boolean optional pattern, giving users
explicit enable/disable forms. Keep the existing flag names and help text
behavior aligned across the related parser entries.
In `@src/sampleworks/utils/guidance_script_utils.py`:
- Around line 184-197: The `get_model_and_device` docstring is not following the
required NumPy style because it uses `Arguments:` and is missing a `Returns`
section. Update the docstring in `guidance_script_utils` for
`get_model_and_device` to use standard NumPy-style sections (`Parameters`,
`Returns`, and any needed `Raises`), keeping the existing parameter descriptions
but reformatted to match the project’s docstring conventions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c9f36ab8-9000-4ad9-bda2-59022088c5f3
⛔ Files ignored due to path filters (1)
pixi.lockis excluded by!**/*.lock
📒 Files selected for processing (16)
.actlignorepyproject.tomlsrc/sampleworks/cli/guidance.pysrc/sampleworks/core/samplers/edm.pysrc/sampleworks/data/cc89_epoch415.yamlsrc/sampleworks/models/protpardelle/__init__.pysrc/sampleworks/models/protpardelle/wrapper.pysrc/sampleworks/utils/guidance_constants.pysrc/sampleworks/utils/guidance_script_arguments.pysrc/sampleworks/utils/guidance_script_utils.pysrc/sampleworks/utils/imports.pytests/cli/test_guidance_cli.pytests/models/protpardelle/__init__.pytests/models/protpardelle/conftest.pytests/models/protpardelle/test_protpardelle_wrapper.pytests/runs/test_runner.py
k-chrispens
left a comment
There was a problem hiding this comment.
Looks good!! A few downstream issues we should track. Another main concern is that we don't have a GPU test for this, which will be important for integration and regressions down the line. We should also add this to the list of modelwrappers in tests/conftest.py so it gets passed through the current integration tests
|
|
||
| from loguru import logger | ||
|
|
||
| from sampleworks.utils.guidance_script_utils import get_model_and_device, run_guidance |
There was a problem hiding this comment.
A quick question, why should we import it here not at the starting of the file?
There was a problem hiding this comment.
@smallfishabc Good question, I think something must have gotten messed up with the commit history, like a rebase was missed somewhere. I shouldn't need to change this file at all.
In general, imports inside functions are made to speed things up--e.g. if I only needed to import something when one particular function was called, and it was a slow import, I might guard it like this.
There was a problem hiding this comment.
Oh, I see what's going on.... Hmmm. This is a change I should have made separately, but it had to do with reconciling arguments across the different models (protenix, protpardelle, rf3, boltz1/2)
DorisMai
left a comment
There was a problem hiding this comment.
I have some confusion points about ProtpardelleWrapper, the main one is probably regarding the topology, as other things might get sorted out in future prs.
| # This should be the way to make the atom mask: | ||
| # atom_mask = atom37_mask_from_aatype(aatype, seq_mask) but it doesn't handle OXT, so: | ||
| atom_mask = torch.zeros( | ||
| (padded_len, ATOM37_NUM_ATOMS), dtype=torch.float, device=self.device | ||
| ) | ||
| atom_mask[atom37_residue_index, atom37_atom_index] = 1 |
There was a problem hiding this comment.
What happens if the input reference structure has missing atoms? it seems that the num_atom count from this atom_mask would be different from that using other models?
There was a problem hiding this comment.
@DorisMai do you mean what happens if we try to align this structure to the reference? We only convert to (and from) the atom37 layout inside ProtpardelleWrapper.step, the alignment is done inside AF3EDMSampler.step, the same for all models, and the reconciler Karson created handles this by aligning only on atoms the two have in common.
It turns out atom_mask's only use is to convert back from atom37 to "normal" coordinates.
| # Contiguous residue ordinal (0..L-1) per atom, in atom order across chains. | ||
| residue_starts = struc.get_residue_starts(atom_array) | ||
| is_start = np.zeros(len(atom_names), dtype=np.int64) | ||
| is_start[residue_starts] = 1 | ||
| residue_ordinals = np.cumsum(is_start) - 1 |
There was a problem hiding this comment.
same concern as before (line 418-423), if there are missing residues (flexible loop), would this numbering be off then? might be good to add a real structure test in addition to the existing toy/minimal ones.
There was a problem hiding this comment.
This is only used to map from an AtomArray{Stack} to the atom37 format, so it's a contiguous tensor index, not an actual residue index. Now, there is a question about whether those missing residues would be in our input to begin with. The models we use generally require a complete sequence, so for the coordinates the model is operating on, there shouldn't be any missing residues.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pyproject.toml (1)
27-28: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemaining dependency cleanup
sfcalculator-torchis still>=0.3.2in[tool.pixi.feature.boltz-osx]; bump it to>=0.3.3if that was the intended floor.[tool.pixi.feature.protpardelle.pypi-dependencies]still uses an unpinned Git ref forprotpardelle; pin it to a tag if you want reproducible installs.[tool.pixi.feature.protpardelle.pypi-options.dependency-overrides]still duplicates the workspace-levelpandas==2.3.1override; keep only one source of truth.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pyproject.toml` around lines 27 - 28, Update the boltz-osx pypi-dependencies entry to require sfcalculator-torch >=0.3.3, pin protpardelle’s Git dependency in its pypi-dependencies to a specific tag, and remove the duplicate pandas==2.3.1 override from protpardelle’s dependency-overrides so the workspace-level override remains the sole source of truth.
🧹 Nitpick comments (2)
src/sampleworks/models/protpardelle/wrapper.py (1)
101-110: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd
atom37_residue_indexandatom37_atom_indexto_FROZEN.These index maps are set once during
featurizeand never modified, but they're absent from_FROZEN, so they can be accidentally mutated after initialization. Adding them keeps the immutability contract consistent with the other structural fields.♻️ Proposed fix
_FROZEN = frozenset( { "aatype", "seq_mask", "residue_index", "chain_index", "atom_mask", + "atom37_residue_index", + "atom37_atom_index", "sequences", } )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 101 - 110, Add "atom37_residue_index" and "atom37_atom_index" to the _FROZEN frozenset in the relevant model wrapper, ensuring these featurize-initialized index maps are protected from mutation like the other structural fields.src/sampleworks/utils/msa.py (1)
25-29: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd full NumPy-style docstring to
_msa_data_key_sort_key.The docstring is a single summary line without
Parameters/Returnssections.As per coding guidelines,
**/*: "Always include NumPy-style docstrings for every function and class."📝 Proposed docstring fix
def _msa_data_key_sort_key(key: str | int) -> tuple[int, int | str]: - """Return a deterministic sort key for supported MSA sequence keys.""" + """Return a deterministic sort key for supported MSA sequence keys. + + Parameters + ---------- + key : str | int + A target/chain key from an ``MSAData`` mapping. + + Returns + ------- + tuple[int, int | str] + A tuple placing all ``int`` keys (sorted numerically) before all + ``str`` keys (sorted lexicographically). + """🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/sampleworks/utils/msa.py` around lines 25 - 29, Expand the `_msa_data_key_sort_key` docstring to NumPy style by documenting the `key` parameter, its supported `int`/`str` types, and the returned `(int, int | str)` sort-key tuple in `Parameters` and `Returns` sections.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@pyproject.toml`:
- Around line 27-28: Update the boltz-osx pypi-dependencies entry to require
sfcalculator-torch >=0.3.3, pin protpardelle’s Git dependency in its
pypi-dependencies to a specific tag, and remove the duplicate pandas==2.3.1
override from protpardelle’s dependency-overrides so the workspace-level
override remains the sole source of truth.
---
Nitpick comments:
In `@src/sampleworks/models/protpardelle/wrapper.py`:
- Around line 101-110: Add "atom37_residue_index" and "atom37_atom_index" to the
_FROZEN frozenset in the relevant model wrapper, ensuring these
featurize-initialized index maps are protected from mutation like the other
structural fields.
In `@src/sampleworks/utils/msa.py`:
- Around line 25-29: Expand the `_msa_data_key_sort_key` docstring to NumPy
style by documenting the `key` parameter, its supported `int`/`str` types, and
the returned `(int, int | str)` sort-key tuple in `Parameters` and `Returns`
sections.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: dec962de-033f-474a-bce6-841fb7901371
📒 Files selected for processing (25)
Dockerfile.asteradocker/astera/install-ext.shpyproject.tomlsrc/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/sf.pysrc/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/transformer.pysrc/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/unitcell.pysrc/sampleworks/core/samplers/edm.pysrc/sampleworks/core/scalers/fk_steering.pysrc/sampleworks/metrics/lddt.pysrc/sampleworks/metrics/rmsd.pysrc/sampleworks/models/boltz/wrapper.pysrc/sampleworks/models/protenix/wrapper.pysrc/sampleworks/models/protpardelle/wrapper.pysrc/sampleworks/models/rf3/wrapper.pysrc/sampleworks/utils/framework_utils.pysrc/sampleworks/utils/guidance_script_arguments.pysrc/sampleworks/utils/guidance_script_utils.pysrc/sampleworks/utils/imports.pysrc/sampleworks/utils/msa.pytests/cli/test_guidance_cli.pytests/conftest.pytests/models/protpardelle/test_protpardelle_wrapper.pytests/utils/test_atom_array_utils.pytests/utils/test_framework_utils.pytests/utils/test_msa.py
💤 Files with no reviewable changes (5)
- src/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/transformer.py
- src/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/unitcell.py
- src/sampleworks/core/forward_models/xray/real_space_density_deps/qfit/sf.py
- tests/cli/test_guidance_cli.py
- src/sampleworks/utils/guidance_script_arguments.py
✅ Files skipped from review due to trivial changes (8)
- docker/astera/install-ext.sh
- src/sampleworks/metrics/rmsd.py
- src/sampleworks/metrics/lddt.py
- src/sampleworks/utils/framework_utils.py
- tests/utils/test_framework_utils.py
- tests/utils/test_atom_array_utils.py
- src/sampleworks/models/boltz/wrapper.py
- src/sampleworks/models/protenix/wrapper.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/sampleworks/utils/imports.py
- src/sampleworks/utils/guidance_script_utils.py
## Summary Fixes the Protenix MSA typing/runtime issues from ENG-76 / #247. - Introduces an `MSAData` mapping type so MSA helpers can accept string-keyed, int-keyed, or mixed-key sequence mappings without tripping `ty`. - Adds an explicit output type for `_compute_msa()` so returned MSA paths remain `dict[str | int, Path]`. - Makes Protenix MSA sequence ordering deterministic for mixed key types by sorting items by their stringified key before splitting keys/sequences. - Passes `str(out_dir)` to Protenix `msa_search`, matching the external API expectation. ## Validation - `uvx ty check scripts/eval/classify_altloc_regions.py src/sampleworks/utils/msa.py tests/utils/test_msa.py` - `uvx ruff check src/sampleworks/utils/msa.py tests/utils/test_msa.py scripts/eval/classify_altloc_regions.py` - `PYTHONPATH=src uvx --with pytest --with loguru --with requests --with tqdm pytest --noconftest tests/utils/test_msa.py` - `7 passed` Note: the targeted local pytest invocation uses `--noconftest` because the repository-level test conftest imports heavier model/runtime dependencies such as `torch` that are not installed in the lightweight local `uvx` environment. Fixes #247. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved MSA input handling to accept broader mapping-based formats beyond plain dictionaries. * Made Protenix-specific MSA generation order deterministic for mixed numeric and string keys. * **Bug Fixes** * Improved consistency in how mixed-key MSA inputs are processed. * **Tests** * Added coverage to verify the mixed numeric/string key sorting behavior used during MSA generation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: xraymemory <me.anzuoni@gmail.com>
Completes the Protpardelle debugging work from ENG-75 / #257 on top of `mdc/add-protpardelle`. This PR intentionally targets `mdc/add-protpardelle` so the review contains only the final Protpardelle fixes, not the whole in-progress integration branch. Key changes: - Restores the EDM sampler/model-wrapper call shape to the protocol-compatible `step(noisy_state, t_hat, features=features)` after removing the temporary extra `eps` argument. - Implements Protpardelle step-time noise handling via `_expand_noise_level()`, broadcasting scalar or per-batch EDM timesteps to Protpardelle's expected `B x L` tensor. - Moves Protpardelle step inputs/conditioning tensors onto the wrapper device before the model forward pass. - Keeps `prot_lens_per_chain` on CPU when calling Protpardelle's sampling helper to avoid CPU/GPU device mismatch in helper-created residue indices. - Maps Atomworks selenomethionine atom name `SE` into Protpardelle atom37's methionine sulfur slot `SD`. - Fixes `ProtpardelleConditioning` immutability so dataclass construction can complete before selected conditioning fields become frozen. - Allows packaged Protpardelle config/data under `src/sampleworks/data/**` through `.actlignore` so ACTL sync includes the runtime YAML config. - Re-enables the slow `step()` behavior test and adds coverage for the MSE selenium atom mapping. Local static checks: - `uvx ty check src/sampleworks/models/protpardelle/wrapper.py src/sampleworks/core/samplers/edm.py tests/models/protpardelle/test_protpardelle_wrapper.py` - `uvx ruff check src/sampleworks/models/protpardelle/wrapper.py src/sampleworks/core/samplers/edm.py tests/models/protpardelle/test_protpardelle_wrapper.py` Remote ACTL / Protpardelle environment checks: - `pixi run -e protpardelle-dev pytest tests/models/protpardelle -m "not slow"` - `27 passed, 1 deselected` - `pixi run -e protpardelle-dev pytest tests/models/protpardelle/test_protpardelle_wrapper.py::TestStep::test_step_returns_coords` - `1 passed` - Exact reduced Protpardelle guidance smoke command from #257 using the shared checkpoint and 1VME inputs - completed successfully with `Guidance run successfully!` - wrote results to `output/protpardelle-smoke-guided/` Non-blocking warnings observed during the smoke run were expected environment warnings for unavailable optional model/tool paths and missing mirror environment variables; they did not prevent the Protpardelle run from completing. Refs #257. Co-authored-by: xraymemory <me.anzuoni@gmail.com>
…flags ProtpardelleWrapper.step() calls Protpardelle.forward() directly, and the sampleworks EDM sampler owns the schedule, stochasticity, and step scaling, so the sampling kwargs assembled for Protpardelle.sample() never took effect. Remove the dead _build_sampling_kwargs method, the ProtpardelleConditioning sampling_kwargs field, and every ProtpardelleConfig field except ensemble_size (num_steps, s_churn, step_scale, sidechain_mode, skip_mpnn_proportion, jump_steps, uniform_steps, temperature, top_p, extra_sampling_kwargs), plus the now-orphaned copy/yaml/files/Any imports and DEFAULT_CONFIG loading. Drop the matching --protpardelle-* CLI flags, their wiring in guidance_script_utils, and the associated tests. BREAKING CHANGE: the --protpardelle-s-churn, --protpardelle-step-scale, --protpardelle-sidechain-mode, --protpardelle-skip-mpnn-proportion, --protpardelle-jump-steps, --protpardelle-uniform-steps, --protpardelle-temperature, and --protpardelle-top-p CLI flags are removed. They were inert (ignored during generation); scripts passing them must drop them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary Fixes the Protenix MSA typing/runtime issues from ENG-76 / #247. - Introduces an `MSAData` mapping type so MSA helpers can accept string-keyed, int-keyed, or mixed-key sequence mappings without tripping `ty`. - Adds an explicit output type for `_compute_msa()` so returned MSA paths remain `dict[str | int, Path]`. - Makes Protenix MSA sequence ordering deterministic for mixed key types by sorting items by their stringified key before splitting keys/sequences. - Passes `str(out_dir)` to Protenix `msa_search`, matching the external API expectation. ## Validation - `uvx ty check scripts/eval/classify_altloc_regions.py src/sampleworks/utils/msa.py tests/utils/test_msa.py` - `uvx ruff check src/sampleworks/utils/msa.py tests/utils/test_msa.py scripts/eval/classify_altloc_regions.py` - `PYTHONPATH=src uvx --with pytest --with loguru --with requests --with tqdm pytest --noconftest tests/utils/test_msa.py` - `7 passed` Note: the targeted local pytest invocation uses `--noconftest` because the repository-level test conftest imports heavier model/runtime dependencies such as `torch` that are not installed in the lightweight local `uvx` environment. Fixes #247. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved MSA input handling to accept broader mapping-based formats beyond plain dictionaries. * Made Protenix-specific MSA generation order deterministic for mixed numeric and string keys. * **Bug Fixes** * Improved consistency in how mixed-key MSA inputs are processed. * **Tests** * Added coverage to verify the mixed numeric/string key sorting behavior used during MSA generation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: xraymemory <me.anzuoni@gmail.com>
Completes the Protpardelle debugging work from ENG-75 / #257 on top of `mdc/add-protpardelle`. This PR intentionally targets `mdc/add-protpardelle` so the review contains only the final Protpardelle fixes, not the whole in-progress integration branch. Key changes: - Restores the EDM sampler/model-wrapper call shape to the protocol-compatible `step(noisy_state, t_hat, features=features)` after removing the temporary extra `eps` argument. - Implements Protpardelle step-time noise handling via `_expand_noise_level()`, broadcasting scalar or per-batch EDM timesteps to Protpardelle's expected `B x L` tensor. - Moves Protpardelle step inputs/conditioning tensors onto the wrapper device before the model forward pass. - Keeps `prot_lens_per_chain` on CPU when calling Protpardelle's sampling helper to avoid CPU/GPU device mismatch in helper-created residue indices. - Maps Atomworks selenomethionine atom name `SE` into Protpardelle atom37's methionine sulfur slot `SD`. - Fixes `ProtpardelleConditioning` immutability so dataclass construction can complete before selected conditioning fields become frozen. - Allows packaged Protpardelle config/data under `src/sampleworks/data/**` through `.actlignore` so ACTL sync includes the runtime YAML config. - Re-enables the slow `step()` behavior test and adds coverage for the MSE selenium atom mapping. Local static checks: - `uvx ty check src/sampleworks/models/protpardelle/wrapper.py src/sampleworks/core/samplers/edm.py tests/models/protpardelle/test_protpardelle_wrapper.py` - `uvx ruff check src/sampleworks/models/protpardelle/wrapper.py src/sampleworks/core/samplers/edm.py tests/models/protpardelle/test_protpardelle_wrapper.py` Remote ACTL / Protpardelle environment checks: - `pixi run -e protpardelle-dev pytest tests/models/protpardelle -m "not slow"` - `27 passed, 1 deselected` - `pixi run -e protpardelle-dev pytest tests/models/protpardelle/test_protpardelle_wrapper.py::TestStep::test_step_returns_coords` - `1 passed` - Exact reduced Protpardelle guidance smoke command from #257 using the shared checkpoint and 1VME inputs - completed successfully with `Guidance run successfully!` - wrote results to `output/protpardelle-smoke-guided/` Non-blocking warnings observed during the smoke run were expected environment warnings for unavailable optional model/tool paths and missing mirror environment variables; they did not prevent the Protpardelle run from completing. Refs #257. Co-authored-by: xraymemory <me.anzuoni@gmail.com>
## Summary Fixes the Protenix MSA typing/runtime issues from ENG-76 / #247. - Introduces an `MSAData` mapping type so MSA helpers can accept string-keyed, int-keyed, or mixed-key sequence mappings without tripping `ty`. - Adds an explicit output type for `_compute_msa()` so returned MSA paths remain `dict[str | int, Path]`. - Makes Protenix MSA sequence ordering deterministic for mixed key types by sorting items by their stringified key before splitting keys/sequences. - Passes `str(out_dir)` to Protenix `msa_search`, matching the external API expectation. ## Validation - `uvx ty check scripts/eval/classify_altloc_regions.py src/sampleworks/utils/msa.py tests/utils/test_msa.py` - `uvx ruff check src/sampleworks/utils/msa.py tests/utils/test_msa.py scripts/eval/classify_altloc_regions.py` - `PYTHONPATH=src uvx --with pytest --with loguru --with requests --with tqdm pytest --noconftest tests/utils/test_msa.py` - `7 passed` Note: the targeted local pytest invocation uses `--noconftest` because the repository-level test conftest imports heavier model/runtime dependencies such as `torch` that are not installed in the lightweight local `uvx` environment. Fixes #247. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved MSA input handling to accept broader mapping-based formats beyond plain dictionaries. * Made Protenix-specific MSA generation order deterministic for mixed numeric and string keys. * **Bug Fixes** * Improved consistency in how mixed-key MSA inputs are processed. * **Tests** * Added coverage to verify the mixed numeric/string key sorting behavior used during MSA generation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: xraymemory <me.anzuoni@gmail.com>
fbf9c8e to
9a82574
Compare
3aa618f to
a88eb4d
Compare
manzuoni-astera
left a comment
There was a problem hiding this comment.
Blocking issues remain in the Protpardelle integration at current head a88eb4d.
- Atom37 output is flattened in canonical mask order instead of being mapped back through explicit residue/atom indices to the input AtomArray order. Common PDB atom ordering therefore associates generated coordinates with the wrong atoms.
- Residue positions are derived from only residues present in the AtomArray while conditioning uses full canonical sequences. Missing loops shift every subsequent mapping.
- Non-protein chains are skipped in sequence conditioning but remain in atom37 conversion, causing unknown atoms or out-of-range/misaligned residue indices.
- The published/Astera image does not install the Protpardelle environment or provide checkpoint/model-parameter resolution, and CI never runs
protpardelle-dev; the new tests therefore skip in existing jobs.
Please use explicit atom index maps/reconciliation for realistic incomplete and heterogeneous structures, provision the image runtime, and add a Protpardelle CI smoke test with realistically ordered atoms.
## Summary - rename structure-predictor name fields to `model_name` across guidance, grid-search jobs, and job results - preserve the public `--model` CLI flag with an explicit argparse destination - keep wrapper constructor `model` parameters unchanged because those hold loaded model objects - intentionally make the serialized schema change cleanly without legacy pickle/JSON migration shims Implements #289. This PR is intentionally stacked on #300 because it updates the Protpardelle-integrated guidance files; #289 should remain open until the stack reaches `main`. The README CLI examples remain valid because `--model` is unchanged. ## Validation - `pytest tests/cli/test_guidance_cli.py tests/utils/test_guidance_script_arguments.py tests/utils/test_guidance_script_utils.py -q` (110 passed) - targeted `ty check` passes - `ruff check` and `ruff format --check` on touched Python files - `git diff --check` --------- Co-authored-by: xraymemory <me.anzuoni@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pyproject.toml`:
- Around line 27-28: Update the sfcalculator-torch dependency in the
pypi-dependencies configuration from >=0.3.2 to >=0.3.3, leaving the other
dependency constraints unchanged.
- Around line 50-55: Move the PyTorch dependency from the Pixi dependencies
table into the appropriate pypi-dependencies table, renaming it to torch while
preserving the >=2.6.0,<2.8 constraint so the GPU-enabled wheel is selected.
Update the protpardelle entry in
[tool.pixi.feature.protpardelle.pypi-dependencies] to include a fixed git
revision, using the reviewed commit pin for reproducible builds.
In `@run_grid_search.py`:
- Line 590: Update the existing-run key construction around
existing_run.get("model_name") to fall back to the legacy "model" field when
"model_name" is absent, then normalize the migrated entry to use "model_name" in
the merged output. Preserve current deduplication behavior for new-schema
results while ensuring legacy results match new_run_keys.
In `@src/sampleworks/models/protpardelle/wrapper.py`:
- Around line 116-121: Add NumPy-style docstrings to the __setattr__ method and
the device property, documenting their purpose and relevant parameters or return
value. Keep the existing frozen-attribute enforcement and device behavior
unchanged.
- Around line 193-204: Update the chain-processing flow around the sequence
collection and asym_unit mapping to retain only L-polypeptide chain IDs, then
filter the atom array to those IDs before applying sequence-derived layout
logic. Ensure mixed inputs cannot pass ligand or non-protein atoms into the
mapping; apply the same filtering at the corresponding logic around the
additional referenced section.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 23207694-ac9a-413d-9c35-cfd97770dc94
⛔ Files ignored due to path filters (1)
pixi.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
.actlignoreGRID_SEARCH.mdpyproject.tomlrun_grid_search.pysrc/sampleworks/cli/guidance.pysrc/sampleworks/data/cc89_epoch415.yamlsrc/sampleworks/models/protpardelle/__init__.pysrc/sampleworks/models/protpardelle/wrapper.pysrc/sampleworks/utils/guidance_constants.pysrc/sampleworks/utils/guidance_script_arguments.pysrc/sampleworks/utils/guidance_script_utils.pysrc/sampleworks/utils/imports.pytests/cli/test_guidance_cli.pytests/integration/test_mismatch_integration.pytests/models/protpardelle/__init__.pytests/models/protpardelle/conftest.pytests/models/protpardelle/test_protpardelle_wrapper.pytests/runs/test_runner.pytests/utils/conftest.pytests/utils/test_guidance_script_arguments.pytests/utils/test_guidance_script_utils.py
🚧 Files skipped from review as they are similar to previous changes (10)
- src/sampleworks/models/protpardelle/init.py
- .actlignore
- src/sampleworks/utils/guidance_constants.py
- tests/models/protpardelle/conftest.py
- src/sampleworks/data/cc89_epoch415.yaml
- src/sampleworks/cli/guidance.py
- tests/runs/test_runner.py
- tests/models/protpardelle/test_protpardelle_wrapper.py
- src/sampleworks/utils/guidance_script_utils.py
- src/sampleworks/utils/imports.py
| pypi-dependencies = {"boltz" = "*", "cuequivariance-torch" = "*", "rdkit" = ">=2025.3.6", "joblib" = "*", "sfcalculator-torch" = ">=0.3.2"} | ||
| platforms = ["osx-arm64"] |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Update sfcalculator-torch minimum version.
A previous review noted that sfcalculator-torch should be pinned to >=0.3.3, but it remains >=0.3.2.
🐛 Proposed fix
-pypi-dependencies = {"boltz" = "*", "cuequivariance-torch" = "*", "rdkit" = ">=2025.3.6", "joblib" = "*", "sfcalculator-torch" = ">=0.3.2"}
+pypi-dependencies = {"boltz" = "*", "cuequivariance-torch" = "*", "rdkit" = ">=2025.3.6", "joblib" = "*", "sfcalculator-torch" = ">=0.3.3"}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pyproject.toml` around lines 27 - 28, Update the sfcalculator-torch
dependency in the pypi-dependencies configuration from >=0.3.2 to >=0.3.3,
leaving the other dependency constraints unchanged.
| pytorch = ">=2.6.0,<2.8" | ||
| tqdm = "*" | ||
| typer = "*" | ||
|
|
||
| [tool.pixi.feature.protpardelle.pypi-dependencies] | ||
| protpardelle = {git = "https://github.com/ProteinDesignLab/protpardelle-1c.git"} |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
Fix PyTorch dependency and pin protpardelle git revision.
Two issues identified in previous reviews remain unaddressed in this block:
pytorchunder the Pixidependenciestable resolves to the CPU version. It should be moved topypi-dependenciesastorch = ">=2.6.0,<2.8"to ensure the correct GPU-enabled wheel is installed.- The
protpardellegit dependency is missing a specific commit pin (e.g.,rev = "ee378400f25b801fa481028000f9060183d7fb4c") to ensure reproducible builds.
🐛 Proposed fix
-pytorch = ">=2.6.0,<2.8"
tqdm = "*"
typer = "*"
[tool.pixi.feature.protpardelle.pypi-dependencies]
+torch = ">=2.6.0,<2.8"
-protpardelle = {git = "https://github.com/ProteinDesignLab/protpardelle-1c.git"}
+protpardelle = {git = "https://github.com/ProteinDesignLab/protpardelle-1c.git", rev = "ee378400f25b801fa481028000f9060183d7fb4c"}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pyproject.toml` around lines 50 - 55, Move the PyTorch dependency from the
Pixi dependencies table into the appropriate pypi-dependencies table, renaming
it to torch while preserving the >=2.6.0,<2.8 constraint so the GPU-enabled
wheel is selected. Update the protpardelle entry in
[tool.pixi.feature.protpardelle.pypi-dependencies] to include a fixed git
revision, using the reviewed commit pin for reproducible builds.
| key = ( | ||
| existing_run.get("protein"), | ||
| existing_run.get("model"), | ||
| existing_run.get("model_name"), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Migrate legacy job results to prevent duplication and schema mismatch.
Because the model field was renamed to model_name, reading a results.json from a previous grid search will yield None for existing_run.get("model_name"). This causes the old run's key to mismatch new_run_keys, resulting in duplicated entries in the merged results rather than proper deduplication when a run is re-executed.
Migrate the key on the fly to maintain backward compatibility, properly deduplicate runs, and standardize the resulting output schema.
🐛 Proposed fix to migrate legacy results
merged_runs = [asdict(r) for r in results]
for existing_run in existing_runs:
+ if "model_name" not in existing_run and "model" in existing_run:
+ existing_run["model_name"] = existing_run.pop("model")
key = (
existing_run.get("protein"),
existing_run.get("model_name"),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| existing_run.get("model_name"), | |
| if "model_name" not in existing_run and "model" in existing_run: | |
| existing_run["model_name"] = existing_run.pop("model") | |
| existing_run.get("model_name"), |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@run_grid_search.py` at line 590, Update the existing-run key construction
around existing_run.get("model_name") to fall back to the legacy "model" field
when "model_name" is absent, then normalize the migrated entry to use
"model_name" in the merged output. Preserve current deduplication behavior for
new-schema results while ensuring legacy results match new_run_keys.
| def __setattr__(self, key, value): | ||
| if key in self._FROZEN and getattr(self, "_initialized", False): | ||
| raise AttributeError( | ||
| f"Cannot set attribute {key!r} on {self.__class__.__name__}, it is frozen!" | ||
| ) | ||
| object.__setattr__(self, key, value) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add docstrings for __setattr__ and device.
Proposed fix
def __setattr__(self, key, value):
+ """Set an attribute while preserving immutable conditioning fields."""
if key in self._FROZEN and getattr(self, "_initialized", False):
`@property`
def device(self) -> torch.device:
+ """Return the device on which the wrapped model runs."""
return self._deviceAs per coding guidelines, every function and class must include a NumPy-style docstring.
Also applies to: 259-261
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 116 - 121, Add
NumPy-style docstrings to the __setattr__ method and the device property,
documenting their purpose and relevant parameters or return value. Keep the
existing frozen-attribute enforcement and device behavior unchanged.
Source: Coding guidelines
| sequences: list[str] = [] | ||
| for chain_id, info in chain_info.items(): | ||
| chain_type: ChainType = info["chain_type"] | ||
| if chain_type == ChainType.POLYPEPTIDE_L: | ||
| sequence = info["processed_entity_canonical_sequence"] | ||
| if sequence: | ||
| sequences.append(sequence) | ||
| else: | ||
| logger.warning( | ||
| f"Skipping non-protein chain {chain_id!r} (chain_type={chain_type}); " | ||
| "Protpardelle only models L-polypeptide chains." | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Filter the atom array to the retained protein chains.
Non-protein chains are reported as skipped, but the full asym_unit is still mapped. Ligand atoms can trigger ValueError, while extra residues can exceed the sequence-derived layout. Filter by the retained protein chain IDs—or reject mixed inputs consistently.
Also applies to: 321-325
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/sampleworks/models/protpardelle/wrapper.py` around lines 193 - 204,
Update the chain-processing flow around the sequence collection and asym_unit
mapping to retain only L-polypeptide chain IDs, then filter the atom array to
those IDs before applying sequence-derived layout logic. Ensure mixed inputs
cannot pass ligand or non-protein atoms into the mapping; apply the same
filtering at the corresponding logic around the additional referenced section.
Adding Protpardelle, attempt 2 (see PR #274)
Closes #258 — protpardelle sampling options were piped through the guidance CLI in #270 (merged into
mdc/add-protpardelle); lands inmainwith this PR.Closes #286 — protpardelle test temp-dir cleanup was done in #297 (merged into
mdc/add-protpardelle); lands inmainwith this PR.Original description:
This is a working version of Protpardelle-1c in SampleWorks. It may still require parameter tuning and other updates--in particular it isn't clear how to use self-conditioning. However we can generate structures with this version and so I'm making this PR as a milestone.
Only a couple significant changes have been made outside the Protpardelle wrapper code itself. One is to make a features class that is unfrozen, so that we can pass self-conditioning input forward to the next Euler step during sampling. Another is that we define different sampling parameters for Protpardelle when instantiating the sampler. There is no CLI control for either change in this PR.
Summary by CodeRabbit
modeltomodel_nameacross guidance and grid-search workflows.