Skip to content

Commit d842e24

Browse files
committed
Add CI quality kit (ruff + pre-commit + smoke test) and apply ruff format
Caller workflow -> ci-templates, ruff.toml + .pre-commit-config.yaml + pytest.ini, tests/test_smoke.py. ruff --fix + format applied (behaviour-neutral). Verified in-container: ruff check clean, pytest 1 passed.
1 parent 123aff7 commit d842e24

20 files changed

Lines changed: 209 additions & 131 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: CI
2+
on: [push, pull_request]
3+
jobs:
4+
quality:
5+
uses: danielstaps/ci-templates/.github/workflows/python-quality.yml@main
6+
with:
7+
python-version: "3.11"

‎.pre-commit-config.yaml‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Canonical pre-commit config for danielstaps research repos.
2+
# Copy into a repo as `.pre-commit-config.yaml`, then: pre-commit install
3+
repos:
4+
- repo: https://github.com/astral-sh/ruff-pre-commit
5+
rev: v0.8.4
6+
hooks:
7+
- id: ruff # lint (with autofix)
8+
args: [--fix]
9+
- id: ruff-format # format
10+
11+
- repo: https://github.com/pre-commit/pre-commit-hooks
12+
rev: v5.0.0
13+
hooks:
14+
- id: trailing-whitespace
15+
- id: end-of-file-fixer
16+
- id: check-yaml
17+
- id: check-toml
18+
- id: check-merge-conflict
19+
- id: check-added-large-files # blocks committing venvs / big data dumps
20+
args: [--maxkb=2048]

‎examples/flag.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
"""GLVQ example using the spiral dataset."""
2+
23
import argparse
34

45
import prototorch as pt
56
import pytorch_lightning as pl
67
import torch
8+
79
# Prototorch One Class Classifier
810
from prototorch_oneclass import SVQ_OCC
911
from prototorch_oneclass.datasets import Flag
10-
from prototorch_oneclass.functions.callbacks import (DynamicCallback,
11-
ThetaCallback)
12-
from prototorch_oneclass.functions.losses import (brier_score, csi_soft_loss,
13-
occ_entropy_loss)
12+
from prototorch_oneclass.functions.callbacks import DynamicCallback, ThetaCallback
13+
from prototorch_oneclass.functions.losses import brier_score
1414

1515
# Configuration
1616
num_classes = 1

‎examples/triangle.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
"""GLVQ example using the spiral dataset."""
2+
23
import argparse
34

45
import prototorch as pt
56
import pytorch_lightning as pl
67
import torch
8+
79
# Prototorch One Class Classifier
810
from prototorch_oneclass import SVQ_OCC
911
from prototorch_oneclass.datasets import Polygon
10-
from prototorch_oneclass.functions.callbacks import (DynamicCallback,
11-
ThetaCallback)
12-
from prototorch_oneclass.functions.losses import (brier_score, lpcsi_loss,
13-
occ_entropy_loss)
12+
from prototorch_oneclass.functions.callbacks import DynamicCallback, ThetaCallback
13+
from prototorch_oneclass.functions.losses import brier_score
1414

1515
# Configuration
1616
num_classes = 3

‎prototorch_oneclass/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from prototorch_oneclass.oneclass import (SVQ_OCC)
1+
from prototorch_oneclass.oneclass import SVQ_OCC
22

33
__all__ = ["SVQ_OCC"]

‎prototorch_oneclass/datasets/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
from prototorch_oneclass.datasets.polygon import Polygon
33
from prototorch_oneclass.datasets.shapes import Shapes
44

5-
__all__ = ['Flag', 'Polygon', 'Shapes']
5+
__all__ = ["Flag", "Polygon", "Shapes"]
Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
1-
""" Datasets for OneClassClassifier inspired by the PalauFlag """
1+
"""Datasets for OneClassClassifier inspired by the PalauFlag"""
22

33
import numpy as np
44
import torch
55

