diff --git a/js/histojs/designFunctionsv4.js b/js/histojs/designFunctionsv4.js index 1ab5ff1..fdfbc57 100644 --- a/js/histojs/designFunctionsv4.js +++ b/js/histojs/designFunctionsv4.js @@ -44,20 +44,26 @@ {id: "2", value: "Styx", hostAPI: "https://styx.neurology.emory.edu/girder/api/v1/"}] * * findObjectByKeyValue( dict, 'id', "2"); - * // => Object { id: "2", value: "Styx", hostAPI: "https://styx.neurology.emory.edu/girder/api/v1/" } - * + * => Object { id: "2", value: "Styx", hostAPI: "https://styx.neurology.emory.edu/girder/api/v1/" } * * findObjectByKeyValue( dict, 'id', "2", 'INDEX'); * => 1 - * + * + * await findObjectByKeyValueTFJS( dict, 'id', "2") + * => Object { id: "2", value: "Styx", hostAPI: "https://styx.neurology.emory.edu/girder/api/v1/" } */ - findObjectByKeyValue = (array, key, value, returnType='DATA') => { - const obj = array.filter( entry => entry[key] === value)[0]; - return obj ? ( returnType === 'DATA' ? obj : ( returnType === 'INDEX' ? array.indexOf(obj) : null )) : null; + findObjectByKeyValue = (arr, key, value, returnType = 'DATA') => { + const obj = arr.filter( entry => entry[key] === value)[0]; + return obj ? ( returnType === 'DATA' ? obj : ( returnType === 'INDEX' ? arr.indexOf(obj) : null )) : null; } - + findObjectByKeyValueTFJS = async (arr, key, value) => { + const result = await tf.data.array(arr).filter( entry => entry[key] === value).toArray(); + return (result.length > 1) ? result : result.length ? result[0] : null; + } + + /** * Remove element or record from array * @@ -74,6 +80,9 @@ * removeArrayElem(['a', 'b', 'c', 'd'], 'c') * => ['a', 'b', 'd'] * + * await removeArrayElemTFJS([1, 2, 3, 4], 3) + * => [1, 2, 4] + * NOTE: TFJS version for numbers only */ removeArrayElem = (array, element) => { @@ -83,6 +92,17 @@ } } + removeArrayElemTFJS = async (array, element) => { + const tensor = tf.tensor(array); + const mask = tf.notEqual(tensor, element); + const result = await tf.booleanMaskAsync(tensor, mask); + return result.arraySync(); + } + + removeArrayElem_v2 = (array, element) => { + return array.filter(elm => elm !== element); + } + /** * Insert element or record into array at specific index @@ -143,11 +163,22 @@ * @returns {Array} arrOfObj2 - The second array of objects to be merged. * @example * - * mergeArrayOfObjByKey( "id", [ {id:"spx-1", Type:"Tumor"}, - * {id:"spx-7", Type:"Immune"} ], + * mergeArrayOfObjByKey( "id", [ {id:"spx-1", Type:"Tumor" }, + * {id:"spx-7", Type:"Immune"} ], + * [{id : "spx-1", area: 250, solidity: 0.95}, + * {id : "spx-3", area: 150, solidity: 0.85}, + * {id : "spx-7", area: 100, solidity: 0.80} ]) + * + * => [{ id: "spx-1", Type:"Tumor", area: 250, solidity: 0.95 }, + * { id: "spx-7", Type: "immune", area: 100, solidity: 0.80 }] + * + * + * await mergeArrayOfObjByKeyTFJS( "id", [ {id:"spx-1", Type:"Tumor" }, + * {id:"spx-7", Type:"Immune"} ], * [{id : "spx-1", area: 250, solidity: 0.95}, * {id : "spx-3", area: 150, solidity: 0.85}, * {id : "spx-7", area: 100, solidity: 0.80} ]) + * * => [{ id: "spx-1", Type:"Tumor", area: 250, solidity: 0.95 }, * { id: "spx-7", Type: "immune", area: 100, solidity: 0.80 }] * @@ -167,18 +198,47 @@ // Create hash for the larger array let largerArrHashByKey = {}; - largerArrayOfObjs.forEach((object, idx) => { + largerArrayOfObjs.forEach(object => { largerArrHashByKey[ object[objKey] ] = object; - }); + }); // Merge both arrays of objects let mergedArrayOfObjs = []; - smallerArrayOfObjs.forEach((object, idx) => { + smallerArrayOfObjs.forEach(object => { mergedArrayOfObjs.push({ ...object, ...largerArrHashByKey[ object[objKey] ]}); }); - return mergedArrayOfObjs; + return mergedArrayOfObjs; + } + + + mergeArrayOfObjByKeyTFJS = async(objKey, arrOfObj1, arrOfObj2) => { + let largerArrayOfObjs, smallerArrayOfObjs; + + if( arrOfObj1.length < arrOfObj2.length) { + largerArrayOfObjs = arrOfObj2; + smallerArrayOfObjs = arrOfObj1; + } else { + largerArrayOfObjs = arrOfObj1; + smallerArrayOfObjs = arrOfObj2; + } + + // Create hash for the larger array + let largerArrHashByKey = {}; + + await tf.data.array(largerArrayOfObjs).forEachAsync(object => { + largerArrHashByKey[ object[objKey] ] = object; + }); + + // Merge both arrays of objects + let mergedArrayOfObjs = []; + + await tf.data.array(smallerArrayOfObjs).forEachAsync(object => { + mergedArrayOfObjs.push({ ...object, ...largerArrHashByKey[ object[objKey] ]}); + }); + + return mergedArrayOfObjs; } /** @@ -232,14 +292,23 @@ * arrayUniqueValues( [1, 1, 2, 3, 2, 5]) * * => [1, 2, 3, 5] + * + * arrayUniqueValuesTFJS( [1, 1, 2, 3, 2, 5]) + * + * => [1, 2, 3, 5] */ arrayUniqueValues = (array) => { - return array.filter((value, index, self) => { return self.indexOf(value) === index; }); - + } + + + arrayUniqueValuesTFJS = (array) => { + const tensor = tf.tensor(array); + const {values, indices} = tf.unique(tensor); + return values.arraySync(); } @@ -253,18 +322,62 @@ * @category Array * @param {Array} array1 - The array of values. * @param {Array} array2 - The array of values. - * @returns {Array} array of concatenation + * @returns {Array | promise} array of concatenation, fastArraysConcatTFJSData fun returns promise * @example * + * array1 = [{ Type: "1", val: 1}, { Type: "2", val: 2}] + * array2 = [{ Type: "3", val: 3}, { Type: "4", val: 4}] + * * fastArraysConcat( [1, 1, 2, 3], [5, 2, 5]) * * => [1, 1, 2, 3, 5, 2, 5] + * + * fastArraysConcat( array1, array2) + * + * => [{ Type: "1", val: 1}, { Type: "2", val: 2}, { Type: "3", val: 3}, { Type: "4", val: 4}] + ********************************************************************************************* + * fastArraysConcatTFJS( [1, 1, 2, 3], [5, 2, 5]) + * + * => [1, 1, 2, 3, 5, 2, 5] + * + * NOTE: fastArraysConcatTFJS can not concate Array of objects. + * + * fastArraysConcatTFJS( array1, array2) + * + * => [ NaN, NaN, NaN, NaN ] + ********************************************************************************************** + * NOTE: fastArraysConcatTFJSData returns promise + * + * await fastArraysConcatTFJSData( [1, 1, 2, 3], [5, 2, 5]) + * OR + * fastArraysConcatTFJSData([1, 1, 2, 3], [5, 2, 5]).then(function(res) { console.log(res) }) + * + * => [1, 1, 2, 3, 5, 2, 5] + * + * await fastArraysConcatTFJSData( array1, array2) + * OR + * fastArraysConcatTFJSData(array1,array2).then(function(res) { console.log(res) }) + * + * => [{ Type: "1", val: 1}, { Type: "2", val: 2}, { Type: "3", val: 3}, { Type: "4", val: 4}] */ fastArraysConcat = (array1, array2) => { return [...array1, ... array2]; } + fastArraysConcatTFJS = (array1, array2) => { + const tensor1 = tf.tensor1d(array1); + const tensor2 = tf.tensor1d(array2); + return tf.concat([tensor1, tensor2]).arraySync(); + } + + + fastArraysConcatTFJSData = (array1, array2) => { + const dataArr1 = tf.data.array(array1); + const dataArr2 = tf.data.array(array2); + return dataArr1.concatenate(dataArr2).toArray(); + } + /** * Find if two arrays are identical. diff --git a/paper/paper.bib b/paper/paper.bib index 4fd1803..52128cf 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -5,6 +5,7 @@ @article{gutman2017digital volume={77}, number={21}, pages={e75--e78}, + doi = {10.1158/0008-5472.CAN-17-0629}, year={2017}, publisher={AACR} } @@ -26,6 +27,7 @@ @article{lin2015highly volume={6}, number={1}, pages={8390}, + doi={10.1038/ncomms9390}, year={2015}, publisher={Nature Publishing Group UK London} } @@ -36,6 +38,7 @@ @article{lin2018highly author={Lin, Jia-Ren and Izar, Benjamin and Wang, Shu and Yapp, Clarence and Mei, Shaolin and Shah, Parin M and Santagata, Sandro and Sorger, Peter K}, journal={elife}, volume={7}, + doi={10.7554/eLife.31657}, year={2018}, publisher={eLife Sciences Publications, Ltd} } @@ -48,6 +51,7 @@ @article{gerdes2013highly volume={110}, number={29}, pages={11982--11987}, + doi = {10.1073/pnas.1300136110}, year={2013}, publisher={National Acad Sciences} } @@ -57,6 +61,7 @@ @inproceedings{schmidt2018cell author={Schmidt, Uwe and Weigert, Martin and Broaddus, Coleman and Myers, Gene}, booktitle={Medical Image Computing and Computer Assisted Intervention--MICCAI 2018: 21st International Conference, Granada, Spain, September 16-20, 2018, Proceedings, Part II 11}, pages={265--273}, + doi={10.1007/978-3-030-00934-2_30}, year={2018}, organization={Springer} } @@ -70,7 +75,7 @@ @article{gabriel1969new volume={18}, number={3}, pages={259--278}, - doi = {https://doi.org/10.2307/2412323}, + doi = {10.2307/2412323}, year={1969}, publisher={Society of Systematic Zoology} } @@ -83,6 +88,7 @@ @article{goltsev2018deep volume={174}, number={4}, pages={968--981}, + doi={10.1016/j.cell.2018.07.010}, year={2018}, publisher={Elsevier} } @@ -94,6 +100,7 @@ @article{angelo2014multiplexed volume={20}, number={4}, pages={436--442}, + doi = {10.1038/nm.3488}, year={2014}, publisher={Nature Publishing Group US New York} }