Skip to content

Commit

Permalink
#1303 Return original format
Browse files Browse the repository at this point in the history
Add new options input-format and output-content-type
  • Loading branch information
AliaksandrDziarkach committed Oct 10, 2023
1 parent 35b4650 commit e7ec558
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 77 deletions.
184 changes: 110 additions & 74 deletions api/wasm/indigo-ketcher/indigo-ketcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,67 +111,68 @@ namespace indigo
std::string toString(const std::map<std::string, std::string>& options, const std::string& outputFormat) const
{
print_js("toString:");
cstring result = nullptr;
if (outputFormat == "molfile" || outputFormat == "rxnfile" || outputFormat == "chemical/x-mdl-molfile" || outputFormat == "chemical/x-mdl-rxnfile")
{
if (is_reaction())
{
return _checkResultString(indigoRxnfile(id()));
}
return _checkResultString(indigoMolfile(id()));
result = _checkResultString(indigoRxnfile(id()));
else
result = _checkResultString(indigoMolfile(id()));
}
else if (outputFormat == "smiles" || outputFormat == "chemical/x-daylight-smiles" || outputFormat == "chemical/x-chemaxon-cxsmiles")
{
if (options.count("smiles") > 0 && options.at("smiles") == "canonical")
{
return _checkResultString(indigoCanonicalSmiles(id()));
result = _checkResultString(indigoCanonicalSmiles(id()));
}
else
{
if (outputFormat == "chemical/x-chemaxon-cxsmiles")
indigoSetOption("smiles-saving-format", "chemaxon");
else if (outputFormat == "chemical/x-daylight-smiles")
indigoSetOption("smiles-saving-format", "daylight");

if (outputFormat == "chemical/x-chemaxon-cxsmiles")
indigoSetOption("smiles-saving-format", "chemaxon");
else if (outputFormat == "chemical/x-daylight-smiles")
indigoSetOption("smiles-saving-format", "daylight");

return _checkResultString(indigoSmiles(id()));
result = _checkResultString(indigoSmiles(id()));
}
}
else if (outputFormat == "smarts" || outputFormat == "chemical/x-daylight-smarts")
{
if (options.count("smarts") > 0 && options.at("smarts") == "canonical")
{
return _checkResultString(indigoCanonicalSmarts(id()));
}
return _checkResultString(indigoSmarts(id()));
result = _checkResultString(indigoCanonicalSmarts(id()));
else
result = _checkResultString(indigoSmarts(id()));
}
else if (outputFormat == "cml" || outputFormat == "chemical/x-cml")
{
return _checkResultString(indigoCml(id()));
result = _checkResultString(indigoCml(id()));
}
else if (outputFormat == "cdxml" || outputFormat == "chemical/x-cdxml")
{
return _checkResultString(indigoCdxml(id()));
result = _checkResultString(indigoCdxml(id()));
}
else if (outputFormat == "cdx" || outputFormat == "chemical/x-cdx")
{
return _checkResultString(indigoCdxBase64(id()));
result = _checkResultString(indigoCdxBase64(id()));
}
else if (outputFormat == "inchi" || outputFormat == "chemical/x-inchi")
{
return _checkResultString(indigoInchiGetInchi(id()));
result = _checkResultString(indigoInchiGetInchi(id()));
}
else if (outputFormat == "inchi-key" || outputFormat == "chemical/x-inchi-key")
{
std::string inchi_str = _checkResultString(indigoInchiGetInchi(id()));
return _checkResultString(indigoInchiGetInchiKey(inchi_str.c_str()));
result = _checkResultString(indigoInchiGetInchiKey(inchi_str.c_str()));
}
else if (outputFormat == "inchi-aux" || outputFormat == "chemical/x-inchi-aux")
{
std::stringstream ss;
ss << _checkResultString(indigoInchiGetInchi(id())) << '\n' << _checkResultString(indigoInchiGetAuxInfo());
return ss.str();
result = ss.str();
}
else if (outputFormat == "ket" || outputFormat == "chemical/x-indigo-ket")
{
print_js(outputFormat.c_str());
return _checkResultString(indigoJson(id()));
result = _checkResultString(indigoJson(id()));
}
else if (outputFormat == "sdf" || outputFormat == "chemical/x-sdf")
{
Expand All @@ -184,13 +185,33 @@ namespace indigo
indigoSdfAppend(buffer.id, mol.id);
}
print_js(outputFormat.c_str());
return _checkResultString(indigoToString(buffer.id));
result = _checkResultString(indigoToString(buffer.id));
}
if (result == nullptr)
{
std::stringstream ss;
ss << "Unknown output format: " << outputFormat;
jsThrow(ss.str().c_str());
return ""; // suppress warning
}
if (auto out = options.find("output-content-type"); out != options.end() && out->second == "application/json")
{
cstring originalFormat = _checkResultString(indigoGetOriginalFormat(id()));
rapidjson::Document resultJson;
auto& allocator = resultJson.GetAllocator();
resultJson.SetObject();
resultJson.AddMember("struct", result, allocator);
resultJson.AddMember("format", outputFormat.c_str(), allocator);
resultJson.AddMember("original_format", originalFormat, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
resultJson.Accept(writer);
return buffer.GetString();
}
else
{
return result;
}

std::stringstream ss;
ss << "Unknown output format: " << outputFormat;
jsThrow(ss.str().c_str());
return ""; // suppress warning
}

