mirror of
https://github.com/sbrl/terrain50-cli.git
synced 2024-11-26 07:33:00 +00:00
Add new analyse-frequencies subcommand
This commit is contained in:
parent
0ffbfc42bd
commit
460e2bc1aa
6 changed files with 129 additions and 4 deletions
|
@ -13,9 +13,15 @@ npm install --save terrain50-cli
|
|||
|
||||
-----
|
||||
|
||||
## v1.5
|
||||
- Update dependencies
|
||||
- Add new `analyse-frequencies` subcommand
|
||||
|
||||
|
||||
## v1.4.1
|
||||
- `validate` subcommand in `stream` mode: Write aggregated stats when validation is complete
|
||||
|
||||
|
||||
## v1.4
|
||||
- [BREAKING] Add new `--use-regex` flag to `validate` subcommand (only takes effect in stream mode: `--mode stream`)
|
||||
|
||||
|
|
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -338,9 +338,9 @@
|
|||
}
|
||||
},
|
||||
"terrain50": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.8.0.tgz",
|
||||
"integrity": "sha512-G6wJw0ysZMet0KCqOZr9Cr0OWTjXn00BpZy0SVMfgIE/GiDTeFbCt2EeHANBwKwc93ItLxGua4nWI+5v42jHmw==",
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.8.1.tgz",
|
||||
"integrity": "sha512-bPAOCOcDHgHoLf2Y7uvk09kDZBRKSkIjBNH5kLzufjzaimxaWVJiALegO9RYw5sHRlU+nzbPZ/0trdJjSs/CRQ==",
|
||||
"requires": {
|
||||
"nexline": "^1.2.1",
|
||||
"nnng": "^1.0.0"
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
"chroma-js": "^2.1.0",
|
||||
"image-encode": "^1.3.0",
|
||||
"nexline": "^1.2.1",
|
||||
"terrain50": "^1.8.0"
|
||||
"terrain50": "^1.8.1"
|
||||
},
|
||||
"bin": {
|
||||
"terrain50": "./src/index.mjs"
|
||||
|
|
50
src/Helpers/StreamHelpers.mjs
Normal file
50
src/Helpers/StreamHelpers.mjs
Normal file
|
@ -0,0 +1,50 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Writes data to a stream, automatically waiting for the drain event if asked.
|
||||
* See also write_safe.
|
||||
* @param {stream.Writable} stream_out The writable stream to write to.
|
||||
* @param {string|Buffer|Uint8Array} data The data to write.
|
||||
* @return {Promise} A promise that resolves when writing is complete.
|
||||
* @private
|
||||
*/
|
||||
function write_safe(stream_out, data) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
// Handle errors
|
||||
let handler_error = (error) => {
|
||||
stream_out.off("error", handler_error);
|
||||
reject(error);
|
||||
};
|
||||
stream_out.on("error", handler_error);
|
||||
|
||||
if(typeof data == "string" ? stream_out.write(data, "utf-8") : stream_out.write(data)) {
|
||||
// We're good to go
|
||||
stream_out.off("error", handler_error);
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
// We need to wait for the drain event before continuing
|
||||
stream_out.once("drain", () => {
|
||||
stream_out.off("error", handler_error);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the given stream to end and finish writing data.
|
||||
* NOTE: This function is not tested and guaranteed yet. (ref #10 the HydroIndexWriter bug)
|
||||
* @param {stream.Writable} stream The stream to end.
|
||||
* @param {Buffer|string} [chunk=undefined] Optional. A chunk to write when calling .end().
|
||||
* @return {Promise} A Promise that resolves when writing is complete.
|
||||
* @private
|
||||
*/
|
||||
function end_safe(stream, chunk = undefined) {
|
||||
return new Promise((resolve, _reject) => {
|
||||
if(typeof chunk == "undefined") stream.end(resolve);
|
||||
else stream.end(chunk, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
export { write_safe, end_safe };
|
50
src/Subcommands/analyse-frequencies/index.mjs
Normal file
50
src/Subcommands/analyse-frequencies/index.mjs
Normal file
|
@ -0,0 +1,50 @@
|
|||
"use strict";
|
||||
|
||||
import fs from 'fs';
|
||||
|
||||
import Terrain50 from 'terrain50';
|
||||
|
||||
import a from '../../Helpers/Ansi.mjs';
|
||||
import l from '../../Helpers/Log.mjs';
|
||||
|
||||
import { percentage } from '../../Helpers/MathsHelpers.mjs';
|
||||
import { write_safe, end_safe } from '../../Helpers/StreamHelpers.mjs';
|
||||
|
||||
export default async function(settings) {
|
||||
// 1: Parse settings
|
||||
let stream_in = process.stdin;
|
||||
if(settings.cli.input !== "-") {
|
||||
l.log(`Reading from ${a.hicol}${settings.cli.input}${a.reset}`);
|
||||
stream_in = fs.createReadStream(settings.cli.input);
|
||||
}
|
||||
else
|
||||
l.log(`Reading from stdin`);
|
||||
|
||||
let stream_out = process.stdout;
|
||||
if(settings.cli.output !== "-") {
|
||||
l.log(`Writing to ${a.hicol}${settings.cli.output}${a.reset}`);
|
||||
stream_out = fs.createWriteStream(settings.cli.output);
|
||||
}
|
||||
else
|
||||
l.log(`Writing to stdout`);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
let result_map = await Terrain50.AnalyseFrequencies(
|
||||
Terrain50.ParseStream(stream_in),
|
||||
settings.cli.ignore_nodata
|
||||
);
|
||||
|
||||
let result_arr = [];
|
||||
for(const [ key, value ] of result_map) {
|
||||
result_arr.push([ key, value ]);
|
||||
}
|
||||
result_arr.sort((a, b) => a[0] - b[0]);
|
||||
|
||||
for(const [ key, value ] of result_arr) {
|
||||
await write_safe(stream_out, `${key} ${value}\n`);
|
||||
}
|
||||
await end_safe(stream_out);
|
||||
|
||||
stream_in.destroy();
|
||||
}
|
19
src/Subcommands/analyse-frequencies/meta.toml
Normal file
19
src/Subcommands/analyse-frequencies/meta.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
description = "Count the frequencies of data values. Data values are rounded down before counting."
|
||||
|
||||
[[arguments]]
|
||||
name = "input"
|
||||
description = "The input file to analyse (default: stdin)"
|
||||
default_value = "-"
|
||||
type = "string"
|
||||
|
||||
[[arguments]]
|
||||
name = "output"
|
||||
description = "The output file to write the results to as tab-separated-values (default: stdout)"
|
||||
default_value = "-"
|
||||
type = "string"
|
||||
|
||||
[[arguments]]
|
||||
name = "ignore-nodata"
|
||||
description = "Ignore NODATA values when analysing."
|
||||
default_value = false
|
||||
type = "boolean"
|
Loading…
Reference in a new issue