66
np.random.seed(42)
77

88

9-
def make_flag(num_samples=300,
10-
dimensions=2,
11-
num_classes=1,
12-
blobs_per_class=1,
13-
elipses=True):
14-
""" Generates a variation of the PalauFlag """
9+
def make_flag(num_samples=300, dimensions=2, num_classes=1, blobs_per_class=1, elipses=True):
10+
"""Generates a variation of the PalauFlag"""
1511
x = np.random.uniform(low=0.0, high=1.0, size=(num_samples, dimensions))
1612
y = np.full(num_samples, num_classes, dtype=int)
1713

1814
test = 1
1915

20-
blob_mean = np.random.uniform(low=0.1,
21-
high=0.9,
22-
size=(num_classes * blobs_per_class,
23-
dimensions))
24-
#blob_mean = np.random.uniform(low=0.5, high=0.5, size=(num_classes*blobs_per_class, dimensions))
25-
#blob_mean[:,0] = 0.2
26-
blob_bord = np.random.uniform(low=0.05 * dimensions * test,
27-
high=0.15 * dimensions * test,
28-
size=(num_classes * blobs_per_class,
29-
dimensions))
16+
blob_mean = np.random.uniform(
17+
low=0.1, high=0.9, size=(num_classes * blobs_per_class, dimensions)
18+
)
19+
# blob_mean = np.random.uniform(low=0.5, high=0.5, size=(num_classes*blobs_per_class, dimensions))
20+
# blob_mean[:,0] = 0.2
21+
blob_bord = np.random.uniform(
22+
low=0.05 * dimensions * test,
23+
high=0.15 * dimensions * test,
24+
size=(num_classes * blobs_per_class, dimensions),
25+
)
3026

