Skip to content

nd2.index

Index ND2 files and print the results as a table.

This module is intended to be used as a command-line utility. It will index the metadata of all ND2 files found in a folder and print the results as a table, or output as CSV or JSON.

Usage

python -m nd2.index [OPTIONS] paths [paths ...]

Positional Arguments

Argument Description
paths Path to an ND2 file or directory containing ND2 files.

Options

Option Short Description
--help -h Show this help message and exit.
--recurse -r Recursively search directories.
--glob-pattern GLOB_PATTERN -g Glob pattern to search for.
--sort-by COLUMN_NAME -s Column to sort by. If not specified, the order is not guaranteed. To sort in reverse, append a hyphen (-).
--format {table,csv,json} -f Output format: table, CSV, or JSON.
--include INCLUDE -i Comma-separated columns to include in the output.
--exclude EXCLUDE -e Comma-separated columns to exclude in the output.
--no-header (none) Don't write the CSV header.
--filter FILTER -F Filter the output using a Python expression (string) that evaluates to True or False. Evaluated in the context of each row. You can use any column name as a variable.
Example: "acquired > '2020' and kb < 500". (Can be used multiple times.)

Example

python -m nd2.index nd2/tests/data

When run on the test data used in testing this nd2 repo, the output looks like this:

asciicast

Classes:

  • Record

    Dict returned by index_file.

Functions:

  • index_file

    Return a dict with the index file data.

  • index_files

    Return a list of Record dicts with the index file data.

Record

Dict returned by index_file.

index_file

index_file(path: Path) -> Record

Return a dict with the index file data.

Source code in nd2/index.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def index_file(path: Path) -> Record:
    """Return a dict with the index file data."""
    with nd2.ND2File(path) as nd:
        if nd.is_legacy:
            software: dict = {}
            acquired: datetime | None = None
            binary = False
        else:
            rdr = cast("ModernReader", nd._rdr)
            software = rdr._app_info()
            acquired = rdr._acquisition_datetime()
            binary = nd.binary_data is not None

        stat = path.stat()
        exp = [(x.type, x.count) for x in nd.experiment]
        axes, shape = zip(*nd.sizes.items())
        if isinstance(acquired, datetime):
            acq_str = acquired.strftime(TIME_FORMAT)
        else:
            acq_str = ""

        return Record(
            {
                "path": str(path.resolve()),
                "name": path.name,
                "version": ".".join(map(str, nd.version)),
                "kb": round(stat.st_size / 1000, 2),
                "acquired": acq_str,
                "experiment": ";".join([f"{t}:{c}" for t, c in exp]),
                "dtype": str(nd.dtype),
                "shape": list(shape),
                "axes": "".join(axes),
                "binary": binary,
                "rois": False if nd.is_legacy else bool(nd.rois),
                "software_name": software.get("SWNameString", ""),
                "software_version": software.get("VersionString", ""),
                "grabber": software.get("GrabberString", ""),
            }
        )

index_files

index_files(paths: Iterable[Path], recurse: bool = False, glob: str = '*.nd2') -> list[Record]

Return a list of Record dicts with the index file data.

Source code in nd2/index.py
149
150
151
152
153
154
155
156
def index_files(
    paths: Iterable[Path], recurse: bool = False, glob: str = "*.nd2"
) -> list[Record]:
    """Return a list of `Record` dicts with the index file data."""
    with ThreadPoolExecutor() as executor:
        results = list(executor.map(index_file, _gather_files(paths, recurse, glob)))

    return results

main

main(argv: Sequence[str] = ()) -> None

Index ND2 files and print the results as a table.

Source code in nd2/index.py
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
def main(argv: Sequence[str] = ()) -> None:
    """Index ND2 files and print the results as a table."""
    args = _parse_args(argv)

    data = index_files(paths=args.paths, recurse=args.recurse, glob=args.glob_pattern)
    data = _filter_data(
        data,
        sort_by=args.sort_by,
        include=args.include,
        exclude=args.exclude,
        filters=args.filter,
    )

    if args.format == "table":
        _pretty_print_table(data, args.sort_by)
    elif args.format == "csv":
        _print_csv(data, args.no_header)
    elif args.format == "json":
        _print_json(data)