Skip to content
Open
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
30 changes: 20 additions & 10 deletions bin/msa_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,21 +249,31 @@ def pop_match(match_fn):
if template_yaml:
template_order, template_entities = parse_template_yaml(template_yaml)
for key in template_order:
# Prefer exact id/type match first
template_entity = template_entities.get(key)
template_type = None
template_payload = None

if template_entity is not None:
template_type = str(template_entity["seq_type"]).strip().lower()
template_payload = template_entity.get("seq_value")
if template_payload is not None:
template_payload = str(template_payload).strip()

# Prefer exact id/type match first, but reject reshuffled ids whose sequence payload does not match the template
def payload_matches_template(entry):
return template_payload is None or entry["payload"] == template_payload

matched = pop_match(
lambda entry: make_entity_key(entry["seq_type"], entry["seq_details"].get("id")) == key
and payload_matches_template(entry)
)

# Fallback: MMseqs may reshuffle/swap ids; match by type + sequence payload
if matched is None and key in template_entities:
template_type = str(template_entities[key]["seq_type"]).strip().lower()
template_payload = template_entities[key].get("seq_value")
if template_payload is not None:
template_payload = str(template_payload).strip()
matched = pop_match(
lambda entry: str(entry["seq_type"]).strip().lower() == template_type
and entry["payload"] == template_payload
)
if matched is None and template_payload is not None:
matched = pop_match(
lambda entry: str(entry["seq_type"]).strip().lower() == template_type
and entry["payload"] == template_payload
)

# Keep template entries even if no MMseqs match, so metadata is retained.
ordered_entries.append(matched)
Expand Down
9 changes: 9 additions & 0 deletions conf/test_nostub.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
stubRun = false

