Skip to content

Add additional alignment strategy parameters#92

Merged
cherman2 merged 6 commits into
qiime2:devfrom
fethalen:alignment-strategy
Jan 14, 2026
Merged

Add additional alignment strategy parameters#92
cherman2 merged 6 commits into
qiime2:devfrom
fethalen:alignment-strategy

Conversation

@fethalen

Copy link
Copy Markdown
Contributor

This PR addresses issue #91 by exposing the following set of additional alignment strategy parameters:

  • globalpair
  • localpair
  • genafpair
  • maxiterate
  • retree
  • nofft
  • auto

These flags allows the user to choose between different alignment algorithms implemented in MAFFT. There is also the --auto flag, which automatically decides on the most appropriate algorithm depending on the input data size.

globalpair, localpair, and genafpair are mutually exclusive but the default behavior of MAFFT is to just pick one based on its own internal logic. I've chosen to retain this behavior in the q2-alignment implementation, but a question I have is whether providing more than one of these flags should raise a warning or an error.

@lizgehret

Copy link
Copy Markdown
Member

Thanks @fethalen! Is this one ready for a review?

@lizgehret lizgehret moved this to Needs Review in 2026.1 ❄️ Oct 30, 2025
@lizgehret lizgehret linked an issue Oct 30, 2025 that may be closed by this pull request
@fethalen

Copy link
Copy Markdown
Contributor Author

Thanks @fethalen! Is this one ready for a review?

Yes, it would be great if someone could have a look at it!

And for the person who does, please consider my question whether we should implement our own logic to handle mutually exclusive parameters or if we should just let MAFFT do its thing.

@lizgehret

Copy link
Copy Markdown
Member

Sounds great, thanks @fethalen! We'll get someone to take a look at this either this week or next 🙂

@fethalen

Copy link
Copy Markdown
Contributor Author

Hi @lizgehret, I'm going on a Christmas break soon, and it would be great if someone could have a look at this PR.

@lizgehret

Copy link
Copy Markdown
Member

Hey @fethalen, sorry for the delay on this- I'm starting my OOO in preparation for the big move, but I just pinged the rest of the team to see if anyone has bandwidth either today or Monday!

@cherman2 cherman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @fethalen,

Thanks for your work on this!

Our major concern is that 'localpair', 'globalpair', 'auto', and 'genafpair' seem like mutually exclusive algorithms. I am pretty sure that MAFFT allows you to pass in all the parameters, but under the hood, it selects the last parameter passed in and uses that.

I see two ways to approach this, so our users understand they can't pass in 2 different algorithms into MAFFT.

  1. Instead of seperate 'localpair', 'globalpair', 'auto', and 'genafpair' params, we could have a "alignment-strategy" param with choices of 'localpair', 'globalpair', 'auto', and 'genafpair'. This would make it obvious to users that these are mutually exclusive selections, but diverges from MAFFTS syntax. I think this is our preference because it seems kinda fool-proof

  2. We can keep these parameters separate, but we should error if they are passed in together. I think this is a more complex approach, but it does mimic MAFTT's syntax. If you feel really strongly that we should keep MAFFT's syntax, I think this is a fine solution.

Let me know what you think!

@cherman2 cherman2 assigned fethalen and unassigned Oddant1 and cherman2 Jan 8, 2026
@cherman2 cherman2 moved this from Needs Review to In Development in 2026.1 ❄️ Jan 8, 2026
@fethalen

Copy link
Copy Markdown
Contributor Author

Hi @fethalen,

Thanks for your work on this!

Our major concern is that 'localpair', 'globalpair', 'auto', and 'genafpair' seem like mutually exclusive algorithms. I am pretty sure that MAFFT allows you to pass in all the parameters, but under the hood, it selects the last parameter passed in and uses that.

I see two ways to approach this, so our users understand they can't pass in 2 different algorithms into MAFFT.

  1. Instead of seperate 'localpair', 'globalpair', 'auto', and 'genafpair' params, we could have a "alignment-strategy" param with choices of 'localpair', 'globalpair', 'auto', and 'genafpair'. This would make it obvious to users that these are mutually exclusive selections, but diverges from MAFFTS syntax. I think this is our preference because it seems kinda fool-proof
  2. We can keep these parameters separate, but we should error if they are passed in together. I think this is a more complex approach, but it does mimic MAFTT's syntax. If you feel really strongly that we should keep MAFFT's syntax, I think this is a fine solution.

Let me know what you think!

Hi @cherman2, and thank you for looking into this PR! I agree that adding an additional parameter with all of the alignment strategies is the best solution. I've now implemented that under the parameter strategy, and updated all of the test. Please, if you have time, have a look at the updated version of my PR. Thanks!

