Skip to content

Commit

Permalink
feat(cli): expose stats on tiles, empty, avg and overview size
Browse files Browse the repository at this point in the history
  • Loading branch information
blacha committed Nov 28, 2023
1 parent fe4088b commit 62bc6a7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
25 changes: 16 additions & 9 deletions packages/cli/src/cli.table.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import c from 'ansi-colors';

interface CliTableInfo<T> {
export interface CliTableInfo<T> {
/** Header for the table */
name: string;
/** Pad the field out to this width */
Expand All @@ -22,15 +22,22 @@ export class CliTable<T> {

print(data: T[], rowPadding = ''): string[] {
const fields = this.fields.filter((f) => data.every((d) => f.enabled?.(d) ?? true));
const rows = data.map((d, index) => {
const row = fields.map((f) => {
const str = f.get(d, index);
return (str ?? '').padEnd(f.width);
});
return rowPadding + row.join('\t');
});
const values = fields.map((f) => data.map((d, i) => f.get(d, i)));
const sizes = values.map((val) => val.reduce((v, c) => Math.max(v, c?.length ?? 0), 0));
console.log(fields.map((m) => m.name));

const rows: string[] = [rowPadding + fields.map((f, i) => c.bold(f.name.padEnd(sizes[i] + 2))).join('\t')];
console.log(rows);
for (let i = 0; i < data.length; i++) {
const row: string[] = [];
for (let f = 0; f < fields.length; f++) {
const fValue = values[f][i];
const fSize = sizes[f];
row.push((fValue ?? '').padEnd(fSize + 2));
}
rows.push(rowPadding + row.join('\t'));
}

rows.unshift(rowPadding + fields.map((f) => c.blue(f.name.padEnd(f.width))).join('\t'));
return rows;
}
}
42 changes: 40 additions & 2 deletions packages/cli/src/commands/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import c from 'ansi-colors';
import { command, flag, option, optional, restPositionals } from 'cmd-ts';

import { ActionUtil, CliResultMap } from '../action.util.js';
import { CliTable } from '../cli.table.js';
import { CliTable, CliTableInfo } from '../cli.table.js';
import { DefaultArgs, Url } from '../common.js';
import { FetchLog } from '../fs.js';
import { ensureS3fs, setupLogger } from '../log.js';
Expand All @@ -23,6 +23,10 @@ export const commandInfo = command({
path: option({ short: 'f', long: 'file', type: optional(Url) }),
tags: flag({ short: 't', long: 'tags', description: 'Dump tiff tags' }),
fetchTags: flag({ long: 'fetch-tags', description: 'Fetch extra tiff tag information' }),
tileStats: flag({
long: 'tile-stats',
description: 'Fetch tile information, like size [this can fetch a lot of data]',
}),
paths: restPositionals({ type: Url, description: 'Files to process' }),
},
async handler(args) {
Expand All @@ -37,6 +41,11 @@ export const commandInfo = command({
const source = fsa.source(path);
const tiff = await new Tiff(source).init();

if (args.tileStats) {
await Promise.all(tiff.images.map((img) => img.fetch(TiffTag.TileByteCounts)));
TiffImageInfoTable.add(tiffTileStats);
}

const header = [
{ key: 'Tiff type', value: `${TiffVersion[tiff.version]} (v${String(tiff.version)})` },
{
Expand Down Expand Up @@ -128,7 +137,13 @@ TiffImageInfoTable.add({
TiffImageInfoTable.add({
name: 'Tile Count',
width: 20,
get: (i) => `${i.tileCount.x}x${i.tileCount.y} (${i.tileCount.x * i.tileCount.y})`,
get: (i) => {
let tileCount = i.tileCount.x * i.tileCount.y;
const offsets = i.value(TiffTag.TileByteCounts) ?? i.value(TiffTag.TileOffsets);
if (offsets) tileCount = offsets.length;

return `${i.tileCount.x}x${i.tileCount.y} (${tileCount})`;
},
enabled: (i) => i.isTiled(),
});
TiffImageInfoTable.add({
Expand Down Expand Up @@ -156,6 +171,29 @@ TiffImageInfoTable.add({
},
});

export const tiffTileStats: CliTableInfo<TiffImage> = {
name: 'Tile Stats',
width: 20,
get: (i) => {
const sizes = i.value(TiffTag.TileByteCounts);
if (sizes == null) return 'N/A';

const stats = {
size: 0,
empty: 0,
};
for (const st of sizes) {
if (st === 0) stats.empty++;
stats.size += st;
}
const empty = stats.empty > 0 ? ` (${c.blue('empty')}: ${stats.empty})` : '';

const avg = stats.size / (sizes.length - stats.empty);
return toByteSizeString(stats.size) + ` (${c.blue('avg:')} ${toByteSizeString(avg)})` + empty;
},
enabled: () => true,
};

/**
* Parse out the GDAL Metadata to be more friendly to read
*
Expand Down

0 comments on commit 62bc6a7

Please sign in to comment.