# How to use the .cross operator for 100 x 100 docking

**URL:** https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361
**Category:** Ask for help
**Tags:** nextflow
**Created:** [September 12, 2025, 9:09pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361 "2025-09-12T21:09:15Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 12, 2025, 9:09pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/1 "2025-09-12T21:09:15Z")

</div>

Hi,

I am conducting virtual screening of some compounds and I am having issues with the docking phase. I wonder why the .cross operator is not generating any output for my ligand vs receptor pairs. I will appreciate any assistance.

Thank you.

---

<div class="post-metadata">

### Author: ![Alexander\_Nater](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/alexander_nater/32/552_2.png) [@Alexander\_Nater](https://community.seqera.io/u/Alexander_Nater)
#### Post date: [September 16, 2025, 11:52am UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/2 "2025-09-16T11:52:36Z")

</div>

You need to provide a code example, otherwise it’s impossible to figure out what’s going on.

---

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 16, 2025, 1:15pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/3 "2025-09-16T13:15:44Z")

</div>

workflow {

```auto
// Step 0: Load ligand files

ligand_files = Channel.fromPath("${params.ligands}/\*.sdf", checkIfExists: true)

// Step 1: Split multi-ligand SDFs

split_sdf_files = splitLigand(ligand_files).flatten()

// Step 2: Rename by ZINC ID

renamed_sdf = renameSDF(split_sdf_files)

// Step 3: Minimize renamed ligands

minimized_sdf = ligandMinimization(renamed_sdf)

 // Step 4: Convert minimized ligands

prepared_ligands = convertLigandtoPDBQT(minimized_sdf)

prepared_ligands_flat = prepared_ligands.flatten()

// Step 5: Load receptor files

receptor_files = Channel.fromPath("${params.receptors}/\*.{pdb,sdf,mol2}", checkIfExists: true)

// Step 6: Convert receptor files to .pdb format

converted_pdbs = convertReceptortoPDB(receptor_files)

// Step 7: Convert .pdb receptor files to .pdbqt

prepared_receptors = convertReceptortoPDBQT(converted_pdbs)

prepared_receptors_flat = prepared_receptors.flatten()

// Call docking process

receptor_centers = Channel.fromPath(‘results/receptor_centers.csv’)
    .splitCsv(header:true)

    .map { row ->

          rec_file = file("results/prepared_pdbqt/${row.receptor}.pdbqt")

          \[ rec_file, row.cx.toBigDecimal(),

          row.cy.toBigDecimal(),

          row.cz.toBigDecimal() \]

    }

    .filter { it\[0\].exists() } // skip missing files

// Step 9: Cartesian product of receptors and ligands

docking_pairs = prepared_receptors_flat.cross(prepared_ligands_flat)

// Step 10: Run docking

vina_docking(docking_pairs)

```

---

<div class="post-metadata">

### Author: ![bentsherman](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/bentsherman/32/52_2.png) [@bentsherman](https://community.seqera.io/u/bentsherman)
#### Post date: [September 16, 2025, 2:14pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/4 "2025-09-16T14:14:45Z")

</div>

The easiest way to debug this is to use the `view` operator to view the upstream channels. If the `cross` isn’t producing any output it’s likely because one of the input channels are empty.

---

<div class="post-metadata">

### Author: ![Alexander\_Nater](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/alexander_nater/32/552_2.png) [@Alexander\_Nater](https://community.seqera.io/u/Alexander_Nater)
#### Post date: [September 17, 2025, 7:54am UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/5 "2025-09-17T07:54:25Z")

</div>

Why are you escaping the square brackets in your script (`\[`)?

---

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 19, 2025, 9:28pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/6 "2025-09-19T21:28:12Z")

</div>

The input channels give the required output. .cross is not generating the required output, I wonder if I am using it correctly.

---

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 19, 2025, 9:29pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/7 "2025-09-19T21:29:09Z")

</div>

That is probably due to the length of the code. It is without that on my end.

---

<div class="post-metadata">