@fethalen fethalen requested a review from cherman2 January 12, 2026 14:39
@cherman2 cherman2 moved this from In Development to Needs Review in 2026.1 ❄️ Jan 12, 2026
@cherman2

Copy link
Copy Markdown
Contributor

Hi @fethalen, I will review this today. Thank you!

@Oddant1 Oddant1 moved this from Needs Review to In Development in 2026.1 ❄️ Jan 12, 2026

@cherman2 cherman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @fethalen,
One more small request. Let me know when you are done, and we will review ASAP.

Comment thread q2_alignment/_mafft.py Outdated
Comment on lines +22 to +41
valid_strategies_str = ", ".join(
[s for s in valid_strategies])

if strategy == "auto":
return ["--auto"]
if strategy == "fftns":
return []
if strategy == "nofft":
return ["--nofft"]
if strategy == "localpair":
return ["--localpair"]
if strategy == "globalpair":
return ["--globalpair"]
if strategy == "genafpair":
return ["--genafpair"]
if strategy is None:
return []
else:
raise ValueError(
f"Invalid alignment strategy '{strategy}'. "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could avoid this code if we used the 'Choices' predicate. Docs are here https://develop.qiime2.org/en/stable/plugins/references/api/types.html#qiime2.plugin.Choices. That way, we can let the framework validate and yell at the user lol.

Then we can prepend a '--' to the strategy param. Ex: 'auto' to '--auto'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could avoid this code if we used the 'Choices' predicate. Docs are here https://develop.qiime2.org/en/stable/plugins/references/api/types.html#qiime2.plugin.Choices. That way, we can let the framework validate and yell at the user lol.

Then we can prepend a '--' to the strategy param. Ex: 'auto' to '--auto'

Thanks for the suggestion. I've removed the parsing function and replaced it with Choices. The only thing that is different now is that fftns is no longer an option. This simplifies the code a bit and it is also more consistent with how MAFFT works.

Comment thread q2_alignment/_mafft.py Outdated
Comment on lines +138 to +140
if strategy:
strategy_flag = _validate_alignment_strategy(strategy)
cmd += strategy_flag

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Choices will handle the validation, we can probably get rid of the _validate_alignment_strategy function and prepend here instead.

@fethalen fethalen requested a review from cherman2 January 13, 2026 14:16

@cherman2 cherman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @fethalen,
One more thing! Thanks for your work.

Comment thread q2_alignment/plugin_setup.py Outdated
Comment on lines +22 to +23
"maxiterate": Int,
"retree": Int,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fethalen,
We were so focused on the alignment strategy that we didn't notice that the same principles could be applied here.

Let's use the. 'Range' predicate here because MAFFT doesn't accept Negative numbers, and 'Range' will safeguard against that. https://develop.qiime2.org/en/latest/plugins/references/api/types.html#qiime2.plugin.Range

Comment thread q2_alignment/_mafft.py
Comment on lines +112 to +122

# --maxiterate is set to 0 by default, so we only pass this argument onto
# MAFFT if it deviates from this value.
if maxiterate not in (None, 0):
cmd += ['--maxiterate', str(maxiterate)]

# --retree is set to 2 by default, so we only pass this argument onto
# MAFFT if it deviates from this value.
if retree not in (None, 2):
cmd += ['--retree', str(retree)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's pass in the defaults to MAFFT.

I am worried about an edge case here where MAFFT changes its defaults, and we don't notice. Then our code would be misleading and say the default is 2 or 0, but it would really be using whatever MAFFT changed its default to.

Kind of a long shot because MAFFT feels pretty stable, but this way we always control what the default is.

@fethalen

Copy link
Copy Markdown
Contributor Author

Hi @cherman2, great suggestion. I've limited --p-maxiterate and --p-retree to 0-∞. I also pass on all values, even if they match the current default.

@fethalen fethalen requested a review from cherman2 January 14, 2026 09:20

@cherman2 cherman2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks Great To Me! Let's Get This Merged!

@cherman2 cherman2 merged commit d2bbfe1 into qiime2:dev Jan 14, 2026
4 checks passed
@cherman2 cherman2 moved this from In Development to Changelog Needed in 2026.1 ❄️ Jan 14, 2026
@fethalen fethalen deleted the alignment-strategy branch January 15, 2026 09:18
@Oddant1 Oddant1 moved this from Changelog Needed to Completed in 2026.1 ❄️ Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Completed

Development

Successfully merging this pull request may close these issues.

Expose additional MAFFT alignment strategy parameters

5 participants