int main (int argc, const char** argv) { int i; int done_with_options = 0; int approximate = 0; int scaffold = 0; int aromatic = 1; const char *outfile_hl = 0; const char *outfile_rg = 0; const char *outfile_maxscaf = 0; const char *outfile_allscafs = 0; const char *outfile_scaf_r = 0; int deco = 0; int structures = 0; indigoSetErrorHandler(onError, 0); printf("R-Group deconvolution utility, powered by Indigo API version %s\n", indigoVersion()); structures = indigoCreateArray(); indigoSetOptionBool("treat-x-as-pseudoatom", 1); indigoSetOptionBool("ignore-stereochemistry-errors", 1); for (i = 1; i < argc; i++) { if (!done_with_options && argv[i][0] == '-') { if (strcmp(argv[i], "--") == 0) done_with_options = 1; else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "/?") == 0 || strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "--help") == 0) { _printHelpMessage(); return 0; } else if (strcmp(argv[i], "-a") == 0) approximate = 1; else if (strcmp(argv[i], "-l") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -l\n"); return -1; } scaffold = indigoLoadMoleculeFromFile(argv[i]); } else if (strcmp(argv[i], "-o") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -o\n"); return -1; } outfile_hl = argv[i]; } else if (strcmp(argv[i], "-r") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -r\n"); return -1; } outfile_rg = argv[i]; } else if (strcmp(argv[i], "-s") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -s\n"); return -1; } outfile_maxscaf = argv[i]; } else if (strcmp(argv[i], "-sr") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -sr\n"); return -1; } outfile_scaf_r = argv[i]; } else if (strcmp(argv[i], "-S") == 0) { if (++i == argc) { fprintf(stderr, "expecting filename after -S\n"); return -1; } outfile_allscafs = argv[i]; } else if (strcmp(argv[i], "-na") == 0) aromatic = 0; else { fprintf(stderr, "Unknown option: %s", argv[i]); _printHelpMessage(); return -1; } } else { char dirname[1024]; char errbuf[1024]; const char *filename = 0; int k; for (k = (int)strlen(argv[i]) - 1; k >= 0; k--) if (argv[i][k] == '/' || argv[i][k] == '\\') break; if (k == -1) strncpy(dirname, ".", sizeof(dirname)); else if (k == 0) { dirname[0] = argv[i][0]; dirname[1] = 0; } else if (k == strlen(argv[i]) - 1) { fprintf(stderr, "can not handle filenames ending with a slash\n"); return -1; } else if (k > sizeof(dirname) - 1) { fprintf(stderr, "filename too long\n"); return -1; } else { memcpy(dirname, argv[i], k); dirname[k] = 0; } _replaceSlashes(dirname); filename = argv[i] + k + 1; { OsDirIter dir_iter; int rc = osDirSearch(dirname, filename, &dir_iter); if (rc == OS_DIR_OK) { int count = 0; while ((rc = osDirNext(&dir_iter)) == OS_DIR_OK) { _replaceSlashes(dir_iter.path); _handleInputFile(dir_iter.path, structures); count++; } if (rc != OS_DIR_END) { fprintf(stderr, "%s\n", osDirLastError(errbuf, sizeof(errbuf))); return -1; } if (count == 0) { fprintf(stderr, "can not find %s in directory %s\n", filename, dirname); return -1; } } else { fprintf(stderr, "%s\n", osDirLastError(errbuf, sizeof(errbuf))); return -1; } } } } if (indigoCount(structures) < 1) { fprintf(stderr, "no input structures\n"); _printHelpMessage(); return -1; } printf("got %d input structures\n", indigoCount(structures)); indigoSetOptionBool("deconvolution-aromatization", aromatic); if (scaffold == 0) { printf("calculating scaffold... "); fflush(stdout); if (approximate) scaffold = indigoExtractCommonScaffold(structures, "approximate"); else scaffold = indigoExtractCommonScaffold(structures, "exact"); printf("done\n"); fflush(stdout); } if (outfile_maxscaf != 0) { printf("saving the scaffold to %s\n", outfile_maxscaf); indigoSaveMolfileToFile(scaffold, outfile_maxscaf); } if (outfile_allscafs != 0) { int output = indigoWriteFile(outfile_allscafs); int allscafs = indigoAllScaffolds(scaffold); int item, iter = indigoIterateArray(allscafs); printf("saving all obtained scaffolds (%d total) to %s\n", indigoCount(allscafs), outfile_allscafs); while ((item = indigoNext(iter))) { indigoSdfAppend(output, item); indigoFree(item); } indigoFree(iter); indigoFree(output); } if (outfile_hl == 0 && outfile_rg == 0 && outfile_scaf_r == 0) { printf("none of -o, -r, -sr specified, nothing left to do\n"); return 0; } printf("decomposing the structures... "); fflush(stdout); deco = indigoDecomposeMolecules(scaffold, structures); printf("done\n"); fflush(stdout); if (outfile_scaf_r != 0) { int sr = indigoDecomposedMoleculeScaffold(deco); indigoLayout(sr); printf("saving the scaffold with R-sites to %s\n", outfile_scaf_r); indigoSaveMolfileToFile(sr, outfile_scaf_r); } if (outfile_hl != 0) { int output = indigoWriteFile(outfile_hl); int item, iter = indigoIterateDecomposedMolecules(deco); printf("saving the highlighted structures to %s\n", outfile_hl); while ((item = indigoNext(iter))) { indigoSdfAppend(output, indigoDecomposedMoleculeHighlighted(item)); indigoFree(item); } indigoFree(iter); indigoFree(output); } if (outfile_rg != 0) { int output = indigoWriteFile(outfile_rg); int item, iter = indigoIterateDecomposedMolecules(deco); printf("saving the structures with R-groups to %s\n", outfile_rg); while ((item = indigoNext(iter))) { indigoSdfAppend(output, indigoDecomposedMoleculeWithRGroups(item)); indigoFree(item); } indigoFree(iter); indigoFree(output); } return 0; };
int parseParams (Params* p, int argc, char *argv[]) { int i; if (strcmp(argv[1], "-") == 0) { if (_isReaction(argv[2])) { p->mode = MODE_SINGLE_REACTION; p->string_to_load = argv[2]; } else { p->mode = MODE_SINGLE_MOLECULE; p->string_to_load = argv[2]; } if (argc <= 3) USAGE(); i = 3; } else { p->infile_ext[0] = 0; if (strlen(argv[1]) >= 4 && argv[1][strlen(argv[1]) - 4] == '.') { p->infile_ext[3] = 0; strncpy(p->infile_ext, argv[1] + strlen(argv[1]) - 3, 3); } else if (strlen(argv[1]) > 7 && argv[1][strlen(argv[1]) - 7] == '.') { p->infile_ext[6] = 0; strncpy(p->infile_ext, argv[1] + strlen(argv[1]) - 6, 6); } p->file_to_load = argv[1]; if (strcasecmp(p->infile_ext, "mol") == 0) p->mode = MODE_SINGLE_MOLECULE; else if (strcasecmp(p->infile_ext, "rxn") == 0) p->mode = MODE_SINGLE_REACTION; else if (strcasecmp(p->infile_ext, "smi") == 0) { int reaction; if (_isMultiline(argv[1], &reaction)) p->mode = MODE_MULTILINE_SMILES; else { if (reaction) p->mode = MODE_SINGLE_REACTION; else p->mode = MODE_SINGLE_MOLECULE; } } else if (strcasecmp(p->infile_ext, "cml") == 0) { int reaction; if (_isMultipleCML(argv[1], &reaction)) p->mode = MODE_MULTIPLE_CML; else { if (reaction) p->mode = MODE_SINGLE_REACTION; else p->mode = MODE_SINGLE_MOLECULE; } } else if (strcasecmp(p->infile_ext, "sdf") == 0 || strcasecmp(p->infile_ext, "sdf.gz") == 0) p->mode = MODE_SDF; else if (strcasecmp(p->infile_ext, "rdf") == 0 || strcasecmp(p->infile_ext, "rdf.gz") == 0) p->mode = MODE_RDF; else USAGE(); i = 2; } p->outfile = argv[i++]; if (strlen(p->outfile) < 5 || p->outfile[strlen(p->outfile) - 4] != '.') USAGE(); p->outfile_ext[3] = 0; strncpy(p->outfile_ext, p->outfile + strlen(p->outfile) - 3, 3); indigoSetOptionBool("treat-x-as-pseudoatom", 1); indigoSetOptionBool("render-coloring", 1); indigoSetOptionBool("render-highlight-color-enabled", 1); for (; i < argc; i++) { if (strcmp(argv[i], "-w") == 0) { if (++i == argc) { fprintf(stderr, "expecting number after -w\n"); return -1; } if (sscanf(argv[i], "%d", &p->width) != 1 || p->width <= 0) { fprintf(stderr, "%s is not a valid width\n", argv[i]); return -1; } } else if (strcmp(argv[i], "-h") == 0) { if (++i == argc) { fprintf(stderr, "expecting number after -h\n"); return -1; } if (sscanf(argv[i], "%d", &p->height) != 1 || p->height <= 0) { fprintf(stderr, "%s is not a valid height\n", argv[i]); return -1; } } else if (strcmp(argv[i], "-margins") == 0) { int horz, vert; if (i + 2 >= argc) { fprintf(stderr, "expecting two numbers after -margins\n"); return -1; } if (sscanf(argv[i + 1], "%d", &horz) != 1 || horz < 0) { fprintf(stderr, "%s is not a valid horizontal margin\n", argv[i]); return -1; } if (sscanf(argv[i + 2], "%d", &vert) != 1 || vert < 0) { fprintf(stderr, "%s is not a valid vertical margin\n", argv[i + 1]); return -1; } indigoSetOptionXY("render-margins", horz, vert); i += 2; } else if (strcmp(argv[i], "-thickness") == 0) { float rt; if (++i == argc) { fprintf(stderr, "expecting number after -thickness\n"); return -1; } if (sscanf(argv[i], "%f", &rt) != 1 || rt < 0) { fprintf(stderr, "%s is not a valid relative thickness\n", argv[i]); return -1; } indigoSetOptionFloat("render-relative-thickness", rt); } else if (strcmp(argv[i], "-linewidth") == 0) { float rt; if (++i == argc) { fprintf(stderr, "expecting number after -linewidth\n"); return -1; } if (sscanf(argv[i], "%f", &rt) != 1 || rt < 0) { fprintf(stderr, "%s is not a valid line width value\n", argv[i]); return -1; } indigoSetOptionFloat("render-bond-line-width", rt); } else if (strcmp(argv[i], "-bond") == 0) { if (++i == argc) { fprintf(stderr, "expecting number after -bond\n"); return -1; } if (sscanf(argv[i], "%d", &p->bond) != 1 || p->bond <= 0) { fprintf(stderr, "%s is not a valid bond length\n", argv[i]); return -1; } } else if (strcmp(argv[i], "-coloring") == 0) { if (++i == argc) { fprintf(stderr, "expecting 'on' or 'off' after -coloring\n"); return -1; } if (strcasecmp(argv[i], "on") == 0) indigoSetOptionBool("render-coloring", 1); else if (strcasecmp(argv[i], "off") == 0) indigoSetOptionBool("render-coloring", 0); else { fprintf(stderr, "expecting 'on' or 'off' after -coloring\n"); return -1; } } else if (strcmp(argv[i], "-hlthick") == 0) { indigoSetOptionBool("render-highlight-thickness-enabled", 1); } else if (strcmp(argv[i], "-hlcolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -hlcolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionBool("render-highlight-color-enabled", 1); indigoSetOptionColor("render-highlight-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-bgcolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -bgcolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionColor("render-background-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-basecolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -basecolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionColor("render-base-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-aamcolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -aamcolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionColor("render-aam-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-dsgcolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -aamcolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionColor("render-data-sgroup-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-hydro") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -hydro\n"); return -1; } indigoSetOption("render-implicit-hydrogens-visible", argv[i]); p->hydro_set = 1; } else if (strcmp(argv[i], "-label") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -label\n"); return -1; } indigoSetOption("render-label-mode", argv[i]); } else if (strcmp(argv[i], "-arom") == 0) { p->aromatization = AROM; } else if (strcmp(argv[i], "-dearom") == 0) { p->aromatization = DEAROM; } else if (strcmp(argv[i], "-stereo") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -stereo\n"); return -1; } indigoSetOption("render-stereo-style", argv[i]); } else if (strcmp(argv[i], "-cdbwsa") == 0) { indigoSetOptionBool("render-center-double-bond-when-stereo-adjacent", 1); } else if (strcmp(argv[i], "-query") == 0) { p->query_set = 1; } else if (strcmp(argv[i], "-smarts") == 0) { p->smarts_set = 1; } else if (strcmp(argv[i], "-id") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -id\n"); return -1; } p->id = argv[i]; } else if (strcmp(argv[i], "-catalysts") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -catalysts\n"); return -1; } indigoSetOption("render-catalysts-placement", argv[i]); } else if (strcmp(argv[i], "-comment") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -comment\n"); return -1; } p->comment = argv[i]; } else if (strcmp(argv[i], "-commentoffset") == 0) { int offset; if (++i >= argc) { fprintf(stderr, "expecting an integer after -commentoffset\n"); return -1; } if (sscanf(argv[i], "%d", &offset) != 1 || offset < 0) { fprintf(stderr, "%s is not a valid comment offset\n", argv[i]); return -1; } indigoSetOptionInt("render-comment-offset", offset); } else if (strcmp(argv[i], "-commentfield") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -commentfield\n"); return -1; } p->comment_field = argv[i]; } else if (strcmp(argv[i], "-commentname") == 0) { p->comment_name = 1; } else if (strcmp(argv[i], "-commentsize") == 0) { int commentsize; if (++i == argc) { fprintf(stderr, "expecting number after -commentsize\n"); return -1; } if (sscanf(argv[i], "%d", &commentsize) != 1 || commentsize <= 0) { fprintf(stderr, "%s is not a valid font size\n", argv[i]); return -1; } indigoSetOptionFloat("render-comment-font-size", (float)commentsize); } else if (strcmp(argv[i], "-commentcolor") == 0) { float r, g, b; if (i + 3 >= argc) { fprintf(stderr, "expecting 3 numbers after -commentcolor\n"); return -1; } if (parseColor(argv, i, &r, &g, &b) != 0) return -1; indigoSetOptionColor("render-comment-color", r, g, b); i += 3; } else if (strcmp(argv[i], "-commentalign") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -commentalign\n"); return -1; } indigoSetOption("render-comment-alignment", argv[i]); } else if (strcmp(argv[i], "-commentpos") == 0) { if (++i == argc) { fprintf(stderr, "expecting an identifier after -commentpos\n"); return -1; } indigoSetOption("render-comment-position", argv[i]); } else if (strcmp(argv[i], "-atomnumbers") == 0) indigoSetOptionBool("render-atom-ids-visible", 1); else if (strcmp(argv[i], "-bondnumbers") == 0) indigoSetOptionBool("render-bond-ids-visible", 1); else if (strcmp(argv[i], "-onebased") == 0) indigoSetOptionBool("render-atom-bond-ids-from-one", 1); else if (strcmp(argv[i], "-help") == 0) { usage(); return 0; } else { fprintf(stderr, "unknown option: %s\n", argv[i]); return -1; } } if (p->bond > 0) indigoSetOptionFloat("render-bond-length", (float)p->bond); if (p->width > 0) indigoSetOptionInt("render-image-width", p->width); if (p->height > 0) indigoSetOptionInt("render-image-height", p->height); if (p->hydro_set && p->query_set) { fprintf(stderr, "-hydro conflicts with -query (implicit hydrogens do not exist in queries)\n"); } return 0; }