process {
resourceLimits = [
cpus: 4,
memory: '15.GB',
time: '1.h'
]
}
33 changes: 33 additions & 0 deletions modules/local/boltz_fasta/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
nextflow_process {

name "Test Process BOLTZ_FASTA"
script "../main.nf"
process "BOLTZ_FASTA"

tag "modules"
tag "modules_local"
tag "boltz_fasta"
profile "test_nostub"

test("converts mixed fasta to boltz yaml") {

when {
process {
"""
input[0] = [
[ id: 'mixed_sample' ],
file(params.pipelines_testdata_base_path + 'testdata/sequences/untagged_complex.fasta', checkIfExists: true)
]
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}

}
35 changes: 35 additions & 0 deletions modules/local/boltz_fasta/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"converts mixed fasta to boltz yaml": {
"content": [
{
"0": [
[
{
"id": "mixed_sample"
},
"mixed_sample.yaml:md5,52bdd0470032c2e6c93b886b50906c09"
]
],
"1": [
"versions.yml:md5,0d82efa297b86ccb1ae14852c66f16ab"
],
"boltz_yaml": [
[
{
"id": "mixed_sample"
},
"mixed_sample.yaml:md5,52bdd0470032c2e6c93b886b50906c09"
]
],
"versions": [
"versions.yml:md5,0d82efa297b86ccb1ae14852c66f16ab"
]
}
],
"meta": {
"nf-test": "0.9.2",
"nextflow": "25.10.4"
},
"timestamp": "2026-05-27T18:09:17.307872399"
}
}
33 changes: 33 additions & 0 deletions modules/local/boltz_yaml_to_colabfold_fasta/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
nextflow_process {

name "Test Process BOLTZ_YAML_TO_COLABFOLD_FASTA"
script "../main.nf"
process "BOLTZ_YAML_TO_COLABFOLD_FASTA"

tag "modules"
tag "modules_local"
tag "boltz_yaml_to_colabfold_fasta"
profile "test_nostub"

test("converts boltz yaml to colabfold fasta") {

when {
process {
"""
input[0] = [
[ id: 'mixed_sample' ],
file(params.pipelines_testdata_base_path + 'testdata/sequences/boltz/mixed.yaml', checkIfExists: true)
]
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"converts boltz yaml to colabfold fasta": {
"content": [
{
"0": [
[
{
"id": "mixed_sample"
},
"mixed_sample.fasta:md5,475da65322d4589b4bfe1c6374a5b1a2"
]
],
"1": [
"versions.yml:md5,7f72de6c3c7727358d4638fd60c2a674"
],
"query_fasta": [
[
{
"id": "mixed_sample"
},
"mixed_sample.fasta:md5,475da65322d4589b4bfe1c6374a5b1a2"
]
],
"versions": [
"versions.yml:md5,7f72de6c3c7727358d4638fd60c2a674"
]
}
],
"meta": {
"nf-test": "0.9.2",
"nextflow": "25.10.4"
},
"timestamp": "2026-05-27T18:44:11.575259411"
}
}
42 changes: 42 additions & 0 deletions modules/local/mmseqs_colabfoldsearch/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
nextflow_process {

name "Test Process MMSEQS_COLABFOLDSEARCH"
script "../main.nf"
process "MMSEQS_COLABFOLDSEARCH"
config "./nextflow.config"

tag "modules"
tag "modules_local"
tag "mmseqs_colabfoldsearch"
profile "test_nostub"

test("runs mmseqs colabfoldsearch") {

when {
process {
"""
def dbDir = file('db')
dbDir.mkdirs()
file('db/dummy.db').text = 'x'

def uniref30Dir = file('s3://proteinfold-dataset/test-data/mini_dbs/colabfold_uniref30/*', checkIfExists: true)

input[0] = [
[ id: 'mixed' ],
file(params.pipelines_testdata_base_path + 'testdata/sequences/mmseqs/ubq.fasta', checkIfExists: true)
]
input[1] = file('db/*')
input[2] = uniref30Dir
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}

}
51 changes: 51 additions & 0 deletions modules/local/mmseqs_colabfoldsearch/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"runs mmseqs colabfoldsearch": {
"content": [
{
"0": [
[
{
"id": "mixed"
},
"ubq.a3m:md5,48af8d06679fa8d083df615c1bbdafb4"
]
],
"1": [
[
{
"id": "mixed"
},
"ubq.json:md5,1d038ed924926e239647485dc3219dae"
]
],
"2": [
"versions.yml:md5,4655c25b6d38ecaeb0960ba8d95c2a35"
],
"a3m": [
[
{
"id": "mixed"
},
"ubq.a3m:md5,48af8d06679fa8d083df615c1bbdafb4"
]
],
"json": [
[
{
"id": "mixed"
},
"ubq.json:md5,1d038ed924926e239647485dc3219dae"
]
],
"versions": [
"versions.yml:md5,4655c25b6d38ecaeb0960ba8d95c2a35"
]
}
],
"meta": {
"nf-test": "0.9.2",
"nextflow": "25.10.4"
},
"timestamp": "2026-05-30T13:54:01.899878117"
}
}
6 changes: 6 additions & 0 deletions modules/local/mmseqs_colabfoldsearch/tests/nextflow.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
process {
withName: MMSEQS_COLABFOLDSEARCH {
//ext.args = '--use-env=0 --pair-mode=unpaired' //https://github.com/sokrypton/ColabFold/issues/821
ext.args = '--use-env=0' //TODO: multimer test when above bug fixed
}
}
55 changes: 55 additions & 0 deletions modules/local/split_msa/tests/main.nf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
nextflow_process {

name "Test Process SPLIT_MSA"
script "../main.nf"
process "SPLIT_MSA"

tag "modules"
tag "modules_local"
tag "split_msa"
profile "test_nostub"

test("splits msa from af3 json using yaml template") {

when {
process {
"""
input[0] = [
[ id: 'mixed_sample' ],
file(params.pipelines_testdata_base_path + 'testdata/sequences/boltz/mixed.json', checkIfExists: true),
file(params.pipelines_testdata_base_path + 'testdata/sequences/boltz/mixed.yaml', checkIfExists: true)
]
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}

test("splits msa from af3 json with renamed chains using yaml template") {

when {
process {
"""
input[0] = [
[ id: 'renamed_sample' ],
file(params.pipelines_testdata_base_path + 'testdata/sequences/boltz/renamed.json', checkIfExists: true),
file(params.pipelines_testdata_base_path + 'testdata/sequences/boltz/original.yaml', checkIfExists: true)
]
"""
}
}

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }
)
}
}
}
Loading
Loading