Skip to content

Commit

Permalink
Merged in development (pull request #24)
Browse files Browse the repository at this point in the history
* Feat: Allow setting list-type parameters with single values
* Refac: Move logging from wrapper/ -> utils/
* Add single-value type hints in ConstavaParameters help
* Hotfix: Special treatment of None in set_single_as_list-decorator.
* Add parameter table to README. Minor fix in help texts.
* Hotfix: Fix typos, clarify README.
  • Loading branch information
aethertier committed Sep 26, 2023
1 parent 7938b44 commit 6a3a292
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 42 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div align="center">
<a href="bio2byte.be/b2btools" target="_blank" ref="noreferrer noopener">
<img src="https://pbs.twimg.com/profile_images/1247824923546079232/B9b_Yg7n_400x400.jpg" width="80px"/>
</a>
</a>

# Constava
</div>
Expand All @@ -25,6 +25,7 @@
* [Extracting backbone dihedrals as a DataFrame](#extracting-backbone-dihedrals-as-a-dataframe)
* [Setting parameters and analyzing a conformational ensemble](#setting-parameters-and-analyzing-a-conformational-ensemble)
* [Generating and loading conformational state models](#generating-and-loading-conformational-state-models)
* [Constava-class parameters vs. command line arguments](#constava-class-parameters-vs-command-line-arguments)
* [License](#license)
* [Authors](#authors)
* [Acknowledgements](#acknowledgments)
Expand Down Expand Up @@ -393,8 +394,8 @@ output_file = f"./{PDBID}_constava.csv"
c = Constava(
input_files = input_files,
output_file = output_file,
window = None,
bootstrap = [3,5,10,25],
input_degrees = True,
verbose = 2)

# Alter parameters after initialization
Expand Down Expand Up @@ -451,6 +452,39 @@ c.run()

[<Go to top>](#constava)

#### Constava-class parameters vs. command line arguments

In the following table, all available parameters of the Python interface (`Constava`
class) and their corresponding command line arguments are listed. The defaults for
parameters in Python and command line are the same.

| Python parameter | Command line argument | Description |
|---|---|---|
| `input_files : List[str] or str` | `constava analyze --input <file> [<file> ...]` | Input file(s) that contain the dihedral angles. |
| `input_format : str` | `constava analyze --input-format <enum>` | Format of the input file: `{'auto', 'csv', 'xvg'}` |
| `output_file : str` | `constava analyze --output <file>` | The file to write the output to. |
| `output_format : str` | `constava analyze --output-format <enum>` | Format of output file: `{'auto', 'csv', 'json', 'tsv'}` |
| | | |
| `model_type : str` | `constava fit-model --model-type <enum>` | The probabilistic conformational state model used. Default is `kde`. The alternative `grid` runs significantly faster while slightly sacrificing accuracy: `{'kde', 'grid'}` |
| `model_load : str` | `constava analyze --load-model <file>` | Load a conformational state model from the given pickled file. |
| `model_data : str` | `constava fit-model --input <file>` | Fit conformational state models to data provided in the given file. |
| `model_dump : str` | `constava fit-model --output <file>` | Write the generated model to a pickled file, that can be loaded again using `model_load`. |
| | | |
| `window : List[int] or int` | `constava analyze --window <Int> [<Int> ...]` | Do inference using a moving reading-frame of <int> consecutive samples. Multiple values can be given as a list. |
| `window_series : List[int] or int` | `constava analyze --window-series <Int> [<Int> ...]` | Do inference using a moving reading-frame of <int> consecutive samples. Return the results for every window rather than the average. Multiple values can be given as a list. |
| `bootstrap : List[int] or int` | `constava analyze --bootstrap <Int> [<Int> ...]` | Do inference using <Int> samples obtained through bootstrapping. Multiple values can be given as a list. |
| `bootstrap_samples : int` | `constava analyze --bootstrap-samples <Int> ` | When bootstrapping, sample <Int> times from the input data. |
| | | |
| `input_degrees : bool` | `constava analyze --degrees` | Set `True` if input files are in degrees. |
| `model_data_degrees : bool` | `constava fit-model --degrees` | Set `True` if the data given under `model_data` to is given in degrees. |
| `precision : int` | `constava analyze --precision <int> ` | Sets the number of decimals in the output files. By default, 4 decimals. |
| `kde_bandwidth : float` | `constava fit-model --kde-bandwidth <float>` | This controls the bandwidth of the Gaussian kernel density estimator. |
| `grid_points : int` | `constava analyze --grid-points <int>` | When `model_type` equals 'grid', this controls how many grid points are used to describe the probability density function. |
| `seed : int` | `constava analyze --seed <int>` | Set the random seed especially for bootstrapping. |
| `verbose : int` | `constava <...> -v [-v] ` | Set verbosity level of screen output. |

[<Go to top>](#constava)

## License

Distributed under the GNU General Public License v3 (GPLv3) License.
Expand Down
2 changes: 1 addition & 1 deletion constava/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def parse_parameters(cmdline_arguments):
"""\
Set this flag, if dihedrals in the input files are in
degrees."""))
anaMisc.add_argument("--precision", type=int, default=4,
anaMisc.add_argument("--precision", metavar="<int>", type=int, default=4,
help="Sets the number of decimals in the output files.")
anaMisc.add_argument("--seed", metavar="<int>", type=int, default=None,
required=False, help="Set random seed for bootstrap sampling")
Expand Down
12 changes: 2 additions & 10 deletions constava/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from constava import Constava
from constava.utils.constants import CONSTAVA_DATA_DIR
from constava.calc.csmodels import ConfStateModelLoadingError, ConfStateModelKDE, ConfStateModelGrid
from constava.wrapper.logging import logging
from constava.utils.logging import logging

logger = logging.getLogger("Constava")

Expand Down Expand Up @@ -55,10 +55,6 @@ def get_test_count(cls):
def test_csmodel_loading_kde(self):
logger.warning(f"TEST #{self.get_test_count()}: Testing loading procedures for 'kde' models...")
cva = Constava(verbose=1)
# It should fail to load a 'grid' model as kde
# with self.assertRaises(ConfStateModelLoadingError):
# c.initialize_calculator(model_type = "kde",
# load_model = self.grid_model)
# Load the KDE model
csmodel0 = cva.load_csmodel(pickled_csmodel = self.kde_model)
self.assertIsInstance(csmodel0, ConfStateModelKDE, "Failed to load conformational state model.")
Expand All @@ -78,10 +74,6 @@ def test_csmodel_loading_kde(self):
def test_csmodel_loading_grid(self):
logger.warning(f"TEST #{self.get_test_count()}: Testing loading procedures for 'grid' models...")
cva = Constava(verbose=1)
# # It should fail to load a 'grid' model as kde
# with self.assertRaises(ConfStateModelLoadingError):
# c.initialize_calculator(model_type = "grid",
# load_model = self.kde_model)
# Load the KDE model
cva.load_csmodel(pickled_csmodel = self.grid_model)
csmodel0, cshash0 = cva._csmodel, cva._cshash
Expand Down Expand Up @@ -111,7 +103,7 @@ def test_inference_kde(self):

def test_inference_grid(self):
logger.warning(f"TEST #{self.get_test_count()}: Testing inference for 'grid' models...")
input_files = [f"{self.tmpdir}/csv/dihedrals.csv"]
input_files = f"{self.tmpdir}/csv/dihedrals.csv"
expected_result = f"{self.tmpdir}/csv/result_grid.csv"
output_file = tempfile.NamedTemporaryFile(prefix="grid.", suffix=".csv", dir=self.tmpdir)
c = Constava(
Expand Down
File renamed without changes.
66 changes: 39 additions & 27 deletions constava/wrapper/params.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,43 @@
from dataclasses import dataclass, field
from typing import List, ClassVar
from .logging import logging
import typing
from ..utils.logging import logging

logger = logging.getLogger("Constava")

def set_logger_level(func):
"""Set logger.level while modifying verbose-attribute"""
def _inner_(self, __attr, __value):
rvalue = func(self, __attr, __value)
if __attr == "verbose":
if __value == 0:
logger.setLevel(logging.WARNING)
elif __value == 1:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.DEBUG)
return rvalue
return _inner_

def set_single_as_list(func):
"""Allows list-attributes (e.g., window) to be set with a single value"""
def _inner_(self, __attr, __value):
dtype = typing.get_type_hints(self).get(__attr, None)
if typing.get_origin(dtype) is list:
if __value is None:
__value = []
elif not isinstance(__value, typing.Iterable) or isinstance(__value, str):
__value = [__value]
return func(self, __attr, __value)
return _inner_


@dataclass
class ConstavaParameters:
"""The parameters that govern the function of Constava
Parameters:
-----------
input_files : List[str]
input_files : List[str] or str
Input file(s) that contain the dihedral angles.
input_format : str
Format of the input file: {'auto', 'csv', 'xvg'}
Expand All @@ -32,14 +58,14 @@ class ConstavaParameters:
Write the generated model to a pickled file, that can be loaded
again using `model_load`.
window : List[int]
window : List[int] or int
Do inference using a moving reading-frame of <int> consecutive samples.
Multiple values can be given as a list.
window_series : List[int]
window_series : List[int] or int
Do inference using a moving reading-frame of <int> consecutive samples.
Return the results for every window rather than the average. Multiple
values can be given as a list.
bootstrap : List[int]
bootstrap : List[int] or int
Do inference using <Int> samples obtained through bootstrapping.
Multiple values can be given as a list.
bootstrap_samples : int
Expand All @@ -60,7 +86,7 @@ class ConstavaParameters:
Set the random seed especially for bootstrapping.
"""
# Input/Output Options
input_files : List[str] = None
input_files : typing.List[str] = field(default_factory=list)
input_format : str = "auto"
output_file : str = None
output_format : str = "auto"
Expand All @@ -72,9 +98,9 @@ class ConstavaParameters:
model_dump : str = None

# Subsampling Options
window : List[int] = field(default_factory=list)
bootstrap : List[int] = field(default_factory=list)
window_series : List[int] = field(default_factory=list)
window : typing.List[int] = field(default_factory=list)
bootstrap : typing.List[int] = field(default_factory=list)
window_series : typing.List[int] = field(default_factory=list)
bootstrap_samples : int = 500

# Miscellaneous Options
Expand All @@ -89,22 +115,8 @@ class ConstavaParameters:
# References to the owning Constava object, not to be set by user
_constava = None

@set_logger_level
@set_single_as_list
def __setattr__(self, __attr, __value) -> None:
"""Custom function to set attributes, to catch certain special behaviours"""
# Set the actual value
super(ConstavaParameters, self).__setattr__(__attr, __value)
# Some special behaviours for selected cases
# ... "model_load" and "model_data" are mutually exclusive
if __attr == "model_load" and __value is not None and self.model_data is not None:
logger.warning("`model_load` takes precedence over `model_data`. The latter will be ignored.")
# ... "model_load" and "model_data" are mutually exclusive
elif __attr == "model_data" and __value is not None and __value and self.model_load is not None:
logger.warning("`model_load` is not None. While `model_load` is set `model_data` will be ignored")
# ... if verbosity is changed, apply to logger
elif __attr == "verbose":
if __value == 0:
logger.setLevel(logging.WARNING)
elif __value == 1:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.DEBUG)
super().__setattr__(__attr, __value)
2 changes: 1 addition & 1 deletion constava/wrapper/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List

from ..utils.constants import DEFAULT_TRAINING_DATA_PATH
from .logging import logging
from ..utils.logging import logging
from .params import ConstavaParameters
from ..io import ResultsWriter, EnsembleReader
from ..calc.calculator import ConfStateCalculator
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="constava",
version="1.0.0b3",
version="1.0.0b4",
author="Wim Vranken",
author_email="[email protected]",
description="This software is used to calculate conformational states probability & conformational state "
Expand Down

0 comments on commit 6a3a292

Please sign in to comment.