starbash 0.1.8__py3-none-any.whl → 0.1.10__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.
Potentially problematic release.
This version of starbash might be problematic. Click here for more details.
- repo/__init__.py +2 -1
- repo/manager.py +31 -268
- repo/repo.py +294 -0
- starbash/__init__.py +20 -0
- starbash/aliases.py +100 -0
- starbash/analytics.py +4 -0
- starbash/app.py +740 -151
- starbash/commands/__init__.py +0 -17
- starbash/commands/info.py +72 -3
- starbash/commands/process.py +154 -0
- starbash/commands/repo.py +185 -78
- starbash/commands/select.py +135 -44
- starbash/database.py +397 -155
- starbash/defaults/starbash.toml +35 -0
- starbash/main.py +4 -1
- starbash/paths.py +18 -2
- starbash/recipes/master_bias/starbash.toml +32 -19
- starbash/recipes/master_dark/starbash.toml +36 -0
- starbash/recipes/master_flat/starbash.toml +27 -17
- starbash/recipes/osc_dual_duo/starbash.py +1 -5
- starbash/recipes/osc_dual_duo/starbash.toml +8 -4
- starbash/recipes/osc_single_duo/starbash.toml +4 -4
- starbash/recipes/starbash.toml +28 -3
- starbash/selection.py +115 -46
- starbash/templates/repo/master.toml +13 -0
- starbash/templates/repo/processed.toml +10 -0
- starbash/templates/userconfig.toml +1 -1
- starbash/toml.py +29 -0
- starbash/tool.py +199 -67
- {starbash-0.1.8.dist-info → starbash-0.1.10.dist-info}/METADATA +20 -13
- starbash-0.1.10.dist-info/RECORD +40 -0
- starbash-0.1.8.dist-info/RECORD +0 -33
- {starbash-0.1.8.dist-info → starbash-0.1.10.dist-info}/WHEEL +0 -0
- {starbash-0.1.8.dist-info → starbash-0.1.10.dist-info}/entry_points.txt +0 -0
- {starbash-0.1.8.dist-info → starbash-0.1.10.dist-info}/licenses/LICENSE +0 -0
starbash/commands/select.py
CHANGED
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from typing import Any
|
|
5
|
+
from collections import Counter
|
|
5
6
|
import typer
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing_extensions import Annotated
|
|
8
|
-
from datetime import datetime
|
|
9
9
|
from rich.table import Table
|
|
10
|
+
import logging
|
|
10
11
|
|
|
12
|
+
import starbash
|
|
13
|
+
from starbash import to_shortdate
|
|
11
14
|
from starbash.app import Starbash, copy_images_to_dir
|
|
12
|
-
from starbash.database import Database, get_column_name
|
|
15
|
+
from starbash.database import Database, SessionRow, get_column_name
|
|
13
16
|
from starbash import console
|
|
14
17
|
from starbash.commands import (
|
|
15
18
|
format_duration,
|
|
16
|
-
to_shortdate,
|
|
17
19
|
TABLE_COLUMN_STYLE,
|
|
18
20
|
TABLE_VALUE_STYLE,
|
|
19
21
|
)
|
|
@@ -21,6 +23,58 @@ from starbash.commands import (
|
|
|
21
23
|
app = typer.Typer()
|
|
22
24
|
|
|
23
25
|
|
|
26
|
+
def get_column(sb: Starbash, column_name: str) -> Counter:
|
|
27
|
+
|
|
28
|
+
# Also do a complete unfiltered search so we can compare for the users
|
|
29
|
+
allsessions = sb.db.search_session(("", []))
|
|
30
|
+
|
|
31
|
+
column_name = get_column_name(column_name)
|
|
32
|
+
allfound = [session[column_name] for session in allsessions if session[column_name]]
|
|
33
|
+
|
|
34
|
+
# Count occurrences of each telescope
|
|
35
|
+
all_counts = Counter(allfound)
|
|
36
|
+
|
|
37
|
+
return all_counts
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def complete_date(incomplete: str, column_name: str):
|
|
41
|
+
"""calls get_column() and assumes the returned str->count object has iso datetime strings as the keys
|
|
42
|
+
it merges the counts for all dates that are on the same local timezone day.
|
|
43
|
+
in the returned str->count, just include the date portion (YYYY-MM-DD)."""
|
|
44
|
+
|
|
45
|
+
# We need to use stderr_logging to prevent confusing the bash completion parser
|
|
46
|
+
starbash.log_filter_level = (
|
|
47
|
+
logging.ERROR
|
|
48
|
+
) # avoid showing output while doing completion
|
|
49
|
+
with Starbash("select.complete.date", stderr_logging=True) as sb:
|
|
50
|
+
c = get_column(sb, column_name)
|
|
51
|
+
|
|
52
|
+
# Merge counts by date (YYYY-MM-DD) in local timezone
|
|
53
|
+
date_counts = Counter()
|
|
54
|
+
for datetime_str, count in c.items():
|
|
55
|
+
# Extract just the date portion (YYYY-MM-DD) from local datetime
|
|
56
|
+
date_only = to_shortdate(datetime_str)
|
|
57
|
+
date_counts[date_only] += count
|
|
58
|
+
|
|
59
|
+
# Yield completions matching the incomplete input
|
|
60
|
+
for date, count in sorted(date_counts.items(), reverse=True):
|
|
61
|
+
if date.startswith(incomplete):
|
|
62
|
+
yield (date, f"{count} sessions")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def complete_column(incomplete: str, column_name: str):
|
|
66
|
+
# We need to use stderr_logging to prevent confusing the bash completion parser
|
|
67
|
+
starbash.log_filter_level = (
|
|
68
|
+
logging.ERROR
|
|
69
|
+
) # avoid showing output while doing completion
|
|
70
|
+
with Starbash("repo.complete.column", stderr_logging=True) as sb:
|
|
71
|
+
c = get_column(sb, column_name)
|
|
72
|
+
|
|
73
|
+
for item, count in c.items():
|
|
74
|
+
if item.lower().startswith(incomplete.lower()):
|
|
75
|
+
yield (item, f"{count} sessions")
|
|
76
|
+
|
|
77
|
+
|
|
24
78
|
@app.command(name="any")
|
|
25
79
|
def clear():
|
|
26
80
|
"""Remove any filters on sessions, etc... (select everything)."""
|
|
@@ -34,7 +88,10 @@ def target(
|
|
|
34
88
|
target_name: Annotated[
|
|
35
89
|
str,
|
|
36
90
|
typer.Argument(
|
|
37
|
-
help="Target name to add to the selection (e.g., 'M31', 'NGC 7000')"
|
|
91
|
+
help="Target name to add to the selection (e.g., 'M31', 'NGC 7000')",
|
|
92
|
+
autocompletion=lambda incomplete: complete_column(
|
|
93
|
+
incomplete, Database.OBJECT_KEY
|
|
94
|
+
),
|
|
38
95
|
),
|
|
39
96
|
],
|
|
40
97
|
):
|
|
@@ -52,7 +109,10 @@ def telescope(
|
|
|
52
109
|
telescope_name: Annotated[
|
|
53
110
|
str,
|
|
54
111
|
typer.Argument(
|
|
55
|
-
help="Telescope name to add to the selection (e.g., 'Vespera', 'EdgeHD 8')"
|
|
112
|
+
help="Telescope name to add to the selection (e.g., 'Vespera', 'EdgeHD 8')",
|
|
113
|
+
autocompletion=lambda incomplete: complete_column(
|
|
114
|
+
incomplete, Database.TELESCOP_KEY
|
|
115
|
+
),
|
|
56
116
|
),
|
|
57
117
|
],
|
|
58
118
|
):
|
|
@@ -67,21 +127,41 @@ def telescope(
|
|
|
67
127
|
)
|
|
68
128
|
|
|
69
129
|
|
|
130
|
+
def complete_name(incomplete: str, names: list[str]):
|
|
131
|
+
"""Return typer style autocompletion from a list of string constants."""
|
|
132
|
+
for name in names:
|
|
133
|
+
if name.startswith(incomplete):
|
|
134
|
+
yield name
|
|
135
|
+
|
|
136
|
+
|
|
70
137
|
@app.command()
|
|
71
138
|
def date(
|
|
72
139
|
operation: Annotated[
|
|
73
140
|
str,
|
|
74
|
-
typer.Argument(
|
|
141
|
+
typer.Argument(
|
|
142
|
+
help="Date operation: 'after', 'before', or 'between'",
|
|
143
|
+
autocompletion=lambda incomplete: complete_name(
|
|
144
|
+
incomplete, ["after", "before", "between"]
|
|
145
|
+
),
|
|
146
|
+
),
|
|
75
147
|
],
|
|
76
148
|
date_value: Annotated[
|
|
77
149
|
str,
|
|
78
150
|
typer.Argument(
|
|
79
|
-
help="Date in ISO format (YYYY-MM-DD) or two dates separated by space for 'between'"
|
|
151
|
+
help="Date in ISO format (YYYY-MM-DD) or two dates separated by space for 'between'",
|
|
152
|
+
autocompletion=lambda incomplete: complete_date(
|
|
153
|
+
incomplete, Database.START_KEY
|
|
154
|
+
),
|
|
80
155
|
),
|
|
81
156
|
],
|
|
82
157
|
end_date: Annotated[
|
|
83
158
|
str | None,
|
|
84
|
-
typer.Argument(
|
|
159
|
+
typer.Argument(
|
|
160
|
+
help="End date for 'between' operation (YYYY-MM-DD)",
|
|
161
|
+
autocompletion=lambda incomplete: complete_date(
|
|
162
|
+
incomplete, Database.START_KEY
|
|
163
|
+
),
|
|
164
|
+
),
|
|
85
165
|
] = None,
|
|
86
166
|
):
|
|
87
167
|
"""Limit to sessions in the specified date range.
|
|
@@ -122,7 +202,14 @@ def date(
|
|
|
122
202
|
|
|
123
203
|
|
|
124
204
|
@app.command(name="list")
|
|
125
|
-
def list_sessions(
|
|
205
|
+
def list_sessions(
|
|
206
|
+
verbose: bool = typer.Option(
|
|
207
|
+
False,
|
|
208
|
+
"--verbose",
|
|
209
|
+
"-v",
|
|
210
|
+
help="Show all sessions (normally Dark/Bias/Flat are hidden)",
|
|
211
|
+
)
|
|
212
|
+
):
|
|
126
213
|
"""List sessions (filtered based on the current selection)"""
|
|
127
214
|
|
|
128
215
|
with Starbash("selection.list") as sb:
|
|
@@ -166,6 +253,13 @@ def list_sessions():
|
|
|
166
253
|
telescope = get_key(Database.TELESCOP_KEY)
|
|
167
254
|
telescopes.add(telescope)
|
|
168
255
|
|
|
256
|
+
# Show the non normalized target name
|
|
257
|
+
metadata = sess.get("metadata")
|
|
258
|
+
if metadata:
|
|
259
|
+
long_name = metadata.get("OBJECT")
|
|
260
|
+
if long_name:
|
|
261
|
+
object = long_name
|
|
262
|
+
|
|
169
263
|
# Format total exposure time as integer seconds
|
|
170
264
|
exptime_raw = get_key(Database.EXPTIME_TOTAL_KEY)
|
|
171
265
|
try:
|
|
@@ -223,6 +317,32 @@ def list_sessions():
|
|
|
223
317
|
sb.analytics.set_data("session.image_types", image_types)
|
|
224
318
|
|
|
225
319
|
|
|
320
|
+
def selection_by_number(
|
|
321
|
+
sb: Starbash,
|
|
322
|
+
session_num: int,
|
|
323
|
+
) -> SessionRow:
|
|
324
|
+
"""Get the session corresponding to the given session number in the current selection."""
|
|
325
|
+
# Get the filtered sessions
|
|
326
|
+
sessions = sb.search_session()
|
|
327
|
+
|
|
328
|
+
if not sessions or not isinstance(sessions, list):
|
|
329
|
+
console.print("[red]No sessions found. Check your selection criteria.[/red]")
|
|
330
|
+
raise typer.Exit(1)
|
|
331
|
+
|
|
332
|
+
# Validate session number
|
|
333
|
+
if session_num < 1 or session_num > len(sessions):
|
|
334
|
+
console.print(
|
|
335
|
+
f"[red]Error: Session number {session_num} is out of range. "
|
|
336
|
+
f"Valid range is 1-{len(sessions)}.[/red]"
|
|
337
|
+
)
|
|
338
|
+
console.print("[yellow]Use 'select list' to see available sessions.[/yellow]")
|
|
339
|
+
raise typer.Exit(1)
|
|
340
|
+
|
|
341
|
+
# Get the selected session (convert from 1-based to 0-based index)
|
|
342
|
+
session = sessions[session_num - 1]
|
|
343
|
+
return session
|
|
344
|
+
|
|
345
|
+
|
|
226
346
|
@app.command()
|
|
227
347
|
def export(
|
|
228
348
|
session_num: Annotated[
|
|
@@ -242,36 +362,16 @@ def export(
|
|
|
242
362
|
The session number corresponds to the '#' column in 'select list' output.
|
|
243
363
|
"""
|
|
244
364
|
with Starbash("selection.export") as sb:
|
|
245
|
-
# Get the filtered sessions
|
|
246
|
-
sessions = sb.search_session()
|
|
247
|
-
|
|
248
|
-
if not sessions or not isinstance(sessions, list):
|
|
249
|
-
console.print(
|
|
250
|
-
"[red]No sessions found. Check your selection criteria.[/red]"
|
|
251
|
-
)
|
|
252
|
-
raise typer.Exit(1)
|
|
253
|
-
|
|
254
|
-
# Validate session number
|
|
255
|
-
if session_num < 1 or session_num > len(sessions):
|
|
256
|
-
console.print(
|
|
257
|
-
f"[red]Error: Session number {session_num} is out of range. "
|
|
258
|
-
f"Valid range is 1-{len(sessions)}.[/red]"
|
|
259
|
-
)
|
|
260
|
-
console.print(
|
|
261
|
-
"[yellow]Use 'select list' to see available sessions.[/yellow]"
|
|
262
|
-
)
|
|
263
|
-
raise typer.Exit(1)
|
|
264
|
-
|
|
265
365
|
# Get the selected session (convert from 1-based to 0-based index)
|
|
266
|
-
session =
|
|
366
|
+
session = selection_by_number(sb, session_num)
|
|
267
367
|
|
|
268
|
-
# Get
|
|
269
|
-
|
|
270
|
-
if
|
|
368
|
+
# Get images for this session
|
|
369
|
+
images = sb.get_session_images(session)
|
|
370
|
+
if not images:
|
|
271
371
|
console.print(
|
|
272
|
-
f"[red]Error:
|
|
372
|
+
f"[red]Error: No images found for session {session_num}.[/red]"
|
|
273
373
|
)
|
|
274
|
-
raise typer.Exit(
|
|
374
|
+
raise typer.Exit(0)
|
|
275
375
|
|
|
276
376
|
# Determine output directory
|
|
277
377
|
output_dir = Path(destdir)
|
|
@@ -279,15 +379,6 @@ def export(
|
|
|
279
379
|
# Create output directory if it doesn't exist
|
|
280
380
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
281
381
|
|
|
282
|
-
# Get images for this session
|
|
283
|
-
images = sb.get_session_images(session_id)
|
|
284
|
-
|
|
285
|
-
if not images:
|
|
286
|
-
console.print(
|
|
287
|
-
f"[yellow]Warning: No images found for session {session_num}.[/yellow]"
|
|
288
|
-
)
|
|
289
|
-
raise typer.Exit(0)
|
|
290
|
-
|
|
291
382
|
copy_images_to_dir(images, output_dir)
|
|
292
383
|
|
|
293
384
|
|