Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cff-version: 1.2.0
title: garg-aml
title: garg-aml-smurfing
message: >-
If you use this software, please cite both the software and the paper it
implements.
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ registered with:
| Field | Value |
|---|---|
| Owner | `VerbekeLab` |
| Repository | `garg-aml` |
| Repository | `garg-aml` (the GitHub repo) |
| PyPI project | `garg-aml-smurfing` |
| Workflow | `release.yml` |
| Environment | `release` |

Expand All @@ -99,7 +100,7 @@ confirm it works with nothing else present.

### If you cannot publish to PyPI

The `garg-aml` name has a single owner. If that account is unreachable, the code
The `garg-aml-smurfing` name has a single owner. If that account is unreachable, the code
is still safe — it lives in the `VerbekeLab` organisation — but the name is not
reclaimable quickly. Publish under a new name instead: change `name` in
`pyproject.toml`, register Trusted Publishing for the new project, and release
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# garg-aml
# GARG-AML

Graph-based detection of **smurfing** patterns in transaction networks.

Expand All @@ -9,16 +9,18 @@ are empty and whose off-diagonal parts are dense. GARG-AML scores every account
by exactly that contrast — one number in [-1, 1], computed from local structure
alone, with no training and no labels.

[![PyPI](https://img.shields.io/pypi/v/garg-aml.svg)](https://pypi.org/project/garg-aml/)
[![Python](https://img.shields.io/pypi/pyversions/garg-aml.svg)](https://pypi.org/project/garg-aml/)
[![PyPI](https://img.shields.io/pypi/v/garg-aml-smurfing.svg)](https://pypi.org/project/garg-aml-smurfing/)
[![Python](https://img.shields.io/pypi/pyversions/garg-aml-smurfing.svg)](https://pypi.org/project/garg-aml-smurfing/)
[![License: MIT](https://img.shields.io/badge/License-MIT-orange.svg)](LICENSE)

## Install

```bash
pip install garg-aml
pip install garg-aml-smurfing
```

> Installed as **`garg-aml-smurfing`**, imported as **`garg_aml`**. The shorter name was already taken on PyPI by an unrelated project.

## Use

```python
Expand Down
2 changes: 1 addition & 1 deletion docs/decisions/0006-no-torch-dependency.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ needs `torch` and `torch-geometric`. That baseline lives in the research
repository.

**Why.** GARG-AML computes a closed-form structural score; nothing in it learns.
A practitioner evaluating it should be able to `pip install garg-aml` and get a
A practitioner evaluating it should be able to `pip install garg-aml-smurfing` and get a
handful of megabytes. Pulling a deep-learning stack behind an unrelated score
would cost adoption for no functional gain, and would make the package
unusable in the locked-down environments where compliance teams work.
Expand Down
6 changes: 4 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# garg-aml
# GARG-AML

Find **smurfing** in a transaction network: one score per account, computed from
local structure, with nothing to train and no labels required.

```bash
pip install garg-aml
pip install garg-aml-smurfing
```

> Installed as **`garg-aml-smurfing`**, imported as **`garg_aml`**. The shorter name was already taken on PyPI by an unrelated project.

```python
import garg_aml as ga

Expand Down
10 changes: 5 additions & 5 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Installation

```bash
pip install garg-aml
pip install garg-aml-smurfing
```

Python 3.10 or newer. The core depends only on numpy, pandas, networkx and
Expand All @@ -11,11 +11,11 @@ scipy — no deep-learning stack, nothing that needs compiling.

| Extra | Install | What it adds |
|---|---|---|
| `progress` | `pip install 'garg-aml[progress]'` | `progress=True` progress bars (tqdm) |
| `parallel` | `pip install 'garg-aml[parallel]'` | `n_jobs` other than 1 (joblib) |
| `sklearn` | `pip install 'garg-aml[sklearn]'` | the `GargAmlScorer` estimator |
| `progress` | `pip install 'garg-aml-smurfing[progress]'` | `progress=True` progress bars (tqdm) |
| `parallel` | `pip install 'garg-aml-smurfing[parallel]'` | `n_jobs` other than 1 (joblib) |
| `sklearn` | `pip install 'garg-aml-smurfing[sklearn]'` | the `GargAmlScorer` estimator |

Ask for several at once with `pip install 'garg-aml[progress,parallel]'`.
Ask for several at once with `pip install 'garg-aml-smurfing[progress,parallel]'`.

Each is genuinely optional: the package imports and scores without any of them,
and reaching for a feature you have not installed raises an error that names the
Expand Down
2 changes: 1 addition & 1 deletion docs/reproducing.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ only through a function no experiment called. It is not ported. See
Pin an exact version when reproducing published numbers:

```bash
pip install garg-aml==0.1.0
pip install garg-aml-smurfing==0.1.0
```

Each release is tagged in the repository and archived with a DOI, so a paper can
Expand Down
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
site_name: garg-aml
site_name: GARG-AML
site_description: Graph-based detection of smurfing patterns in transaction networks
repo_url: https://github.com/VerbekeLab/garg-aml
edit_uri: edit/main/docs/
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["hatchling>=1.27"]
build-backend = "hatchling.build"

[project]
name = "garg-aml"
name = "garg-aml-smurfing"
dynamic = ["version"]
description = "Graph-based detection of smurfing patterns in transaction networks."
readme = "README.md"
Expand Down
3 changes: 2 additions & 1 deletion src/garg_aml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ def __getattr__(name: str) -> Any:
from .estimator import GargAmlScorer
except ImportError as exc: # pragma: no cover - depends on the environment
raise ImportError(
"GargAmlScorer needs scikit-learn: pip install 'garg-aml[sklearn]'"
"GargAmlScorer needs scikit-learn: "
"pip install 'garg-aml-smurfing[sklearn]'"
) from exc
return GargAmlScorer
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
5 changes: 3 additions & 2 deletions src/garg_aml/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def _progress(nodes: list, show: bool) -> Iterable:
from tqdm import tqdm
except ImportError as exc: # pragma: no cover - depends on the environment
raise ImportError(
"progress=True needs tqdm: pip install 'garg-aml[progress]'"
"progress=True needs tqdm: pip install 'garg-aml-smurfing[progress]'"
) from exc
return tqdm(nodes)

Expand Down Expand Up @@ -56,7 +56,8 @@ def measure(node: Hashable) -> tuple[float, ...]:
from joblib import Parallel, delayed
except ImportError as exc: # pragma: no cover - depends on the environment
raise ImportError(
"n_jobs other than 1 needs joblib: pip install 'garg-aml[parallel]'"
"n_jobs other than 1 needs joblib: "
"pip install 'garg-aml-smurfing[parallel]'"
) from exc

# Each worker receives its own copy of the graph, so the memory cost scales
Expand Down
Loading