ddacs 2.0.0__py3-none-any.whl
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.
- ddacs/__init__.py +65 -0
- ddacs/cli.py +462 -0
- ddacs/generators.py +256 -0
- ddacs/pytorch.py +212 -0
- ddacs/utils.py +441 -0
- ddacs-2.0.0.dist-info/METADATA +275 -0
- ddacs-2.0.0.dist-info/RECORD +11 -0
- ddacs-2.0.0.dist-info/WHEEL +5 -0
- ddacs-2.0.0.dist-info/entry_points.txt +2 -0
- ddacs-2.0.0.dist-info/licenses/LICENSE +21 -0
- ddacs-2.0.0.dist-info/top_level.txt +1 -0
ddacs/__init__.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DDACS - Deep Drawing and Cutting Simulations Dataset.
|
|
3
|
+
|
|
4
|
+
A Python package for accessing and processing the DDACS dataset containing
|
|
5
|
+
FEM simulations of sheet metal forming processes.
|
|
6
|
+
|
|
7
|
+
Examples:
|
|
8
|
+
>>> from ddacs import iter_ddacs, count_available_simulations
|
|
9
|
+
>>> count = count_available_simulations('./data')
|
|
10
|
+
>>> for sim_id, metadata, h5_path in iter_ddacs('./data'):
|
|
11
|
+
... print(f"Simulation {sim_id}")
|
|
12
|
+
|
|
13
|
+
>>> from ddacs.utils import extract_mesh, extract_element_thickness
|
|
14
|
+
>>> vertices, triangles = extract_mesh('simulation.h5', 'blank')
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__version__ = "2.0.0"
|
|
18
|
+
|
|
19
|
+
from .generators import (
|
|
20
|
+
count_available_simulations,
|
|
21
|
+
get_simulation_by_id,
|
|
22
|
+
iter_ddacs,
|
|
23
|
+
iter_h5_files,
|
|
24
|
+
sample_simulations,
|
|
25
|
+
)
|
|
26
|
+
from .utils import (
|
|
27
|
+
compute_von_mises,
|
|
28
|
+
display_structure,
|
|
29
|
+
extract_element_strain,
|
|
30
|
+
extract_element_stress,
|
|
31
|
+
extract_element_thickness,
|
|
32
|
+
extract_mesh,
|
|
33
|
+
extract_point_cloud,
|
|
34
|
+
extract_point_springback,
|
|
35
|
+
non_degenerate_mask,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Optional PyTorch dataset (only if PyTorch is available)
|
|
39
|
+
try:
|
|
40
|
+
from .pytorch import DDACSDataset
|
|
41
|
+
except ImportError:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
__all__ = [
|
|
45
|
+
# Version
|
|
46
|
+
"__version__",
|
|
47
|
+
# Generators
|
|
48
|
+
"iter_ddacs",
|
|
49
|
+
"iter_h5_files",
|
|
50
|
+
"get_simulation_by_id",
|
|
51
|
+
"sample_simulations",
|
|
52
|
+
"count_available_simulations",
|
|
53
|
+
# Utils
|
|
54
|
+
"extract_point_cloud",
|
|
55
|
+
"extract_mesh",
|
|
56
|
+
"extract_element_thickness",
|
|
57
|
+
"extract_element_stress",
|
|
58
|
+
"extract_element_strain",
|
|
59
|
+
"extract_point_springback",
|
|
60
|
+
"compute_von_mises",
|
|
61
|
+
"non_degenerate_mask",
|
|
62
|
+
"display_structure",
|
|
63
|
+
# PyTorch (optional)
|
|
64
|
+
"DDACSDataset",
|
|
65
|
+
]
|
ddacs/cli.py
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DDACS dataset CLI for downloading data from DaRUS.
|
|
3
|
+
|
|
4
|
+
Provides commands to view dataset information and download files from the
|
|
5
|
+
DDACS (Deep Drawing and Cutting Simulations) dataset hosted on DaRUS.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
ddacs info # Show dataset info and versions
|
|
9
|
+
ddacs download # Download dataset v2.0, extract, ready to use
|
|
10
|
+
ddacs download --small # Download small test set for demos
|
|
11
|
+
ddacs download --files a.zip # Download specific files
|
|
12
|
+
ddacs download --no-extract # Download without extracting
|
|
13
|
+
ddacs download --keep-zip # Keep zip files after extraction
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
__version__ = "2.0.0"
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import os
|
|
20
|
+
import zipfile
|
|
21
|
+
|
|
22
|
+
import requests
|
|
23
|
+
from humanfriendly import format_size
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.panel import Panel
|
|
26
|
+
from rich.progress import (
|
|
27
|
+
BarColumn,
|
|
28
|
+
DownloadColumn,
|
|
29
|
+
Progress,
|
|
30
|
+
TextColumn,
|
|
31
|
+
TimeRemainingColumn,
|
|
32
|
+
TransferSpeedColumn,
|
|
33
|
+
)
|
|
34
|
+
from rich.prompt import Confirm
|
|
35
|
+
from rich.table import Table
|
|
36
|
+
|
|
37
|
+
console = Console()
|
|
38
|
+
|
|
39
|
+
# DaRUS repository configuration
|
|
40
|
+
DARUS_URL = "https://darus.uni-stuttgart.de"
|
|
41
|
+
DDACS_DOI = "doi:10.18419/darus-4801"
|
|
42
|
+
DDACS_NAME = "DDACS"
|
|
43
|
+
SMALL_TEST_FILES = ["metadata.csv", "403926_406296.zip"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _api_get(endpoint: str, headers: dict[str, str]) -> dict | None:
|
|
47
|
+
"""
|
|
48
|
+
Make GET request to DaRUS API.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
endpoint: API endpoint path (without base URL).
|
|
52
|
+
headers: HTTP headers including optional API token.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Response data dict if successful, None on error.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
r = requests.get(f"{DARUS_URL}/api/{endpoint}", headers=headers)
|
|
59
|
+
r.raise_for_status()
|
|
60
|
+
return r.json()["data"]
|
|
61
|
+
except Exception as e:
|
|
62
|
+
console.print(f"[red]API Error:[/red] {e}")
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _get_version_files(version: str, headers: dict[str, str]) -> set[str]:
|
|
67
|
+
"""
|
|
68
|
+
Fetch filenames for a specific dataset version.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
version: Dataset version string (e.g., "2.0").
|
|
72
|
+
headers: HTTP headers for API authentication.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Set of filenames in the specified version.
|
|
76
|
+
"""
|
|
77
|
+
data = _api_get(f"datasets/:persistentId/versions/{version}?persistentId={DDACS_DOI}", headers)
|
|
78
|
+
if data:
|
|
79
|
+
return {f["dataFile"]["filename"] for f in data.get("files", [])}
|
|
80
|
+
return set()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _get_file_info(file_meta: dict, original: bool = True) -> tuple[str, int]:
|
|
84
|
+
"""
|
|
85
|
+
Extract filename and size from DaRUS file metadata.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
file_meta: File metadata dict from DaRUS API.
|
|
89
|
+
original: If True, prefer original filename over transformed.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Tuple of (filename, file_size_bytes).
|
|
93
|
+
"""
|
|
94
|
+
df = file_meta["dataFile"]
|
|
95
|
+
if original and "originalFileName" in df:
|
|
96
|
+
return df["originalFileName"], df.get("originalFileSize", df["filesize"])
|
|
97
|
+
return df["filename"], df["filesize"]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _compute_changes(current_files: set[str], previous_files: set[str]) -> list[str]:
|
|
101
|
+
"""
|
|
102
|
+
Compute file changes between two dataset versions.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
current_files: Set of filenames in current version.
|
|
106
|
+
previous_files: Set of filenames in previous version.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
List of change descriptions with Rich markup for display.
|
|
110
|
+
"""
|
|
111
|
+
added = current_files - previous_files
|
|
112
|
+
removed = previous_files - current_files
|
|
113
|
+
|
|
114
|
+
changes = []
|
|
115
|
+
for f in sorted(added):
|
|
116
|
+
changes.append(f"[green]+ {f}[/green]")
|
|
117
|
+
for f in sorted(removed):
|
|
118
|
+
changes.append(f"[red]- {f}[/red]")
|
|
119
|
+
|
|
120
|
+
return changes if changes else ["no changes"]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def cmd_info(args: argparse.Namespace) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Display dataset information and available versions.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
args: Parsed command-line arguments containing optional token.
|
|
129
|
+
"""
|
|
130
|
+
headers = {"X-Dataverse-key": args.token} if args.token else {}
|
|
131
|
+
|
|
132
|
+
with console.status("[bold blue]Fetching dataset information..."):
|
|
133
|
+
versions = _api_get(f"datasets/:persistentId/versions?persistentId={DDACS_DOI}", headers)
|
|
134
|
+
if not versions:
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
dataset_url = f"{DARUS_URL}/dataset.xhtml?persistentId={DDACS_DOI}"
|
|
138
|
+
latest = versions[0] if versions else {}
|
|
139
|
+
license_name = latest.get("license", {}).get("name", "Unknown")
|
|
140
|
+
|
|
141
|
+
info = (
|
|
142
|
+
f"[bold]URL:[/bold] [link={dataset_url}]{dataset_url}[/link]\n"
|
|
143
|
+
f"[bold]Persistent ID:[/bold] {DDACS_DOI}\n"
|
|
144
|
+
f"[bold]Authors:[/bold] Sebastian Baum, Pascal Heinzelmann\n"
|
|
145
|
+
f"[bold]License:[/bold] {license_name}"
|
|
146
|
+
)
|
|
147
|
+
console.print()
|
|
148
|
+
console.print(Panel(info, title=f"{DDACS_NAME} Dataset", border_style="cyan"))
|
|
149
|
+
|
|
150
|
+
version_files = {}
|
|
151
|
+
with console.status("[bold blue]Fetching version details..."):
|
|
152
|
+
for v in versions:
|
|
153
|
+
ver_num = v.get("versionNumber", "?")
|
|
154
|
+
ver_minor = v.get("versionMinorNumber", "0")
|
|
155
|
+
ver_str = f"{ver_num}.{ver_minor}"
|
|
156
|
+
if "files" in v:
|
|
157
|
+
version_files[ver_str] = {f["dataFile"]["filename"] for f in v.get("files", [])}
|
|
158
|
+
else:
|
|
159
|
+
version_files[ver_str] = _get_version_files(ver_str, headers)
|
|
160
|
+
|
|
161
|
+
table = Table(
|
|
162
|
+
title="Available Versions", show_header=True, header_style="bold cyan", show_lines=True
|
|
163
|
+
)
|
|
164
|
+
table.add_column("Version", style="white")
|
|
165
|
+
table.add_column("State", style="yellow")
|
|
166
|
+
table.add_column("Release Date", style="green")
|
|
167
|
+
table.add_column("Files", justify="right")
|
|
168
|
+
table.add_column("Changes", max_width=40)
|
|
169
|
+
table.add_column("Notes", max_width=40)
|
|
170
|
+
|
|
171
|
+
version_list = list(version_files.keys())
|
|
172
|
+
for i, v in enumerate(versions):
|
|
173
|
+
version_num = f"{v.get('versionNumber', '?')}.{v.get('versionMinorNumber', '0')}"
|
|
174
|
+
state = v.get("versionState", "Unknown")
|
|
175
|
+
release_date = v.get("releaseTime", v.get("createTime", "Unknown"))
|
|
176
|
+
if release_date and release_date != "Unknown":
|
|
177
|
+
release_date = release_date[:10]
|
|
178
|
+
|
|
179
|
+
file_count = v.get("fileCount", len(v.get("files", [])))
|
|
180
|
+
version_note = v.get("versionNote", "-")
|
|
181
|
+
|
|
182
|
+
if state == "RELEASED":
|
|
183
|
+
state_str = "[green]Released[/green]"
|
|
184
|
+
elif state == "DRAFT":
|
|
185
|
+
state_str = "[yellow]Draft[/yellow]"
|
|
186
|
+
else:
|
|
187
|
+
state_str = state
|
|
188
|
+
|
|
189
|
+
if i < len(version_list) - 1:
|
|
190
|
+
current_files = version_files.get(version_num, set())
|
|
191
|
+
previous_files = version_files.get(version_list[i + 1], set())
|
|
192
|
+
changes = _compute_changes(current_files, previous_files)
|
|
193
|
+
else:
|
|
194
|
+
changes = ["initial release"]
|
|
195
|
+
|
|
196
|
+
table.add_row(
|
|
197
|
+
version_num, state_str, release_date, str(file_count), "\n".join(changes), version_note
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
console.print()
|
|
201
|
+
console.print(table)
|
|
202
|
+
console.print()
|
|
203
|
+
console.print("Use 'ddacs download <version>' to download a specific version of the dataset.")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def cmd_download(args: argparse.Namespace) -> None:
|
|
207
|
+
"""
|
|
208
|
+
Download dataset files from DaRUS repository.
|
|
209
|
+
|
|
210
|
+
Handles file selection, download with progress display, and optional
|
|
211
|
+
extraction of zip archives.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
args: Parsed command-line arguments containing version, output path,
|
|
215
|
+
and download options (files, small, no_extract, keep_zip, yes).
|
|
216
|
+
"""
|
|
217
|
+
headers = {"X-Dataverse-key": args.token} if args.token else {}
|
|
218
|
+
|
|
219
|
+
with console.status("[bold blue]Fetching dataset metadata..."):
|
|
220
|
+
data = _api_get(
|
|
221
|
+
f"datasets/:persistentId/versions/{args.version}?persistentId={DDACS_DOI}",
|
|
222
|
+
headers,
|
|
223
|
+
)
|
|
224
|
+
if not data:
|
|
225
|
+
return
|
|
226
|
+
all_files = data["files"]
|
|
227
|
+
|
|
228
|
+
version_number = data.get("versionNumber", "?")
|
|
229
|
+
version_minor = data.get("versionMinorNumber", "0")
|
|
230
|
+
version_state = data.get("versionState", "")
|
|
231
|
+
last_update = data.get("lastUpdateTime", "Unknown")[:10]
|
|
232
|
+
license_name = data.get("license", {}).get("name", "Unknown")
|
|
233
|
+
dataset_url = f"{DARUS_URL}/dataset.xhtml?persistentId={DDACS_DOI}"
|
|
234
|
+
|
|
235
|
+
version_str = f"{version_number}.{version_minor}"
|
|
236
|
+
if version_state == "DRAFT":
|
|
237
|
+
version_str += " [yellow](Draft)[/yellow]"
|
|
238
|
+
|
|
239
|
+
dataset_info = (
|
|
240
|
+
f"[bold]URL:[/bold] [link={dataset_url}]{dataset_url}[/link]\n"
|
|
241
|
+
f"[bold]Persistent ID:[/bold] {DDACS_DOI}\n"
|
|
242
|
+
f"[bold]Version:[/bold] {version_str}\n"
|
|
243
|
+
f"[bold]Last Update:[/bold] {last_update}\n"
|
|
244
|
+
f"[bold]License:[/bold] {license_name}"
|
|
245
|
+
)
|
|
246
|
+
console.print()
|
|
247
|
+
console.print(Panel(dataset_info, title=f"{DDACS_NAME} Dataset", border_style="cyan"))
|
|
248
|
+
|
|
249
|
+
original = True # Always download original format
|
|
250
|
+
|
|
251
|
+
# Determine which files to download
|
|
252
|
+
if args.files:
|
|
253
|
+
# User specified specific files
|
|
254
|
+
selected_files = [
|
|
255
|
+
f
|
|
256
|
+
for f in all_files
|
|
257
|
+
if _get_file_info(f, original)[0] in args.files
|
|
258
|
+
or f["dataFile"]["filename"] in args.files
|
|
259
|
+
]
|
|
260
|
+
elif args.small:
|
|
261
|
+
# Download small test set for demos/testing
|
|
262
|
+
selected_files = [
|
|
263
|
+
f
|
|
264
|
+
for f in all_files
|
|
265
|
+
if _get_file_info(f, original)[0] in SMALL_TEST_FILES
|
|
266
|
+
or f["dataFile"]["filename"] in SMALL_TEST_FILES
|
|
267
|
+
]
|
|
268
|
+
else:
|
|
269
|
+
# Default: download all files
|
|
270
|
+
selected_files = all_files
|
|
271
|
+
|
|
272
|
+
if not selected_files:
|
|
273
|
+
console.print("[yellow]No files found matching criteria.[/yellow]")
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
selected_files.sort(key=lambda f: f["dataFile"]["filesize"])
|
|
277
|
+
|
|
278
|
+
table = Table(title="Files to Download", header_style="bold cyan")
|
|
279
|
+
table.add_column("Filename", max_width=40)
|
|
280
|
+
table.add_column("Size", justify="right", style="green")
|
|
281
|
+
table.add_column("Description", max_width=50)
|
|
282
|
+
|
|
283
|
+
total_bytes = 0
|
|
284
|
+
for f in selected_files:
|
|
285
|
+
name, size = _get_file_info(f, original)
|
|
286
|
+
desc = f.get("description", "No description")
|
|
287
|
+
total_bytes += size
|
|
288
|
+
table.add_row(name, format_size(size), desc)
|
|
289
|
+
|
|
290
|
+
console.print()
|
|
291
|
+
console.print(table)
|
|
292
|
+
|
|
293
|
+
summary = (
|
|
294
|
+
f"[bold]Files:[/bold] {len(selected_files)}\n"
|
|
295
|
+
f"[bold]Total size:[/bold] {format_size(total_bytes)}\n"
|
|
296
|
+
f"[bold]Destination:[/bold] {os.path.abspath(args.out)}"
|
|
297
|
+
)
|
|
298
|
+
console.print()
|
|
299
|
+
console.print(Panel(summary, title="Download Summary", border_style="blue"))
|
|
300
|
+
|
|
301
|
+
console.print()
|
|
302
|
+
if not args.yes and not Confirm.ask("Proceed with download?"):
|
|
303
|
+
console.print("[yellow]Download cancelled.[/yellow]")
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
os.makedirs(args.out, exist_ok=True)
|
|
307
|
+
|
|
308
|
+
downloaded_files = []
|
|
309
|
+
failed_downloads = []
|
|
310
|
+
failed_extractions = []
|
|
311
|
+
|
|
312
|
+
with Progress(
|
|
313
|
+
TextColumn("[bold blue]{task.fields[filename]}", justify="right"),
|
|
314
|
+
BarColumn(bar_width=40),
|
|
315
|
+
"[progress.percentage]{task.percentage:>3.1f}%",
|
|
316
|
+
DownloadColumn(),
|
|
317
|
+
TransferSpeedColumn(),
|
|
318
|
+
TimeRemainingColumn(),
|
|
319
|
+
console=console,
|
|
320
|
+
) as progress:
|
|
321
|
+
for f in selected_files:
|
|
322
|
+
file_name, _ = _get_file_info(f, original)
|
|
323
|
+
file_id = f["dataFile"]["id"]
|
|
324
|
+
directory = f.get("directoryLabel", "")
|
|
325
|
+
|
|
326
|
+
dl_url = f"{DARUS_URL}/api/access/datafile/{file_id}"
|
|
327
|
+
if original:
|
|
328
|
+
dl_url += "?format=original"
|
|
329
|
+
|
|
330
|
+
target_dir = os.path.join(args.out, directory)
|
|
331
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
332
|
+
local_path = os.path.join(target_dir, file_name)
|
|
333
|
+
|
|
334
|
+
try:
|
|
335
|
+
with requests.get(dl_url, headers=headers, stream=True) as r:
|
|
336
|
+
r.raise_for_status()
|
|
337
|
+
total_file_size = int(r.headers.get("content-length", 0))
|
|
338
|
+
|
|
339
|
+
task = progress.add_task(
|
|
340
|
+
"download",
|
|
341
|
+
filename=file_name[:30],
|
|
342
|
+
total=total_file_size,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
with open(local_path, "wb") as out_f:
|
|
346
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
347
|
+
written = out_f.write(chunk)
|
|
348
|
+
progress.update(task, advance=written)
|
|
349
|
+
|
|
350
|
+
downloaded_files.append(local_path)
|
|
351
|
+
except Exception as e:
|
|
352
|
+
failed_downloads.append((file_name, str(e)))
|
|
353
|
+
console.print(f"[red]Failed to download {file_name}:[/red] {e}")
|
|
354
|
+
|
|
355
|
+
if not args.no_extract and downloaded_files:
|
|
356
|
+
console.print()
|
|
357
|
+
zip_files = [p for p in downloaded_files if p.endswith(".zip")]
|
|
358
|
+
if zip_files:
|
|
359
|
+
with Progress(
|
|
360
|
+
TextColumn("[bold blue]{task.description}", justify="right"),
|
|
361
|
+
BarColumn(bar_width=40),
|
|
362
|
+
"[progress.percentage]{task.percentage:>3.1f}%",
|
|
363
|
+
TimeRemainingColumn(),
|
|
364
|
+
TextColumn("{task.fields[current_file]}"),
|
|
365
|
+
console=console,
|
|
366
|
+
) as progress:
|
|
367
|
+
for local_path in zip_files:
|
|
368
|
+
zip_name = os.path.basename(local_path)
|
|
369
|
+
try:
|
|
370
|
+
extract_dir = os.path.dirname(local_path)
|
|
371
|
+
with zipfile.ZipFile(local_path, "r") as zf:
|
|
372
|
+
members = zf.namelist()
|
|
373
|
+
task = progress.add_task(
|
|
374
|
+
f"Extracting {zip_name[:20]}",
|
|
375
|
+
total=len(members),
|
|
376
|
+
current_file="",
|
|
377
|
+
)
|
|
378
|
+
for member in members:
|
|
379
|
+
progress.update(task, current_file=os.path.basename(member)[:30])
|
|
380
|
+
zf.extract(member, extract_dir)
|
|
381
|
+
progress.advance(task)
|
|
382
|
+
console.print(f"[green]Extracted:[/green] {zip_name}")
|
|
383
|
+
if not args.keep_zip:
|
|
384
|
+
os.remove(local_path)
|
|
385
|
+
console.print(f"[dim]Removed:[/dim] {zip_name}")
|
|
386
|
+
except Exception as e:
|
|
387
|
+
failed_extractions.append((zip_name, str(e)))
|
|
388
|
+
console.print(f"[red]Failed to extract {zip_name}:[/red] {e}")
|
|
389
|
+
|
|
390
|
+
console.print()
|
|
391
|
+
success_count = len(downloaded_files)
|
|
392
|
+
total_count = len(selected_files)
|
|
393
|
+
|
|
394
|
+
if failed_downloads or failed_extractions:
|
|
395
|
+
summary_lines = [f"[green]Downloaded {success_count}/{total_count} file(s)[/green]"]
|
|
396
|
+
if failed_downloads:
|
|
397
|
+
summary_lines.append(f"[red]Failed downloads: {len(failed_downloads)}[/red]")
|
|
398
|
+
if failed_extractions:
|
|
399
|
+
summary_lines.append(f"[red]Failed extractions: {len(failed_extractions)}[/red]")
|
|
400
|
+
console.print(
|
|
401
|
+
Panel("\n".join(summary_lines), title="Complete with errors", border_style="yellow")
|
|
402
|
+
)
|
|
403
|
+
else:
|
|
404
|
+
console.print(
|
|
405
|
+
Panel(
|
|
406
|
+
f"[green]Successfully downloaded {success_count} file(s)[/green]",
|
|
407
|
+
title="Complete",
|
|
408
|
+
border_style="green",
|
|
409
|
+
)
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def main() -> None:
|
|
414
|
+
"""CLI entry point for DDACS dataset commands."""
|
|
415
|
+
parser = argparse.ArgumentParser(
|
|
416
|
+
prog="ddacs",
|
|
417
|
+
description="DDACS Dataset CLI - Download simulation data from DaRUS",
|
|
418
|
+
)
|
|
419
|
+
parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
|
|
420
|
+
parser.add_argument("--token", help="DaRUS API token (for draft access)")
|
|
421
|
+
|
|
422
|
+
subparsers = parser.add_subparsers(dest="command", help="Command")
|
|
423
|
+
|
|
424
|
+
subparsers.add_parser(
|
|
425
|
+
"info",
|
|
426
|
+
help="Show dataset info and versions",
|
|
427
|
+
description="Display dataset metadata, available versions, and changelog.",
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
dl_parser = subparsers.add_parser(
|
|
431
|
+
"download",
|
|
432
|
+
help="Download dataset files",
|
|
433
|
+
description="Download DDACS dataset files from DaRUS repository.",
|
|
434
|
+
)
|
|
435
|
+
dl_parser.add_argument(
|
|
436
|
+
"version", nargs="?", default="2.0", help="Dataset version (default: 2.0)"
|
|
437
|
+
)
|
|
438
|
+
dl_parser.add_argument("--files", nargs="+", help="Specific filenames to download")
|
|
439
|
+
dl_parser.add_argument(
|
|
440
|
+
"--small",
|
|
441
|
+
action="store_true",
|
|
442
|
+
help="Download small test set for demos/testing",
|
|
443
|
+
)
|
|
444
|
+
dl_parser.add_argument("--out", default="./data", help="Output directory (default: ./data)")
|
|
445
|
+
dl_parser.add_argument("-y", "--yes", action="store_true", help="Skip confirmation prompt")
|
|
446
|
+
dl_parser.add_argument("--no-extract", action="store_true", help="Skip extraction of zip files")
|
|
447
|
+
dl_parser.add_argument(
|
|
448
|
+
"--keep-zip", action="store_true", help="Keep zip files after extraction"
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
args = parser.parse_args()
|
|
452
|
+
|
|
453
|
+
if args.command == "info":
|
|
454
|
+
cmd_info(args)
|
|
455
|
+
elif args.command == "download":
|
|
456
|
+
cmd_download(args)
|
|
457
|
+
else:
|
|
458
|
+
parser.print_help()
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
if __name__ == "__main__":
|
|
462
|
+
main()
|