### Author: ![bentsherman](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/bentsherman/32/52_2.png) [@bentsherman](https://community.seqera.io/u/bentsherman)
#### Post date: [September 22, 2025, 2:30pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/8 "2025-09-22T14:30:03Z")

</div>

In that case, can you give an example that just creates some fake input channels and calls the `cross` operator? That way I can run it for myself and see what’s wrong

---

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 23, 2025, 5:25pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/9 "2025-09-23T17:25:24Z")

</div>

#!/usr/bin/env nextflow  
nextflow.enable.dsl=2

workflow {

```auto

ligands = Channel.of("lig1.pdbqt", "lig2.pdbqt", "lig3.pdbqt")

receptors = Channel.of(
    ["recA.pdbqt", 10.0, 20.0, 30.0],
    ["recB.pdbqt", 40.0, 50.0, 60.0]
)

pairs = ligands.cross(receptors)

```

}

---

<div class="post-metadata">

### Author: ![bentsherman](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/bentsherman/32/52_2.png) [@bentsherman](https://community.seqera.io/u/bentsherman)
#### Post date: [September 23, 2025, 5:55pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/10 "2025-09-23T17:55:25Z")

</div>

Okay I see. The caveat with the [cross](https://nextflow.io/docs/latest/reference/operator.html#cross) operator is that it only crosses inputs that have a matching key. Despite it’s name, it does not do a full cross product.

You can specify a closure to define the matching key in terms of an input value. So you could make this closure return a constant value to force a full cross product:

```auto
ligands.cross(receptors) { v -> 0 }

```

Honestly this should probably be the default behavior, but this was before my time 🤷‍♂️

---

<div class="post-metadata">

### Author: ![Funmilola\_Bashorun](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/funmilola_bashorun/32/2005_2.png) [@Funmilola\_Bashorun](https://community.seqera.io/u/Funmilola_Bashorun)
#### Post date: [September 23, 2025, 7:10pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/11 "2025-09-23T19:10:57Z")

</div>

PAIR: [lig1.pdbqt, recA.pdbqt]

PAIR: [lig1.pdbqt, recB.pdbqt] - it does not ouput all pairs. Is there another way to achieve a cartesian product for 50 x 50 docking?

#!/usr/bin/env nextflow  
nextflow.enable.dsl=2

workflow {

```auto

ligands = Channel.of("lig1.pdbqt", "lig2.pdbqt", "lig3.pdbqt")

receptors = Channel.of(
    ["recA.pdbqt", 10.0, 20.0, 30.0],
    ["recB.pdbqt", 40.0, 50.0, 60.0]
)

docking_pairs = receptors.flatMap { receptor_list ->
    ligands.map { ligand ->
        [
            receptor_list[0], // receptor file
            receptor_list[1], // cx
            receptor_list[2], // cy
            receptor_list[3], // cz
            ligand // ligand file
        ]
    }
}

docking_pairs.view { p -> "DOCK_PAIR: ${p}" }

```

}

\>\> DOCK\_PAIR: DataflowBroadcast around DataflowStream[?]

DOCK\_PAIR: DataflowBroadcast around DataflowStream[?]

---

<div class="post-metadata">

### Author: ![bentsherman](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/bentsherman/32/52_2.png) [@bentsherman](https://community.seqera.io/u/bentsherman)
#### Post date: [September 23, 2025, 8:42pm UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/12 "2025-09-23T20:42:38Z")

</div>

If you want the outputs to be flat, you can use the `combine` operator:

```auto
ligands.combine(receptors)

```

---

<div class="post-metadata">

### Author: ![system](https://dub1.discourse-cdn.com/flex013/user_avatar/community.seqera.io/system/32/2402_2.png) [@system](https://community.seqera.io/u/system)
#### Post date: [November 22, 2025, 12:16am UTC](https://community.seqera.io/t/how-to-use-the-cross-operator-for-100-x-100-docking/2361/13 "2025-11-22T00:16:26Z")

</div>

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.
