Skip to content

Commit

Permalink
Merge pull request #448 from MannLabs/fix_fasta_in_cli
Browse files Browse the repository at this point in the history
Fix fasta in cli
  • Loading branch information
GeorgWa authored Jan 24, 2025
2 parents 2b315ed + 034a9f4 commit 21a2e11
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 18 deletions.
4 changes: 2 additions & 2 deletions alphadia/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ def run(*args, **kwargs):
cli_params_config = {
**({ConfigKeys.RAW_PATHS: raw_paths} if raw_paths else {}),
**({ConfigKeys.LIBRARY_PATH: args.library} if args.library is not None else {}),
**({ConfigKeys.FASTA_PATHS: args.library} if args.fasta else {}),
**({ConfigKeys.FASTA_PATHS: args.fasta} if args.fasta else {}),
**(
{ConfigKeys.QUANT_DIRECTORY: args.library}
{ConfigKeys.QUANT_DIRECTORY: args.quant_dir}
if args.quant_dir is not None
else {}
),
Expand Down
22 changes: 12 additions & 10 deletions alphadia/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def ion_hash(precursor_idx, number, type, charge):


@nb.njit
def extended_ion_hash(precursor_idx, rank, number, type, charge):
def extended_ion_hash(precursor_idx, rank, number, type, charge): # TODO: unused?
# create a 64 bit hash from the precursor_idx, number and type
# the precursor_idx is the lower 32 bits
# the number is the next 8 bits
Expand All @@ -73,7 +73,9 @@ def extended_ion_hash(precursor_idx, rank, number, type, charge):
return precursor_idx + (rank << 32) + (number << 40) + (type << 48) + (charge << 56)


def recursive_update(full_dict: dict, update_dict: dict):
def recursive_update(
full_dict: dict, update_dict: dict
): # TODO merge with Config._update
"""recursively update a dict with a second dict. The dict is updated inplace.
Parameters
Expand All @@ -99,12 +101,12 @@ def recursive_update(full_dict: dict, update_dict: dict):
full_dict[key] = value


def normal(x, mu, sigma):
def normal(x, mu, sigma): # TODO: unused?
""" """
return 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(-np.power((x - mu) / sigma, 2) / 2)


def plt_limits(mobility_limits, dia_cycle_limits):
def plt_limits(mobility_limits, dia_cycle_limits): # TODO: unused?
mobility_len = mobility_limits[1] - mobility_limits[0]
dia_cycle_len = dia_cycle_limits[1] - dia_cycle_limits[0]

Expand Down Expand Up @@ -202,7 +204,7 @@ def amean0(array):


@nb.njit()
def astd0(array):
def astd0(array): # TODO: unused?
out = np.zeros(array.shape[1])
for i in range(len(out)):
out[i] = np.std(array[:, i])
Expand Down Expand Up @@ -248,11 +250,11 @@ def mass_range(mz_list, ppm_tolerance):
return out_mz


def function_call(q):
def function_call(q): # TODO: unused?
q.put("X" * 1000000)


def modify(n, x, s, A):
def modify(n, x, s, A): # TODO: unused?
n.value **= 2
x.value **= 2
s.value = s.value.upper()
Expand All @@ -261,7 +263,7 @@ def modify(n, x, s, A):
a.y **= 2


class Point(Structure):
class Point(Structure): # TODO: unused?
_fields_ = [("x", c_double), ("y", c_double)]


Expand Down Expand Up @@ -315,7 +317,7 @@ def make_slice_2d(start_stop):


@nb.njit
def fourier_filter(dense_stack, kernel):
def fourier_filter(dense_stack, kernel): # TODO: unused?
"""Numba helper function to apply a gaussian filter to a dense stack.
The filter is applied as convolution wrapping around the edges, calculated in fourier space.
Expand Down Expand Up @@ -512,7 +514,7 @@ def channel_score_groups(elution_group_idx, decoy, rank):


@nb.njit()
def profile_correlation(profile, tresh=3, shift=2, kernel_size=12):
def profile_correlation(profile, tresh=3, shift=2, kernel_size=12): # TODO: unused?
mask = np.sum((profile >= tresh).astype(np.int8), axis=0) == profile.shape[0]

output = np.zeros(profile.shape, dtype=np.float32)
Expand Down
121 changes: 115 additions & 6 deletions tests/unit_tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,119 @@
#!python -m unittest tests.test_utils
"""This module provides unit tests for alphadia.cli."""

# builtin
import unittest
from unittest.mock import MagicMock, mock_open, patch

# local
import yaml

if __name__ == "__main__":
unittest.main()
from alphadia.cli import _get_config_from_args, _get_from_args_or_config, run

# TODO add tests for _get_raw_path_list_from_args_and_config


def test_get_config_from_args():
"""Test the _get_config_from_args function correctly merges configs."""
mock_args = MagicMock(config="config.yaml", config_dict='{"key3": "value3"}')

yaml_content = {"key1": "value1", "key2": "value2"}
mock_yaml = yaml.dump(yaml_content)

with patch("builtins.open", mock_open(read_data=mock_yaml)):
result = _get_config_from_args(mock_args)

assert result == {"key1": "value1", "key2": "value2", "key3": "value3"}


def test_get_from_args_or_config_returns_value_from_args():
"""Test that the function returns the value from the args when it is not None."""
args = MagicMock(output="cli_output")
config = {"output_directory": "config_output"}

# when
result = _get_from_args_or_config(
args, config, args_key="output", config_key="output_directory"
)

assert result == "cli_output"


def test_get_from_args_or_config_returns_value_from_config_when_args_none():
"""Test that the function returns the value from the config when the args value is None."""
args = MagicMock(output=None)
config = {"output_directory": "config_output"}

# when
result = _get_from_args_or_config(
args, config, args_key="output", config_key="output_directory"
)

assert result == "config_output"


@patch("alphadia.cli.parser.parse_known_args")
@patch("builtins.print")
@patch("alphadia.cli.SearchPlan")
def test_cli_unknown_args(
mock_search_plan,
mock_print,
mock_parse_known_args,
):
mock_parse_known_args.return_value = (MagicMock, ["unknown_arg"])

# when
run()

mock_print.assert_called_once_with("Unknown arguments: ['unknown_arg']")
mock_search_plan.assert_not_called()


@patch("alphadia.cli.parser.parse_known_args")
@patch("alphadia.cli.reporting.init_logging")
@patch("alphadia.cli.SearchPlan")
def test_cli_minimal_args(mock_search_plan, mock_init_logging, mock_parse_known_args):
"""Test the run function of the CLI with minimal arguments maps correctly to SearchPlan."""
mock_args = MagicMock(config=None, version=None, output="/output")
mock_parse_known_args.return_value = (mock_args, [])

# when
run()

mock_search_plan.assert_called_once_with(
"/output",
{},
{
# TODO raw_paths missing here
"library_path": mock_args.library,
"fasta_paths": mock_args.fasta,
"quant_directory": mock_args.quant_dir,
},
)

mock_init_logging.assert_called_once_with("/output")


@patch("alphadia.cli.parser.parse_known_args")
@patch("alphadia.cli.reporting.init_logging")
@patch("alphadia.cli.SearchPlan")
def test_cli_minimal_args_all_none(
mock_search_plan, mock_init_logging, mock_parse_known_args
):
"""Test the run function of the CLI with minimal arguments maps correctly to SearchPlan if nothing given."""
mock_args = MagicMock(
config=None,
version=None,
output="/output",
fasta=None,
library=None,
quant_dir=None,
)
mock_parse_known_args.return_value = (mock_args, [])

# when
run()

mock_search_plan.assert_called_once_with(
"/output",
{},
{},
)

mock_init_logging.assert_called_once_with("/output")

0 comments on commit 21a2e11

Please sign in to comment.