<gh_stars>1-10
"""
Author:
    <NAME>, PhD Student
Institution:
    Ishida Laboratory, Department of Computer Science, School of Computing, Tokyo Institute of Technology
Updated on:
    May, 2021
"""

from PIL.Image import Image
from PIL import Image as Img
from typing import List, Union

from rdkit.Chem.AllChem import ChemicalReaction

from .general_utils import ReactionRepresentationUtils

from ..chemical_compounds.visualization_utils import CompoundVisualizationUtils


class ReactionVisualizationUtils:
    """
    Description:
        Group of methods for handling chemical reaction visualization.
    """

    @staticmethod
    def draw_reaction(reaction: Union[str, ChemicalReaction], show_agents: bool = True, show_mapping: bool = True,
                      reactive_atoms: List[List[int]] = None, image_size_x: int = 300,
                      image_size_y: int = 300, verbose: bool = False) -> Union[Image, None]:
        """
        Description:
            Draw the chemical reaction with or without highlighted reactive substructures.
        Input:
            reaction (str or ChemicalReaction): The chemical reaction as a reaction SMILES or SMARTS string or a
                                                ChemicalReaction object.
            show_agents (bool): The flag signalizing whether the agents of the reaction should be displayed.
            show_mapping (bool): The flag signalizing whether atom map numbers should be displayed.
            reactive_atoms (List): The list of lists of atom indices that will be highlighted as reactive. If it is not
                                   specified, the individual compounds will be drawn with no highlighting.
            image_size_x (int): The width of the generated image.
            image_size_y (int): The height of the generated image.
            verbose (bool): The flag signalizing whether feedback messages should be displayed in the console.
        Output:
            (Image or None): The generated image for the chemical reaction or None if the ChemicalReaction object cannot
                             be converted to a string representation.
        """

        if isinstance(reaction, ChemicalReaction):
            reaction = ReactionRepresentationUtils.reaction_to_string(reaction)

            if reaction is None:
                if verbose:
                    print("Unable to obtain a reaction SMILES string representation from the given ChemicalReaction "
                          "object. Please make sure that the object represents a valid chemical reaction.")

                    return None

        reactants, agents, products = ReactionRepresentationUtils.parse_info_from_reaction(
            reaction=reaction,
            info_type="mol" if show_mapping else "mol_no_maps"
        )

        if reactive_atoms is None:
            reactive_atoms = [[], []]

        mol_images = []

        for r_ind, reactant in enumerate(reactants):
            if len(reactive_atoms[0]) > 0:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=reactant,
                        highlight_atoms=[reactive_atoms[0][r_ind]],
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )
            else:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=reactant,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

            if r_ind == len(reactants) - 1:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/arrow.png"))
            else:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        if len(agents) > 0 and show_agents:
            for a_ind, agent in enumerate(agents):
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=agent,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

                if a_ind == len(agents) - 1:
                    mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/arrow.png"))
                else:
                    mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        for p_ind, product in enumerate(products):
            if len(reactive_atoms[1]) > 0:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=product,
                        highlight_atoms=[reactive_atoms[1][p_ind]],
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )
            else:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=product,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

            if p_ind != len(products) - 1:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        widths, heights = zip(*(i.size for i in mol_images))
        total_width = sum(widths)
        max_height = max(heights)
        new_image = Img.new("RGB", (total_width, max_height), (255, 255, 255))

        x_offset, y_offset = 0, 0

        for im_ind, image in enumerate(mol_images):
            if im_ind % 2 != 0:
                y_offset = round(image_size_y / 2 - image.size[1] / 2)
            else:
                y_offset = 0

            new_image.paste(image, (x_offset, y_offset))
            x_offset += image.size[0]

        return new_image

"""
Author:
    <NAME>, PhD Student
Institution:
    Ishida Laboratory, Department of Computer Science, School of Computing, Tokyo Institute of Technology
Updated on:
    May, 2021
"""

from PIL.Image import Image
from PIL import Image as Img
from typing import List, Union

from rdkit.Chem.AllChem import ChemicalReaction

from .general_utils import ReactionRepresentationUtils

from ..chemical_compounds.visualization_utils import CompoundVisualizationUtils


