Skip to content

Commit 101365b

Browse files
authored
Updates table library to prettytable (#16)
* Changes table library from tabular to prettytable * Updates tests with new table library * Updates tables in Controls
1 parent bbfebd4 commit 101365b

File tree

7 files changed

+432
-365
lines changed

7 files changed

+432
-365
lines changed

RAT/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from RAT.classlist import ClassList
2+
from RAT.controls import Controls
23
from RAT.project import Project

RAT/classlist.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import collections
55
from collections.abc import Iterable, Sequence
66
import contextlib
7-
import tabulate
7+
import prettytable
88
from typing import Any, Union
99
import warnings
1010

@@ -55,8 +55,10 @@ def __repr__(self):
5555
output = repr(self.data)
5656
else:
5757
if any(model.__dict__ for model in self.data):
58-
table = [model.__dict__ for model in self.data]
59-
output = tabulate.tabulate(table, headers='keys', showindex=True)
58+
table = prettytable.PrettyTable()
59+
table.field_names = ['index'] + [key.replace('_', ' ') for key in self.data[0].__dict__.keys()]
60+
table.add_rows([[index] + list(model.__dict__.values()) for index, model in enumerate(self.data)])
61+
output = table.get_string()
6062
else:
6163
output = repr(self.data)
6264
return output

RAT/controls.py

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import tabulate
2-
from typing import Union
1+
import prettytable
32
from pydantic import BaseModel, Field, field_validator
3+
from typing import Union
4+
45
from RAT.utils.enums import ParallelOptions, Procedures, DisplayOptions, BoundHandlingOptions, StrategyOptions
56

67

7-
class BaseProcedure(BaseModel, validate_assignment = True, extra = 'forbid'):
8-
"""
9-
Defines the base class with properties used in all five procedures.
10-
"""
8+
class BaseProcedure(BaseModel, validate_assignment=True, extra='forbid'):
9+
"""Defines the base class with properties used in all five procedures."""
1110
parallel: ParallelOptions = ParallelOptions.Single
1211
calcSldDuringFit: bool = False
13-
resamPars: list[float] = Field([0.9, 50], min_length = 2, max_length = 2)
12+
resamPars: list[float] = Field([0.9, 50], min_length=2, max_length=2)
1413
display: DisplayOptions = DisplayOptions.Iter
1514

1615
@field_validator("resamPars")
16+
@classmethod
1717
def check_resamPars(cls, resamPars):
1818
if not 0 < resamPars[0] < 1:
1919
raise ValueError('resamPars[0] must be between 0 and 1')
@@ -22,63 +22,53 @@ def check_resamPars(cls, resamPars):
2222
return resamPars
2323

2424

25-
class Calculate(BaseProcedure, validate_assignment = True, extra = 'forbid'):
26-
"""
27-
Defines the class for the calculate procedure.
28-
"""
29-
procedure: Procedures = Field(Procedures.Calculate, frozen = True)
25+
class Calculate(BaseProcedure, validate_assignment=True, extra='forbid'):
26+
"""Defines the class for the calculate procedure."""
27+
procedure: Procedures = Field(Procedures.Calculate, frozen=True)
3028

3129

32-
class Simplex(BaseProcedure, validate_assignment = True, extra = 'forbid'):
33-
"""
34-
Defines the class for the simplex procedure.
35-
"""
36-
procedure: Procedures = Field(Procedures.Simplex, frozen = True)
37-
tolX: float = Field(1e-6, gt = 0)
38-
tolFun: float = Field(1e-6, gt = 0)
39-
maxFunEvals: int = Field(10000, gt = 0)
40-
maxIter: int = Field(1000, gt = 0)
30+
class Simplex(BaseProcedure, validate_assignment=True, extra='forbid'):
31+
"""Defines the class for the simplex procedure."""
32+
procedure: Procedures = Field(Procedures.Simplex, frozen=True)
33+
tolX: float = Field(1.0e-6, gt=0.0)
34+
tolFun: float = Field(1.0e-6, gt=0.0)
35+
maxFunEvals: int = Field(10000, gt=0)
36+
maxIter: int = Field(1000, gt=0)
4137
updateFreq: int = -1
4238
updatePlotFreq: int = -1
4339

4440

45-
class DE(BaseProcedure, validate_assignment = True, extra = 'forbid'):
46-
"""
47-
Defines the class for the Differential Evolution procedure.
48-
"""
49-
procedure: Procedures = Field(Procedures.DE, frozen = True)
50-
populationSize: int = Field(20, ge = 1)
41+
class DE(BaseProcedure, validate_assignment=True, extra='forbid'):
42+
"""Defines the class for the Differential Evolution procedure."""
43+
procedure: Procedures = Field(Procedures.DE, frozen=True)
44+
populationSize: int = Field(20, ge=1)
5145
fWeight: float = 0.5
52-
crossoverProbability: float = Field(0.8, gt = 0, lt = 1)
46+
crossoverProbability: float = Field(0.8, gt=0.0, lt=1.0)
5347
strategy: StrategyOptions = StrategyOptions.RandomWithPerVectorDither
54-
targetValue: float = Field(1.0, ge = 1)
55-
numGenerations: int = Field(500, ge = 1)
56-
57-
58-
class NS(BaseProcedure, validate_assignment = True, extra = 'forbid'):
59-
"""
60-
Defines the class for the Nested Sampler procedure.
61-
"""
62-
procedure: Procedures = Field(Procedures.NS, frozen = True)
63-
Nlive: int = Field(150, ge = 1)
64-
Nmcmc: float = Field(0.0, ge = 0)
65-
propScale: float = Field(0.1, gt = 0, lt = 1)
66-
nsTolerance: float = Field(0.1, ge = 0)
67-
68-
69-
class Dream(BaseProcedure, validate_assignment = True, extra = 'forbid'):
70-
"""
71-
Defines the class for the Dream procedure
72-
"""
73-
procedure: Procedures = Field(Procedures.Dream, frozen = True)
74-
nSamples: int = Field(50000, ge = 0)
75-
nChains: int = Field(10, gt = 0)
76-
jumpProb: float = Field(0.5, gt = 0, lt = 1)
77-
pUnitGamma:float = Field(0.2, gt = 0, lt = 1)
48+
targetValue: float = Field(1.0, ge=1.0)
49+
numGenerations: int = Field(500, ge=1)
50+
51+
52+
class NS(BaseProcedure, validate_assignment=True, extra='forbid'):
53+
"""Defines the class for the Nested Sampler procedure."""
54+
procedure: Procedures = Field(Procedures.NS, frozen=True)
55+
Nlive: int = Field(150, ge=1)
56+
Nmcmc: float = Field(0.0, ge=0.0)
57+
propScale: float = Field(0.1, gt=0.0, lt=1.0)
58+
nsTolerance: float = Field(0.1, ge=0.0)
59+
60+
61+
class Dream(BaseProcedure, validate_assignment=True, extra='forbid'):
62+
"""Defines the class for the Dream procedure."""
63+
procedure: Procedures = Field(Procedures.Dream, frozen=True)
64+
nSamples: int = Field(50000, ge=0)
65+
nChains: int = Field(10, gt=0)
66+
jumpProb: float = Field(0.5, gt=0.0, lt=1.0)
67+
pUnitGamma: float = Field(0.2, gt=0.0, lt=1.0)
7868
boundHandling: BoundHandlingOptions = BoundHandlingOptions.Fold
7969

8070

81-
class ControlsClass:
71+
class Controls:
8272

8373
def __init__(self,
8474
procedure: Procedures = Procedures.Calculate,
@@ -104,7 +94,7 @@ def controls(self, value: Union[Calculate, Simplex, DE, NS, Dream]) -> None:
10494
self._controls = value
10595

10696
def __repr__(self) -> str:
107-
properties = [["Property", "Value"]] +\
108-
[[k, v] for k, v in self._controls.__dict__.items()]
109-
table = tabulate.tabulate(properties, headers="firstrow")
110-
return table
97+
table = prettytable.PrettyTable()
98+
table.field_names = ['Property', 'Value']
99+
table.add_rows([[k, v] for k, v in self._controls.__dict__.items()])
100+
return table.get_string()

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
numpy >= 1.20
2+
prettytable >= 3.9.0
23
pydantic >= 2.4.0
34
pytest >= 7.4.0
45
pytest-cov >= 4.1.0
5-
StrEnum >= 0.4.15
6-
tabulate >= 0.9.0
6+
StrEnum >= 0.4.15

tests/test_classlist.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ def two_name_class_list():
2222
return ClassList([InputAttributes(name='Alice'), InputAttributes(name='Bob')])
2323

2424

25+
@pytest.fixture
26+
def two_name_class_list_table():
27+
"""The table representation of the ClassList defined in the "two_name_class_list" fixture."""
28+
return(
29+
'+-------+-------+\n'
30+
'| index | name |\n'
31+
'+-------+-------+\n'
32+
'| 0 | Alice |\n'
33+
'| 1 | Bob |\n'
34+
'+-------+-------+'
35+
)
36+
37+
2538
@pytest.fixture
2639
def three_name_class_list():
2740
"""A ClassList of InputAttributes, containing three elements with names defined."""
@@ -104,12 +117,9 @@ def test_identical_name_fields(self, input_list: Sequence[object], name_field: s
104117
ClassList(input_list, name_field=name_field)
105118

106119

107-
@pytest.mark.parametrize("expected_string", [
108-
' name\n-- ------\n 0 Alice\n 1 Bob',
109-
])
110-
def test_repr_table(two_name_class_list: 'ClassList', expected_string: str) -> None:
120+
def test_repr_table(two_name_class_list: 'ClassList', two_name_class_list_table: str) -> None:
111121
"""For classes with the __dict__ attribute, we should be able to print the ClassList like a table."""
112-
assert repr(two_name_class_list) == expected_string
122+
assert repr(two_name_class_list) == two_name_class_list_table
113123

114124

115125
def test_repr_empty_table() -> None:

0 commit comments

Comments
 (0)