imerss-bioinfo 1.0.0
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/README.md +156 -0
- package/build.js +196 -0
- package/docs/css/imerss-viz-all.css +1227 -0
- package/docs/css/imerss-viz-wp-overrides.css +70 -0
- package/docs/css/pepiowelh.css +76 -0
- package/docs/css/xetthecum-external.css +47 -0
- package/docs/css/xetthecum-shared.css +80 -0
- package/docs/css/xetthecum.css +526 -0
- package/docs/js/imerss-viz-all.js +58 -0
- package/docs/js/imerss-viz-all.js.map +1 -0
- package/docs/js/jquery.js +10881 -0
- package/index.html +81 -0
- package/index.js +7 -0
- package/indexWithJustMap.html +92 -0
- package/indexWithMap.html +79 -0
- package/indexWithMapHoweSound.html +91 -0
- package/indexWithMapPepiowelh.html +119 -0
- package/indexWithMapValdes.html +90 -0
- package/indexWithMapXetthecum.html +90 -0
- package/package.json +50 -0
- package/src/WoRMS/taxonAPI.js +13 -0
- package/src/arphify.js +662 -0
- package/src/assignNames.js +103 -0
- package/src/auxBuild/restoreJQuery.js +1 -0
- package/src/buildSource/Comprehensive Lists.html +42 -0
- package/src/buildSource/Data Paper Part I Visualisation.html +50 -0
- package/src/buildSource/Galiano Life List.html +43 -0
- package/src/buildSource/Metchosin/index.html +22 -0
- package/src/buildSource/Pe'pi'ow'elh.html +72 -0
- package/src/buildSource/Squamish Life List.html +48 -0
- package/src/buildSource/Valdes Island Biodiversity.html +64 -0
- package/src/buildSource/Xetthecum.html +40 -0
- package/src/buildSource/dataPaperSunburstAndMap.html +30 -0
- package/src/buildSource/index.html +224 -0
- package/src/client/css/imerss-viz-wp-overrides.css +70 -0
- package/src/client/css/imerss-viz.css +531 -0
- package/src/client/css/pepiowelh.css +76 -0
- package/src/client/css/xetthecum-external.css +47 -0
- package/src/client/css/xetthecum-shared.css +80 -0
- package/src/client/css/xetthecum.css +526 -0
- package/src/client/html/imerss-viz-map-only.html +75 -0
- package/src/client/html/imerss-viz-map-pepi.html +77 -0
- package/src/client/html/imerss-viz-map-xetthecum.html +90 -0
- package/src/client/html/imerss-viz-map.html +75 -0
- package/src/client/html/imerss-viz.html +58 -0
- package/src/client/html/importing Xetthecum patterns.txt +10 -0
- package/src/client/html/xetthecum-patterns.html +27 -0
- package/src/client/img/Animalia_2.svg +1 -0
- package/src/client/img/Animalia_Annelida.svg +655 -0
- package/src/client/img/Animalia_Chaetognatha.svg +72 -0
- package/src/client/img/Animalia_Cnidaria.svg +173 -0
- package/src/client/img/Animalia_Ctenophora.svg +298 -0
- package/src/client/img/Animalia_Nemertea.svg +54 -0
- package/src/client/img/Animalia_Phoronida.svg +271 -0
- package/src/client/img/Animalia_Platyhelminthes.svg +58 -0
- package/src/client/img/Animalia_Porifera.svg +220 -0
- package/src/client/img/Animalia_Sipuncula.svg +155 -0
- package/src/client/img/Arachnoidiscus_schmidtii_web_1-2-scaled.webp +0 -0
- package/src/client/img/Arrow-down.svg +11 -0
- package/src/client/img/Arrow-up.svg +6 -0
- package/src/client/img/Chromista.svg +1 -0
- package/src/client/img/Pepiowelh/BlackNoWe2-wb-bb.png +0 -0
- package/src/client/img/Pepiowelh/BlackNoWe2-wb.png +0 -0
- package/src/client/img/Pepiowelh/BlackNoWe2.png +0 -0
- package/src/client/img/Pepiowelh/Ecocultural Mapping Banner.svg +1 -0
- package/src/client/img/Plankton.jpg +0 -0
- package/src/client/img/Plantae.svg +1 -0
- package/src/client/img/Plantae_2.svg +1 -0
- package/src/client/img/Protista.svg +1 -0
- package/src/client/img/Valdes/Valdes Island Conservancy.jpg +0 -0
- package/src/client/img/Xetthecum/Agricultural.jpg +0 -0
- package/src/client/img/Xetthecum/Anthropogenic_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Broad_Leaf.jpg +0 -0
- package/src/client/img/Xetthecum/Caves.jpg +0 -0
- package/src/client/img/Xetthecum/Coastal_Bluffs.jpg +0 -0
- package/src/client/img/Xetthecum/Conifer_Pole_Sapling.jpg +0 -0
- package/src/client/img/Xetthecum/Developed.jpg +0 -0
- package/src/client/img/Xetthecum/Dock.jpg +0 -0
- package/src/client/img/Xetthecum/Eelgrass.jpg +0 -0
- package/src/client/img/Xetthecum/Forests_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Freshwater_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Greig_Creek.jpg +0 -0
- package/src/client/img/Xetthecum/Intertidal.jpg +0 -0
- package/src/client/img/Xetthecum/Laughlin_Lake.jpg +0 -0
- package/src/client/img/Xetthecum/Marine_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Mature_Conifer_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/Porlier_Pass_Road.jpg +0 -0
- package/src/client/img/Xetthecum/Riparian.jpg +0 -0
- package/src/client/img/Xetthecum/Rural.jpg +0 -0
- package/src/client/img/Xetthecum/Subtidal.jpg +0 -0
- package/src/client/img/Xetthecum/Wetland.jpg +0 -0
- package/src/client/img/Xetthecum/Woodland.jpg +0 -0
- package/src/client/img/Xetthecum/Woodland_banner.jpg +0 -0
- package/src/client/img/Xetthecum/Xetthecum.jpg +0 -0
- package/src/client/img/Xetthecum/Young_Conifer_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/Young_Mixed_Forest.jpg +0 -0
- package/src/client/img/Xetthecum/food.svg +38 -0
- package/src/client/img/Xetthecum/indicator.svg +52 -0
- package/src/client/img/Xetthecum/material.svg +186 -0
- package/src/client/img/Xetthecum/medicinal.svg +62 -0
- package/src/client/img/Xetthecum/missing-value.svg +3 -0
- package/src/client/img/Xetthecum/spiritual.svg +13 -0
- package/src/client/img/Xetthecum/trade.svg +74 -0
- package/src/client/img/audio.svg +5 -0
- package/src/client/img/external-link.svg +3 -0
- package/src/client/img/selected-eye.svg +4 -0
- package/src/client/img/selected-tick.svg +3 -0
- package/src/client/img/thumbs/BCLeps.jpg +0 -0
- package/src/client/img/thumbs/Checklist.jpg +0 -0
- package/src/client/img/thumbs/Data-Paper-Figma.jpg +0 -0
- package/src/client/img/thumbs/Galiano-Data-Paper.jpg +0 -0
- package/src/client/img/thumbs/Galiano.jpg +0 -0
- package/src/client/img/thumbs/Maxwell.jpg +0 -0
- package/src/client/img/thumbs/Squamish.jpg +0 -0
- package/src/client/img/thumbs/Valdes.jpg +0 -0
- package/src/client/img/thumbs/Xetthecum.jpg +0 -0
- package/src/client/img/up-arrow.svg +4 -0
- package/src/client/js/autocomplete.js +53 -0
- package/src/client/js/checklist.js +179 -0
- package/src/client/js/colour.js +139 -0
- package/src/client/js/datasetControls.js +212 -0
- package/src/client/js/imerss-viz.js +1397 -0
- package/src/client/js/leafletMap.js +357 -0
- package/src/client/js/leafletMapWithGrid.js +337 -0
- package/src/client/js/leafletMapWithRegions.js +381 -0
- package/src/client/js/renderSVG.js +108 -0
- package/src/client/js/tabs.js +53 -0
- package/src/client/js/xetthecum.js +106 -0
- package/src/client/json/emptyPhyloMap.json +1 -0
- package/src/client/json/kingdomPhyloMap.json +17 -0
- package/src/client/json/phyloMap.json +58 -0
- package/src/compare.js +97 -0
- package/src/compilecsv.js +47 -0
- package/src/dataProcessing/LZ4.js +27 -0
- package/src/dataProcessing/coordinatePatch.js +151 -0
- package/src/dataProcessing/readCSV.js +107 -0
- package/src/dataProcessing/readCSVwithMap.js +90 -0
- package/src/dataProcessing/readCSVwithoutMap.js +25 -0
- package/src/dataProcessing/readJSON.js +23 -0
- package/src/dataProcessing/sqlite.js +174 -0
- package/src/dataProcessing/summarise.js +122 -0
- package/src/dataProcessing/taxonScrape.js +14 -0
- package/src/dataProcessing/worker.js +31 -0
- package/src/dataProcessing/writeCSV.js +34 -0
- package/src/dataProcessing/writeJSON.js +15 -0
- package/src/dbtaxa.js +96 -0
- package/src/deAuthorise.js +48 -0
- package/src/deqgis.js +148 -0
- package/src/expressions/expr.js +65 -0
- package/src/expressions/jsep.js +925 -0
- package/src/filterFirst.js +51 -0
- package/src/geom/geoJSON.js +121 -0
- package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Acmispon americanus americanus.json +200 -0
- package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Flabellina japonica.json +61 -0
- package/src/iNaturalist/examples/www.inaturalist.org-taxa-877359.json +132 -0
- package/src/iNaturalist/iNatUrls.js +17 -0
- package/src/iNaturalist/obsAPI.js +150 -0
- package/src/iNaturalist/taxonAPI.js +460 -0
- package/src/inatObs.js +120 -0
- package/src/inattify.js +123 -0
- package/src/intersect.js +80 -0
- package/src/intersectFilter.js +48 -0
- package/src/landlocked.js +137 -0
- package/src/lib/jquery.binarytransport.js +51 -0
- package/src/lib/lz4-commentary.txt +9 -0
- package/src/lib/lz4.js +73 -0
- package/src/lib/point-in-polygon.js +36 -0
- package/src/lz4.js +40 -0
- package/src/marmalise.js +333 -0
- package/src/materialise.js +68 -0
- package/src/reintegrate.js +71 -0
- package/src/taxonomise.js +615 -0
- package/src/unscrewGBIF.js +44 -0
- package/src/utils/dataSource.js +173 -0
- package/src/utils/settleStructure.js +62 -0
- package/src/utils/utils.js +92 -0
- package/src/viz/plethify.js +39 -0
- package/src/wormify.js +154 -0
- package/src/xetthecum/xetthecumFilters.js +126 -0
- package/test/testDataSource.js +182 -0
- package/test/testiNatObsSource.js +38 -0
- package/test/testiNatSource.js +50 -0
package/src/inatObs.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
const fluid = require("infusion");
|
|
6
|
+
const minimist = require("minimist");
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
|
|
9
|
+
require("./dataProcessing/readJSON.js");
|
|
10
|
+
require("./dataProcessing/writeJSON.js");
|
|
11
|
+
require("./dataProcessing/writeCSV.js");
|
|
12
|
+
|
|
13
|
+
require("./iNaturalist/obsAPI.js");
|
|
14
|
+
|
|
15
|
+
const hortis = fluid.registerNamespace("hortis");
|
|
16
|
+
|
|
17
|
+
hortis.iNatProjects = {
|
|
18
|
+
GalianoData: {
|
|
19
|
+
paramMap: {
|
|
20
|
+
project_id: 5799,
|
|
21
|
+
taxon_id: 1
|
|
22
|
+
},
|
|
23
|
+
outputFile: "data/iNaturalist/Galiano_Catalogue_Animalia_%Date.csv"
|
|
24
|
+
},
|
|
25
|
+
Valdes: {
|
|
26
|
+
paramMap: {
|
|
27
|
+
project_id: 43522,
|
|
28
|
+
taxon_id: 48460 // Life
|
|
29
|
+
},
|
|
30
|
+
outputFile: "data/Valdes/iNaturalist_Catalogue_%Date.csv"
|
|
31
|
+
},
|
|
32
|
+
Xetthecum: {
|
|
33
|
+
paramMap: {
|
|
34
|
+
project_id: "xetthecum",
|
|
35
|
+
taxon_id: 48460 // Life
|
|
36
|
+
},
|
|
37
|
+
outputFile: "data/Xetthecum/iNaturalist_Catalogue_%Date.csv"
|
|
38
|
+
},
|
|
39
|
+
Pepiowelh: {
|
|
40
|
+
paramMap: {
|
|
41
|
+
project_id: "pe-pi-ow-elh",
|
|
42
|
+
taxon_id: 48460 // Life
|
|
43
|
+
},
|
|
44
|
+
outputFile: "data/Pepiowelh/iNaturalist_Catalogue_%Date.csv"
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const parsedArgs = minimist(process.argv.slice(2));
|
|
49
|
+
|
|
50
|
+
console.log("parsedArgs", parsedArgs);
|
|
51
|
+
|
|
52
|
+
const projectArgs = hortis.iNatProjects[parsedArgs._[0] || "GalianoData"];
|
|
53
|
+
|
|
54
|
+
const jwt = hortis.readJSONSync("jwt.json", "reading JWT token file");
|
|
55
|
+
|
|
56
|
+
const source = hortis.iNat.obsSource({
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: "Bearer " + jwt.api_token
|
|
59
|
+
},
|
|
60
|
+
paramMap: projectArgs.paramMap
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const fileVars = {
|
|
64
|
+
Date: new Date().toISOString().substring(0, 10).replaceAll("-", "_")
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
fluid.setLogging(true);
|
|
68
|
+
|
|
69
|
+
const rows = [];
|
|
70
|
+
|
|
71
|
+
const directModel = {
|
|
72
|
+
per_page: 200
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
hortis.logObsResponse = function (data) {
|
|
76
|
+
const tolog = Object.assign({}, data);
|
|
77
|
+
tolog.results = "[ " + data.results.length + " ]";
|
|
78
|
+
fluid.log("Got response " + JSON.stringify(tolog, null, 4));
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
hortis.writeObs = function (filename, rows) {
|
|
82
|
+
const togo = fluid.promise();
|
|
83
|
+
const headers = Object.keys(rows[0]);
|
|
84
|
+
hortis.writeCSV(filename, headers, rows, togo);
|
|
85
|
+
return togo;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
hortis.applyResponse = function (data) {
|
|
89
|
+
hortis.logObsResponse(data);
|
|
90
|
+
hortis.writeJSONSync("obsoutput.json", data);
|
|
91
|
+
if (data.results.length > 0) {
|
|
92
|
+
hortis.pushResultRows(rows, data);
|
|
93
|
+
const lastId = fluid.peek(rows).id;
|
|
94
|
+
console.log("got last id " + lastId);
|
|
95
|
+
directModel.id_above = lastId;
|
|
96
|
+
setTimeout(function () {
|
|
97
|
+
hortis.makeObsRequest(directModel);
|
|
98
|
+
}, 1000);
|
|
99
|
+
} else {
|
|
100
|
+
hortis.writeObs("obsoutput.csv", rows).then(function () {
|
|
101
|
+
const fileTarget = fluid.stringTemplate(projectArgs.outputFile, fileVars);
|
|
102
|
+
fs.copyFileSync("obsoutput.csv", fileTarget);
|
|
103
|
+
const stats = fs.statSync(fileTarget);
|
|
104
|
+
console.log("Written " + stats.size + " bytes to " + fileTarget);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
hortis.makeObsRequest = function (directModel) {
|
|
110
|
+
console.log("Making request ", directModel);
|
|
111
|
+
const promise = source.get(directModel);
|
|
112
|
+
|
|
113
|
+
promise.then(function (data) {
|
|
114
|
+
hortis.applyResponse(data);
|
|
115
|
+
}, function (error) {
|
|
116
|
+
console.log("Got ERROUR: ", error);
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
hortis.makeObsRequest(directModel);
|
package/src/inattify.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
// This script is now obsoleted by the new-style "taxonomise.js" using taxonAPI.js to cache results within the SQLite database
|
|
6
|
+
// %imerss-bioinfo/data/iNaturalist/taxa.db/taxa.sqlite3 - will be kept for a while for reference purposes
|
|
7
|
+
|
|
8
|
+
const fluid = require("infusion");
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const kettle = require("kettle");
|
|
11
|
+
const minimist = require("minimist");
|
|
12
|
+
|
|
13
|
+
require("./utils/utils.js");
|
|
14
|
+
require("./utils/settleStructure.js");
|
|
15
|
+
require("./dataProcessing/readJSON.js");
|
|
16
|
+
require("./dataProcessing/readCSV.js");
|
|
17
|
+
require("./dataProcessing/readCSVwithMap.js");
|
|
18
|
+
require("./dataProcessing/taxonScrape.js");
|
|
19
|
+
|
|
20
|
+
require("./iNaturalist/taxonAPI.js");
|
|
21
|
+
|
|
22
|
+
const hortis = fluid.registerNamespace("hortis");
|
|
23
|
+
const taxonAPIFileBase = "data/iNaturalist/taxonAPI";
|
|
24
|
+
|
|
25
|
+
const source = kettle.dataSource.URL({
|
|
26
|
+
url: "https://www.inaturalist.org/taxa/%id.json",
|
|
27
|
+
termMap: {
|
|
28
|
+
id: "%id"
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const parsedArgs = minimist(process.argv.slice(2));
|
|
33
|
+
|
|
34
|
+
const mapFile = parsedArgs.map || "data/Galiano WoL/Galiano-data-out-map.json";
|
|
35
|
+
const map = hortis.readJSONSync(mapFile);
|
|
36
|
+
|
|
37
|
+
const files = parsedArgs._;
|
|
38
|
+
|
|
39
|
+
const readFiles = files.map(function (file) {
|
|
40
|
+
return hortis.csvReaderWithMap({
|
|
41
|
+
inputFile: file,
|
|
42
|
+
mapColumns: map.columns
|
|
43
|
+
}).completionPromise;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const resultsPromise = hortis.settleStructure(readFiles);
|
|
47
|
+
|
|
48
|
+
resultsPromise.then(function (results) {
|
|
49
|
+
const allRows = fluid.flatten(fluid.transform(results, function (oneResult) {
|
|
50
|
+
return oneResult.rows;
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
console.log("Got " + allRows.length + " rows");
|
|
54
|
+
|
|
55
|
+
console.log(allRows[0]);
|
|
56
|
+
const queue = fluid.transform(allRows, function (row) {
|
|
57
|
+
return {id: row.iNaturalistTaxonId};
|
|
58
|
+
});
|
|
59
|
+
hortis.queueFetchWork(queue);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// fluid.setLogging(true);
|
|
63
|
+
|
|
64
|
+
hortis.enqueueAncestry = function (doc, queue) {
|
|
65
|
+
const ancestours = hortis.iNat.parentTaxaIds(doc);
|
|
66
|
+
const elements = ancestours.map(function (oneAnc) {
|
|
67
|
+
return {id: oneAnc};
|
|
68
|
+
});
|
|
69
|
+
queue.unshift.apply(queue, elements);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
hortis.logWork = function (that) {
|
|
73
|
+
console.log("Remaining " + that.queue.length + "/" + (that.queue.length + that.fetched.length));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
hortis.noteSkip = function (that, message) {
|
|
77
|
+
++that.skipCount;
|
|
78
|
+
if (that.skipCount % 50000 === 0) {
|
|
79
|
+
console.log(message);
|
|
80
|
+
hortis.logWork(that);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
hortis.queueFetchWork = function (queue) {
|
|
85
|
+
const nextWork = function () {
|
|
86
|
+
hortis.logWork(that);
|
|
87
|
+
setTimeout(oneWork, 1000);
|
|
88
|
+
};
|
|
89
|
+
const that = {
|
|
90
|
+
queue: queue,
|
|
91
|
+
cache: {},
|
|
92
|
+
skipCount: 0,
|
|
93
|
+
fetched: []
|
|
94
|
+
};
|
|
95
|
+
const oneWork = function () {
|
|
96
|
+
if (that.queue.length) {
|
|
97
|
+
const head = that.queue.shift();
|
|
98
|
+
const filename = hortis.iNat.filenameFromTaxonId(taxonAPIFileBase, head.id);
|
|
99
|
+
let doc;
|
|
100
|
+
if (that.cache[filename] || fs.existsSync(filename)) {
|
|
101
|
+
hortis.noteSkip(that, "File " + filename + " exists, skipping");
|
|
102
|
+
doc = that.cache[filename];
|
|
103
|
+
if (!doc) {
|
|
104
|
+
doc = hortis.readJSONSync(filename);
|
|
105
|
+
that.cache[filename] = doc;
|
|
106
|
+
}
|
|
107
|
+
hortis.enqueueAncestry(doc, that.queue);
|
|
108
|
+
fluid.invokeLater(oneWork);
|
|
109
|
+
} else {
|
|
110
|
+
doc = source.get(head).then(function (doc) {
|
|
111
|
+
that.fetched.push(head);
|
|
112
|
+
hortis.enqueueAncestry(doc, that.queue);
|
|
113
|
+
hortis.writeTaxonDoc(filename, doc);
|
|
114
|
+
that.cache[filename] = doc;
|
|
115
|
+
nextWork();
|
|
116
|
+
}, function (err) {
|
|
117
|
+
console.log("Received ERROR for id " + head.id, err);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
nextWork();
|
|
123
|
+
};
|
package/src/intersect.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var fluid = require("infusion");
|
|
6
|
+
var fs = require("fs");
|
|
7
|
+
|
|
8
|
+
require("./dataProcessing/readCSV.js");
|
|
9
|
+
require("./dataProcessing/readCSVwithMap.js");
|
|
10
|
+
require("./lib/point-in-polygon.js");
|
|
11
|
+
require("./geom/geoJSON.js");
|
|
12
|
+
|
|
13
|
+
var hortis = fluid.registerNamespace("hortis");
|
|
14
|
+
fluid.registerNamespace("hortis.intersect");
|
|
15
|
+
|
|
16
|
+
var protected_areas = require("../data/Galiano/Protected_Areas_2013_2.json");
|
|
17
|
+
|
|
18
|
+
var map = require("../data/iNaturalist-obs-map.json");
|
|
19
|
+
|
|
20
|
+
var completionPromise = hortis.imerss.csvReader({
|
|
21
|
+
inputFile: "data/Galiano/observations-iNat.csv",
|
|
22
|
+
mapColumns: map.columns
|
|
23
|
+
}).completionPromise;
|
|
24
|
+
|
|
25
|
+
hortis.countUniqueInFeature = function (counts, feature, mappedRows) {
|
|
26
|
+
mappedRows.forEach(function (row) {
|
|
27
|
+
if (hortis.intersectsFeature(feature, row)) {
|
|
28
|
+
if (counts[row.id]) {
|
|
29
|
+
counts[row.id]++;
|
|
30
|
+
} else {
|
|
31
|
+
counts[row.id] = 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
hortis.intersect.mapOneiNaturalistRow = function (row) {
|
|
38
|
+
return {
|
|
39
|
+
id: row.scientificName,
|
|
40
|
+
point: [
|
|
41
|
+
row.longitude,
|
|
42
|
+
row.latitude
|
|
43
|
+
]
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
var fileHeader = "var json_Protected_Areas_2013_2 = {\n\"type\": \"FeatureCollection\",\n\"name\": \"Protected_Areas_2013_2\",\n\"crs\": { \"type\": \"name\""
|
|
48
|
+
+ ", \"properties\": { \"name\": \"urn:ogc:def:crs:OGC:1.3:CRS84\" } },\n\"features\": [\n";
|
|
49
|
+
var fileFooter = "\n]\n}\n";
|
|
50
|
+
|
|
51
|
+
hortis.intersect.writeUpdatedFeatures = function (featuresWithCounts) {
|
|
52
|
+
var outFile = fs.openSync("Protected_Areas_2013_2_counts.js", "w");
|
|
53
|
+
fs.writeSync(outFile, fileHeader);
|
|
54
|
+
var body = featuresWithCounts.map(function (feature) {
|
|
55
|
+
return JSON.stringify(feature);
|
|
56
|
+
});
|
|
57
|
+
fs.writeSync(outFile, body.join(",\n"));
|
|
58
|
+
fs.writeSync(outFile, fileFooter);
|
|
59
|
+
fs.closeSync(outFile);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
var start = Date.now();
|
|
63
|
+
|
|
64
|
+
completionPromise.then(function (result) {
|
|
65
|
+
var read = Date.now();
|
|
66
|
+
console.log("Read " + result.rows.length + " in " + (read - start) + "ms");
|
|
67
|
+
console.log(JSON.stringify(result.rows[0], null, 2));
|
|
68
|
+
var mappedRows = result.rows.map(hortis.intersect.mapOneiNaturalistRow);
|
|
69
|
+
var featureCounts = protected_areas.features.map(function (feature) {
|
|
70
|
+
console.log("Mapping feature " + feature.properties.NAME + " id " + feature.properties.ID);
|
|
71
|
+
var counts = hortis.countUniqueInFeature(counts, feature, mappedRows);
|
|
72
|
+
return Object.keys(counts).length;
|
|
73
|
+
});
|
|
74
|
+
console.log("Mapped " + result.rows.length + " against " + protected_areas.features.length + " features in " + (Date.now() - read) + "ms");
|
|
75
|
+
console.log("Got featureCounts ", featureCounts);
|
|
76
|
+
var featuresWithCounts = protected_areas.features.map(function (feature, index) {
|
|
77
|
+
return fluid.extend(true, {}, feature, {properties: {speciesCount: featureCounts[index]}});
|
|
78
|
+
});
|
|
79
|
+
hortis.intersect.writeUpdatedFeatures(featuresWithCounts);
|
|
80
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var fluid = require("infusion");
|
|
6
|
+
|
|
7
|
+
require("./dataProcessing/readCSV.js");
|
|
8
|
+
require("./dataProcessing/writeCSV.js");
|
|
9
|
+
require("./dataProcessing/readCSVwithoutMap.js");
|
|
10
|
+
require("./lib/point-in-polygon.js");
|
|
11
|
+
require("./geom/geoJSON.js");
|
|
12
|
+
|
|
13
|
+
var hortis = fluid.registerNamespace("hortis");
|
|
14
|
+
fluid.registerNamespace("hortis.intersect");
|
|
15
|
+
|
|
16
|
+
var polygon = require("../data/Galiano/Galiano-boundary.json");
|
|
17
|
+
|
|
18
|
+
var completionPromise = hortis.imerss.csvReaderWithoutMap({
|
|
19
|
+
inputFile: process.argv[2],
|
|
20
|
+
csvOptions: {
|
|
21
|
+
separator: "\t",
|
|
22
|
+
quote: "\0",
|
|
23
|
+
escape: "\0"
|
|
24
|
+
}
|
|
25
|
+
}).completionPromise;
|
|
26
|
+
|
|
27
|
+
hortis.intersect.mapGBIFRow = function (row) {
|
|
28
|
+
return {
|
|
29
|
+
point: [
|
|
30
|
+
Number.parseFloat(row.decimalLongitude),
|
|
31
|
+
Number.parseFloat(row.decimalLatitude)
|
|
32
|
+
]
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
completionPromise.then(function (result) {
|
|
37
|
+
console.log(JSON.stringify(result.rows[0], null, 2));
|
|
38
|
+
var feature = polygon.features[0];
|
|
39
|
+
var outs = [];
|
|
40
|
+
result.rows.forEach(function (oneRow) {
|
|
41
|
+
var mappedRow = hortis.intersect.mapGBIFRow(oneRow);
|
|
42
|
+
if (hortis.intersectsFeature(feature, mappedRow)) {
|
|
43
|
+
outs.push(oneRow);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
console.log("Found " + outs.length + " intersecting rows");
|
|
47
|
+
hortis.imerss.writeCSV("intersected.csv", result.headers, outs, fluid.promise());
|
|
48
|
+
});
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
var fluid = require("infusion");
|
|
6
|
+
var minimist = require("minimist");
|
|
7
|
+
fluid.require("%imerss-bioinfo");
|
|
8
|
+
|
|
9
|
+
require("./utils/utils.js");
|
|
10
|
+
require("./dataProcessing/readJSON.js");
|
|
11
|
+
require("./dataProcessing/readCSV.js");
|
|
12
|
+
require("./dataProcessing/readCSVwithMap.js");
|
|
13
|
+
require("./dataProcessing/readCSVwithoutMap.js");
|
|
14
|
+
require("./dataProcessing/writeCSV.js");
|
|
15
|
+
require("./lib/point-in-polygon.js");
|
|
16
|
+
require("./geom/geoJSON.js");
|
|
17
|
+
|
|
18
|
+
var hortis = fluid.registerNamespace("hortis");
|
|
19
|
+
|
|
20
|
+
fluid.setLogging(true);
|
|
21
|
+
|
|
22
|
+
fluid.loadInContext(fluid.module.resolvePath("%imerss-bioinfo/data/Galiano/Galiano_map_0.js"), true); // produces json_Galiano_map_0
|
|
23
|
+
fluid.loadInContext(fluid.module.resolvePath("%imerss-bioinfo/data/Xetthecum/Site_class_4.js"), true); // produces json_Site_Class_4
|
|
24
|
+
fluid.loadInContext(fluid.module.resolvePath("%imerss-bioinfo/data/Xetthecum/Trincomali_2.js"), true); // produces json_Trincomali_2
|
|
25
|
+
// var xetthecum_boundary = hortis.readJSONSync(fluid.module.resolvePath("%imerss-bioinfo/data/Xetthecum/Xetthecum_Project_Boundary_WGS_84.geojson"), "Xetthecum boundary");
|
|
26
|
+
|
|
27
|
+
var parsedArgs = minimist(process.argv.slice(2));
|
|
28
|
+
|
|
29
|
+
var outputFile = parsedArgs.o || "landlocked.csv";
|
|
30
|
+
var inputFile = parsedArgs._[0] || "%imerss-bioinfo/data/dataPaper/reintegrated-obs.csv";
|
|
31
|
+
var mapFile = parsedArgs.map || "%imerss-bioinfo/data/dataPaper/combinedOutMap-obs.json";
|
|
32
|
+
|
|
33
|
+
var map = hortis.readJSONSync(fluid.module.resolvePath(mapFile), "reading map file");
|
|
34
|
+
|
|
35
|
+
var reader = hortis.csvReaderWithMap({
|
|
36
|
+
inputFile: fluid.module.resolvePath(inputFile),
|
|
37
|
+
mapColumns: map.columns
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
var Galiano_island = fluid.global.json_Galiano_map_0.features;
|
|
41
|
+
var Xetthecum_site_class = fluid.global.json_Site_Class_4.features;
|
|
42
|
+
var Trincomali = fluid.global.json_Trincomali_2.features;
|
|
43
|
+
|
|
44
|
+
var Xetthecum_extract_props = ["CLASS", "SUB_CLASS"];
|
|
45
|
+
var Xetthecum_id_prop = "fid";
|
|
46
|
+
|
|
47
|
+
hortis.findFeatureProperties = function (allFeatures, row, properties, idprop) {
|
|
48
|
+
var features = allFeatures.filter(function (feature) {
|
|
49
|
+
return hortis.intersectsFeature(feature, row);
|
|
50
|
+
});
|
|
51
|
+
// features array of each feature which contains the row
|
|
52
|
+
var propValues = properties.map(function (propKey) {
|
|
53
|
+
return fluid.getMembers(features, ["properties", propKey]);
|
|
54
|
+
});
|
|
55
|
+
// propValues has one element for each property, element for each feature containing property value
|
|
56
|
+
var propVals = propValues.map(function (propList, index) {
|
|
57
|
+
var hash = fluid.arrayToHash(propList);
|
|
58
|
+
var keys = Object.keys(hash);
|
|
59
|
+
if (keys.length > 1) {
|
|
60
|
+
console.log("Warning: row ", row, " matched multiple features with ids ", fluid.getMembers(features, idprop),
|
|
61
|
+
" with mismatching values for property " + properties[index] + ": values were ", keys);
|
|
62
|
+
}
|
|
63
|
+
return keys[0];
|
|
64
|
+
});
|
|
65
|
+
return propVals;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
var TrincomaliFeature = fluid.extend(true, Trincomali[0], {
|
|
69
|
+
properties: {
|
|
70
|
+
fid: 99,
|
|
71
|
+
CLASS: "Trincomali",
|
|
72
|
+
SUB_CLASS: ""
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
var allXetthecumFeatures = Xetthecum_site_class.concat(TrincomaliFeature);
|
|
77
|
+
|
|
78
|
+
hortis.getXetthecumProps = function (obsRows) {
|
|
79
|
+
var now = Date.now();
|
|
80
|
+
var extractedProps = obsRows.map(function (row) {
|
|
81
|
+
row.point = [hortis.parseFloat(row.longitude), hortis.parseFloat(row.latitude)];
|
|
82
|
+
return hortis.findFeatureProperties(allXetthecumFeatures, row, Xetthecum_extract_props, Xetthecum_id_prop);
|
|
83
|
+
});
|
|
84
|
+
console.log("Evaluated " + hortis.intersections + " intersections in " + (Date.now() - now) + " ms");
|
|
85
|
+
var filtered = [];
|
|
86
|
+
obsRows.forEach(function (row, index) {
|
|
87
|
+
if (extractedProps[index][0]) {
|
|
88
|
+
var asProps = {};
|
|
89
|
+
Xetthecum_extract_props.forEach(function (prop, propIndex) {
|
|
90
|
+
asProps[prop] = extractedProps[index][propIndex];
|
|
91
|
+
});
|
|
92
|
+
filtered.push(fluid.extend(true, {}, row, asProps));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return filtered;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// NB: These are not (yet) the same as "filters" in "taxonomise"
|
|
99
|
+
fluid.registerNamespace("hortis.filters");
|
|
100
|
+
|
|
101
|
+
hortis.filters.Xetthecum = {
|
|
102
|
+
filter: function (rows) {
|
|
103
|
+
return hortis.getXetthecumProps(rows);
|
|
104
|
+
},
|
|
105
|
+
extraProps: Xetthecum_extract_props
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
hortis.filters.Galiano = {
|
|
109
|
+
filter: hortis.makeFeatureRowFilter(Galiano_island),
|
|
110
|
+
extraProps: []
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
var activeFilter =
|
|
114
|
+
// hortis.filters.Xetthecum;
|
|
115
|
+
hortis.filters.Galiano;
|
|
116
|
+
|
|
117
|
+
reader.completionPromise.then(function () {
|
|
118
|
+
var obsRows = reader.rows;
|
|
119
|
+
console.log("Matching against " + obsRows.length + " observations");
|
|
120
|
+
|
|
121
|
+
var filtered = activeFilter.filter(obsRows);
|
|
122
|
+
|
|
123
|
+
var mapped = filtered.map(function (row) {
|
|
124
|
+
var outRow = {
|
|
125
|
+
observationId: row.observationId,
|
|
126
|
+
latitude: row.point[1],
|
|
127
|
+
longitude: row.point[0],
|
|
128
|
+
iNaturalistTaxonName: row.iNaturalistTaxonName
|
|
129
|
+
};
|
|
130
|
+
activeFilter.extraProps.forEach(function (prop) {
|
|
131
|
+
outRow[prop] = row[prop];
|
|
132
|
+
});
|
|
133
|
+
return outRow;
|
|
134
|
+
});
|
|
135
|
+
var completion = fluid.promise();
|
|
136
|
+
hortis.writeCSV(fluid.module.resolvePath(outputFile), ["observationId", "latitude", "longitude", "iNaturalistTaxonName"].concat(activeFilter.extraProps), mapped, completion);
|
|
137
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jquery.binarytransport.js
|
|
3
|
+
*
|
|
4
|
+
* @description. jQuery ajax transport for making binary data type requests.
|
|
5
|
+
* @version 1.0
|
|
6
|
+
* @author Henry Algus <henryalgus@gmail.com>
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// use this transport for "binary" data type
|
|
11
|
+
$.ajaxTransport("+binary", function(options, originalOptions, jqXHR){
|
|
12
|
+
// check for conditions and support for blob / arraybuffer response type
|
|
13
|
+
if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
|
|
14
|
+
{
|
|
15
|
+
return {
|
|
16
|
+
// create new XMLHttpRequest
|
|
17
|
+
send: function(headers, callback){
|
|
18
|
+
// setup all variables
|
|
19
|
+
var xhr = new XMLHttpRequest(),
|
|
20
|
+
url = options.url,
|
|
21
|
+
type = options.type,
|
|
22
|
+
async = options.async || true,
|
|
23
|
+
// blob or arraybuffer. Default is blob
|
|
24
|
+
dataType = options.responseType || "blob",
|
|
25
|
+
data = options.data || null,
|
|
26
|
+
username = options.username || null,
|
|
27
|
+
password = options.password || null;
|
|
28
|
+
|
|
29
|
+
xhr.addEventListener('load', function(){
|
|
30
|
+
var data = {};
|
|
31
|
+
data[options.dataType] = xhr.response;
|
|
32
|
+
// make callback and send data
|
|
33
|
+
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
xhr.open(type, url, async, username, password);
|
|
37
|
+
|
|
38
|
+
// setup custom headers
|
|
39
|
+
for (var i in headers ) {
|
|
40
|
+
xhr.setRequestHeader(i, headers[i] );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
xhr.responseType = dataType;
|
|
44
|
+
xhr.send(data);
|
|
45
|
+
},
|
|
46
|
+
abort: function(){
|
|
47
|
+
jqXHR.abort();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
This implementation was grabbed from the inside of the bower package for the 0.6.0 release of
|
|
2
|
+
https://github.com/pierrec/node-lz4 since
|
|
3
|
+
- the build/lz4.js file was found to be mysteriously irrelevant, despite being updated recently
|
|
4
|
+
- the actual build shell script failed even when tested in a Linux VM on "not finding ./bindings", perhaps a node mismatch issue
|
|
5
|
+
|
|
6
|
+
There is a sign we could revisit this at some point and produce a smaller and more reproducible decoder by mashing
|
|
7
|
+
together the 3 files in "Benzinga's" https://github.com/Benzinga/lz4js
|
|
8
|
+
|
|
9
|
+
Better notion: Move to standard zlib operated by pako https://github.com/nodeca/pako
|