Skip to content

Commit 50f4ddb

Browse files
committed
add initial files
1 parent 2d8db70 commit 50f4ddb

File tree

10 files changed

+270
-0
lines changed

10 files changed

+270
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**Minimal Working Example**
14+
Please provide a piece of code that leads to the bug you encounter.
15+
16+
If the code is **runnable**, it will help us identify the problem faster.
17+
18+
**Package versions**
19+
20+
Please provide the versions you use. To do this, run the code:
21+
```julia
22+
using Pkg
23+
Pkg.status([
24+
"Package1", "Package2"]; # etc.
25+
mode = PKGMODE_MANIFEST
26+
)
27+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the feature you'd like to have**
11+
12+
**Cite scientific papers related to the feature/algorithm**
13+
14+
**If possible, sketch out an implementation strategy**

.github/workflows/CompatHelper.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: CompatHelper
2+
on:
3+
schedule:
4+
- cron: 0 0 * * *
5+
workflow_dispatch:
6+
permissions:
7+
contents: write
8+
pull-requests: write
9+
jobs:
10+
CompatHelper:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Check if Julia is already available in the PATH
14+
id: julia_in_path
15+
run: which julia
16+
continue-on-error: true
17+
- name: Install Julia, but only if it is not already available in the PATH
18+
uses: julia-actions/setup-julia@v1
19+
with:
20+
version: '1'
21+
arch: ${{ runner.arch }}
22+
if: steps.julia_in_path.outcome != 'success'
23+
- name: "Add the General registry via Git"
24+
run: |
25+
import Pkg
26+
ENV["JULIA_PKG_SERVER"] = ""
27+
Pkg.Registry.add("General")
28+
shell: julia --color=yes {0}
29+
- name: "Install CompatHelper"
30+
run: |
31+
import Pkg
32+
name = "CompatHelper"
33+
uuid = "aa819f21-2bde-4658-8897-bab36330d9b7"
34+
version = "3"
35+
Pkg.add(; name, uuid, version)
36+
shell: julia --color=yes {0}
37+
- name: "Run CompatHelper"
38+
run: |
39+
import CompatHelper
40+
CompatHelper.main()
41+
shell: julia --color=yes {0}
42+
env:
43+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
45+
# COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}

.github/workflows/TagBot.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: TagBot
2+
on:
3+
issue_comment:
4+
types:
5+
- created
6+
workflow_dispatch:
7+
jobs:
8+
TagBot:
9+
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: JuliaRegistries/TagBot@v1
13+
with:
14+
token: ${{ secrets.GITHUB_TOKEN }}
15+
ssh: ${{ secrets.DOCUMENTER_KEY }}

.github/workflows/ci.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: CI
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
- '**' # matches every branch
7+
push:
8+
branches:
9+
- main
10+
tags: '*'
11+
jobs:
12+
test:
13+
name: Tests, Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
version:
19+
- '1'
20+
os: [ubuntu-latest] # adjust according to need, e.g. os: [ubuntu-latest] if testing only on linux
21+
arch:
22+
- x64
23+
steps:
24+
# Cancel ongoing CI test runs if pushing to branch again before the previous tests
25+
# have finished
26+
- name: Cancel ongoing test runs for previous commits
27+
uses: styfle/[email protected]
28+
with:
29+
access_token: ${{ github.token }}
30+
31+
# Do tests
32+
- uses: actions/checkout@v2
33+
- uses: julia-actions/setup-julia@v1
34+
with:
35+
version: ${{ matrix.version }}
36+
arch: ${{ matrix.arch }}
37+
- uses: actions/cache@v1
38+
env:
39+
cache-name: cache-artifacts
40+
with:
41+
path: ~/.julia/artifacts
42+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
43+
restore-keys: |
44+
${{ runner.os }}-test-${{ env.cache-name }}-
45+
${{ runner.os }}-test-
46+
${{ runner.os }}-
47+
- uses: julia-actions/julia-buildpkg@v1
48+
49+
- uses: julia-actions/julia-runtest@v1
50+
- uses: julia-actions/julia-processcoverage@v1
51+
- uses: codecov/codecov-action@v1
52+
with:
53+
file: lcov.info

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 JuliaDynamics
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name = "ClusteringAPI"
2+
uuid = "c60ac3cc-f4a1-4e3a-9706-ecb4d2c8df9c"
3+
authors = ["Datseris <[email protected]>"]
4+
version = "0.1.0"

src/ClusteringAPI.jl

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
module ClusteringAPI
2+
3+
# Use the README as the module docs
4+
@doc let
5+
path = joinpath(dirname(@__DIR__), "README.md")
6+
include_dependency(path)
7+
read(path, String)
8+
end ClusteringAPI
9+
10+
export ClusteringAlgorithm, ClusteringResults
11+
export cluster, cluster_number, cluster_labels
12+
13+
abstract type ClusteringAlgorithm end
14+
abstract type ClusteringResults end
15+
16+
"""
17+
cluster(ca::ClusteringAlgortihm, data) → cr::ClusteringResults
18+
19+
Cluster input `data` according to the algorithm specified by `ca`.
20+
All options related to the algorithm are given as keyword arguments when
21+
constructing `ca`. The input data can be specified two ways:
22+
23+
- as a (d, m) matrix, with d the dimension of the data points and m the amount of
24+
data points (i.e., each column is a data point).
25+
- as a length-m vector of length-d vectors (i.e., each inner vector is a data point).
26+
27+
The cluster labels are always the
28+
positive integers `1:n` with `n::Int` the number of created clusters.
29+
30+
The output is always a subtype of `ClusteringResults`,
31+
which always extends the following two methods:
32+
33+
- `cluster_number(cr)` returns `n`.
34+
- `cluster_labels(cr)` returns `labels::Vector{Int}` a length-m vector of labels
35+
mapping each data point to each cluster (`1:n`).
36+
37+
and always includes `ca` in the field `algorithm`.
38+
39+
Other algorithm-related output can be obtained as a field of the result type,
40+
or other specific functions of the result type.
41+
This is described in the individual algorithm implementations.
42+
"""
43+
function cluster(ca::ClusteringAlgorithm, data::AbstractMatrix)
44+
throw(ArgumentError("No implementation for `cluster` for $(typeof(ca))."))
45+
end
46+
47+
"""
48+
cluster_number(cr::ClusteringResults) → n::Int
49+
50+
Return the number of created clusters in the output of [`cluster`](@ref).
51+
"""
52+
function cluster_number(cr::ClusteringResults)
53+
return length(Set(cluster_labels(cr))) # fastest way to count unique elements
54+
end
55+
56+
"""
57+
cluster_labels(cr::ClusteringResults) → labels::Vector{Int}
58+
59+
Return the cluster labels of the data points used in [`cluster`](@ref).
60+
"""
61+
function cluster_labels(cr::ClusteringResults)
62+
return cr.labels # typically there
63+
end
64+
65+
# two helper functions for agnostic input data type
66+
"""
67+
input_data_size(data) → (d, m)
68+
69+
Return the data point dimension and number of data points.
70+
"""
71+
input_data_size(A::AbstractMatrix) = size(A)
72+
input_data_size(A::AbstractVector{<:AbstractVector}) = (length(first(A)), length(A))
73+
74+
"""
75+
each_data_point(data)
76+
77+
Return an indexable iterator over each data point in `data`, that can be
78+
indexed with indices `1:m`.
79+
"""
80+
each_data_point(A::AbstractMatrix) = eachcol(A)
81+
each_data_point(A::AbstractVector{<:AbstractVector}) = A
82+
83+
end

test/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[deps]
2+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3+
Clustering = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"

test/runtests.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
using Test
2+
using ClusteringAPI
3+
4+
@test true
5+

0 commit comments

Comments
 (0)