IndigoKetcherObject substructure(const std::vector<int>& selected_atoms) const
Expand All @@ -216,7 +237,7 @@ namespace indigo
{
for (const auto& option : options)
{
if (option.first != "smiles" && option.first != "smarts")
if (option.first != "smiles" && option.first != "smarts" && option.first != "input-format" && option.first != "output-content-type")
{
_checkResult(indigoSetOption(option.first.c_str(), option.second.c_str()));
}
Expand Down Expand Up @@ -274,53 +295,68 @@ namespace indigo
IndigoRendererSession& operator=(IndigoRendererSession&&) = delete;
};

IndigoKetcherObject loadMoleculeOrReaction(const std::string& data)
IndigoKetcherObject loadMoleculeOrReaction(const std::string& data, const std::map<std::string, std::string>& options)
{
print_js("loadMoleculeOrReaction:");
std::vector<std::string> exceptionMessages;
exceptionMessages.reserve(4);

int objectId = -1;
if (data.find("InChI") == 0)
if (auto input_format = options.find("input-format");
input_format != options.end() && (input_format->second == "smarts" || input_format->second == "chemical/x-daylight-smarts"))
{
objectId = indigoInchiLoadMolecule(data.c_str());
print_js("load as smarts");
objectId = indigoLoadSmartsFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMolecule);
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMoleculeQuery);
}
exceptionMessages.emplace_back(indigoGetLastError());
}

// Let's try a simple molecule
print_js("try as molecule");
objectId = indigoLoadMoleculeFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
else
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMolecule);
}
exceptionMessages.emplace_back(indigoGetLastError());

// Let's try reaction
print_js("try as reaction");
objectId = indigoLoadReactionFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETReaction);
}
exceptionMessages.emplace_back(indigoGetLastError());
// Let's try query reaction
print_js("try as query reaction");
objectId = indigoLoadQueryReactionFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETReactionQuery);
}
exceptionMessages.emplace_back(indigoGetLastError());
// Let's try query molecule
print_js("try as query molecule");
objectId = indigoLoadQueryMoleculeFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMoleculeQuery);
if (data.find("InChI") == 0)
{
objectId = indigoInchiLoadMolecule(data.c_str());
if (objectId >= 0)
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMolecule);
}

// Let's try a simple molecule
print_js("try as molecule");
objectId = indigoLoadMoleculeFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMolecule);
}
exceptionMessages.emplace_back(indigoGetLastError());

