diff --git a/pysatl_experiment/cli/commands/common/common.py b/pysatl_experiment/cli/commands/common/common.py index cb03819..098e412 100644 --- a/pysatl_experiment/cli/commands/common/common.py +++ b/pysatl_experiment/cli/commands/common/common.py @@ -1,14 +1,10 @@ import json from enum import Enum from pathlib import Path -from typing import cast +from typing import cast, overload from click import ClickException, Context -from pysatl_criterion.statistics import ( - AbstractExponentialityGofStatistic, - AbstractNormalityGofStatistic, - AbstractWeibullGofStatistic, -) +from pysatl_criterion import DistributionType from pysatl_criterion.statistics.goodness_of_fit import AbstractGoodnessOfFitStatistic @@ -128,7 +124,19 @@ def list_possible_parameter_values(param_type: type[Enum]) -> str: return param_type_values_str -def get_statistics_short_codes_for_hypothesis(hypothesis: str) -> list[str]: +@overload +def get_statistics_short_codes_for_hypothesis(hypothesis: str) -> list[str]: ... + + +@overload +def get_statistics_short_codes_for_hypothesis(hypothesis: list[str]) -> dict[str, list[str]]: ... + + +@overload +def get_statistics_short_codes_for_hypothesis(hypothesis: None) -> dict[str, list[str]]: ... + + +def get_statistics_short_codes_for_hypothesis(hypothesis: str | list[str] | None) -> list[str] | dict[str, list[str]]: """ Get statistics codes for hypothesis. @@ -137,13 +145,10 @@ def get_statistics_short_codes_for_hypothesis(hypothesis: str) -> list[str]: :return: statistics codes for hypothesis. """ - hypothesis_to_base_class = { - "exponential": AbstractExponentialityGofStatistic, - "normal": AbstractNormalityGofStatistic, - "weibull": AbstractWeibullGofStatistic, - } + if hypothesis is None or isinstance(hypothesis, list): + return {member.value: get_statistics_short_codes_for_hypothesis(member.value) for member in DistributionType} - base_class = hypothesis_to_base_class[hypothesis] + base_class = DistributionType(hypothesis).base_class valid_criteria_types = cast( list[type[AbstractGoodnessOfFitStatistic]], diff --git a/pysatl_experiment/cli/commands/criteria/criteria.py b/pysatl_experiment/cli/commands/criteria/criteria.py index d780a3c..5205d35 100644 --- a/pysatl_experiment/cli/commands/criteria/criteria.py +++ b/pysatl_experiment/cli/commands/criteria/criteria.py @@ -1,23 +1,36 @@ -from click import Choice, argument, command, echo, option +from click import Choice, command, echo, option +from pysatl_criterion.utils.distribution import DistributionType from pysatl_experiment.cli.commands.common.common import get_statistics_short_codes_for_hypothesis -from pysatl_experiment.configuration.model.hypothesis.hypothesis import Hypothesis + + +def __show_available_criteria(distribution: str, codes: list[str]): + echo(f"Available criteria for {distribution}:") + if len(codes) > 0: + for code in codes: + echo(f"code: {code}") + else: + echo("No criteria found") @command() -@argument( - "distribution", - type=Choice(Hypothesis.list()), +@option( + "--distribution", "-d", required=False, type=Choice(DistributionType.list()), help="Distribution. Empty for all" ) @option("--description/--no-description", "-y/-n", default=False, help="Show criteria description") -def available_criteria(distribution: str, description: bool) -> None: +def available_criteria(distribution: str | None, description: bool) -> None: """ Collect all existing criteria. :param distribution: distribution. """ - codes = get_statistics_short_codes_for_hypothesis(distribution) + codes: list[str] | dict[str, list[str]] = get_statistics_short_codes_for_hypothesis(distribution) + + if distribution is None and isinstance(codes, dict): + for key, value in codes.items(): + __show_available_criteria(key, value) + return echo(f"Available criteria for {distribution}:") if len(codes) > 0: diff --git a/pysatl_experiment/experiment/generator/generators.py b/pysatl_experiment/experiment/generator/generators.py index e5e5042..6591a9e 100644 --- a/pysatl_experiment/experiment/generator/generators.py +++ b/pysatl_experiment/experiment/generator/generators.py @@ -1,23 +1,23 @@ -from pysatl_criterion.core.distribution.beta import generate_beta -from pysatl_criterion.core.distribution.cauchy import generate_cauchy -from pysatl_criterion.core.distribution.chi2 import generate_chi2 -from pysatl_criterion.core.distribution.expon import generate_expon -from pysatl_criterion.core.distribution.gamma import generate_gamma -from pysatl_criterion.core.distribution.gompertz import generate_gompertz -from pysatl_criterion.core.distribution.gumbel import generate_gumbel -from pysatl_criterion.core.distribution.invgauss import generate_invgauss -from pysatl_criterion.core.distribution.laplace import generate_laplace -from pysatl_criterion.core.distribution.lo_con_norm import generate_lo_con_norm -from pysatl_criterion.core.distribution.logistic import generate_logistic -from pysatl_criterion.core.distribution.lognormal import generate_lognorm -from pysatl_criterion.core.distribution.mix_con_norm import generate_mix_con_norm -from pysatl_criterion.core.distribution.norm import generate_norm -from pysatl_criterion.core.distribution.rice import generate_rice -from pysatl_criterion.core.distribution.scale_con_norm import generate_scale_con_norm -from pysatl_criterion.core.distribution.student import generate_t -from pysatl_criterion.core.distribution.truncnormal import generate_truncnorm -from pysatl_criterion.core.distribution.tukey import generate_tukey -from pysatl_criterion.core.distribution.weibull import generate_weibull +from pysatl_criterion.core.distributions.beta import generate_beta +from pysatl_criterion.core.distributions.cauchy import generate_cauchy +from pysatl_criterion.core.distributions.chi2 import generate_chi2 +from pysatl_criterion.core.distributions.expon import generate_expon +from pysatl_criterion.core.distributions.gamma import generate_gamma +from pysatl_criterion.core.distributions.gompertz import generate_gompertz +from pysatl_criterion.core.distributions.gumbel import generate_gumbel +from pysatl_criterion.core.distributions.invgauss import generate_invgauss +from pysatl_criterion.core.distributions.laplace import generate_laplace +from pysatl_criterion.core.distributions.lo_con_norm import generate_lo_con_norm +from pysatl_criterion.core.distributions.logistic import generate_logistic +from pysatl_criterion.core.distributions.lognormal import generate_lognorm +from pysatl_criterion.core.distributions.mix_con_norm import generate_mix_con_norm +from pysatl_criterion.core.distributions.norm import generate_norm +from pysatl_criterion.core.distributions.rice import generate_rice +from pysatl_criterion.core.distributions.scale_con_norm import generate_scale_con_norm +from pysatl_criterion.core.distributions.student import generate_t +from pysatl_criterion.core.distributions.truncnormal import generate_truncnorm +from pysatl_criterion.core.distributions.tukey import generate_tukey +from pysatl_criterion.core.distributions.weibull import generate_weibull from typing_extensions import override from pysatl_experiment.experiment.generator.model import AbstractRVSGenerator diff --git a/pysatl_experiment/experiment/step/execution/critical_value/critical_value.py b/pysatl_experiment/experiment/step/execution/critical_value/critical_value.py index 8629b58..fd7ccf5 100644 --- a/pysatl_experiment/experiment/step/execution/critical_value/critical_value.py +++ b/pysatl_experiment/experiment/step/execution/critical_value/critical_value.py @@ -2,10 +2,7 @@ from dataclasses import dataclass from line_profiler import profile -from pysatl_criterion.persistence.model.limit_distribution.limit_distribution import ( - ILimitDistributionStorage, - LimitDistributionModel, -) +from pysatl_criterion.persistence.models.limit_distribution import ILimitDistributionStorage, LimitDistributionModel from pysatl_experiment.configuration.model.experiment_type.experiment_type import ExperimentType from pysatl_experiment.experiment.model.experiment_step.experiment_step import IExperimentStep diff --git a/pysatl_experiment/experiment/step/report_building/critical_value/critical_value.py b/pysatl_experiment/experiment/step/report_building/critical_value/critical_value.py index 7f4d978..cb785e4 100644 --- a/pysatl_experiment/experiment/step/report_building/critical_value/critical_value.py +++ b/pysatl_experiment/experiment/step/report_building/critical_value/critical_value.py @@ -1,11 +1,8 @@ from pathlib import Path from line_profiler import profile -from pysatl_criterion.critical_value.cv_calculator.cv_calculator import CVCalculator -from pysatl_criterion.persistence.model.limit_distribution.limit_distribution import ( - ILimitDistributionStorage, - LimitDistributionQuery, -) +from pysatl_criterion.hypothesis_testing.critical_values.cv_calculator.cv_calculator import CVCalculator +from pysatl_criterion.persistence.models.limit_distribution import ILimitDistributionStorage, LimitDistributionQuery from typing_extensions import override from pysatl_experiment.configuration.criteria_config.criteria_config import CriterionConfig diff --git a/pysatl_experiment/factory/critical_value/critical_value.py b/pysatl_experiment/factory/critical_value/critical_value.py index 5a68f3f..a578cd7 100644 --- a/pysatl_experiment/factory/critical_value/critical_value.py +++ b/pysatl_experiment/factory/critical_value/critical_value.py @@ -1,7 +1,4 @@ -from pysatl_criterion.persistence.model.limit_distribution.limit_distribution import ( - ILimitDistributionStorage, - LimitDistributionQuery, -) +from pysatl_criterion.persistence.models.limit_distribution import ILimitDistributionStorage, LimitDistributionQuery from pysatl_experiment.configuration.experiment_data.critical_value.critical_value import CriticalValueExperimentData from pysatl_experiment.experiment.step.execution.common.hypothesis_generator_data.hypothesis_generator_data import ( # noqa: E501 diff --git a/pysatl_experiment/factory/model/abstract_experiment_factory/abstract_experiment_factory.py b/pysatl_experiment/factory/model/abstract_experiment_factory/abstract_experiment_factory.py index d6ff867..657c506 100644 --- a/pysatl_experiment/factory/model/abstract_experiment_factory/abstract_experiment_factory.py +++ b/pysatl_experiment/factory/model/abstract_experiment_factory/abstract_experiment_factory.py @@ -1,9 +1,9 @@ from abc import ABC, abstractmethod from typing import Any, Generic, TypeVar, cast -from pysatl_criterion.persistence.limit_distribution.datastorage.datastorage import AlchemyLimitDistributionStorage -from pysatl_criterion.persistence.model.common.data_storage.data_storage import IDataStorage -from pysatl_criterion.persistence.model.limit_distribution.limit_distribution import LimitDistributionQuery +from pysatl_criterion.persistence.models.base import IDataStorage +from pysatl_criterion.persistence.models.limit_distribution import LimitDistributionQuery +from pysatl_criterion.persistence.sqlalchemy.datastorage import AlchemyLimitDistributionStorage from pysatl_criterion.statistics import ( AbstractExponentialityGofStatistic, AbstractNormalityGofStatistic, diff --git a/pysatl_experiment/persistence/model/experiment/experiment.py b/pysatl_experiment/persistence/model/experiment/experiment.py index 85931c0..ce29063 100644 --- a/pysatl_experiment/persistence/model/experiment/experiment.py +++ b/pysatl_experiment/persistence/model/experiment/experiment.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass -from pysatl_criterion.persistence.model.common.data_storage.data_storage import DataModel, DataQuery, IDataStorage +from pysatl_criterion.persistence.models.base import DataModel, DataQuery, IDataStorage @dataclass diff --git a/pysatl_experiment/persistence/model/power/power.py b/pysatl_experiment/persistence/model/power/power.py index bf49188..c077027 100644 --- a/pysatl_experiment/persistence/model/power/power.py +++ b/pysatl_experiment/persistence/model/power/power.py @@ -1,7 +1,7 @@ from abc import ABC from dataclasses import dataclass -from pysatl_criterion.persistence.model.common.data_storage.data_storage import DataModel, DataQuery, IDataStorage +from pysatl_criterion.persistence.models.base import DataModel, DataQuery, IDataStorage @dataclass diff --git a/pysatl_experiment/persistence/model/random_values/random_values.py b/pysatl_experiment/persistence/model/random_values/random_values.py index 481e94e..445bd3d 100644 --- a/pysatl_experiment/persistence/model/random_values/random_values.py +++ b/pysatl_experiment/persistence/model/random_values/random_values.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass -from pysatl_criterion.persistence.model.common.data_storage.data_storage import DataModel, DataQuery, IDataStorage +from pysatl_criterion.persistence.models.base import DataModel, DataQuery, IDataStorage @dataclass diff --git a/pysatl_experiment/persistence/model/time_complexity/time_complexity.py b/pysatl_experiment/persistence/model/time_complexity/time_complexity.py index d51ae39..660680c 100644 --- a/pysatl_experiment/persistence/model/time_complexity/time_complexity.py +++ b/pysatl_experiment/persistence/model/time_complexity/time_complexity.py @@ -1,7 +1,7 @@ from abc import ABC from dataclasses import dataclass -from pysatl_criterion.persistence.model.common.data_storage.data_storage import DataModel, DataQuery, IDataStorage +from pysatl_criterion.persistence.models.base import DataModel, DataQuery, IDataStorage @dataclass diff --git a/pysatl_experiment/persistence/random_values_storage.py b/pysatl_experiment/persistence/random_values_storage.py index c3a8b46..b081db2 100644 --- a/pysatl_experiment/persistence/random_values_storage.py +++ b/pysatl_experiment/persistence/random_values_storage.py @@ -3,7 +3,7 @@ import json from typing import ClassVar -from pysatl_criterion.persistence.alchemy_decorator import CompressedFloatArray +from pysatl_criterion.persistence.sqlalchemy.alchemy_decorator import CompressedFloatArray from sqlalchemy import Integer, String, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from typing_extensions import override diff --git a/pysatl_experiment/worker/power/power.py b/pysatl_experiment/worker/power/power.py index 9d1bc92..7b96e70 100644 --- a/pysatl_experiment/worker/power/power.py +++ b/pysatl_experiment/worker/power/power.py @@ -1,9 +1,9 @@ from dataclasses import dataclass -from pysatl_criterion.critical_value.resolver.storage_resolver import StorageCriticalValueResolver -from pysatl_criterion.persistence.limit_distribution.datastorage.datastorage import AlchemyLimitDistributionStorage +from pysatl_criterion import GoodnessOfFitTest +from pysatl_criterion.hypothesis_testing.critical_values.resolver.storage_resolver import StorageCriticalValueResolver +from pysatl_criterion.persistence.sqlalchemy.datastorage import AlchemyLimitDistributionStorage from pysatl_criterion.statistics.goodness_of_fit import AbstractGoodnessOfFitStatistic -from pysatl_criterion.test.goodness_of_fit_test.goodness_of_fit_test import GoodnessOfFitTest from pysatl_experiment.worker.model.abstract_worker.abstract_worker import IWorker, WorkerResult @@ -45,7 +45,7 @@ def execute(self) -> PowerWorkerResult: cv_resolver = StorageCriticalValueResolver(storage) gof_test = GoodnessOfFitTest( - statistics=self.statistics, + statistics=[self.statistics], significance_level=self.significance_level, cv_resolver=cv_resolver, ) diff --git a/tests/cli/commands/test_common.py b/tests/cli/commands/test_common.py new file mode 100644 index 0000000..32913cb --- /dev/null +++ b/tests/cli/commands/test_common.py @@ -0,0 +1,62 @@ +import pytest +from pysatl_criterion import DistributionType + +from pysatl_experiment.cli.commands.common.common import get_statistics_short_codes_for_hypothesis + + +def test_get_statistics_short_codes_for_single_hypothesis(): + """Should return list[str] for a single hypothesis.""" + + hypothesis = DistributionType.NORMAL.value + + result = get_statistics_short_codes_for_hypothesis(hypothesis) + + assert isinstance(result, list) + assert len(result) > 0 + assert all(isinstance(code, str) for code in result) + + +def test_get_statistics_short_codes_for_none(): + """Should return mapping for all hypotheses.""" + + result = get_statistics_short_codes_for_hypothesis(None) + + assert isinstance(result, dict) + + expected_keys = {member.value for member in DistributionType} + + assert set(result.keys()) == expected_keys + + for value in result.values(): + assert isinstance(value, list) + assert all(isinstance(code, str) for code in value) + + +def test_get_statistics_short_codes_for_list_input(): + """ + Current implementation ignores provided list + and returns all distributions. + """ + + result = get_statistics_short_codes_for_hypothesis([DistributionType.NORMAL.value]) + + expected_keys = {member.value for member in DistributionType} + + assert isinstance(result, dict) + assert set(result.keys()) == expected_keys + + +def test_invalid_hypothesis_raises_value_error(): + """Unknown hypothesis should raise ValueError.""" + + with pytest.raises(ValueError): + get_statistics_short_codes_for_hypothesis("invalid_distribution") + + +def test_returned_codes_do_not_contain_suffix(): + """Codes should be truncated by split('_')[0].""" + + result = get_statistics_short_codes_for_hypothesis(DistributionType.NORMAL.value) + + for code in result: + assert "_" not in code diff --git a/tests/core/distribution/distribution_test.py b/tests/core/distribution/distribution_test.py index 16fc759..975666b 100644 --- a/tests/core/distribution/distribution_test.py +++ b/tests/core/distribution/distribution_test.py @@ -2,24 +2,24 @@ import numpy as np import pytest -from pysatl_criterion.core.distribution.beta import generate_beta -from pysatl_criterion.core.distribution.cauchy import generate_cauchy -from pysatl_criterion.core.distribution.chi2 import generate_chi2 -from pysatl_criterion.core.distribution.expon import generate_expon -from pysatl_criterion.core.distribution.gamma import generate_gamma -from pysatl_criterion.core.distribution.gumbel import generate_gumbel -from pysatl_criterion.core.distribution.laplace import generate_laplace -from pysatl_criterion.core.distribution.lo_con_norm import generate_lo_con_norm -from pysatl_criterion.core.distribution.logistic import generate_logistic -from pysatl_criterion.core.distribution.lognormal import generate_lognorm -from pysatl_criterion.core.distribution.mix_con_norm import generate_mix_con_norm -from pysatl_criterion.core.distribution.norm import generate_norm -from pysatl_criterion.core.distribution.scale_con_norm import generate_scale_con_norm -from pysatl_criterion.core.distribution.student import generate_t -from pysatl_criterion.core.distribution.truncnormal import generate_truncnorm -from pysatl_criterion.core.distribution.tukey import generate_tukey -from pysatl_criterion.core.distribution.uniform import generate_uniform -from pysatl_criterion.core.distribution.weibull import generate_weibull +from pysatl_criterion.core.distributions.beta import generate_beta +from pysatl_criterion.core.distributions.cauchy import generate_cauchy +from pysatl_criterion.core.distributions.chi2 import generate_chi2 +from pysatl_criterion.core.distributions.expon import generate_expon +from pysatl_criterion.core.distributions.gamma import generate_gamma +from pysatl_criterion.core.distributions.gumbel import generate_gumbel +from pysatl_criterion.core.distributions.laplace import generate_laplace +from pysatl_criterion.core.distributions.lo_con_norm import generate_lo_con_norm +from pysatl_criterion.core.distributions.logistic import generate_logistic +from pysatl_criterion.core.distributions.lognormal import generate_lognorm +from pysatl_criterion.core.distributions.mix_con_norm import generate_mix_con_norm +from pysatl_criterion.core.distributions.norm import generate_norm +from pysatl_criterion.core.distributions.scale_con_norm import generate_scale_con_norm +from pysatl_criterion.core.distributions.student import generate_t +from pysatl_criterion.core.distributions.truncnormal import generate_truncnorm +from pysatl_criterion.core.distributions.tukey import generate_tukey +from pysatl_criterion.core.distributions.uniform import generate_uniform +from pysatl_criterion.core.distributions.weibull import generate_weibull @pytest.mark.skip(reason="no way of currently testing this")