@ca-plant-list/ca-plant-list 0.4.20 → 0.4.21
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.
- package/data/synonyms.csv +0 -1
- package/data/taxa.csv +1899 -1899
- package/lib/config.js +15 -1
- package/lib/csv.js +23 -1
- package/lib/externalsites.js +29 -3
- package/lib/files.js +1 -1
- package/lib/genera.js +3 -0
- package/lib/htmltaxon.js +13 -0
- package/lib/index.d.ts +25 -7
- package/lib/index.js +3 -2
- package/lib/taxa.js +1 -1
- package/lib/taxon.js +16 -15
- package/lib/tools/calflora.js +0 -1
- package/lib/tools/cch2.js +95 -0
- package/lib/tools/jepsoneflora.js +1 -1
- package/lib/web/pagetaxon.js +11 -3
- package/package.json +1 -1
- package/scripts/cpl-tools.js +12 -0
package/lib/config.js
CHANGED
@@ -2,9 +2,15 @@ import * as path from "node:path";
|
|
2
2
|
import * as url from "node:url";
|
3
3
|
import { Files } from "./files.js";
|
4
4
|
|
5
|
+
/** @type {Object<string,string>} */
|
6
|
+
const COUNTY_NAMES = {
|
7
|
+
ALA: "Alameda",
|
8
|
+
CCA: "Contra Costa",
|
9
|
+
};
|
10
|
+
|
5
11
|
class Config {
|
6
12
|
static #packageDir = path.dirname(
|
7
|
-
path.dirname(url.fileURLToPath(import.meta.url))
|
13
|
+
path.dirname(url.fileURLToPath(import.meta.url)),
|
8
14
|
);
|
9
15
|
|
10
16
|
/** @type {Object<string,Object<string,Object<string,{}>>>} */
|
@@ -55,6 +61,14 @@ class Config {
|
|
55
61
|
return [];
|
56
62
|
}
|
57
63
|
|
64
|
+
/**
|
65
|
+
* @returns {string[]}
|
66
|
+
*/
|
67
|
+
getCountyNames() {
|
68
|
+
const counties = this.getCountyCodes();
|
69
|
+
return counties.map((c) => COUNTY_NAMES[c]);
|
70
|
+
}
|
71
|
+
|
58
72
|
/**
|
59
73
|
* @param {string} name
|
60
74
|
* @param {string} dflt
|
package/lib/csv.js
CHANGED
@@ -13,7 +13,7 @@ class CSV {
|
|
13
13
|
*/
|
14
14
|
static #getOptions(fileName, columns, delimiter) {
|
15
15
|
/** @type {import("csv-parse").Options} */
|
16
|
-
const options = { relax_column_count_less: true };
|
16
|
+
const options = { relax_column_count_less: true, bom: true };
|
17
17
|
options.columns = columns;
|
18
18
|
if (path.extname(fileName) === ".tsv") {
|
19
19
|
options.delimiter = "\t";
|
@@ -44,6 +44,7 @@ class CSV {
|
|
44
44
|
* @param {boolean|import("csv-parse").ColumnOption[]} columns
|
45
45
|
* @param {string|undefined} delimiter
|
46
46
|
* @param {function (any):void} callback
|
47
|
+
* @deprecated Use parseFileStream
|
47
48
|
*/
|
48
49
|
static async parseStream(
|
49
50
|
dir,
|
@@ -72,6 +73,27 @@ class CSV {
|
|
72
73
|
await processFile();
|
73
74
|
}
|
74
75
|
|
76
|
+
/**
|
77
|
+
* @template T
|
78
|
+
* @param {string} fileName
|
79
|
+
* @param {function (T):void} callback
|
80
|
+
*/
|
81
|
+
static async parseFileStream(fileName, callback) {
|
82
|
+
const options = this.#getOptions(fileName, true, undefined);
|
83
|
+
const processFile = async () => {
|
84
|
+
const parser = fs.createReadStream(fileName).pipe(parse(options));
|
85
|
+
parser.on("readable", function () {
|
86
|
+
let record;
|
87
|
+
while ((record = parser.read()) !== null) {
|
88
|
+
callback(record);
|
89
|
+
}
|
90
|
+
});
|
91
|
+
await finished(parser);
|
92
|
+
};
|
93
|
+
// Parse the CSV content
|
94
|
+
await processFile();
|
95
|
+
}
|
96
|
+
|
75
97
|
/**
|
76
98
|
* @param {string} fileName
|
77
99
|
* @param {boolean|import("csv-parse").ColumnOption[]|function (string[]):string[]} [columns]
|
package/lib/externalsites.js
CHANGED
@@ -5,7 +5,35 @@
|
|
5
5
|
taxon_id?: string;
|
6
6
|
}} InatObsOptions */
|
7
7
|
|
8
|
-
class ExternalSites {
|
8
|
+
export class ExternalSites {
|
9
|
+
/**
|
10
|
+
* @param {import("./taxon.js").Taxon} taxon
|
11
|
+
* @param {import("./config.js").Config} config
|
12
|
+
* @returns {URL|undefined}
|
13
|
+
*/
|
14
|
+
static getCCH2ObsLink(taxon, config) {
|
15
|
+
const url = new URL(
|
16
|
+
"https://www.cch2.org/portal/collections/listtabledisplay.php?usethes=1&taxontype=2&sortfield1=o.eventDate&sortorder=desc",
|
17
|
+
);
|
18
|
+
url.searchParams.set("county", config.getCountyNames().join(";"));
|
19
|
+
url.searchParams.set("taxa", taxon.getName());
|
20
|
+
return url;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* @param {import("./taxon.js").Taxon} taxon
|
25
|
+
* @returns {URL|undefined}
|
26
|
+
*/
|
27
|
+
static getCCH2RefLink(taxon) {
|
28
|
+
const id = taxon.getCCH2ID();
|
29
|
+
if (!id) {
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
const url = new URL("https://www.cch2.org/portal/taxa/index.php");
|
33
|
+
url.searchParams.set("taxon", id);
|
34
|
+
return url;
|
35
|
+
}
|
36
|
+
|
9
37
|
/**
|
10
38
|
* @param {InatObsOptions} options
|
11
39
|
*/
|
@@ -44,5 +72,3 @@ class ExternalSites {
|
|
44
72
|
return url.toString();
|
45
73
|
}
|
46
74
|
}
|
47
|
-
|
48
|
-
export { ExternalSites };
|
package/lib/files.js
CHANGED
package/lib/genera.js
CHANGED
package/lib/htmltaxon.js
CHANGED
@@ -54,6 +54,19 @@ const DEFAULT_TAXA_COLUMNS = [
|
|
54
54
|
];
|
55
55
|
|
56
56
|
class HTMLTaxon {
|
57
|
+
/**
|
58
|
+
* @param {string[]} links
|
59
|
+
* @param {URL|string|undefined} href
|
60
|
+
* @param {string} label
|
61
|
+
*/
|
62
|
+
static addLink(links, href, label) {
|
63
|
+
if (href === undefined) {
|
64
|
+
return;
|
65
|
+
}
|
66
|
+
const link = HTML.getLink(href.toString(), label, {}, true);
|
67
|
+
links.push(link);
|
68
|
+
}
|
69
|
+
|
57
70
|
/**
|
58
71
|
* @param {import("./taxon.js").Taxon} taxon
|
59
72
|
* @returns {string|undefined}
|
package/lib/index.d.ts
CHANGED
@@ -2,11 +2,14 @@ import { Command } from "commander";
|
|
2
2
|
|
3
3
|
// Types
|
4
4
|
|
5
|
+
export type NativeStatusCode = "N" | "NC" | "U" | "X";
|
6
|
+
|
5
7
|
export type TaxonData = {
|
6
8
|
bloom_end: string;
|
7
9
|
bloom_start: string;
|
8
10
|
calrecnum: string;
|
9
11
|
calscape_cn?: string;
|
12
|
+
cch2_id: string;
|
10
13
|
CESA: string;
|
11
14
|
"common name": string;
|
12
15
|
CRPR: string;
|
@@ -18,7 +21,7 @@ export type TaxonData = {
|
|
18
21
|
life_cycle: string;
|
19
22
|
"RPI ID": string;
|
20
23
|
SRank: string;
|
21
|
-
status:
|
24
|
+
status: NativeStatusCode;
|
22
25
|
taxon_name: string;
|
23
26
|
};
|
24
27
|
|
@@ -58,6 +61,15 @@ export class Exceptions {
|
|
58
61
|
hasException(name: string, cat: string, subcat: string): boolean;
|
59
62
|
}
|
60
63
|
|
64
|
+
export class ExternalSites {
|
65
|
+
static getCCH2ObsLink(taxon: Taxon, config: Config): URL | undefined;
|
66
|
+
static getCCH2RefLink(taxon: Taxon): URL | undefined;
|
67
|
+
}
|
68
|
+
|
69
|
+
export class Family {
|
70
|
+
getName(): string;
|
71
|
+
}
|
72
|
+
|
61
73
|
export class Files {
|
62
74
|
static exists(fileName: string): boolean;
|
63
75
|
static fetch(
|
@@ -69,6 +81,12 @@ export class Files {
|
|
69
81
|
static write(fileName: string, data: string, overwrite: boolean): void;
|
70
82
|
}
|
71
83
|
|
84
|
+
export class Genera {}
|
85
|
+
|
86
|
+
export class Genus {
|
87
|
+
getTaxa(): Taxon[];
|
88
|
+
}
|
89
|
+
|
72
90
|
export class HTML {
|
73
91
|
static arrayToLI(items: string[]): string;
|
74
92
|
static getLink(
|
@@ -90,6 +108,11 @@ export class HTML {
|
|
90
108
|
}
|
91
109
|
|
92
110
|
export class HTMLTaxon {
|
111
|
+
static addLink(
|
112
|
+
links: string[],
|
113
|
+
href: URL | string | undefined,
|
114
|
+
label: string,
|
115
|
+
): void;
|
93
116
|
static getFooterHTML(taxon: Taxon): string;
|
94
117
|
static getListSectionHTML(
|
95
118
|
list: string[],
|
@@ -118,12 +141,6 @@ export class Program {
|
|
118
141
|
static getProgram(): Command;
|
119
142
|
}
|
120
143
|
|
121
|
-
export class Family {}
|
122
|
-
|
123
|
-
export class Genera {}
|
124
|
-
|
125
|
-
export class Genus {}
|
126
|
-
|
127
144
|
export class Taxa {
|
128
145
|
constructor(
|
129
146
|
inclusionList: Record<string, TaxonData> | true,
|
@@ -145,6 +162,7 @@ export class Taxon {
|
|
145
162
|
getCNDDBRank(): string | undefined;
|
146
163
|
getCommonNames(): string[];
|
147
164
|
getFamily(): Family;
|
165
|
+
getFileName(): string;
|
148
166
|
getFESA(): string | undefined;
|
149
167
|
getGenus(): Genus;
|
150
168
|
getGenusName(): string;
|
package/lib/index.js
CHANGED
@@ -3,6 +3,7 @@ import { Config } from "./config.js";
|
|
3
3
|
import { CSV } from "./csv.js";
|
4
4
|
import { ErrorLog } from "./errorlog.js";
|
5
5
|
import { Exceptions } from "./exceptions.js";
|
6
|
+
import { ExternalSites } from "./externalsites.js";
|
6
7
|
import { Families } from "./families.js";
|
7
8
|
import { Files } from "./files.js";
|
8
9
|
import { HTML } from "./html.js";
|
@@ -11,7 +12,7 @@ import { Jekyll } from "./jekyll.js";
|
|
11
12
|
import { PlantBook } from "./ebook/plantbook.js";
|
12
13
|
import { Program } from "./program.js";
|
13
14
|
import { Taxa } from "./taxa.js";
|
14
|
-
import { Taxon
|
15
|
+
import { Taxon } from "./taxon.js";
|
15
16
|
|
16
17
|
export {
|
17
18
|
BasePageRenderer,
|
@@ -19,6 +20,7 @@ export {
|
|
19
20
|
CSV,
|
20
21
|
ErrorLog,
|
21
22
|
Exceptions,
|
23
|
+
ExternalSites,
|
22
24
|
Families,
|
23
25
|
Files,
|
24
26
|
HTML,
|
@@ -27,6 +29,5 @@ export {
|
|
27
29
|
PlantBook,
|
28
30
|
Program,
|
29
31
|
Taxa,
|
30
|
-
TAXA_COLNAMES,
|
31
32
|
Taxon,
|
32
33
|
};
|
package/lib/taxa.js
CHANGED
@@ -255,7 +255,7 @@ class Taxa {
|
|
255
255
|
for (const row of taxaCSV) {
|
256
256
|
const name = row["taxon_name"];
|
257
257
|
|
258
|
-
/** @type {import("./index.js").TaxonData|{status?:import("./
|
258
|
+
/** @type {import("./index.js").TaxonData|{status?:import("./index.js").NativeStatusCode}} */
|
259
259
|
let taxon_overrides = {};
|
260
260
|
if (inclusionList !== true) {
|
261
261
|
taxon_overrides = inclusionList[name];
|
package/lib/taxon.js
CHANGED
@@ -1,17 +1,6 @@
|
|
1
1
|
import { HTML } from "./html.js";
|
2
2
|
import { RarePlants } from "./rareplants.js";
|
3
3
|
|
4
|
-
/**
|
5
|
-
* @typedef {"N" | "NC" | "U" | "X"} StatusCode
|
6
|
-
*/
|
7
|
-
|
8
|
-
const TAXA_COLNAMES = {
|
9
|
-
BLOOM_START: "bloom_start",
|
10
|
-
BLOOM_END: "bloom_end",
|
11
|
-
COMMON_NAME: "common name",
|
12
|
-
FLOWER_COLOR: "flower_color",
|
13
|
-
};
|
14
|
-
|
15
4
|
class Taxon {
|
16
5
|
#genera;
|
17
6
|
#name;
|
@@ -25,6 +14,7 @@ class Taxon {
|
|
25
14
|
#iNatID;
|
26
15
|
/**@type {string|undefined} */
|
27
16
|
#iNatSyn;
|
17
|
+
#cch2id;
|
28
18
|
#calscapeCN;
|
29
19
|
#lifeCycle;
|
30
20
|
#flowerColors;
|
@@ -62,6 +52,7 @@ class Taxon {
|
|
62
52
|
this.#jepsonID = data["jepson id"];
|
63
53
|
this.#calRecNum = data["calrecnum"];
|
64
54
|
this.#iNatID = data["inat id"];
|
55
|
+
this.#cch2id = data.cch2_id;
|
65
56
|
this.#calscapeCN =
|
66
57
|
data.calscape_cn === "" ? undefined : data.calscape_cn;
|
67
58
|
this.#lifeCycle = data.life_cycle;
|
@@ -173,6 +164,13 @@ class Taxon {
|
|
173
164
|
return name.replace(" subsp.", " ssp.");
|
174
165
|
}
|
175
166
|
|
167
|
+
/**
|
168
|
+
* @returns {string}
|
169
|
+
*/
|
170
|
+
getCCH2ID() {
|
171
|
+
return this.#cch2id;
|
172
|
+
}
|
173
|
+
|
176
174
|
getCESA() {
|
177
175
|
return this.#cesa;
|
178
176
|
}
|
@@ -303,12 +301,18 @@ class Taxon {
|
|
303
301
|
return this.#rankRPI;
|
304
302
|
}
|
305
303
|
|
304
|
+
/**
|
305
|
+
* @deprecated
|
306
|
+
*/
|
306
307
|
getRPIRankAndThreatTooltip() {
|
307
308
|
return RarePlants.getRPIRankAndThreatDescriptions(
|
308
309
|
this.getRPIRankAndThreat(),
|
309
310
|
).join("<br>");
|
310
311
|
}
|
311
312
|
|
313
|
+
/**
|
314
|
+
* @deprecated
|
315
|
+
*/
|
312
316
|
getRPITaxonLink() {
|
313
317
|
const rpiID = this.getRPIID();
|
314
318
|
if (!rpiID) {
|
@@ -323,9 +327,6 @@ class Taxon {
|
|
323
327
|
return link;
|
324
328
|
}
|
325
329
|
|
326
|
-
/**
|
327
|
-
* @returns {StatusCode}
|
328
|
-
*/
|
329
330
|
getStatus() {
|
330
331
|
return this.#status;
|
331
332
|
}
|
@@ -385,4 +386,4 @@ class Taxon {
|
|
385
386
|
}
|
386
387
|
}
|
387
388
|
|
388
|
-
export {
|
389
|
+
export { Taxon };
|
package/lib/tools/calflora.js
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
import path from "node:path";
|
2
|
+
import { CSV } from "../csv.js";
|
3
|
+
import { TaxaCSV } from "./taxacsv.js";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* @typedef {{id:string}} CCHTaxon
|
7
|
+
* @typedef {Map<string,CCHTaxon>} CCHTaxa
|
8
|
+
*/
|
9
|
+
|
10
|
+
export class CCH2 {
|
11
|
+
/**
|
12
|
+
* @param {string} toolsDataDir
|
13
|
+
* @param {string} dataDir
|
14
|
+
* @param {import("../taxa.js").Taxa} taxa
|
15
|
+
* @param {import("../errorlog.js").ErrorLog} errorLog
|
16
|
+
* @param {boolean} update
|
17
|
+
*/
|
18
|
+
static async analyze(toolsDataDir, dataDir, taxa, errorLog, update) {
|
19
|
+
const toolsDataPath = path.join(toolsDataDir, "cch2");
|
20
|
+
|
21
|
+
const cchTaxa = await getCCHTaxa(toolsDataPath, taxa);
|
22
|
+
|
23
|
+
const idsToUpdate = new Map();
|
24
|
+
for (const taxon of taxa.getTaxonList()) {
|
25
|
+
const cchTaxon = cchTaxa.get(taxon.getName());
|
26
|
+
if (!cchTaxon) {
|
27
|
+
errorLog.log(taxon.getName(), "not found in CCH data");
|
28
|
+
continue;
|
29
|
+
}
|
30
|
+
if (cchTaxon.id !== taxon.getCCH2ID()) {
|
31
|
+
errorLog.log(
|
32
|
+
taxon.getName(),
|
33
|
+
"id in CCH data does not match id in taxa.csv",
|
34
|
+
cchTaxon.id,
|
35
|
+
taxon.getCCH2ID(),
|
36
|
+
);
|
37
|
+
idsToUpdate.set(taxon.getName(), cchTaxon.id);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
if (update) {
|
42
|
+
updateTaxaCSV(dataDir, idsToUpdate);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @param {string} toolsDataPath
|
49
|
+
* @param {import("../taxa.js").Taxa} taxa
|
50
|
+
* @returns {Promise<CCHTaxa>}
|
51
|
+
*/
|
52
|
+
async function getCCHTaxa(toolsDataPath, taxa) {
|
53
|
+
/**
|
54
|
+
* @param {{taxonID:string,scientificName:string,rankID:string,acceptance:"0"|"1",acceptedTaxonID:string}} record
|
55
|
+
*/
|
56
|
+
function callback(record) {
|
57
|
+
if (parseInt(record.rankID) < 220) {
|
58
|
+
// Ignore ranks above species.
|
59
|
+
return;
|
60
|
+
}
|
61
|
+
if (record.acceptance !== "1") {
|
62
|
+
return;
|
63
|
+
}
|
64
|
+
if (!taxa.getTaxon(record.scientificName)) {
|
65
|
+
// If we're not tracking the taxon, ignore it.
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
data.set(record.scientificName, { id: record.acceptedTaxonID });
|
69
|
+
}
|
70
|
+
|
71
|
+
const fileName = path.join(toolsDataPath, "taxa.csv");
|
72
|
+
const data = new Map();
|
73
|
+
|
74
|
+
await CSV.parseFileStream(fileName, callback);
|
75
|
+
|
76
|
+
return data;
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* @param {string} dataDir
|
81
|
+
* @param {Map<string,string>} idsToUpdate
|
82
|
+
*/
|
83
|
+
function updateTaxaCSV(dataDir, idsToUpdate) {
|
84
|
+
const taxa = new TaxaCSV(dataDir);
|
85
|
+
|
86
|
+
for (const taxonData of taxa.getTaxa()) {
|
87
|
+
const id = idsToUpdate.get(taxonData.taxon_name);
|
88
|
+
if (!id) {
|
89
|
+
continue;
|
90
|
+
}
|
91
|
+
taxonData.cch2_id = id;
|
92
|
+
}
|
93
|
+
|
94
|
+
taxa.write();
|
95
|
+
}
|
@@ -228,7 +228,7 @@ export class JepsonEFlora {
|
|
228
228
|
|
229
229
|
/**
|
230
230
|
* @param {JepsonTaxon} jepsInfo
|
231
|
-
* @returns {import("../
|
231
|
+
* @returns {import("../index.js").NativeStatusCode|undefined}
|
232
232
|
*/
|
233
233
|
#getStatusCode(jepsInfo) {
|
234
234
|
switch (jepsInfo.type) {
|
package/lib/web/pagetaxon.js
CHANGED
@@ -5,7 +5,7 @@ import { ExternalSites } from "../externalsites.js";
|
|
5
5
|
import { HTML } from "../html.js";
|
6
6
|
import { HTMLTaxon } from "../htmltaxon.js";
|
7
7
|
|
8
|
-
class PageTaxon extends GenericPage {
|
8
|
+
export class PageTaxon extends GenericPage {
|
9
9
|
#config;
|
10
10
|
#taxon;
|
11
11
|
|
@@ -42,6 +42,11 @@ class PageTaxon extends GenericPage {
|
|
42
42
|
if (rpiLink) {
|
43
43
|
links.push(rpiLink);
|
44
44
|
}
|
45
|
+
HTMLTaxon.addLink(
|
46
|
+
links,
|
47
|
+
ExternalSites.getCCH2RefLink(this.#taxon),
|
48
|
+
"CCH2",
|
49
|
+
);
|
45
50
|
return links;
|
46
51
|
}
|
47
52
|
|
@@ -76,6 +81,11 @@ class PageTaxon extends GenericPage {
|
|
76
81
|
),
|
77
82
|
);
|
78
83
|
}
|
84
|
+
HTMLTaxon.addLink(
|
85
|
+
links,
|
86
|
+
ExternalSites.getCCH2ObsLink(this.#taxon, this.#config),
|
87
|
+
"CCH2",
|
88
|
+
);
|
79
89
|
|
80
90
|
return links;
|
81
91
|
}
|
@@ -218,5 +228,3 @@ class PageTaxon extends GenericPage {
|
|
218
228
|
this.writeFile(html);
|
219
229
|
}
|
220
230
|
}
|
221
|
-
|
222
|
-
export { PageTaxon };
|
package/package.json
CHANGED
package/scripts/cpl-tools.js
CHANGED
@@ -13,10 +13,12 @@ import { Config } from "../lib/config.js";
|
|
13
13
|
import { Taxa } from "../lib/taxa.js";
|
14
14
|
import { SupplementalText } from "../lib/tools/supplementaltext.js";
|
15
15
|
import { JepsonFamilies } from "../lib/tools/jepsonfamilies.js";
|
16
|
+
import { CCH2 } from "../lib/tools/cch2.js";
|
16
17
|
|
17
18
|
const TOOLS = {
|
18
19
|
CALFLORA: "calflora",
|
19
20
|
CALSCAPE: "calscape",
|
21
|
+
CCH2: "cch",
|
20
22
|
INAT: "inat",
|
21
23
|
JEPSON_EFLORA: "jepson-eflora",
|
22
24
|
JEPSON_FAM: "jepson-families",
|
@@ -27,6 +29,7 @@ const TOOLS = {
|
|
27
29
|
const ALL_TOOLS = [
|
28
30
|
TOOLS.CALFLORA,
|
29
31
|
TOOLS.CALSCAPE,
|
32
|
+
TOOLS.CCH2,
|
30
33
|
TOOLS.INAT,
|
31
34
|
TOOLS.JEPSON_EFLORA,
|
32
35
|
TOOLS.RPI,
|
@@ -77,6 +80,15 @@ async function build(program, options) {
|
|
77
80
|
!!options.update,
|
78
81
|
);
|
79
82
|
break;
|
83
|
+
case TOOLS.CCH2:
|
84
|
+
await CCH2.analyze(
|
85
|
+
TOOLS_DATA_DIR,
|
86
|
+
options.datadir,
|
87
|
+
taxa,
|
88
|
+
errorLog,
|
89
|
+
!!options.update,
|
90
|
+
);
|
91
|
+
break;
|
80
92
|
case TOOLS.INAT:
|
81
93
|
await INat.analyze(
|
82
94
|
TOOLS_DATA_DIR,
|