viewinline 0.3.1__tar.gz → 0.3.2__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.
- {viewinline-0.3.1 → viewinline-0.3.2}/PKG-INFO +3 -3
- {viewinline-0.3.1 → viewinline-0.3.2}/pyproject.toml +1 -1
- {viewinline-0.3.1 → viewinline-0.3.2}/src/viewinline/viewinline.py +198 -136
- {viewinline-0.3.1 → viewinline-0.3.2}/.github/FUNDING.yml +0 -0
- {viewinline-0.3.1 → viewinline-0.3.2}/.gitignore +0 -0
- {viewinline-0.3.1 → viewinline-0.3.2}/LICENSE +0 -0
- {viewinline-0.3.1 → viewinline-0.3.2}/README.md +2 -2
- {viewinline-0.3.1 → viewinline-0.3.2}/src/viewinline/__init__.py +0 -0
- {viewinline-0.3.1 → viewinline-0.3.2}/viewinline_gif1.gif +0 -0
- {viewinline-0.3.1 → viewinline-0.3.2}/viewinline_gif2.gif +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: viewinline
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Quick look geospatial viewer for the terminal, with inline image previews
|
|
5
5
|
Project-URL: Homepage, https://github.com/nkeikon/viewinline
|
|
6
6
|
Project-URL: Repository, https://github.com/nkeikon/viewinline
|
|
@@ -217,12 +217,12 @@ General:
|
|
|
217
217
|
Raster:
|
|
218
218
|
--band BAND Band number to display (single raster), or slice number for NetCDF. (default: 1)
|
|
219
219
|
--bands BANDS Display multiple bands as a grid. Accepts ranges (30-40), lists (3,4,5), or mixed (1,5,10-15).
|
|
220
|
+
--rgb R G B Three band numbers for RGB display (e.g., --rgb 4 3 2). Overrides default 1 2 3.
|
|
221
|
+
--rgbfiles R G B Three single-band rasters for RGB composite. Can also provide as positional arguments.
|
|
220
222
|
--timestep INTEGER Alias for --band when working with NetCDF files.
|
|
221
223
|
--subset INTEGER Variable index for NetCDF/HDF files (e.g., --subset 1).
|
|
222
224
|
--reduce DIM_NAME For 3D NetCDF variables, specify which dimension to use as the band/slider axis. Auto-detected if omitted.
|
|
223
225
|
--colormap Apply colormap to single-band rasters. Flag without the color scheme → 'terrain'.
|
|
224
|
-
--rgb R G B Three band numbers for RGB display (e.g., --rgb 4 3 2). Overrides default 1 2 3.
|
|
225
|
-
--rgbfiles R G B Three single-band rasters for RGB composite. Can also provide as positional arguments.
|
|
226
226
|
--vmin VMIN Minimum pixel value for raster display scaling.
|
|
227
227
|
--vmax VMAX Maximum pixel value for raster display scaling.
|
|
228
228
|
--nodata NODATA Override nodata value for rasters if dataset metadata is missing or incorrect.
|
|
@@ -9,14 +9,11 @@ Supports:
|
|
|
9
9
|
|
|
10
10
|
Display:
|
|
11
11
|
Sends iTerm2-style inline image escape sequences. Works in terminals that support
|
|
12
|
-
the iTerm2 inline image protocol (iTerm2, WezTerm, Konsole, etc.).
|
|
13
|
-
|
|
12
|
+
the iTerm2 inline image protocol (iTerm2, WezTerm, Konsole, etc.). For others,
|
|
13
|
+
please see line 48-58.
|
|
14
14
|
|
|
15
15
|
Particularly useful on HPC systems and remote servers accessed via SSH — images
|
|
16
16
|
render on your local terminal without X11 forwarding, VNC, or file downloads.
|
|
17
|
-
|
|
18
|
-
No detection, no fallbacks. If images are not shown, it means that the terminal
|
|
19
|
-
is not compatible.
|
|
20
17
|
"""
|
|
21
18
|
|
|
22
19
|
import sys, os, base64, shutil, argparse
|
|
@@ -28,19 +25,13 @@ from matplotlib import colormaps
|
|
|
28
25
|
import matplotlib as mpl
|
|
29
26
|
import subprocess
|
|
30
27
|
|
|
31
|
-
try:
|
|
32
|
-
import netCDF4
|
|
33
|
-
HAS_NETCDF4 = True
|
|
34
|
-
except ImportError:
|
|
35
|
-
HAS_NETCDF4 = False
|
|
36
|
-
|
|
37
28
|
import warnings
|
|
38
29
|
|
|
39
30
|
warnings.filterwarnings("ignore", message="More than one layer found", category=UserWarning)
|
|
40
31
|
warnings.filterwarnings("ignore", message="Dataset has no geotransform", category=UserWarning)
|
|
41
32
|
warnings.filterwarnings("ignore", message="invalid scale_factor or add_offset attribute", category=UserWarning)
|
|
42
33
|
|
|
43
|
-
__version__ = "0.3.
|
|
34
|
+
__version__ = "0.3.2"
|
|
44
35
|
|
|
45
36
|
AVAILABLE_COLORMAPS = [
|
|
46
37
|
"viridis", "inferno", "magma", "plasma",
|
|
@@ -266,6 +257,23 @@ def parse_bands(s: str) -> list[int]:
|
|
|
266
257
|
print(f"[WARN] Could not parse band: {part}")
|
|
267
258
|
return sorted(set(bands))
|
|
268
259
|
|
|
260
|
+
def parse_rgb(values: list[str]) -> list[int]:
|
|
261
|
+
"""Parse --rgb: accepts '4 3 2' or '4,3,2'."""
|
|
262
|
+
if len(values) == 1:
|
|
263
|
+
# comma-separated: '4,3,2'
|
|
264
|
+
parts = values[0].split(",")
|
|
265
|
+
else:
|
|
266
|
+
# space-separated: '4' '3' '2'
|
|
267
|
+
parts = values
|
|
268
|
+
try:
|
|
269
|
+
result = [int(p.strip()) for p in parts]
|
|
270
|
+
if len(result) != 3:
|
|
271
|
+
raise ValueError
|
|
272
|
+
return result
|
|
273
|
+
except ValueError:
|
|
274
|
+
print("[WARN] --rgb requires exactly 3 band numbers. e.g. --rgb 4 3 2 or --rgb 4,3,2")
|
|
275
|
+
return None
|
|
276
|
+
|
|
269
277
|
# ---------------------------------------------------------------------
|
|
270
278
|
# CSV handling
|
|
271
279
|
# ---------------------------------------------------------------------
|
|
@@ -304,11 +312,18 @@ def preview_df(df, max_rows: int = 10, query_mode: bool = False, filename: str =
|
|
|
304
312
|
# -------------------------------------------------------------
|
|
305
313
|
if n_rows <= max_rows:
|
|
306
314
|
rows_to_show = df
|
|
315
|
+
elif query_mode:
|
|
316
|
+
ans = input(f"Filtered results: {n_rows} rows. Show first {max_rows} or all? [first/all]: ").strip().lower()
|
|
317
|
+
if ans == "all":
|
|
318
|
+
rows_to_show = df
|
|
319
|
+
else:
|
|
320
|
+
rows_to_show = df.head(max_rows)
|
|
307
321
|
else:
|
|
308
|
-
ans = input(f"
|
|
309
|
-
if ans
|
|
310
|
-
|
|
311
|
-
|
|
322
|
+
ans = input(f"Large file: {n_rows} rows. Show first {max_rows} or all? [first/all]: ").strip().lower()
|
|
323
|
+
if ans == "all":
|
|
324
|
+
rows_to_show = df
|
|
325
|
+
else:
|
|
326
|
+
rows_to_show = df.head(max_rows)
|
|
312
327
|
|
|
313
328
|
# -------------------------------------------------------------
|
|
314
329
|
# Build pretty table
|
|
@@ -610,8 +625,15 @@ def normalize_to_uint8(band: np.ndarray, vmin=None, vmax=None, nodata=None) -> n
|
|
|
610
625
|
valid_vals = band[valid]
|
|
611
626
|
|
|
612
627
|
# --- Manual scaling ---
|
|
613
|
-
if vmin is not None
|
|
614
|
-
|
|
628
|
+
if vmin is not None or vmax is not None:
|
|
629
|
+
# Use percentile for whichever end is not specified
|
|
630
|
+
if valid_vals.size < 1_000_000:
|
|
631
|
+
sample = valid_vals
|
|
632
|
+
else:
|
|
633
|
+
sample = np.random.choice(valid_vals, 1_000_000, replace=False)
|
|
634
|
+
p2, p98 = np.percentile(sample, (2, 98))
|
|
635
|
+
mn = vmin if vmin is not None else p2
|
|
636
|
+
mx = vmax if vmax is not None else p98
|
|
615
637
|
print(f"[VIEW] Using manual scaling: {mn} to {mx}")
|
|
616
638
|
|
|
617
639
|
# --- Percentile fallback ---
|
|
@@ -664,7 +686,9 @@ def render_netcdf_via_netcdf4(path, args):
|
|
|
664
686
|
"""Read a NetCDF file via netCDF4 (bypassing GDAL). Handles hierarchical
|
|
665
687
|
groups and hyperspectral cubes where GDAL aborts or interprets axes wrong.
|
|
666
688
|
"""
|
|
667
|
-
|
|
689
|
+
try:
|
|
690
|
+
import netCDF4
|
|
691
|
+
except ImportError:
|
|
668
692
|
print("[ERROR] netCDF4 not installed. Install with:")
|
|
669
693
|
print(" pip install netCDF4")
|
|
670
694
|
print(" or: pip install viewinline[netcdf]")
|
|
@@ -759,7 +783,7 @@ def render_netcdf_via_netcdf4(path, args):
|
|
|
759
783
|
# BANDS GALLERY for NetCDF
|
|
760
784
|
if getattr(args, "bands", None):
|
|
761
785
|
band_list = parse_bands(args.bands)
|
|
762
|
-
print(f"[DEBUG] band_count={band_count}, band_list={band_list}")
|
|
786
|
+
# print(f"[DEBUG] band_count={band_count}, band_list={band_list}")
|
|
763
787
|
valid_bands = [b for b in band_list if 1 <= b <= band_count]
|
|
764
788
|
if not valid_bands:
|
|
765
789
|
print(f"[ERROR] No valid bands. Variable has {band_count} bands along '{var.dimensions[spectral_axis]}'.")
|
|
@@ -773,10 +797,48 @@ def render_netcdf_via_netcdf4(path, args):
|
|
|
773
797
|
nc.close()
|
|
774
798
|
colormap = args.colormap if args.colormap else "viridis"
|
|
775
799
|
render_bands_gallery(np.stack(slices, axis=0), valid_bands, band_count,
|
|
776
|
-
|
|
777
|
-
|
|
800
|
+
grid=getattr(args, "gallery", None),
|
|
801
|
+
display_scale=getattr(args, "display", None),
|
|
802
|
+
colormap=colormap)
|
|
778
803
|
return
|
|
779
804
|
|
|
805
|
+
# RGB COMPOSITE for NetCDF
|
|
806
|
+
if getattr(args, "rgb", None):
|
|
807
|
+
try:
|
|
808
|
+
# rgb_bands = args.rgb
|
|
809
|
+
rgb_bands = parse_rgb(args.rgb)
|
|
810
|
+
if rgb_bands is None:
|
|
811
|
+
return
|
|
812
|
+
if len(rgb_bands) != 3:
|
|
813
|
+
raise ValueError("exactly 3 bands required")
|
|
814
|
+
slices = []
|
|
815
|
+
for b in rgb_bands:
|
|
816
|
+
if b < 1 or b > band_count:
|
|
817
|
+
raise ValueError(f"band {b} out of range (1-{band_count})")
|
|
818
|
+
slicer = [slice(None)] * 3
|
|
819
|
+
slicer[spectral_axis] = b - 1
|
|
820
|
+
slices.append(np.asarray(var[tuple(slicer)], dtype=np.float64))
|
|
821
|
+
nc.close()
|
|
822
|
+
print(f"[INFO] Using RGB bands: {rgb_bands}")
|
|
823
|
+
img = np.stack([normalize_to_uint8(s, vmin=args.vmin, vmax=args.vmax, nodata=args.nodata)
|
|
824
|
+
for s in slices], axis=-1)
|
|
825
|
+
H, W = img.shape[:2]
|
|
826
|
+
if args.display:
|
|
827
|
+
new_w = max(1, int(W * args.display))
|
|
828
|
+
new_h = max(1, int(H * args.display))
|
|
829
|
+
img = np.array(Image.fromarray(img).resize((new_w, new_h), Image.BILINEAR))
|
|
830
|
+
else:
|
|
831
|
+
max_dim = 2000
|
|
832
|
+
if max(H, W) > max_dim:
|
|
833
|
+
scale = max_dim / max(H, W)
|
|
834
|
+
new_w, new_h = int(W * scale), int(H * scale)
|
|
835
|
+
img = np.array(Image.fromarray(img).resize((new_w, new_h), Image.BILINEAR))
|
|
836
|
+
show_image_auto(img, getattr(args, "display", None), is_vector=False)
|
|
837
|
+
return
|
|
838
|
+
except ValueError as e:
|
|
839
|
+
print(f"[WARN] Invalid --rgb: {e}. Falling back to band 1.")
|
|
840
|
+
|
|
841
|
+
# Single band slicer
|
|
780
842
|
slicer = [slice(None)] * 3
|
|
781
843
|
slicer[spectral_axis] = band_idx
|
|
782
844
|
data = np.asarray(var[tuple(slicer)], dtype=np.float64)
|
|
@@ -970,14 +1032,13 @@ def render_raster(paths: list[str], args) -> None:
|
|
|
970
1032
|
if band_count >= 3 and not paths[0].lower().endswith('.nc') and not user_specified_band and getattr(args, 'rgb', None):
|
|
971
1033
|
|
|
972
1034
|
if getattr(args, "rgb", None):
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
if len(rgb_idx) != 3:
|
|
976
|
-
raise ValueError
|
|
977
|
-
print(f"[INFO] Using RGB bands: {args.rgb}")
|
|
978
|
-
except Exception:
|
|
1035
|
+
rgb_parsed = parse_rgb(args.rgb)
|
|
1036
|
+
if rgb_parsed is None:
|
|
979
1037
|
print("[WARN] Invalid --rgb. Using default 1 2 3")
|
|
980
1038
|
rgb_idx = [0, 1, 2]
|
|
1039
|
+
else:
|
|
1040
|
+
rgb_idx = [b - 1 for b in rgb_parsed]
|
|
1041
|
+
print(f"[INFO] Using RGB bands: {rgb_parsed}")
|
|
981
1042
|
else:
|
|
982
1043
|
rgb_idx = [0, 1, 2]
|
|
983
1044
|
|
|
@@ -1100,6 +1161,7 @@ def render_gallery(folder: str, grid: str = "4x4", display_scale=None, is_vector
|
|
|
1100
1161
|
|
|
1101
1162
|
# Load thumbnails
|
|
1102
1163
|
thumbs = []
|
|
1164
|
+
loaded_files = []
|
|
1103
1165
|
thumb_size = (128, 128)
|
|
1104
1166
|
for f in files:
|
|
1105
1167
|
try:
|
|
@@ -1122,6 +1184,7 @@ def render_gallery(folder: str, grid: str = "4x4", display_scale=None, is_vector
|
|
|
1122
1184
|
img = Image.open(f).convert("RGB")
|
|
1123
1185
|
img.thumbnail(thumb_size)
|
|
1124
1186
|
thumbs.append(img)
|
|
1187
|
+
loaded_files.append(f)
|
|
1125
1188
|
|
|
1126
1189
|
except Exception as e:
|
|
1127
1190
|
print(f"[SKIP] {os.path.basename(f)} — {e}")
|
|
@@ -1147,8 +1210,12 @@ def render_gallery(folder: str, grid: str = "4x4", display_scale=None, is_vector
|
|
|
1147
1210
|
canvas.paste(img, (x, y))
|
|
1148
1211
|
|
|
1149
1212
|
print(f"[INFO] Displaying {n} images ({cols}×{rows} grid)")
|
|
1150
|
-
show_image_auto(np.array(canvas), display_scale, is_vector)
|
|
1151
1213
|
|
|
1214
|
+
for r in range(rows):
|
|
1215
|
+
row_files = loaded_files[r * cols:(r + 1) * cols]
|
|
1216
|
+
print(" ".join(f"{os.path.basename(f):<20}" for f in row_files))
|
|
1217
|
+
|
|
1218
|
+
show_image_auto(np.array(canvas), display_scale, is_vector)
|
|
1152
1219
|
except Exception as e:
|
|
1153
1220
|
print(f"[ERROR] Failed to render gallery: {e}")
|
|
1154
1221
|
|
|
@@ -1156,7 +1223,6 @@ def render_bands_gallery(data: np.ndarray, band_list: list[int], band_count: int
|
|
|
1156
1223
|
grid: str = None, display_scale=None, colormap: str = "viridis") -> None:
|
|
1157
1224
|
"""Render multiple bands from a single raster as a grid of thumbnails."""
|
|
1158
1225
|
import math
|
|
1159
|
-
from PIL import ImageDraw
|
|
1160
1226
|
|
|
1161
1227
|
# Validate bands
|
|
1162
1228
|
valid_bands = [b for b in band_list if 1 <= b <= band_count]
|
|
@@ -1223,14 +1289,22 @@ def render_bands_gallery(data: np.ndarray, band_list: list[int], band_count: int
|
|
|
1223
1289
|
x = margin + c * cell_w
|
|
1224
1290
|
y = margin + r * cell_h
|
|
1225
1291
|
canvas.paste(img, (x, y))
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1292
|
+
if _TERMINAL_SUPPORTS_IMAGES:
|
|
1293
|
+
# Draw label on canvas background below the thumbnail
|
|
1294
|
+
label = f"B{valid_bands[i]}"
|
|
1295
|
+
lx = x + (thumb_w - len(label) * 6) // 2
|
|
1296
|
+
ly = y + thumb_h + 2
|
|
1297
|
+
draw.text((lx, ly), label, fill=(0, 0, 0), font=font)
|
|
1231
1298
|
|
|
1232
1299
|
print(f"[INFO] Displaying {n} bands ({cols}×{rows} grid, colormap: {colormap})")
|
|
1233
1300
|
# print(f"[DEBUG] canvas size: {canvas_w}×{canvas_h}px")
|
|
1301
|
+
|
|
1302
|
+
if not _TERMINAL_SUPPORTS_IMAGES:
|
|
1303
|
+
# Print band labels as text grid
|
|
1304
|
+
for r in range(rows):
|
|
1305
|
+
row_bands = valid_bands[r * cols:(r + 1) * cols]
|
|
1306
|
+
print(" ".join(f"B{b:<4}" for b in row_bands))
|
|
1307
|
+
|
|
1234
1308
|
show_image_auto(np.array(canvas), display_scale)
|
|
1235
1309
|
|
|
1236
1310
|
# ---------------------------------------------------------------------
|
|
@@ -1592,153 +1666,141 @@ def main() -> None:
|
|
|
1592
1666
|
formatter_class=SmartDefaults
|
|
1593
1667
|
)
|
|
1594
1668
|
|
|
1595
|
-
|
|
1669
|
+
# File input
|
|
1596
1670
|
parser.add_argument(
|
|
1597
|
-
"paths", nargs="*",
|
|
1671
|
+
"paths", nargs="*",
|
|
1598
1672
|
help="Path to raster(s), vector, or CSV file. Provide 1 file or exactly 3 rasters for RGB (R G B)."
|
|
1599
1673
|
)
|
|
1600
|
-
|
|
1601
|
-
|
|
1674
|
+
|
|
1675
|
+
# General options
|
|
1676
|
+
general = parser.add_argument_group("General")
|
|
1677
|
+
general.add_argument(
|
|
1602
1678
|
"--display", type=float, default=None,
|
|
1603
1679
|
help="Resize only the displayed image (0.5=smaller, 2=bigger). Default: auto-fit to terminal."
|
|
1604
1680
|
)
|
|
1681
|
+
general.add_argument(
|
|
1682
|
+
"--gallery", nargs="?", const="4x4", metavar="GRID",
|
|
1683
|
+
help="Display all image files in a folder as thumbnails (e.g., --gallery 5x4). Incompatible files are skipped."
|
|
1684
|
+
)
|
|
1605
1685
|
|
|
1606
1686
|
# Raster options
|
|
1607
|
-
parser.
|
|
1687
|
+
raster = parser.add_argument_group("Raster")
|
|
1688
|
+
raster.add_argument(
|
|
1608
1689
|
"--band", type=int, default=None,
|
|
1609
|
-
help="Band number to display (single raster
|
|
1690
|
+
help="Band number to display (single raster), or slice number for NetCDF. (default: 1)"
|
|
1610
1691
|
)
|
|
1611
|
-
|
|
1692
|
+
raster.add_argument(
|
|
1693
|
+
"--bands", type=str,
|
|
1694
|
+
help="Display multiple bands as a grid. Accepts ranges (30-40), lists (3,4,5), or mixed (1,3,10-15)."
|
|
1695
|
+
)
|
|
1696
|
+
raster.add_argument(
|
|
1612
1697
|
"--timestep", type=int, default=None,
|
|
1613
|
-
help="Alias for --band when working with NetCDF files
|
|
1698
|
+
help="Alias for --band when working with NetCDF files."
|
|
1614
1699
|
)
|
|
1615
|
-
|
|
1700
|
+
raster.add_argument(
|
|
1701
|
+
"--subset", type=int, default=None,
|
|
1702
|
+
help="Variable index for NetCDF/HDF files (e.g., --subset 1)."
|
|
1703
|
+
)
|
|
1704
|
+
raster.add_argument(
|
|
1705
|
+
"--reduce", dest="reduce_dim", type=str, default=None, metavar="DIM_NAME",
|
|
1706
|
+
help="For 3D NetCDF variables, specify which dimension to use as the band/slider axis. Auto-detected if omitted."
|
|
1707
|
+
)
|
|
1708
|
+
raster.add_argument(
|
|
1616
1709
|
"--colormap", nargs="?", const="terrain",
|
|
1617
1710
|
choices=AVAILABLE_COLORMAPS, default=None,
|
|
1618
|
-
help="Apply colormap to single-band rasters
|
|
1711
|
+
help="Apply colormap to single-band rasters. Flag without value → 'terrain'."
|
|
1619
1712
|
)
|
|
1620
|
-
|
|
1621
|
-
"--rgb", nargs=
|
|
1622
|
-
help="Three band numbers for RGB display (e.g., --rgb 4 3 2). Overrides default 1 2 3."
|
|
1713
|
+
raster.add_argument(
|
|
1714
|
+
"--rgb", nargs='+', type=str, metavar='BAND', default=None,
|
|
1715
|
+
help="Three band numbers for RGB display (e.g., --rgb 4 3 2 or --rgb 4,3,2). Overrides default 1 2 3."
|
|
1623
1716
|
)
|
|
1624
|
-
|
|
1717
|
+
raster.add_argument(
|
|
1625
1718
|
"--rgbfiles", nargs=3, type=str, metavar=('R', 'G', 'B'),
|
|
1626
|
-
help="Three single-band rasters for RGB composite
|
|
1719
|
+
help="Three single-band rasters for RGB composite. Can also provide as positional arguments."
|
|
1627
1720
|
)
|
|
1628
|
-
|
|
1721
|
+
raster.add_argument(
|
|
1629
1722
|
"--vmin", type=float, default=None,
|
|
1630
1723
|
help="Minimum pixel value for raster display scaling."
|
|
1631
1724
|
)
|
|
1632
|
-
|
|
1725
|
+
raster.add_argument(
|
|
1633
1726
|
"--vmax", type=float, default=None,
|
|
1634
1727
|
help="Maximum pixel value for raster display scaling."
|
|
1635
1728
|
)
|
|
1636
|
-
|
|
1729
|
+
raster.add_argument(
|
|
1637
1730
|
"--nodata", type=float, default=None,
|
|
1638
1731
|
help="Override nodata value for rasters if dataset metadata is missing or incorrect."
|
|
1639
1732
|
)
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
"
|
|
1646
|
-
help="Variable index for NetCDF files (e.g. --subset 1)."
|
|
1733
|
+
|
|
1734
|
+
# Vector options
|
|
1735
|
+
vector = parser.add_argument_group("Vector")
|
|
1736
|
+
vector.add_argument(
|
|
1737
|
+
"--color-by", type=str, default=None,
|
|
1738
|
+
help="Numeric column to color vector features by."
|
|
1647
1739
|
)
|
|
1648
|
-
|
|
1649
|
-
"--
|
|
1650
|
-
|
|
1651
|
-
help="For 3D NetCDF variables, specify which dimension to use as the band axis (auto-detected if omitted)."
|
|
1740
|
+
vector.add_argument(
|
|
1741
|
+
"--width", type=float, default=0.7,
|
|
1742
|
+
help="Line width for vector boundaries."
|
|
1652
1743
|
)
|
|
1653
|
-
|
|
1654
|
-
"--
|
|
1655
|
-
|
|
1656
|
-
|
|
1744
|
+
vector.add_argument(
|
|
1745
|
+
"--edgecolor", type=str, default="#F6FF00",
|
|
1746
|
+
help="Edge color for vector outlines (hex or named color)."
|
|
1747
|
+
)
|
|
1748
|
+
vector.add_argument(
|
|
1749
|
+
"--layer", type=str, default=None,
|
|
1750
|
+
help="Layer name for GeoPackage/multi-layer files, or variable name for NetCDF files."
|
|
1751
|
+
)
|
|
1752
|
+
vector.add_argument(
|
|
1753
|
+
"--table", action="store_true",
|
|
1754
|
+
help="Display vector/parquet file as tabular data instead of rendering geometry."
|
|
1657
1755
|
)
|
|
1658
1756
|
|
|
1659
|
-
#
|
|
1660
|
-
parser.
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
help="Show histograms for all numeric columns or specify one column name."
|
|
1757
|
+
# Tabular options
|
|
1758
|
+
tabular = parser.add_argument_group("Tabular")
|
|
1759
|
+
tabular.add_argument(
|
|
1760
|
+
"--hist", nargs="?", const=True,
|
|
1761
|
+
help="Show histograms for all numeric columns or specify one column name."
|
|
1665
1762
|
)
|
|
1666
|
-
|
|
1667
|
-
"--describe",
|
|
1668
|
-
nargs="?",
|
|
1669
|
-
const=True,
|
|
1763
|
+
tabular.add_argument(
|
|
1764
|
+
"--describe", nargs="?", const=True,
|
|
1670
1765
|
help="Show summary statistics for all numeric columns or specify one column name."
|
|
1671
1766
|
)
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1767
|
+
tabular.add_argument(
|
|
1768
|
+
"--bins", type=int, default=20,
|
|
1769
|
+
help="Number of bins for histograms (used with --hist)."
|
|
1675
1770
|
)
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1771
|
+
tabular.add_argument(
|
|
1772
|
+
"--scatter", nargs=2, metavar=("X", "Y"),
|
|
1773
|
+
help="Scatter plot of two numeric columns (e.g. --scatter area_km2 year)."
|
|
1679
1774
|
)
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
help="Show unique values for a categorical column and exit"
|
|
1775
|
+
tabular.add_argument(
|
|
1776
|
+
"--unique", metavar="COLUMN",
|
|
1777
|
+
help="Show unique values for a categorical column."
|
|
1684
1778
|
)
|
|
1685
|
-
|
|
1686
|
-
"--where",
|
|
1687
|
-
|
|
1688
|
-
default=None,
|
|
1689
|
-
help="Filter rows using SQL WHERE clause (DuckDB required). Example: --where \"year > 2010\""
|
|
1779
|
+
tabular.add_argument(
|
|
1780
|
+
"--where", type=str, default=None,
|
|
1781
|
+
help="Filter rows using SQL WHERE clause (e.g. --where \"year > 2010\")."
|
|
1690
1782
|
)
|
|
1691
|
-
|
|
1692
|
-
"--sort",
|
|
1693
|
-
|
|
1694
|
-
default=None,
|
|
1695
|
-
help="Sort rows by values in the specified column, ascending by default (e.g. --sort population). Use --desc to reverse."
|
|
1783
|
+
tabular.add_argument(
|
|
1784
|
+
"--sort", type=str, default=None,
|
|
1785
|
+
help="Sort rows by column, ascending by default. Use --desc to reverse."
|
|
1696
1786
|
)
|
|
1697
|
-
|
|
1698
|
-
"--desc",
|
|
1699
|
-
action="store_true",
|
|
1787
|
+
tabular.add_argument(
|
|
1788
|
+
"--desc", action="store_true",
|
|
1700
1789
|
help="Sort in descending order."
|
|
1701
1790
|
)
|
|
1702
|
-
|
|
1703
|
-
"--limit",
|
|
1704
|
-
type=int,
|
|
1705
|
-
default=None,
|
|
1791
|
+
tabular.add_argument(
|
|
1792
|
+
"--limit", type=int, default=None,
|
|
1706
1793
|
help="Limit number of rows shown (e.g. --limit 100)."
|
|
1707
1794
|
)
|
|
1708
|
-
|
|
1709
|
-
"--select",
|
|
1710
|
-
|
|
1711
|
-
help="Select specific columns (space separated) (e.g. --select Country City)"
|
|
1795
|
+
tabular.add_argument(
|
|
1796
|
+
"--select", nargs="+",
|
|
1797
|
+
help="Select specific columns (e.g. --select Country City)."
|
|
1712
1798
|
)
|
|
1713
|
-
|
|
1714
|
-
"--sql",
|
|
1715
|
-
|
|
1716
|
-
help="Execute full DuckDB SQL query against CSV (advanced mode)."
|
|
1799
|
+
tabular.add_argument(
|
|
1800
|
+
"--sql", type=str,
|
|
1801
|
+
help="Execute full DuckDB SQL query against CSV/parquet (advanced mode)."
|
|
1717
1802
|
)
|
|
1718
1803
|
|
|
1719
|
-
# Vector options
|
|
1720
|
-
parser.add_argument(
|
|
1721
|
-
"--color-by", type=str, default=None,
|
|
1722
|
-
help="Numeric column to color vector features by (optional)."
|
|
1723
|
-
)
|
|
1724
|
-
parser.add_argument(
|
|
1725
|
-
"--width", type=float, default=0.7,
|
|
1726
|
-
help="Line width for vector boundaries"
|
|
1727
|
-
)
|
|
1728
|
-
parser.add_argument(
|
|
1729
|
-
"--edgecolor", type=str, default="#F6FF00",
|
|
1730
|
-
help="Edge color for vector outlines (hex or named color)."
|
|
1731
|
-
)
|
|
1732
|
-
parser.add_argument(
|
|
1733
|
-
"--layer", type=str, default=None,
|
|
1734
|
-
# help="Layer name for GeoPackage or multi-layer files."
|
|
1735
|
-
help="Layer name for GeoPackage/multi-layer files, or variable name for NetCDF files."
|
|
1736
|
-
)
|
|
1737
|
-
parser.add_argument(
|
|
1738
|
-
"--table", action="store_true",
|
|
1739
|
-
help="Display vector/parquet file as tabular data instead of rendering geometry."
|
|
1740
|
-
)
|
|
1741
|
-
|
|
1742
1804
|
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
1743
1805
|
|
|
1744
1806
|
args = parser.parse_args()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -184,12 +184,12 @@ General:
|
|
|
184
184
|
Raster:
|
|
185
185
|
--band BAND Band number to display (single raster), or slice number for NetCDF. (default: 1)
|
|
186
186
|
--bands BANDS Display multiple bands as a grid. Accepts ranges (30-40), lists (3,4,5), or mixed (1,5,10-15).
|
|
187
|
+
--rgb R G B Three band numbers for RGB display (e.g., --rgb 4 3 2). Overrides default 1 2 3.
|
|
188
|
+
--rgbfiles R G B Three single-band rasters for RGB composite. Can also provide as positional arguments.
|
|
187
189
|
--timestep INTEGER Alias for --band when working with NetCDF files.
|
|
188
190
|
--subset INTEGER Variable index for NetCDF/HDF files (e.g., --subset 1).
|
|
189
191
|
--reduce DIM_NAME For 3D NetCDF variables, specify which dimension to use as the band/slider axis. Auto-detected if omitted.
|
|
190
192
|
--colormap Apply colormap to single-band rasters. Flag without the color scheme → 'terrain'.
|
|
191
|
-
--rgb R G B Three band numbers for RGB display (e.g., --rgb 4 3 2). Overrides default 1 2 3.
|
|
192
|
-
--rgbfiles R G B Three single-band rasters for RGB composite. Can also provide as positional arguments.
|
|
193
193
|
--vmin VMIN Minimum pixel value for raster display scaling.
|
|
194
194
|
--vmax VMAX Maximum pixel value for raster display scaling.
|
|
195
195
|
--nodata NODATA Override nodata value for rasters if dataset metadata is missing or incorrect.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|