diff --git a/src/Makefile b/src/Makefile index 67a1b4e9..2a32ec03 100644 --- a/src/Makefile +++ b/src/Makefile @@ -79,7 +79,7 @@ CPPFLAGS+=-g -Wall #-pedantic #-DNO_LZMA # -DUSE_OS_TIMER OBJSUFFIX=.o EXESUFFIX= -FILES=mcx_core mcx_utils mcx_shapes mcx_tictoc mcx mcx_bench mcx_mie cjson/cJSON ubj/ubjw +FILES=mcx_core mcx_utils mcx_shapes mcx_tictoc mcx mcx_bench mcx_neurojson mcx_mie cjson/cJSON ubj/ubjw ifeq ($(findstring _NT-,$(PLATFORM)), _NT-) CC=nvcc diff --git a/src/mcx_neurojson.cpp b/src/mcx_neurojson.cpp new file mode 100644 index 00000000..a57ca231 --- /dev/null +++ b/src/mcx_neurojson.cpp @@ -0,0 +1,68 @@ +/***************************************************************************//** +** \mainpage Mesh-based Monte Carlo (MMC) - a 3D photon simulator +** +** \author Qianqian Fang +** \copyright Qianqian Fang, 2010-2024 +** +** \section sref Reference: +** \li \c (\b Fang2010) Qianqian Fang, +** "Mesh-based Monte Carlo Method Using Fast Ray-Tracing +** in Plucker Coordinates," Biomed. Opt. Express, 1(1) 165-175 (2010). +** \li \c (\b Fang2012) Qianqian Fang and David R. Kaeli, +** +** "Accelerating mesh-based Monte Carlo method on modern CPU architectures," +** Biomed. Opt. Express 3(12), 3223-3230 (2012) +** \li \c (\b Yao2016) Ruoyang Yao, Xavier Intes, and Qianqian Fang, +** +** "Generalized mesh-based Monte Carlo for wide-field illumination and detection +** via mesh retessellation," Biomed. Optics Express, 7(1), 171-184 (2016) +** \li \c (\b Fang2019) Qianqian Fang and Shijie Yan, +** +** "Graphics processing unit-accelerated mesh-based Monte Carlo photon transport +** simulations," J. of Biomedical Optics, 24(11), 115002 (2019) +** \li \c (\b Yuan2021) Yaoshen Yuan, Shijie Yan, and Qianqian Fang, +** +** "Light transport modeling in highly complex tissues using the implicit +** mesh-based Monte Carlo algorithm," Biomed. Optics Express, 12(1) 147-161 (2021) +** +** \section slicense License +** GPL v3, see LICENSE.txt for details +*******************************************************************************/ + +#include +#include +#include +#include "mcx_neurojson.h" + +#define ALLOC_CHUNK 4096 + +int runcommand(char* cmd, char* param, char** output) { + int len = ALLOC_CHUNK, pos = 0; + char buffer[256] = {'\0'}, fullcmd[ALLOC_CHUNK] = {'\0'}; + + snprintf(fullcmd, ALLOC_CHUNK, "%s%s", cmd, param); + FILE* pipe = popen(fullcmd, "r"); + + if (!pipe) { + return -1; + } + + free(*output); + *output = (char*)calloc(ALLOC_CHUNK, 1); + + while (fgets(buffer, sizeof(buffer), pipe) != NULL) { + int buflen = strlen(buffer); + + if (buflen > len - pos - 1) { + *output = (char*)realloc(*output, len + ALLOC_CHUNK); + len += ALLOC_CHUNK; + } + + strncpy(*output + pos, buffer, len - pos - 1); + pos += buflen; + } + + *output = (char*)realloc(*output, pos + 1); + pclose(pipe); + return pos; +} diff --git a/src/mcx_neurojson.h b/src/mcx_neurojson.h new file mode 100644 index 00000000..caf74967 --- /dev/null +++ b/src/mcx_neurojson.h @@ -0,0 +1,44 @@ +/***************************************************************************//** +** \mainpage Mesh-based Monte Carlo (MMC) - a 3D photon simulator +** +** \author Qianqian Fang +** \copyright Qianqian Fang, 2010-2024 +** +** \section sref Reference: +** \li \c (\b Fang2010) Qianqian Fang, +** "Mesh-based Monte Carlo Method Using Fast Ray-Tracing +** in Plucker Coordinates," Biomed. Opt. Express, 1(1) 165-175 (2010). +** \li \c (\b Fang2012) Qianqian Fang and David R. Kaeli, +** +** "Accelerating mesh-based Monte Carlo method on modern CPU architectures," +** Biomed. Opt. Express 3(12), 3223-3230 (2012) +** \li \c (\b Yao2016) Ruoyang Yao, Xavier Intes, and Qianqian Fang, +** +** "Generalized mesh-based Monte Carlo for wide-field illumination and detection +** via mesh retessellation," Biomed. Optics Express, 7(1), 171-184 (2016) +** \li \c (\b Fang2019) Qianqian Fang and Shijie Yan, +** +** "Graphics processing unit-accelerated mesh-based Monte Carlo photon transport +** simulations," J. of Biomedical Optics, 24(11), 115002 (2019) +** \li \c (\b Yuan2021) Yaoshen Yuan, Shijie Yan, and Qianqian Fang, +** +** "Light transport modeling in highly complex tissues using the implicit +** mesh-based Monte Carlo algorithm," Biomed. Optics Express, 12(1) 147-161 (2021) +** +** \section slicense License +** GPL v3, see LICENSE.txt for details +*******************************************************************************/ + +#ifndef _MCEXTREME_NEUROJSON_API_H +#define _MCEXTREME_NEUROJSON_API_H + +#ifdef __cplusplus +extern "C" { +#endif +int runcommand(char* cmd, char* param, char** output); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mcx_utils.c b/src/mcx_utils.c index 26372639..a0648a3d 100644 --- a/src/mcx_utils.c +++ b/src/mcx_utils.c @@ -51,6 +51,7 @@ #include "mcx_core.h" #include "mcx_bench.h" #include "mcx_mie.h" +#include "mcx_neurojson.h" #if defined(_WIN32) && defined(USE_OS_TIMER) && !defined(MCX_CONTAINER) #include "mmc_tictoc.h" @@ -108,7 +109,7 @@ const char shortopt[] = {'h', 'i', 'f', 'n', 't', 'T', 's', 'a', 'g', 'b', '-', 'z', 'u', 'H', 'P', 'd', 'r', 'S', 'p', 'e', 'U', 'R', 'l', 'L', '-', 'I', '-', 'G', 'M', 'A', 'E', 'v', 'D', 'k', 'q', 'Y', 'O', 'F', '-', '-', 'x', 'X', '-', 'K', 'm', 'V', 'B', 'W', 'w', '-', - '-', '-', 'Z', 'j', '-', '-', '-', '\0' + 'Q', '-', 'Z', 'j', '-', '-', '-', 'N', '\0' }; /** @@ -128,7 +129,7 @@ const char* fullopt[] = {"--help", "--interactive", "--input", "--photon", "--maxvoidstep", "--saveexit", "--saveref", "--gscatter", "--mediabyte", "--momentum", "--specular", "--bc", "--workload", "--savedetflag", "--internalsrc", "--bench", "--dumpjson", "--zip", "--json", "--atomic", - "--srcid", "--trajstokes", "" + "--srcid", "--trajstokes", "--net", "" }; /** @@ -5057,6 +5058,67 @@ void mcx_parsecmd(int argc, char* argv[], Config* cfg) { break; + case 'Q': + if (i + 1 < argc && isalpha((int)argv[i + 1][0]) ) { + int idx = mcx_keylookup(argv[++i], benchname); + + if (idx == -1) { + MCX_ERROR(-1, "Unsupported bechmark."); + } + + isinteractive = 0; + jsoninput = (char*)benchjson[idx]; + } else { + MCX_FPRINTF(cfg->flog, "Built-in benchmarks:\n"); + + for (int i = 0; i < sizeof(benchname) / sizeof(char*) - 1; i++) { + MCX_FPRINTF(cfg->flog, "\t%s\n", benchname[i]); + } + + exit(0); + } + + break; + + case 'N': + if (i == argc - 1 || argv[i + 1][0] == '-') { + int j, doclen; + char* jbuf = NULL; + runcommand("curl -s -X GET 'https://neurojson.io:7777/mcx/_all_docs'", "", &jbuf); + cJSON* root = cJSON_Parse(jbuf), *docs = cJSON_GetObjectItem(root, "rows"), *subitem, *tmp; + + if (!docs) { + MCX_ERROR(-1, jbuf); + } + + doclen = cJSON_GetArraySize(docs); + subitem = docs->child; + printf("Downloading %d simulations from NeuroJSON.io (https://neurojson.org/db/mcx)\n", doclen - 1); + + for (j = 0; j < doclen; j++) { + if (strchr(FIND_JSON_KEY("id", "id", subitem, "", valuestring), '_') == NULL) { + printf("\t%s\n", FIND_JSON_KEY("id", "id", subitem, "", valuestring)); + } + + subitem = subitem->next; + } + + free(jbuf); + exit(0); + } else { + if (strstr(argv[i + 1], "http") == argv[i + 1]) { + runcommand("curl -s -X GET ", argv[i + 1], &jsoninput); + } else if (strchr(argv[i + 1], '/')) { + runcommand("curl -s -X GET https://neurojson.io:7777/", argv[i + 1], &jsoninput); + } else { + runcommand("curl -s -X GET https://neurojson.io:7777/mcx/", argv[i + 1], &jsoninput); + } + + isinteractive = 2; + } + + break; + case '-': /*additional verbose parameters*/ if (strcmp(argv[i] + 2, "maxvoidstep") == 0) { i = mcx_readarg(argc, argv, i, &(cfg->maxvoidstep), "int"); @@ -5081,29 +5143,6 @@ void mcx_parsecmd(int argc, char* argv[], Config* cfg) { } else { i = mcx_readarg(argc, argv, i, &(cfg->isdumpjson), "int"); } - } else if (strcmp(argv[i] + 2, "bench") == 0) { - if (i + 1 < argc && isalpha(argv[i + 1][0]) ) { - int idx = mcx_keylookup(argv[++i], benchname); - - if (idx == -1) { - MCX_ERROR(-1, "Unsupported bechmark."); - } - - isinteractive = 0; - jsoninput = (char*)benchjson[idx]; - } else { - MCX_FPRINTF(cfg->flog, "Built-in benchmarks:\n"); - - for (int i = 0; i < MAX_MCX_BENCH - 1; i++) { - if (benchname[i][0] == '\0') { - break; - } - - MCX_FPRINTF(cfg->flog, "\t%s\n", benchname[i]); - } - - exit(0); - } } else if (strcmp(argv[i] + 2, "reflectin") == 0) { i = mcx_readarg(argc, argv, i, &(cfg->isrefint), "char"); } else if (strcmp(argv[i] + 2, "atomic") == 0) { @@ -5147,7 +5186,10 @@ void mcx_parsecmd(int argc, char* argv[], Config* cfg) { } if (cfg->isgpuinfo != 2) { /*print gpu info only*/ - if (isinteractive) { + if (isinteractive == 2 && jsoninput) { + mcx_readconfig(jsoninput, cfg); + free(jsoninput); + } else if (isinteractive) { mcx_readconfig((char*)"", cfg); } else if (jsoninput) { mcx_readconfig(jsoninput, cfg); @@ -5450,8 +5492,11 @@ where possible parameters include (the first value in [*|*] is the default)\n\ if the string starts with '{', it is parsed as\n\ an inline JSON input file\n\ or\n\ - --bench ['cube60','skinvessel',..] run a buint-in benchmark specified by name\n\ - run --bench without parameter to get a list\n\ + -Q/--bench [cube60, skinvessel,...] run a buint-in benchmark specified by name\n\ + run -Q without parameter to get a list\n\ + -N benchmark (--net) get benchmark from NeuroJSON.io, -N only to list\n\ + benchmark can be dataset URL,or dbname/benchname\n\ + requires 'curl', install from https://curl.se/\n\ \n"S_BOLD S_CYAN"\ == MC options ==\n" S_RESET"\ -n [0|int] (--photon) total photon number (exponential form accepted)\n\