// Let's try reaction
print_js("try as reaction");
objectId = indigoLoadReactionFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETReaction);
}
exceptionMessages.emplace_back(indigoGetLastError());
// Let's try query reaction
print_js("try as query reaction");
objectId = indigoLoadQueryReactionFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETReactionQuery);
}
exceptionMessages.emplace_back(indigoGetLastError());
// Let's try query molecule
print_js("try as query molecule");
objectId = indigoLoadQueryMoleculeFromBuffer(data.c_str(), data.size());
if (objectId >= 0)
{
return IndigoKetcherObject(objectId, IndigoKetcherObject::EKETMoleculeQuery);
}
exceptionMessages.emplace_back(indigoGetLastError());
}
exceptionMessages.emplace_back(indigoGetLastError());
// It's not anything we can load, let's throw an exception
std::stringstream ss;
ss << "Given string could not be loaded as (query or plain) molecule or reaction, see the error messages: ";
Expand Down Expand Up @@ -348,15 +384,15 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
IndigoKetcherObject iko = loadMoleculeOrReaction(data);
IndigoKetcherObject iko = loadMoleculeOrReaction(data, options);
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}

std::string aromatize(const std::string& data, const std::string& outputFormat, const std::map<std::string, std::string>& options)
{
const IndigoSession session;
indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
_checkResult(indigoAromatize(iko.id()));
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}
Expand All @@ -365,7 +401,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
_checkResult(indigoDearomatize(iko.id()));
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}
Expand All @@ -374,7 +410,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
_checkResult(indigoLayout(iko.id()));
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}
Expand All @@ -384,7 +420,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
auto iko = loadMoleculeOrReaction(data.c_str());
auto iko = loadMoleculeOrReaction(data.c_str(), options);
const auto& subiko = (selected_atoms.empty()) ? iko : iko.substructure(selected_atoms);
_checkResult(indigoClean2d(subiko.id()));
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
Expand All @@ -394,7 +430,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
_checkResult(indigoAutomap(iko.id(), mode.c_str()));
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}
Expand All @@ -403,7 +439,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
return _checkResultString(indigoCheckObj(iko.id(), properties.c_str()));
}

Expand All @@ -413,7 +449,7 @@ namespace indigo
indigoSetOptions(options);
indigoSetOption("json-saving-add-stereo-desc", "true");
indigoSetOption("molfile-saving-add-stereo-desc", "true");
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
return iko.toString(options, outputFormat.size() ? outputFormat : "ket");
}

Expand Down Expand Up @@ -661,7 +697,7 @@ namespace indigo
{
const IndigoSession session;
indigoSetOptions(options);
auto iko = loadMoleculeOrReaction(data.c_str());
auto iko = loadMoleculeOrReaction(data.c_str(), options);
rapidjson::Document result;
auto& allocator = result.GetAllocator();
result.SetObject();
Expand Down Expand Up @@ -701,7 +737,7 @@ namespace indigo
const IndigoRendererSession indigoRendererSession(session.getSessionId());

indigoSetOptions(options);
const auto iko = loadMoleculeOrReaction(data.c_str());
const auto iko = loadMoleculeOrReaction(data.c_str(), options);
auto buffer_object = IndigoObject(_checkResult(indigoWriteBuffer()));
char* raw_ptr = nullptr;
int size = 0;
Expand Down
15 changes: 12 additions & 3 deletions utils/indigo-service/backend/service/v2/indigo_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,12 @@ def indigo_init(options={}):
tls.indigo.setOption(option, value)
for option, value in options.items():
# TODO: Remove this when Indigo API supports smiles type option
if option in {
if option in (
"smiles",
}:
"smarts",
"input-format",
"output-content-type",
):
continue
tls.indigo.setOption(option, value)
return tls.indigo
Expand Down Expand Up @@ -313,6 +316,12 @@ def load_moldata(
)
md = MolData()

if "input-format" in options and options["input-format"] in (
"smarts",
"chemical/x-daylight-smarts",
):
md.struct = indigo.loadSmarts(molstr)
md.is_query = True
if molstr.startswith("InChI"):
md.struct = indigo.inchi.loadMolecule(molstr)
md.is_rxn = False
Expand Down Expand Up @@ -427,7 +436,7 @@ def get_response(md, output_struct_format, json_output, options, indigo):
"[RESPONSE]", output_struct_format, options, output_mol.encode("utf-8")
)

if json_output:
if json_output or options.get("output-content-type") == "application/json":
return (
jsonify(
{
Expand Down

0 comments on commit e7ec558

Please sign in to comment.