edm98 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- edm98-0.1.0/LICENSE +26 -0
- edm98-0.1.0/PKG-INFO +372 -0
- edm98-0.1.0/README.md +332 -0
- edm98-0.1.0/pyproject.toml +69 -0
- edm98-0.1.0/setup.cfg +4 -0
- edm98-0.1.0/src/edm98/__init__.py +5 -0
- edm98-0.1.0/src/edm98/cli.py +227 -0
- edm98-0.1.0/src/edm98/constants.py +21 -0
- edm98-0.1.0/src/edm98/gradio_app.py +754 -0
- edm98-0.1.0/src/edm98/inference/__init__.py +15 -0
- edm98-0.1.0/src/edm98/inference/helpers.py +60 -0
- edm98-0.1.0/src/edm98/inference/labels.py +28 -0
- edm98-0.1.0/src/edm98/inference/model.py +191 -0
- edm98-0.1.0/src/edm98/inference/pipeline.py +603 -0
- edm98-0.1.0/src/edm98/inference/postprocess.py +93 -0
- edm98-0.1.0/src/edm98/loaders.py +85 -0
- edm98-0.1.0/src/edm98/resources/LICENSE +21 -0
- edm98-0.1.0/src/edm98/resources/__init__.py +5 -0
- edm98-0.1.0/src/edm98/resources/dataset.jsonl +98 -0
- edm98-0.1.0/src/edm98/resources/splits/__init__.py +1 -0
- edm98-0.1.0/src/edm98/resources/splits/test.txt +10 -0
- edm98-0.1.0/src/edm98/resources/splits/train.txt +79 -0
- edm98-0.1.0/src/edm98/resources/splits/val.txt +11 -0
- edm98-0.1.0/src/edm98/schema.py +151 -0
- edm98-0.1.0/src/edm98.egg-info/PKG-INFO +372 -0
- edm98-0.1.0/src/edm98.egg-info/SOURCES.txt +32 -0
- edm98-0.1.0/src/edm98.egg-info/dependency_links.txt +1 -0
- edm98-0.1.0/src/edm98.egg-info/entry_points.txt +2 -0
- edm98-0.1.0/src/edm98.egg-info/requires.txt +17 -0
- edm98-0.1.0/src/edm98.egg-info/top_level.txt +1 -0
- edm98-0.1.0/tests/test_cli.py +71 -0
- edm98-0.1.0/tests/test_inference_optional.py +15 -0
- edm98-0.1.0/tests/test_schema.py +35 -0
- edm98-0.1.0/tests/test_smoke.py +5 -0
edm98-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Creative Commons Attribution 4.0 International Public License
|
|
2
|
+
|
|
3
|
+
By exercising the Licensed Rights (defined below), You accept and agree
|
|
4
|
+
to be bound by the terms and conditions of this Creative Commons
|
|
5
|
+
Attribution 4.0 International Public License ("Public License").
|
|
6
|
+
To the extent this Public License may be interpreted as a contract,
|
|
7
|
+
You are granted the Licensed Rights in consideration of Your acceptance
|
|
8
|
+
of these terms and conditions, and the Licensor grants You such rights
|
|
9
|
+
in consideration of benefits the Licensor receives from making
|
|
10
|
+
the Licensed Material available under these terms and conditions.
|
|
11
|
+
|
|
12
|
+
You are free to:
|
|
13
|
+
- Share — copy and redistribute the material in any medium or format
|
|
14
|
+
- Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
|
15
|
+
|
|
16
|
+
Under the following terms:
|
|
17
|
+
- Attribution — You must give appropriate credit, provide a link to the license,
|
|
18
|
+
and indicate if changes were made. You may do so in any reasonable manner,
|
|
19
|
+
but not in any way that suggests the licensor endorses you or your use.
|
|
20
|
+
|
|
21
|
+
No additional restrictions — You may not apply legal terms or
|
|
22
|
+
technological measures that legally restrict others from doing
|
|
23
|
+
anything the license permits.
|
|
24
|
+
|
|
25
|
+
Full license text:
|
|
26
|
+
https://creativecommons.org/licenses/by/4.0/legalcode
|
edm98-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: edm98
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: EDM-98 dataset package with optional EDMFormer inference tooling
|
|
5
|
+
Author: Sahal Sajeer Kalandan
|
|
6
|
+
License: CC-BY-4.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/25ohms/EDM-98
|
|
8
|
+
Project-URL: Repository, https://github.com/25ohms/EDM-98
|
|
9
|
+
Project-URL: Issues, https://github.com/25ohms/EDM-98/issues
|
|
10
|
+
Project-URL: Paper, https://arxiv.org/abs/2603.08759
|
|
11
|
+
Keywords: music,dataset,edm,structure-analysis,audio
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
License-File: src/edm98/resources/LICENSE
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff>=0.11.0; extra == "dev"
|
|
28
|
+
Requires-Dist: PyYAML>=6.0; extra == "dev"
|
|
29
|
+
Provides-Extra: inference
|
|
30
|
+
Requires-Dist: PyYAML>=6.0; extra == "inference"
|
|
31
|
+
Requires-Dist: torch>=2.4.0; extra == "inference"
|
|
32
|
+
Requires-Dist: librosa>=0.11.0; extra == "inference"
|
|
33
|
+
Requires-Dist: omegaconf>=2.3.0; extra == "inference"
|
|
34
|
+
Requires-Dist: safetensors>=0.5.3; extra == "inference"
|
|
35
|
+
Requires-Dist: x-transformers>=2.4.14; extra == "inference"
|
|
36
|
+
Requires-Dist: scipy>=1.15.0; extra == "inference"
|
|
37
|
+
Provides-Extra: ui
|
|
38
|
+
Requires-Dist: gradio>=5.0; extra == "ui"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# EDM-98
|
|
42
|
+
|
|
43
|
+
`EDM-98` packages the EDM-98 dataset and an optional EDMFormer-based inference stack for local experimentation, app development, and downstream tooling.
|
|
44
|
+
|
|
45
|
+
## What Is Included
|
|
46
|
+
|
|
47
|
+
- the canonical EDM-98 label artifact packaged with the module
|
|
48
|
+
- canonical split files packaged with the module
|
|
49
|
+
- a lightweight Python package for dataset loading and validation
|
|
50
|
+
- an optional inference pipeline for EDMFormer
|
|
51
|
+
- a CLI for validation, prediction, cache warming, and demo launch
|
|
52
|
+
- a Gradio app with a waveform timeline and color-coded section predictions
|
|
53
|
+
|
|
54
|
+
## Dataset
|
|
55
|
+
|
|
56
|
+
EDM-98 was created from a curated 98-song set with Rekordbox cue-point labeling. The original dataset artifact was created as JSON and later converted to JSONL to match the label-file format expected by the SongFormer architecture.
|
|
57
|
+
|
|
58
|
+
The dataset and split files are loaded from packaged resources inside `edm98`, under `src/edm98/resources/`. That packaged copy is the canonical source used by the Python API and PyPI distribution.
|
|
59
|
+
|
|
60
|
+
The primary labels exposed by the EDMFormer setup are:
|
|
61
|
+
|
|
62
|
+
- `intro`
|
|
63
|
+
- `buildup`
|
|
64
|
+
- `drop`
|
|
65
|
+
- `breakdown`
|
|
66
|
+
- `outro`
|
|
67
|
+
- `silence`
|
|
68
|
+
|
|
69
|
+
Each packaged dataset record currently includes:
|
|
70
|
+
|
|
71
|
+
- `id`: the Deezer track identifier used as the canonical record ID
|
|
72
|
+
- `labels`: a strictly increasing list of `[time, label]` pairs terminated by `end`
|
|
73
|
+
- `file_path`: the original filename used during labeling when available
|
|
74
|
+
|
|
75
|
+
For local preprocessing and training, the canonical audio contract is that each downloaded song is stored as `<deezer_id>.<ext>`, for example `1060564312.mp3`. `file_path` is preserved as provenance metadata, not as the primary lookup key.
|
|
76
|
+
|
|
77
|
+
The package does not redistribute the audio itself. The Deezer IDs are included so users can map the metadata back to externally downloaded audio.
|
|
78
|
+
|
|
79
|
+
## Accessing The Dataset
|
|
80
|
+
|
|
81
|
+
Load the canonical packaged dataset:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from edm98.loaders import load_dataset_records, load_all_splits, load_records_by_split
|
|
85
|
+
|
|
86
|
+
records = load_dataset_records()
|
|
87
|
+
splits = load_all_splits()
|
|
88
|
+
train_records = load_records_by_split("train")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Example record shape:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
{
|
|
95
|
+
"id": "1060564312",
|
|
96
|
+
"labels": [
|
|
97
|
+
(0.054, "intro"),
|
|
98
|
+
(35.942, "buildup"),
|
|
99
|
+
(58.38, "silence"),
|
|
100
|
+
(62.866, "drop"),
|
|
101
|
+
...
|
|
102
|
+
(247.0, "end"),
|
|
103
|
+
],
|
|
104
|
+
"file_path": "01 - Oak - Airwalk.mp3",
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If you have downloaded the corresponding audio externally, you can join the metadata back to a local music directory by Deezer ID. For example:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from pathlib import Path
|
|
112
|
+
|
|
113
|
+
from edm98.loaders import load_dataset_records
|
|
114
|
+
|
|
115
|
+
audio_dir = Path("/path/to/downloaded/audio")
|
|
116
|
+
records = load_dataset_records()
|
|
117
|
+
extensions = (".mp3", ".wav", ".flac", ".m4a")
|
|
118
|
+
|
|
119
|
+
for record in records:
|
|
120
|
+
for ext in extensions:
|
|
121
|
+
candidate = audio_dir / f"{record['id']}{ext}"
|
|
122
|
+
if candidate.exists():
|
|
123
|
+
print(record["id"], candidate, record["labels"][:3])
|
|
124
|
+
break
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This assumes you have already acquired the audio separately. `edm98` provides the labels, IDs, and split definitions; it does not fetch or ship the songs.
|
|
128
|
+
|
|
129
|
+
## Training Preparation
|
|
130
|
+
|
|
131
|
+
`edm98` is primarily a dataset package, but the packaged labels and split files can also be used as the canonical dataset-side inputs for EDMFormer-style training.
|
|
132
|
+
|
|
133
|
+
The repository includes a simple notebook at `notebooks/edm98_training_prep.ipynb` that shows:
|
|
134
|
+
|
|
135
|
+
- how to load the packaged metadata and split IDs
|
|
136
|
+
- how to map dataset records back to externally downloaded audio
|
|
137
|
+
- how to structure the four embedding directories EDMFormer expects
|
|
138
|
+
- how to construct the minimal train/eval dataset configuration
|
|
139
|
+
|
|
140
|
+
The audio itself is still external. A typical flow is:
|
|
141
|
+
|
|
142
|
+
1. Install `edm98` and load the packaged records.
|
|
143
|
+
2. Download the songs separately using the provided Deezer IDs and store them as `<deezer_id>.<ext>`.
|
|
144
|
+
3. Generate the MuQ and MusicFM embeddings required by EDMFormer.
|
|
145
|
+
4. Point your training configuration at the packaged JSONL labels and split files.
|
|
146
|
+
|
|
147
|
+
Minimal example:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from pathlib import Path
|
|
151
|
+
|
|
152
|
+
from edm98.loaders import load_records_by_split
|
|
153
|
+
|
|
154
|
+
audio_dir = Path("/path/to/downloaded/audio")
|
|
155
|
+
train_records = load_records_by_split("train")
|
|
156
|
+
extensions = (".mp3", ".wav", ".flac", ".m4a")
|
|
157
|
+
|
|
158
|
+
resolved = []
|
|
159
|
+
for record in train_records:
|
|
160
|
+
for ext in extensions:
|
|
161
|
+
candidate = audio_dir / f"{record['id']}{ext}"
|
|
162
|
+
if candidate.exists():
|
|
163
|
+
resolved.append(
|
|
164
|
+
{
|
|
165
|
+
"id": record["id"],
|
|
166
|
+
"audio_path": candidate,
|
|
167
|
+
"labels": record["labels"],
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
break
|
|
171
|
+
|
|
172
|
+
resolved[:2]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
That resolved list is the starting point for a preprocessing step that generates the EDMFormer-compatible MuQ and MusicFM embedding directories used during training.
|
|
176
|
+
|
|
177
|
+
## Installation
|
|
178
|
+
|
|
179
|
+
### Dataset-only
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pip install edm98
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Inference
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
git clone https://github.com/25ohms/EDM-98.git
|
|
189
|
+
cd EDM-98
|
|
190
|
+
./scripts/install_inference_deps.sh
|
|
191
|
+
pip install -e ".[ui]"
|
|
192
|
+
export MUSICFMPATH="$PWD/third_party/musicfm"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`third_party/musicfm` is provisioned locally by the install script because upstream MusicFM is not published as an installable Python package. The same script also installs MuQ from its upstream source repository. Set `MUSICFMPATH` to that checkout when using the optional local inference workflow.
|
|
196
|
+
|
|
197
|
+
## Checkpoints And Cache
|
|
198
|
+
|
|
199
|
+
Expected local inference assets:
|
|
200
|
+
|
|
201
|
+
- `data/checkpoints/model.pt`
|
|
202
|
+
- `data/checkpoints/pretrained_msd.pt`
|
|
203
|
+
- `data/checkpoints/msd_stats.json`
|
|
204
|
+
- `configs/edmformer.yaml`
|
|
205
|
+
|
|
206
|
+
MuQ and MusicFM also depend on Hugging Face-backed upstream assets. Those are cached automatically under `.cache/huggingface/` on first use and reused on later runs.
|
|
207
|
+
|
|
208
|
+
Optional cache commands:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
python -m edm98.cli warm-cache
|
|
212
|
+
python -m edm98.cli predict --offline path/to/song.mp3
|
|
213
|
+
python -m edm98.cli predict --no-cache path/to/song.mp3
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## CLI
|
|
217
|
+
|
|
218
|
+
Validate the dataset:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
python -m edm98.cli validate-dataset
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Run inference on one file:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
python -m edm98.cli predict --device cuda --low-memory path/to/song.mp3
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Launch the Gradio demo:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
python -m edm98.cli demo --device cuda --server-name 0.0.0.0 --server-port 7860
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Gradio Demo
|
|
237
|
+
|
|
238
|
+
The Gradio app uses the same inference backend as the CLI and preloads the inference pipeline when the app starts. That pipeline stays alive until the process exits, so the app does not rebuild the full EDMFormer, MuQ, and MusicFM stack for every request.
|
|
239
|
+
|
|
240
|
+
The demo is intentionally persistent. Start it once, keep the process running, and reuse the loaded pipeline until you close the app.
|
|
241
|
+
|
|
242
|
+
The demo currently provides:
|
|
243
|
+
|
|
244
|
+
- a file upload flow
|
|
245
|
+
- a full-width color-coded waveform timeline
|
|
246
|
+
- labeled section regions
|
|
247
|
+
- a moving playback cursor
|
|
248
|
+
- a tabular view of predicted sections with minute-second timestamps
|
|
249
|
+
|
|
250
|
+
To launch the demo:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
./scripts/install_inference_deps.sh
|
|
254
|
+
pip install -e ".[ui]"
|
|
255
|
+
export MUSICFMPATH="$PWD/third_party/musicfm"
|
|
256
|
+
python -m edm98.cli demo --device cuda --server-name 0.0.0.0 --server-port 7860
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
If you are running on a remote machine, expose or forward the chosen port and open the forwarded local URL in your browser.
|
|
260
|
+
|
|
261
|
+
### Demo Options
|
|
262
|
+
|
|
263
|
+
Useful demo flags:
|
|
264
|
+
|
|
265
|
+
- `--device auto`: pick the best available backend automatically
|
|
266
|
+
- `--device cuda`: run on an NVIDIA GPU
|
|
267
|
+
- `--device mps`: run on Apple Silicon via Metal
|
|
268
|
+
- `--device cpu`: force CPU inference
|
|
269
|
+
- `--server-name 0.0.0.0`: bind on all interfaces so you can forward or expose the port
|
|
270
|
+
- `--server-port 7860`: choose a different port if needed
|
|
271
|
+
- `--offline`: require Hugging Face-backed assets to already exist in the local cache
|
|
272
|
+
- `--no-cache`: use a temporary cache directory for this run
|
|
273
|
+
- `--hf-cache-dir <path>`: override the default Hugging Face cache location
|
|
274
|
+
|
|
275
|
+
`--low-memory` is useful for one-off CLI prediction runs, but it is not the intended mode for the Gradio demo. The demo is designed to keep its models resident until shutdown.
|
|
276
|
+
|
|
277
|
+
## Platform Notes
|
|
278
|
+
|
|
279
|
+
The CLI currently supports `--device auto`, `--device cpu`, `--device cuda`, and `--device mps`.
|
|
280
|
+
|
|
281
|
+
### Linux
|
|
282
|
+
|
|
283
|
+
Linux is the most straightforward setup for GPU-backed demo usage.
|
|
284
|
+
|
|
285
|
+
- NVIDIA GPU: use `--device cuda`
|
|
286
|
+
- CPU-only: use `--device cpu`
|
|
287
|
+
- Typical demo launch:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
./scripts/install_inference_deps.sh
|
|
291
|
+
pip install -e ".[ui]"
|
|
292
|
+
export MUSICFMPATH="$PWD/third_party/musicfm"
|
|
293
|
+
python -m edm98.cli demo --device cuda --server-name 0.0.0.0 --server-port 7860
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### macOS
|
|
297
|
+
|
|
298
|
+
On Apple Silicon, use Metal via `--device mps`.
|
|
299
|
+
|
|
300
|
+
- Apple Silicon demo launch:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
./scripts/install_inference_deps.sh
|
|
304
|
+
pip install -e ".[ui]"
|
|
305
|
+
export MUSICFMPATH="$PWD/third_party/musicfm"
|
|
306
|
+
python -m edm98.cli demo --device mps --server-name 127.0.0.1 --server-port 7860
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- If MPS is unavailable or unstable in your local environment, fall back to `--device cpu`
|
|
310
|
+
|
|
311
|
+
### Windows
|
|
312
|
+
|
|
313
|
+
The supported install helper in this repository is `scripts/install_inference_deps.sh`, which is a Bash script. Because of that, the smoothest Windows path is currently a Bash-compatible environment such as WSL2 or Git Bash, with WSL2 being the more predictable choice for ML dependencies.
|
|
314
|
+
|
|
315
|
+
- Windows + WSL2 + NVIDIA GPU: use `--device cuda`
|
|
316
|
+
- Windows + WSL2 CPU-only: use `--device cpu`
|
|
317
|
+
- If you want a browser on Windows to access a demo running inside WSL2, open the forwarded localhost URL from Windows after launch
|
|
318
|
+
|
|
319
|
+
If you are running a fully native Windows Python environment instead of WSL2, the same CLI flags apply, but you will need to reproduce the install-script steps manually.
|
|
320
|
+
|
|
321
|
+
## Python API
|
|
322
|
+
|
|
323
|
+
For one-off inference:
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
from edm98.inference import predict_file
|
|
327
|
+
|
|
328
|
+
prediction = predict_file("song.mp3", device="cuda", low_memory=True)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
For app integration or repeated use, create the pipeline once and reuse it:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
from edm98.inference import create_pipeline
|
|
335
|
+
|
|
336
|
+
pipeline = create_pipeline(
|
|
337
|
+
device="cuda",
|
|
338
|
+
persistent_models=True,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
prediction = pipeline.predict_file("song.mp3")
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
This is the same pattern used by the Gradio app.
|
|
345
|
+
|
|
346
|
+
## Developer Notes
|
|
347
|
+
|
|
348
|
+
- `predict` is suitable for single-use command-line workflows.
|
|
349
|
+
- `InferencePipeline` is the stable object to reuse inside other applications.
|
|
350
|
+
- `create_pipeline(...)` is provided as a small convenience wrapper for app startup code.
|
|
351
|
+
- the current repo-local cache behavior is the default and should remain transparent to most users
|
|
352
|
+
|
|
353
|
+
## Validation
|
|
354
|
+
|
|
355
|
+
Dataset validation:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
python -m edm98.cli validate-dataset
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Test suite:
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
pytest -q
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Licensing
|
|
368
|
+
|
|
369
|
+
This repository uses separate licenses by component:
|
|
370
|
+
|
|
371
|
+
- repository code and model-related materials: CC BY 4.0
|
|
372
|
+
- packaged dataset metadata and split files: MIT
|