3127
for target in range(num_classes):
3228
for blob in range(blobs_per_class):
@@ -36,7 +32,7 @@ def make_flag(num_samples=300,
3632
x_shf_pow = np.power(x_shifted, 2)
3733
bbord_pow = np.power(bord, 2)
3834
distances = np.sum(np.divide(x_shf_pow, bbord_pow), axis=1)
39-
in_border = np.where(distances < 1.)[0]
35+
in_border = np.where(distances < 1.0)[0]
4036
y[in_border] = target
4137

4238
print(x.shape, y.shape)
@@ -45,7 +41,7 @@ def make_flag(num_samples=300,
4541

4642

4743
class Flag(torch.utils.data.TensorDataset):
48-
""" Flag dataset for OOC.
44+
"""Flag dataset for OOC.
4945
5046
This datasets consists of n blobs of different classes and a background garbage noise.
5147
@@ -66,14 +62,16 @@ class Flag(torch.utils.data.TensorDataset):
6662
:param num_samples: number of random samples
6763
:param noise: noise added to the spirals
6864
"""
69-
def __init__(self,
70-
num_samples: int = 500,
71-
dimensions: int = 2,
72-
num_classes: int = 1,
73-
blobs_per_class: int = 1,
74-
elipses: bool = True):
75-
x, y = make_flag(num_samples, dimensions, num_classes, blobs_per_class,
76-
elipses)
65+
66+
def __init__(
67+
self,
68+
num_samples: int = 500,
69+
dimensions: int = 2,
70+
num_classes: int = 1,
71+
blobs_per_class: int = 1,
72+
elipses: bool = True,
73+
):
74+
x, y = make_flag(num_samples, dimensions, num_classes, blobs_per_class, elipses)
7775
self.data = torch.Tensor(x)
7876
self.target = torch.LongTensor(y)
7977
super().__init__(self.data, self.target)

‎prototorch_oneclass/datasets/polygon.py‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" Datasets for OneClassClassifier inspired by the PalauFlag """
1+
"""Datasets for OneClassClassifier inspired by the PalauFlag"""
22

33
import matplotlib.pyplot as plt
44
import numpy as np
@@ -20,8 +20,7 @@ def make_polygon(num_samples=300, dimensions=2, num_classes=3, thickness=0.1):
2020
high=[-1 + thickness, x_len + thickness],
2121
size=(num_samples // num_classes, dimensions),
2222
)
23-
rot = np.asarray([[np.cos(phi), -np.sin(phi)],
24-
[np.sin(phi), np.cos(phi)]])
23+
rot = np.asarray([[np.cos(phi), -np.sin(phi)], [np.sin(phi), np.cos(phi)]])
2524
x_ = np.matmul(x_, rot)
2625
x.append(x_)
2726
y.append(np.full(num_samples // num_classes, i))
@@ -33,7 +32,6 @@ def make_polygon(num_samples=300, dimensions=2, num_classes=3, thickness=0.1):
3332

3433

3534
class Polygon(torch.utils.data.TensorDataset):
36-
3735
def __init__(
3836
self,
3937
num_samples: int = 500,
@@ -47,7 +45,7 @@ def __init__(
4745
super().__init__(self.data, self.target)
4846

4947

50-
if __name__ == '__main__':
48+
if __name__ == "__main__":
5149
import matplotlib.pyplot as plt
5250

5351
for i in range(2):
@@ -60,6 +58,6 @@ def __init__(
6058
thickness=0.1 + 0.5 * i,
6159
)
6260
plt.subplot(2, 4, (i * 4) + j + 1)
63-
plt.axis('equal')
61+
plt.axis("equal")
6462
plt.scatter(x[:, 0], x[:, 1], c=y)
6563
plt.show()

‎prototorch_oneclass/datasets/s_shaped.py‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def make_S(
1717
center = radius
1818

1919
# first 'circle' centered at center with radius r
20-
t1 = np.random.uniform(0., 3 * np.pi / 2, int(n_samples / 2))
20+
t1 = np.random.uniform(0.0, 3 * np.pi / 2, int(n_samples / 2))
2121
x1 = radius * np.cos(t1)
2222
y1 = radius * np.sin(t1) + center
2323

@@ -50,13 +50,15 @@ def make_S(
5050

5151

5252
class S_Shape(torch.utils.data.TensorDataset):
53-
def __init__(self,
54-
n_samples: int = 800,
55-
center: float = 0.5,
56-
radius: float = 0.5,
57-
noise: float = 0.3,
58-
ratio: float = 0.5,
59-
**kwargs):
53+
def __init__(
54+
self,
55+
n_samples: int = 800,
56+
center: float = 0.5,
57+
radius: float = 0.5,
58+
noise: float = 0.3,
59+
ratio: float = 0.5,
60+
**kwargs,
61+
):
6062
x, y = make_S(n_samples, radius, noise, ratio)
6163
self.data = torch.squeeze(torch.Tensor(x))
6264
self.target = torch.squeeze(torch.LongTensor(y))

‎prototorch_oneclass/datasets/shapes.py‎

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,46 @@
55
np.random.seed(42)
66

77

8-
def create_shapes(num_samples=300,
9-
num_shapes=1,
10-
num_classes=1,
11-
outliers=0.0,
12-
**kwargs):
8+
def create_shapes(num_samples=300, num_shapes=1, num_classes=1, outliers=0.0, **kwargs):
139

14-
keys = ['centers', 'cluster_std', 'random_state', 'noise', 'factor']
10+
keys = ["centers", "cluster_std", "random_state", "noise", "factor"]
1511
for key in keys:
16-
if key not in kwargs.keys() and key != 'factor':
12+
if key not in kwargs.keys() and key != "factor":
1713
kwargs[key] = None
18-
if key not in kwargs.keys() and key == 'factor':
14+
if key not in kwargs.keys() and key == "factor":
1915
kwargs[key] = 0.8
2016

2117
outlier = int(outliers * num_samples)
2218
num_samples = num_samples - outlier
2319

2420
types = {
25-
'blobs':
26-
make_blobs(n_samples=num_samples,
27-
centers=kwargs['centers'],
28-
cluster_std=kwargs['cluster_std'],
29-
random_state=kwargs['random_state']),
30-
'circle':
31-
make_circles(n_samples=num_samples,
32-
noise=kwargs['noise'],
33-
random_state=kwargs['random_state'],
34-
factor=kwargs['factor']),
35-
'moon':
36-
make_moons(n_samples=num_samples,
37-
noise=kwargs['noise'],
38-
random_state=kwargs['random_state'])
21+
"blobs": make_blobs(
22+
n_samples=num_samples,
23+
centers=kwargs["centers"],
24+
cluster_std=kwargs["cluster_std"],
25+
random_state=kwargs["random_state"],
26+
),
27+
"circle": make_circles(
28+
n_samples=num_samples,
29+
noise=kwargs["noise"],
30+
random_state=kwargs["random_state"],
31+
factor=kwargs["factor"],
32+
),
33+
"moon": make_moons(
34+
n_samples=num_samples, noise=kwargs["noise"], random_state=kwargs["random_state"]
35+
),
3936
}
4037

41-
if kwargs['kind'] is None:
42-
kwargs['kind'] = 'moon'
43-
if not any(map(lambda shape: shape in kwargs['kind'], types.keys())):
44-
msg = 'kind must be in [{}, {}, {}]'.format(*types.keys())
38+
if kwargs["kind"] is None:
39+
kwargs["kind"] = "moon"
40+
if not any(map(lambda shape: shape in kwargs["kind"], types.keys())):
41+
msg = "kind must be in [{}, {}, {}]".format(*types.keys())
4542
raise ValueError(msg)
4643

4744
dataset, targets = [], []
4845
# TODO: extend for multiple shapes per class
4946
for j in range(num_shapes):
50-
dataset.append(types[kwargs['kind']])
47+
dataset.append(types[kwargs["kind"]])
5148

5249
datasets, targets = zip(*dataset)
5350
datasets = np.asarray(datasets)
@@ -56,23 +53,24 @@ def create_shapes(num_samples=300,
5653

5754

5855
class Shapes(torch.utils.data.TensorDataset):
59-
def __init__(self,
60-
num_samples: int = 300,
61-
num_shapes: int = 1,
62-
num_classes: int = 1,
63-
outliers=0.0,
64-
**kwargs):
65-
x, y = create_shapes(num_samples, num_shapes, num_classes, outliers,
66-
**kwargs)
56+
def __init__(
57+
self,
58+
num_samples: int = 300,
59+
num_shapes: int = 1,
60+
num_classes: int = 1,
61+
outliers=0.0,
62+
**kwargs,
63+
):
64+
x, y = create_shapes(num_samples, num_shapes, num_classes, outliers, **kwargs)
6765
self.data = torch.squeeze(torch.Tensor(x))
6866
print(self.data.shape)
6967
self.target = torch.squeeze(torch.LongTensor(y))
7068
super().__init__(self.data, self.target)
7169

7270

73-
if __name__ == '__main__':
71+
if __name__ == "__main__":
7472
# Configuration
75-
kind = 'blobs'
73+
kind = "blobs"
7674
num_samples = 1000
7775
num_shapes = 1
7876
num_classes = 2
@@ -85,12 +83,12 @@ def __init__(self,
8583
prototypes_per_class = 1
8684

8785
kwargs = {
88-
'kind': kind,
89-
'centers': center,
90-
'cluster_std': cluster_std,
91-
'random_state': random_state,
92-
'noise': noise,
93-
'factor': factor,
86+
"kind": kind,
87+
"centers": center,
88+
"cluster_std": cluster_std,
89+
"random_state": random_state,
90+
"noise": noise,
91+
"factor": factor,
9492
}
9593

9694
# Dataset

0 commit comments

Comments
 (0)