/************************************************************************* * * * This file is part of the 20n/act project. * * 20n/act enables DNA prediction for synthetic biology/bioengineering. * * Copyright (C) 2017 20n Labs, Inc. * * * * Please direct all queries to act@20n.com. * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * *************************************************************************/ package act.installer.reachablesexplorer; import chemaxon.struc.Molecule; import com.act.analysis.chemicals.molecules.MoleculeImporter; import com.act.biointerpretation.mechanisminspection.ReactionRenderer; import com.act.jobs.FileChecker; import org.apache.commons.codec.digest.DigestUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.Optional; public class MoleculeRenderer { private static final Logger LOGGER = LogManager.getFormatterLogger(MoleculeRenderer.class); private static final String PNG_EXTENSION = ".png"; private static ReactionRenderer renderer = new ReactionRenderer(); private File assetLocation; public MoleculeRenderer(File assetLocation) { if (assetLocation.exists()) { this.assetLocation = assetLocation; } else { String msg = String.format("Could not find or create directory at %s for storing assets.", assetLocation.getAbsolutePath()); LOGGER.error(msg); throw new RuntimeException(msg); } } public File getRenderingFile(String inchi) { String md5 = DigestUtils.md5Hex(inchi); String postfix = String.format("-%s%s", md5, PNG_EXTENSION); String renderingFilename = String.join("", "molecule", postfix); return Paths.get(this.assetLocation.getPath(), renderingFilename).toFile(); } public Optional<File> generateRendering(String inchi) { File rendering = getRenderingFile(inchi); if (!rendering.exists()) { try { Molecule mol = MoleculeImporter.importMolecule(inchi); renderer.drawMolecule(mol, rendering); FileChecker.verifyInputFile(rendering); } catch (IOException e) { LOGGER.error("Unable to generate rendering for %s at location %s", inchi, rendering.toPath().toString()); return Optional.empty(); } catch (StackOverflowError e) { // Very rarely, a very large molecule will trigger a StackOverFlowError. Catch it and move on! LOGGER.error("Unable to generate rendering for %s at location %s", inchi, rendering.toPath().toString()); return Optional.empty(); } } return Optional.of(rendering); } }