class ReactionVisualizationUtils:
    """
    Description:
        Group of methods for handling chemical reaction visualization.
    """

    @staticmethod
    def draw_reaction(reaction: Union[str, ChemicalReaction], show_agents: bool = True, show_mapping: bool = True,
                      reactive_atoms: List[List[int]] = None, image_size_x: int = 300,
                      image_size_y: int = 300, verbose: bool = False) -> Union[Image, None]:
        """
        Description:
            Draw the chemical reaction with or without highlighted reactive substructures.
        Input:
            reaction (str or ChemicalReaction): The chemical reaction as a reaction SMILES or SMARTS string or a
                                                ChemicalReaction object.
            show_agents (bool): The flag signalizing whether the agents of the reaction should be displayed.
            show_mapping (bool): The flag signalizing whether atom map numbers should be displayed.
            reactive_atoms (List): The list of lists of atom indices that will be highlighted as reactive. If it is not
                                   specified, the individual compounds will be drawn with no highlighting.
            image_size_x (int): The width of the generated image.
            image_size_y (int): The height of the generated image.
            verbose (bool): The flag signalizing whether feedback messages should be displayed in the console.
        Output:
            (Image or None): The generated image for the chemical reaction or None if the ChemicalReaction object cannot
                             be converted to a string representation.
        """

        if isinstance(reaction, ChemicalReaction):
            reaction = ReactionRepresentationUtils.reaction_to_string(reaction)

            if reaction is None:
                if verbose:
                    print("Unable to obtain a reaction SMILES string representation from the given ChemicalReaction "
                          "object. Please make sure that the object represents a valid chemical reaction.")

                    return None

        reactants, agents, products = ReactionRepresentationUtils.parse_info_from_reaction(
            reaction=reaction,
            info_type="mol" if show_mapping else "mol_no_maps"
        )

        if reactive_atoms is None:
            reactive_atoms = [[], []]

        mol_images = []

        for r_ind, reactant in enumerate(reactants):
            if len(reactive_atoms[0]) > 0:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=reactant,
                        highlight_atoms=[reactive_atoms[0][r_ind]],
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )
            else:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=reactant,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

            if r_ind == len(reactants) - 1:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/arrow.png"))
            else:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        if len(agents) > 0 and show_agents:
            for a_ind, agent in enumerate(agents):
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=agent,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

                if a_ind == len(agents) - 1:
                    mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/arrow.png"))
                else:
                    mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        for p_ind, product in enumerate(products):
            if len(reactive_atoms[1]) > 0:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=product,
                        highlight_atoms=[reactive_atoms[1][p_ind]],
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )
            else:
                mol_images.append(
                    CompoundVisualizationUtils.draw_compound(
                        compound=product,
                        image_size_x=image_size_x,
                        image_size_y=image_size_y
                    )
                )

            if p_ind != len(products) - 1:
                mol_images.append(Img.open("retrochem_toolbox/chemical_reactions/assets/plus.png"))

        widths, heights = zip(*(i.size for i in mol_images))
        total_width = sum(widths)
        max_height = max(heights)
        new_image = Img.new("RGB", (total_width, max_height), (255, 255, 255))

        x_offset, y_offset = 0, 0

        for im_ind, image in enumerate(mol_images):
            if im_ind % 2 != 0:
                y_offset = round(image_size_y / 2 - image.size[1] / 2)
            else:
                y_offset = 0

            new_image.paste(image, (x_offset, y_offset))
            x_offset += image.size[0]

        return new_image
Author:     <NAME>, PhD Student Institution:     Ishida Laboratory, Department of Computer Science, School of Computing, Tokyo Institute of Technology Updated on:     May, 2021 Description:         Group of methods for handling chemical reaction visualization. Description:             Draw the chemical reaction with or without highlighted reactive substructures.         Input:             reaction (str or ChemicalReaction): The chemical reaction as a reaction SMILES or SMARTS string or a                                                 ChemicalReaction object.             show_agents (bool): The flag signalizing whether the agents of the reaction should be displayed.             show_mapping (bool): The flag signalizing whether atom map numbers should be displayed.             reactive_atoms (List): The list of lists of atom indices that will be highlighted as reactive. If it is not                                    specified, the individual compounds will be drawn with no highlighting.             image_size_x (int): The width of the generated image.             image_size_y (int): The height of the generated image.             verbose (bool): The flag signalizing whether feedback messages should be displayed in the console.         Output:             (Image or None): The generated image for the chemical reaction or None if the ChemicalReaction object cannot                              be converted to a string representation.