Seqera AI making up absolute garbage :shakefist::s...
# rants
j
Seqera AI making up absolute garbage shakefistshakefistshakefistshakefistshakefistshakefist
Copy code
Actually, the cleanest solution - use leftJoin (Nextflow's outer join):
input_genome
    .map { meta, file -> 
        [[id: meta.id], file]
    }
    .leftJoin(parsed_fcsgx)
    .leftJoin(fcsgx_tiara_summary)
    .leftJoin(fcs_adaptor_file)
    .leftJoin(trailingns)
    .leftJoin(barcodes)
    .leftJoin(mito_recommendations)
    .leftJoin(plastid_recommendations)
    .map { items ->
        // Replace null values with placeholder file
        items.withIndex().collect { item, index ->
            if (item == null || (item instanceof List && item.isEmpty())) {
                getEmptyPlaceholder(index)
            } else {
                item
            }
        }
    }
    .set { merge_input_channel }
shakefist 8
m
I find for writing code, it really has a looooong way to go. I tried out the CLI to write out some nf-tests and that was a mistake..
j
It's interesting, because my general experience with LLMs + Nextflow has been very poor, but Seqera AI does a marginally better job (usually seems to have "read the docs", so to speak). But it's obviously up to scratch yet. But generally they're all pretty good at writing straight Groovy.
party this 1
Since I've got you, don't suppose you have a suggestion for a left join with a remainder? Found a bug in ASCC which means that an empty input channel "un-empties" itself as successive non-empty channels are joined to it with a remainder - really only want the remainder if the right-hand channel is empty.
m
I'm in a course at the moment. Give me a bit.
👍 1
How does your example differ from
Copy code
workflow {
    samples_ch = channel.of(
        ['sample1', 'data_A'],
        ['sample2', 'data_B'],
        ['sample3', 'data_C'],
        ['sample4', 'data_D']
    )
    
    metadata_ch = channel.of(
        ['sample1', 'metadata_1'],
        ['sample2', 'metadata_2'],
        ['sample4', 'metadata_4'],
        ['sample5', 'metadata_5'], // don't want this
    )
    
    joined_ch = samples_ch.join(metadata_ch, remainder: true)
        .filter{ _sample_id, data, _metadata -> data }
    
    joined_ch.view { sample_id, data, metadata ->
        "ID: ${sample_id} | Data: ${data} | Metadata: ${metadata ?: 'NO_METADATA'}"
    }
}
j
the problem is:
Copy code
ch_a = channel.empty()
ch_b = channel.of(["a", "b"])

ch_a.join(ch_b, remainder: true).view()

[a, null, b]
that happens over a long chain of joins, the final result should be empty if ch_a is empty. But I think I've figured out a cludgy fix for now - combine the possibly empty channel back on at the end and then drop it from the tuple, essentially re-emptying the channel if needed
m
In your example, you're just missing the filter though right for the left-join?
j
I think writing a filter for each step might be painful as you'd have to track a bespoke index for each successive join?
m
I think you could write a general filter given you know the structure of channel a.
j
That's true
r
RANTS ONLY IN UPPERCASE shakefist 😆
party this 3
👮‍♀️ 6
shakefist 2
🫢 1
👮🏻‍♀️ 3