<commit_before>import json
from sfsimodels.models import soils, buildings, foundations, systems, abstract_models
from collections import OrderedDict
from sfsimodels.functions import add_to_obj
from sfsimodels.exceptions import deprecation, ModelError

standard_types = ["soil", "soil_profile", "foundation", "building", "section", "system", "custom_type"]

def load_json(ffp, custom=None, verbose=0):
    """
    Given a json file it creates a dictionary of sfsi objects

    :param ffp: str, Full file path to json file
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param verbose: int, console output
    :return: dict
    """
    data = json.load(open(ffp))
    return ecp_dict_to_objects(data, custom, verbose=verbose)

def load_json_and_meta(ffp, custom=None, verbose=0):
    data = json.load(open(ffp))
    md = {}
    for item in data:
        if item != "models":
            md[item] = data[item]
    return ecp_dict_to_objects(data, custom, verbose=verbose), md

def loads_json(p_str, custom=None, meta=False, verbose=0):
    """
    Given a json string it creates a dictionary of sfsi objects

    :param ffp: str, Full file path to json file
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param meta: bool, if true then also return all ecp meta data in separate dict
    :param verbose: int, console output
    :return: dict
    """
    data = json.loads(p_str)
    if meta:
        md = {}
        for item in data:
            if item != "models":
                md[item] = data[item]
        return ecp_dict_to_objects(data, custom, verbose=verbose), md
    else:
        return ecp_dict_to_objects(data, custom, verbose=verbose)

# Deprecated name
def dicts_to_objects(data, verbose=0):
    """Deprecated. Use ecp_dict_to_objects"""
    deprecation('Deprecated, dicts_to_objects should be switched to ecp_dict_to_objects')
    ecp_dict_to_objects(data, verbose=verbose)

deprecated_types = OrderedDict([
    ("structure", "sdof"),
    ("frame_building", "building_frame"),
    ("frame_building_2D", "building_frame2D"),
    ("wall_building", "building_wall"),
    ("pad_foundation", "foundation_pad"),
    ("raft_foundation", "foundation_raft")
])

def ecp_dict_to_objects(ecp_dict, custom_map=None, verbose=0):
    """
    Given an ecp dictionary, build a dictionary of sfsi objects

    :param ecp_dict: dict, engineering consistency project dictionary
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param verbose: int, console output
    :return: dict
    """
    if custom_map is None:
        custom_map = {}

    obj_map = {
        "soil-soil": soils.Soil,
        "soil-critical_soil": soils.CriticalSoil,
        "soil-soil_critical": soils.CriticalSoil,  # deprecated type
        "soil-stress_dependent_soil": soils.StressDependentSoil,
        "soil-soil_stress_dependent": soils.StressDependentSoil,
        "soil_profile-soil_profile": soils.SoilProfile,
        "building-building": buildings.Building,
        "building-frame_building": buildings.FrameBuilding,
        "building-frame_building2D": buildings.FrameBuilding2D,
        "building-building_frame2D": buildings.FrameBuilding2D,  # deprecated type
        "building-wall_building": buildings.WallBuilding,
        "building-building_wall": buildings.WallBuilding,  # deprecated type
        "building-structure": buildings.SDOFBuilding,  # Deprecated type, remove in v1
        "building-sdof": buildings.SDOFBuilding,
        "foundation-foundation": foundations.Foundation,
        "foundation-foundation_raft": foundations.RaftFoundation,  # deprecated type
        "foundation-raft_foundation": foundations.RaftFoundation,
        "foundation-raft": foundations.RaftFoundation,  # Deprecated approach for type, remove in v1
        "foundation-pad_foundation": foundations.PadFoundation,
        "foundation-foundation_pad": foundations.PadFoundation,  # deprecated type
        "section-section": buildings.Section,
        "custom_object-custom_object": abstract_models.CustomObject,
        "system-system": systems.SoilStructureSystem,  # deprecated type
        "system-sfs": systems.SoilStructureSystem
    }

    # merge and overwrite the object map with custom maps
    for item in custom_map:
        obj_map[item] = custom_map[item]

    data_models = ecp_dict["models"]

    exception_list = []
    objs = OrderedDict()
    collected = set([])
    # Set base type properly
    mtypes = list(data_models)
    for mtype in mtypes:
        base_type = mtype
        if base_type[:-1] in standard_types:  # support the loading of old plural based ecp files
            base_type = base_type[:-1]
            data_models[base_type] = data_models[mtype]
            del data_models[mtype]
        for m_id in data_models[base_type]:
            data_models[base_type][m_id]["base_type"] = base_type

    for mtype in data_models:
        base_type = mtype
        if base_type in exception_list:
            continue
        collected.add(base_type)
        objs[base_type] = OrderedDict()
        for m_id in data_models[mtype]:
            obj = data_models[mtype][m_id]
            if "type" not in obj:
                obj["type"] = base_type
            try:
                obj_class = obj_map["%s-%s" % (base_type, obj["type"])]
            except KeyError:
                if obj["type"] in deprecated_types:
                    try:
                        obj_class = obj_map["%s-%s" % (base_type, deprecated_types[obj["type"]])]
                    except KeyError:
                        raise KeyError("Map for Model: '%s' index: '%s' and type: '%s' not available, "
                                       "add '%s-%s' to custom dict" % (base_type, m_id, base_type, base_type, obj["type"]))
                else:
                    raise KeyError("Map for Model: '%s' index: '%s' and type: '%s' not available, "
                                   "add '%s-%s' to custom dict" % (base_type, m_id, base_type, base_type, obj["type"]))
            try:
                new_instance = obj_class()
            except TypeError as e:
                if "required positional argument:" in str(e):
                    parameters = [str(e).split("argument: ")[-1]]
                elif "required positional arguments:" in str(e):
                    p_str = str(e).split("arguments: ")[-1]
                    if ", and " in p_str:  # if more than 2
                        partial = p_str.split(", and ")
                        parameters = partial[0].split(", ") + partial[-1:]
                    else:  # if one
                        parameters = p_str.split(" and ")
                else:
                    raise TypeError(e)
                params = []
                for parameter in parameters:
                    parameter = parameter[1:-1]
                    try:
                        params.append(data_models[mtype][m_id][parameter])
                    except KeyError as e2:  # To be removed and just raise exception
                        deprecation("Your file is out of date, "
                                    "run sfsimodels.migrate_ecp(<file-path>, <out-file-path>).")
                        if mtype == "building":
                            params = [len(data_models[mtype][m_id]["storey_masses"])]  # n_storeys
                            if "frame" in data_models[mtype][m_id]["type"]:
                                params.append(len(data_models[mtype][m_id]["bay_lengths"]))
                        else:
                            raise KeyError("Can't find required positional argument: {0} for {1} id: {2}".format(
                                parameter, mtype, m_id
                            ))
                new_instance = obj_class(*params)

            add_to_obj(new_instance, data_models[mtype][m_id], objs=objs, verbose=verbose)
            # print(mtype, m_id)
            objs[base_type][int(data_models[mtype][m_id]["id"])] = new_instance

    # Deal with all the exceptions
    # for mtype in data_models:
    #     base_type = mtype
    #
    #     if base_type in collected:
    #         continue
    #     if base_type not in objs:
    #         objs[base_type] = OrderedDict()

    all_bts = list(objs)
    for base_type in all_bts:  # Support for old style ecp file
        if base_type in standard_types:
            objs[base_type + "s"] = objs[base_type]
    return objs

class Output(object):
    name = ""
    units = ""
    doi = ""
    sfsimodels_version = ""
    comments = ""
    compression = True

    def __init__(self):
        self.unordered_models = OrderedDict()

    def add_to_dict(self, an_object, extras=None):
        """
        Convert models to json serialisable output

        :param an_object: An instance of a model object
        :param extras: A dictionary of extra variables that should be
        :return:
        """
        if an_object.id is None:
            raise ModelError("id must be set on object before adding to output.")
        if hasattr(an_object, "base_type"):
            mtype = an_object.base_type
        elif hasattr(an_object, "type"):
            if an_object.type in standard_types:
                mtype = an_object.type
            else:
                mtype = "custom_type"
        else:
            raise ModelError("Object does not have attribute 'base_type' or 'type', cannot add to output.")
        if mtype not in self.unordered_models:  # Catch any custom objects
            self.unordered_models[mtype] = OrderedDict()

        if hasattr(an_object, "add_to_dict"):
            an_object.add_to_dict(self.unordered_models)

        elif hasattr(an_object, "to_dict"):
            self.unordered_models[mtype][an_object.unique_hash] = an_object.to_dict(compression=self.compression)
        else:
            raise ModelError("Object does not have method 'to_dict', cannot add to output.")

    def add_to_output(self, mtype, m_id, serialisable_dict):
        """
        Can add additional objects or dictionaries to output file that don't conform to standard objects.

        :param mtype:
        :param m_id:
        :param serialisable_dict:
        :return:
        """
        if mtype not in self.unordered_models:
            self.unordered_models[mtype] = OrderedDict()
        self.unordered_models[mtype][m_id] = serialisable_dict

    @property
    def models(self):
        """Unhashed"""
        models_dict = OrderedDict()
        collected = []
        for item in standard_types:
            if item in self.unordered_models:
                new_dict, replacement_dict = unhash_dict(self.unordered_models[item])
                models_dict[item] = new_dict
                collected.append(item)
        for item in self.unordered_models:
            if item not in collected:
                new_dict, replacement_dict = unhash_dict(self.unordered_models[item])
                models_dict[item] = new_dict
        return models_dict

    @staticmethod
    def parameters():
        return ["name", "units", "doi", "sfsimodels_version", "comments", "models"]

    def to_dict(self):
        outputs = OrderedDict()
        for item in self.parameters():
            outputs[item] = self.__getattribute__(item)
        return outputs

def migrate_ecp(in_ffp, out_ffp):
    """Migrates and ECP file to the current version of sfsimodels"""
    objs, meta_data = load_json_and_meta(in_ffp)
    ecp_output = Output()
    for m_type in objs:
        for instance in objs[m_type]:
            ecp_output.add_to_dict(objs[m_type][instance])
    ecp_output.name = meta_data["name"]
    ecp_output.units = meta_data["units"]
    ecp_output.comments = meta_data["comments"]
    ecp_output.sfsimodels_version = meta_data["sfsimodels_version"]
    p_str = json.dumps(ecp_output.to_dict(), skipkeys=["__repr__"], indent=4)
    a = open(out_ffp, "w")
    a.write(p_str)
    a.close()

def unhash_dict(pdict):
    new_dict = OrderedDict()
    replacement_dict = OrderedDict()
    for i, item in enumerate(pdict):
        key = str(i + 1)
        # int(item)  # TODO: stop replacement if item is an int!!!
        new_dict[key] = pdict[item]
        replacement_dict[item] = key
    return new_dict, replacement_dict
<commit_msg>Saving and loading using unique. All tests pass.<commit_after>import json
from sfsimodels.models import soils, buildings, foundations, systems, abstract_models
from collections import OrderedDict
from sfsimodels.functions import add_to_obj
from sfsimodels.exceptions import deprecation, ModelError

standard_types = ["soil", "soil_profile", "foundation", "building", "section", "system", "custom_type"]

def load_json(ffp, custom=None, verbose=0):
    """
    Given a json file it creates a dictionary of sfsi objects

    :param ffp: str, Full file path to json file
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param verbose: int, console output
    :return: dict
    """
    data = json.load(open(ffp))
    return ecp_dict_to_objects(data, custom, verbose=verbose)

def load_json_and_meta(ffp, custom=None, verbose=0):
    data = json.load(open(ffp))
    md = {}
    for item in data:
        if item != "models":
            md[item] = data[item]
    return ecp_dict_to_objects(data, custom, verbose=verbose), md

def loads_json(p_str, custom=None, meta=False, verbose=0):
    """
    Given a json string it creates a dictionary of sfsi objects

    :param ffp: str, Full file path to json file
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param meta: bool, if true then also return all ecp meta data in separate dict
    :param verbose: int, console output
    :return: dict
    """
    data = json.loads(p_str)
    if meta:
        md = {}
        for item in data:
            if item != "models":
                md[item] = data[item]
        return ecp_dict_to_objects(data, custom, verbose=verbose), md
    else:
        return ecp_dict_to_objects(data, custom, verbose=verbose)

# Deprecated name
def dicts_to_objects(data, verbose=0):
    """Deprecated. Use ecp_dict_to_objects"""
    deprecation('Deprecated, dicts_to_objects should be switched to ecp_dict_to_objects')
    ecp_dict_to_objects(data, verbose=verbose)

deprecated_types = OrderedDict([
    ("structure", "sdof"),
    ("frame_building", "building_frame"),
    ("frame_building_2D", "building_frame2D"),
    ("wall_building", "building_wall"),
    ("pad_foundation", "foundation_pad"),
    ("raft_foundation", "foundation_raft")
])

def ecp_dict_to_objects(ecp_dict, custom_map=None, verbose=0):
    """
    Given an ecp dictionary, build a dictionary of sfsi objects

    :param ecp_dict: dict, engineering consistency project dictionary
    :param custom: dict, used to load custom objects, {model type: custom object}
    :param verbose: int, console output
    :return: dict
    """
    if custom_map is None:
        custom_map = {}

    obj_map = {
        "soil-soil": soils.Soil,
        "soil-critical_soil": soils.CriticalSoil,
        "soil-soil_critical": soils.CriticalSoil,  # deprecated type
        "soil-stress_dependent_soil": soils.StressDependentSoil,
        "soil-soil_stress_dependent": soils.StressDependentSoil,
        "soil_profile-soil_profile": soils.SoilProfile,
        "building-building": buildings.Building,
        "building-frame_building": buildings.FrameBuilding,
        "building-frame_building2D": buildings.FrameBuilding2D,
        "building-building_frame2D": buildings.FrameBuilding2D,  # deprecated type
        "building-wall_building": buildings.WallBuilding,
        "building-building_wall": buildings.WallBuilding,  # deprecated type
        "building-structure": buildings.SDOFBuilding,  # Deprecated type, remove in v1
        "building-sdof": buildings.SDOFBuilding,
        "foundation-foundation": foundations.Foundation,
        "foundation-foundation_raft": foundations.RaftFoundation,  # deprecated type
        "foundation-raft_foundation": foundations.RaftFoundation,
        "foundation-raft": foundations.RaftFoundation,  # Deprecated approach for type, remove in v1
        "foundation-pad_foundation": foundations.PadFoundation,
        "foundation-foundation_pad": foundations.PadFoundation,  # deprecated type
        "section-section": buildings.Section,
        "custom_object-custom_object": abstract_models.CustomObject,
        "system-system": systems.SoilStructureSystem,  # deprecated type
        "system-sfs": systems.SoilStructureSystem
    }

    # merge and overwrite the object map with custom maps
    for item in custom_map:
        obj_map[item] = custom_map[item]

    data_models = ecp_dict["models"]

    exception_list = []
    objs = OrderedDict()
    collected = set([])
    # Set base type properly
    mtypes = list(data_models)
    for mtype in mtypes:
        base_type = mtype
        if base_type[:-1] in standard_types:  # support the loading of old plural based ecp files
            base_type = base_type[:-1]
            data_models[base_type] = data_models[mtype]
            del data_models[mtype]
        for m_id in data_models[base_type]:
            data_models[base_type][m_id]["base_type"] = base_type

    for mtype in data_models:
        base_type = mtype
        if base_type in exception_list:
            continue
        collected.add(base_type)
        objs[base_type] = OrderedDict()
        for m_id in data_models[mtype]:
            obj = data_models[mtype][m_id]
            if "type" not in obj:
                obj["type"] = base_type
            try:
                obj_class = obj_map["%s-%s" % (base_type, obj["type"])]
            except KeyError:
                if obj["type"] in deprecated_types:
                    try:
                        obj_class = obj_map["%s-%s" % (base_type, deprecated_types[obj["type"]])]
                    except KeyError:
                        raise KeyError("Map for Model: '%s' index: '%s' and type: '%s' not available, "
                                       "add '%s-%s' to custom dict" % (base_type, m_id, base_type, base_type, obj["type"]))
                else:
                    raise KeyError("Map for Model: '%s' index: '%s' and type: '%s' not available, "
                                   "add '%s-%s' to custom dict" % (base_type, m_id, base_type, base_type, obj["type"]))
            try:
                new_instance = obj_class()
            except TypeError as e:
                if "required positional argument:" in str(e):
                    parameters = [str(e).split("argument: ")[-1]]
                elif "required positional arguments:" in str(e):
                    p_str = str(e).split("arguments: ")[-1]
                    if ", and " in p_str:  # if more than 2
                        partial = p_str.split(", and ")
                        parameters = partial[0].split(", ") + partial[-1:]
                    else:  # if one
                        parameters = p_str.split(" and ")
                else:
                    raise TypeError(e)
                params = []
                for parameter in parameters:
                    parameter = parameter[1:-1]
                    try:
                        params.append(data_models[mtype][m_id][parameter])
                    except KeyError as e2:  # To be removed and just raise exception
                        deprecation("Your file is out of date, "
                                    "run sfsimodels.migrate_ecp(<file-path>, <out-file-path>).")
                        if mtype == "building":
                            params = [len(data_models[mtype][m_id]["storey_masses"])]  # n_storeys
                            if "frame" in data_models[mtype][m_id]["type"]:
                                params.append(len(data_models[mtype][m_id]["bay_lengths"]))
                        else:
                            raise KeyError("Can't find required positional argument: {0} for {1} id: {2}".format(
                                parameter, mtype, m_id
                            ))
                new_instance = obj_class(*params)

            add_to_obj(new_instance, data_models[mtype][m_id], objs=objs, verbose=verbose)
            # print(mtype, m_id)
            objs[base_type][int(data_models[mtype][m_id]["id"])] = new_instance

    # Deal with all the exceptions
    # for mtype in data_models:
    #     base_type = mtype
    #
    #     if base_type in collected:
    #         continue
    #     if base_type not in objs:
    #         objs[base_type] = OrderedDict()

    all_bts = list(objs)
    for base_type in all_bts:  # Support for old style ecp file
        if base_type in standard_types:
            objs[base_type + "s"] = objs[base_type]
    return objs

class Output(object):
    name = ""
    units = ""
    doi = ""
    sfsimodels_version = ""
    comments = ""
    compression = True

    def __init__(self):
        self.unordered_models = OrderedDict()

    def add_to_dict(self, an_object, extras=None):
        """
        Convert models to json serialisable output

        :param an_object: An instance of a model object
        :param extras: A dictionary of extra variables that should be
        :return:
        """
        if an_object.id is None:
            raise ModelError("id must be set on object before adding to output.")
        if hasattr(an_object, "base_type"):
            mtype = an_object.base_type
        elif hasattr(an_object, "type"):
            if an_object.type in standard_types:
                mtype = an_object.type
            else:
                mtype = "custom_type"
        else:
            raise ModelError("Object does not have attribute 'base_type' or 'type', cannot add to output.")
        if mtype not in self.unordered_models:  # Catch any custom objects
            self.unordered_models[mtype] = OrderedDict()

        if hasattr(an_object, "add_to_dict"):
            an_object.add_to_dict(self.unordered_models)

        elif hasattr(an_object, "to_dict"):
            self.unordered_models[mtype][an_object.unique_hash] = an_object.to_dict(compression=self.compression)
        else:
            raise ModelError("Object does not have method 'to_dict', cannot add to output.")

    def add_to_output(self, mtype, m_id, serialisable_dict):
        """
        Can add additional objects or dictionaries to output file that don't conform to standard objects.

        :param mtype:
        :param m_id:
        :param serialisable_dict:
        :return:
        """
        if mtype not in self.unordered_models:
            self.unordered_models[mtype] = OrderedDict()
        self.unordered_models[mtype][m_id] = serialisable_dict

    @property
    def models(self):
        """Unhashed"""
        models_dict = OrderedDict()
        collected = []
        for item in standard_types:
            if item in self.unordered_models:
                new_dict, replacement_dict = unhash_dict(self.unordered_models[item])
                models_dict[item] = new_dict
                collected.append(item)
        for item in self.unordered_models:
            print("item: ", item)
            if item not in collected:
                new_dict, replacement_dict = unhash_dict(self.unordered_models[item])
                models_dict[item] = new_dict
        return models_dict

    @staticmethod
    def parameters():
        return ["name", "units", "doi", "sfsimodels_version", "comments", "models"]

    def to_dict(self):
        outputs = OrderedDict()
        for item in self.parameters():
            outputs[item] = self.__getattribute__(item)
        return outputs

def migrate_ecp(in_ffp, out_ffp):
    """Migrates and ECP file to the current version of sfsimodels"""
    objs, meta_data = load_json_and_meta(in_ffp)
    ecp_output = Output()
    for m_type in objs:
        for instance in objs[m_type]:
            ecp_output.add_to_dict(objs[m_type][instance])
    ecp_output.name = meta_data["name"]
    ecp_output.units = meta_data["units"]
    ecp_output.comments = meta_data["comments"]
    ecp_output.sfsimodels_version = meta_data["sfsimodels_version"]
    p_str = json.dumps(ecp_output.to_dict(), skipkeys=["__repr__"], indent=4)
    a = open(out_ffp, "w")
    a.write(p_str)
    a.close()

def unhash_dict(pdict):
    new_dict = OrderedDict()
    replacement_dict = OrderedDict()
    for i, item in enumerate(pdict):
        key = str(i + 1)
        assert int(item) > 1000  # avoid hashes that are in the same range as ids!
        new_dict[key] = pdict[item]
        replacement_dict[item] = key
    return new_dict, replacement_dict
<|endoftext|>


<commit_before>"""LaTeX Exporter class"""

#-----------------------------------------------------------------------------
# Copyright (c) 2013, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

# Stdlib imports
import os

# IPython imports
from IPython.utils.traitlets import Unicode
from IPython.config import Config

from IPython.nbconvert import filters, preprocessors
from .templateexporter import TemplateExporter

#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------

class LatexExporter(TemplateExporter):
    """
    Exports to a Latex template.  Inherit from this class if your template is
    LaTeX based and you need custom tranformers/filters.  Inherit from it if
    you are writing your own HTML template and need custom tranformers/filters.
    If you don't need custom tranformers/filters, just change the
    'template_file' config option.  Place your template in the special "/latex"
    subfolder of the "../templates" folder.
    """

    def _file_extension_default(self):
        return 'tex'

    def _template_file_default(self):
        return 'article'

    #Latex constants
    def _default_template_path_default(self):
        return os.path.join("..", "templates", "latex")

    template_skeleton_path = Unicode(
        os.path.join("..", "templates", "latex", "skeleton"), config=True,
        help="Path where the template skeleton files are located.")

    #Special Jinja2 syntax that will not conflict when exporting latex.
    jinja_comment_block_start = Unicode("((=", config=True)
    jinja_comment_block_end = Unicode("=))", config=True)
    jinja_variable_block_start = Unicode("(((", config=True)
    jinja_variable_block_end = Unicode(")))", config=True)
    jinja_logic_block_start = Unicode("((*", config=True)
    jinja_logic_block_end = Unicode("*))", config=True)

    #Extension that the template files use.
    template_extension = Unicode(".tplx", config=True)

    output_mimetype = 'text/latex'

    @property
    def default_config(self):
        c = Config({
            'NbConvertBase': {
                'display_data_priority' : ['latex', 'pdf', 'png', 'jpg', 'svg', 'jpeg', 'text']
                },
             'ExtractOutputPreprocessor': {
                    'enabled':True
                 },
             'SVG2PDFPreprocessor': {
                    'enabled':True
                 },
             'LatexPreprocessor': {
                    'enabled':True
                 },
             'SphinxPreprocessor': {
                    'enabled':True
                 },
             'HighlightMagicsPreprocessor': {
                    'enabled':True
                 }
         })
        c.merge(super(LatexExporter,self).default_config)
        return c
<commit_msg>Use _default method instead of redefining trait<commit_after>"""LaTeX Exporter class"""

#-----------------------------------------------------------------------------
# Copyright (c) 2013, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

# Stdlib imports
import os

# IPython imports
from IPython.utils.traitlets import Unicode
from IPython.config import Config

from IPython.nbconvert import filters, preprocessors
from .templateexporter import TemplateExporter

#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------

class LatexExporter(TemplateExporter):
    """
    Exports to a Latex template.  Inherit from this class if your template is
    LaTeX based and you need custom tranformers/filters.  Inherit from it if
    you are writing your own HTML template and need custom tranformers/filters.
    If you don't need custom tranformers/filters, just change the
    'template_file' config option.  Place your template in the special "/latex"
    subfolder of the "../templates" folder.
    """

    def _file_extension_default(self):
        return 'tex'

    def _template_file_default(self):
        return 'article'

    #Latex constants
    def _default_template_path_default(self):
        return os.path.join("..", "templates", "latex")

    def _template_skeleton_path_default(self):
        return os.path.join("..", "templates", "latex", "skeleton")

    #Special Jinja2 syntax that will not conflict when exporting latex.
    jinja_comment_block_start = Unicode("((=", config=True)
    jinja_comment_block_end = Unicode("=))", config=True)
    jinja_variable_block_start = Unicode("(((", config=True)
    jinja_variable_block_end = Unicode(")))", config=True)
    jinja_logic_block_start = Unicode("((*", config=True)
    jinja_logic_block_end = Unicode("*))", config=True)

    #Extension that the template files use.
    template_extension = Unicode(".tplx", config=True)

    output_mimetype = 'text/latex'

    @property
    def default_config(self):
        c = Config({
            'NbConvertBase': {
                'display_data_priority' : ['latex', 'pdf', 'png', 'jpg', 'svg', 'jpeg', 'text']
                },
             'ExtractOutputPreprocessor': {
                    'enabled':True
                 },
             'SVG2PDFPreprocessor': {
                    'enabled':True
                 },
             'LatexPreprocessor': {
                    'enabled':True
                 },
             'SphinxPreprocessor': {
                    'enabled':True
                 },
             'HighlightMagicsPreprocessor': {
                    'enabled':True
                 }
         })
        c.merge(super(LatexExporter,self).default_config)
        return c
<|endoftext|>


<commit_before>import os

from django import template
from django.conf import settings
from django.utils.http import urlquote

from sass.utils import SassUtils
from sass.models import SassModel

register = template.Library()

class SassNode(template.Node):
    def __init__(self, name):
        try:
            self.model = SassModel.objects.get(name=name)
        except SassModel.DoesNotExist, e:
            raise template.TemplateSyntaxError('Sass name "%s" does not exist.' % self.name)

    def render(self, context):
        relative_css_path = self.model.relative_css_path()
        media_url = self.model.css_media_path()
        css = "<link href='%s?%s' rel='stylesheet' type='text/css' />" %(media_url, self.model.digest)
        return css

@register.tag(name="sass")
def do_sass(parser, token):
    try:
        # get the tag and the sass resource.
        tag_name, resource = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, '%s tag requires a single argument.' %token.contents.split()[0]
    if not (resource[0] == resource[-1] and resource[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SassNode(resource[1:-1])
    <commit_msg>Template tag no longer uses digest.<commit_after>import os

from django import template
from django.conf import settings
from django.utils.http import urlquote

from sass.utils import SassUtils
from sass.models import SassModel

register = template.Library()

class SassNode(template.Node):
    def __init__(self, name):
        try:
            self.model = SassModel.objects.get(name=name)
            # check to see if we need to run the source through sass.

        except SassModel.DoesNotExist, e:
            raise template.TemplateSyntaxError('Sass name "%s" does not exist.' % self.name)

    def render(self, context):
        relative_css_path = self.model.relative_css_path()
        media_url = self.model.css_media_path()
        css = "<link href='%s?%s' rel='stylesheet' type='text/css' />" %(media_url, self.model.source_modified_time)
        return css

@register.tag(name="sass")
def do_sass(parser, token):
    try:
        # get the tag and the sass resource.
        tag_name, resource = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, '%s tag requires a single argument.' %token.contents.split()[0]
    if not (resource[0] == resource[-1] and resource[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SassNode(resource[1:-1])
    <|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Created on 15.04.2012

@author: moschlar
'''
#
## SAUCE - System for AUtomated Code Evaluation
## Copyright (C) 2013 Moritz Schlarb
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## 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 Affero General Public License for more details.
##
## You should have received a copy of the GNU Affero General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import sys
import logging

import inspect
from itertools import groupby
from webhelpers.html.builder import literal

from tg import expose, tmpl_context as c, request, flash, lurl, abort
from tg.decorators import before_validate, before_call, before_render,\
    cached_property, override_template, with_trailing_slash
from tg.controllers.tgcontroller import TGController
from tgext.crud import CrudRestController, EasyCrudRestController
from tgext.crud.controller import CrudRestControllerHelpers

from sauce.model import DBSession

import tw2.bootstrap.forms as twb
import tw2.jqplugins.chosen.widgets as twjc
import sprox.widgets.tw2widgets.widgets as sw
from sauce.widgets.datagrid import JSSortableDataGrid

from sprox.sa.widgetselector import SAWidgetSelector
from sauce.controllers.crc.provider import FilterSAORMSelector
from sprox.fillerbase import TableFiller, AddFormFiller, EditFormFiller
from sprox.formbase import AddRecordForm, EditableForm

import transaction
from sqlalchemy.exc import IntegrityError, DatabaseError, ProgrammingError
errors = (IntegrityError, DatabaseError, ProgrammingError)

__all__ = ['FilterCrudRestController']

log = logging.getLogger(__name__)

#--------------------------------------------------------------------------------

class ChosenPropertyMultipleSelectField(twjc.ChosenMultipleSelectField, sw.PropertyMultipleSelectField):

    def _validate(self, value, state=None):
        # Fix inspired by twf.MultipleSelectionField
        if value and not isinstance(value, (list, tuple)):
            value = [value]
        return super(ChosenPropertyMultipleSelectField, self)._validate(value, state)

class ChosenPropertySingleSelectField(twjc.ChosenSingleSelectField, sw.PropertySingleSelectField):
    pass

class MyWidgetSelector(SAWidgetSelector):
    default_multiple_select_field_widget_type = ChosenPropertyMultipleSelectField
    default_single_select_field_widget_type = ChosenPropertySingleSelectField

    def __init__(self, *args, **kw):
        super(MyWidgetSelector, self).__init__(*args, **kw)
#        self.default_widgets.update({sqlat.DateTime: twb.CalendarDateTimePicker})

#--------------------------------------------------------------------------------

class CrudIndexController(TGController):

    def __init__(self, *args, **kw):
        super(CrudIndexController, self).__init__(*args, **kw)
        self.helpers = CrudRestControllerHelpers()

    def _before(self, *args, **kw):
        c.title = self.title
        c.menu_items = self.menu_items
        #c.kept_params = self._kept_params()
        c.crud_helpers = self.helpers
        #c.crud_style = self.style

    @with_trailing_slash
    @expose('sauce.templates.crc.index')
    def index(self):
        return dict(page='event')

#--------------------------------------------------------------------------------

class FilterCrudRestController(EasyCrudRestController):
    '''Generic base class for CrudRestControllers with filters'''

    def __init__(self, query_modifier=None, query_modifiers={},
                 menu_items={}, inject={},
                 allow_new=True, allow_edit=True, allow_delete=True,
                 **kw):
        '''Initialize FilteredCrudRestController with given options

        Arguments:

        ``query_modifier``:
            A callable that may modify the base query from the model entity
        ``query_modifiers``:
            A dict of callable that may modify the relationship query from the model entity
            the keys are the remote side classes
        ``menu_items``:
            A dict of menu_items for ``EasyCrudRestController``
        ``inject``:
            A dict of values to inject into POST requests before validation
        ``allow_new``:
            Whether the "New <Entity>" link shall be displayed on get_all
            and the url /<entity/new will be accesible
        ``allow_edit``:
            Whether the "Edit" link shall be displayed in the actions column
            on get_all and the url /<entity/<id>/delete will be accesible
        ``allow_delete``:
            Whether the "Delete" link shall be displayed in the actions column
            on get_all and the url /<entity/<id>/delete will be accesible
        '''

        self.inject = inject

        self.allow_new = allow_new
        self.allow_edit = allow_edit
        self.allow_delete = allow_delete

#        if not hasattr(self, 'table'):
#            class Table(JSSortableTableBase):
#                __entity__ = self.model
#            self.table = Table(DBSession)

        # To effectively disable pagination and fix issues with tgext.crud.util.SmartPaginationCollection
        if not hasattr(self, 'table_filler'):
            class MyTableFiller(TableFiller):
                __entity__ = self.model
                __actions__ = self.custom_actions
                __provider_type_selector_type__ = FilterSAORMSelector
            self.table_filler = MyTableFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_edit and not hasattr(self, 'edit_form'):
            class EditForm(EditableForm):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.edit_form = EditForm(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_edit and not hasattr(self, 'edit_filler'):
            class EditFiller(EditFormFiller):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.edit_filler = EditFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_new and not hasattr(self, 'new_form'):
            class NewForm(AddRecordForm):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.new_form = NewForm(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_new and not hasattr(self, 'new_filler'):
            class NewFiller(AddFormFiller):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.new_filler = NewFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        self.__table_options__['__base_widget_type__'] = JSSortableDataGrid
        if '__base_widget_args__' in self.__table_options__:
            if 'headers' in self.__table_options__['__base_widget_args__']:
                self.__table_options__['__base_widget_args__']['headers'].update({0: {'sorter': False}})
            else:
                self.__table_options__['__base_widget_args__'].update({'headers': {0: {'sorter': False}}})
        else:
            self.__table_options__['__base_widget_args__'] = {'headers': {0: {'sorter': False}}}

        self.__form_options__['__base_widget_type__'] = twb.HorizontalForm
        self.__form_options__['__widget_selector__'] = MyWidgetSelector()

        # Since DBSession is a scopedsession we don't need to pass it around,
        # so we just use the imported DBSession here
        super(FilterCrudRestController, self).__init__(DBSession, menu_items)

    def _adapt_menu_items(self, menu_items):
        '''Overwrite from CrudRestController to preserve ordering'''
        adapted_menu_items = type(menu_items)()

        for link, model in menu_items.iteritems():
            if inspect.isclass(model):
                adapted_menu_items[link + 's'] = model.__name__
            else:
                adapted_menu_items[link] = model
        return adapted_menu_items

    def custom_actions(self, obj):
        ''''Display bootstrap-styled action fields respecting the allow_* properties'''
        result = []
        count = 0
        try:
            result.append(u''
                u'')
            count += 1
        except:
            pass
        try:
            primary_fields = self.table_filler.__provider__.get_primary_fields(self.table_filler.__entity__)
            pklist = u'/'.join(map(lambda x: unicode(getattr(obj, x)), primary_fields))
            result.append(u''
                u'')
        except:
            pass
        if self.allow_delete:
            result.append(
                u''
                u'  '
                u'' % (obj.id))
        return literal('
'
            % (len(result) * 30) + ''.join(result) + '
')

    def _before(self, *args, **kw):
        super(FilterCrudRestController, self)._before(*args, **kw)
        try:
            c.menu_item = self.menu_item
        except:
            c.menu_item = self.model.__name__

    @expose('sauce.templates.crc.get_delete')
    def get_delete(self, *args, **kw):
        '''This is the code that creates a confirm_delete page'''
        if not self.allow_delete:
            abort(403)
        pks = self.provider.get_primary_fields(self.model)
        kw, d = {}, {}
        for i, pk in  enumerate(pks):
            kw[pk] = args[i]
        for i, arg in enumerate(args):
            d[pks[i]] = arg

        obj = self.provider.delete(self.model, d)
        deps = u'
'
        for k, g in groupby(sorted(o for o in DBSession.deleted if o != obj), lambda x: type(x)):
            deps += u'
' + unicode(k.__name__) + u'
'
            deps += u'
' + u', '.join(sorted(unicode(o) for o in g)) + u'
'
        deps += u'
'

        transaction.doom()

        #obj = self.edit_filler.__provider__.get_obj(self.model, params=kw, fields=self.edit_filler.__fields__)
        pklist = u'/'.join(map(lambda x: unicode(getattr(obj, x)), pks))

        return dict(obj=obj,
            model=self.model.__name__,
            deps=deps,
            pk_count=len(pks), pklist=pklist)

    @staticmethod
    def before_get_all(remainder, params, output):
        # Disable pagination for get_all
        output['value_list'].page_count = 0
        #output['value_list'] = output['value_list'].original_collection
        output['value_list'] = output['value_list'].collection
        c.paginators = []

        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.get_all,
            'mako:sauce.templates.crc.get_all')

        # And respect __search_fields__ as long as tgext.crud doesn't use them
        s = request.controller_state.controller
        if hasattr(s.table, '__search_fields__'):
            output['headers'] = []
            for field in s.table.__search_fields__:
                if isinstance(field, tuple):
                    output['headers'].append((field[0], field[1]))
                else:
                    output['headers'].append((field, field))

        for allow in ('allow_new', 'allow_edit', 'allow_delete'):
            setattr(c, allow, getattr(s, allow, True))

    @staticmethod
    def before_new(remainder, params, output):
        s = request.controller_state.controller
        if not getattr(s, 'allow_new', True):
            abort(403)
        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.new,
            'mako:sauce.templates.crc.new')

    @staticmethod
    def before_edit(remainder, params, output):
        s = request.controller_state.controller
        if not getattr(s, 'allow_edit', True):
            abort(403)
        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.edit,
            'mako:sauce.templates.crc.edit')

    @cached_property
    def mount_point(self):
        return '.'

    @staticmethod
    def injector(remainder, params):
        '''Injects the objects from self.inject into params

        self.inject has to be a dictionary of key, object pairs
        '''
        # Get currently dispatched controller instance
        # Does not work, only returns last statically dispatch controller,
        # but we use _lookup in EventsController
        #s = dispatched_controller()
        s = request.controller_state.controller

        for i in getattr(s, 'inject', []):
            params[i] = s.inject[i]

# Register injection hook for POST requests
before_validate(FilterCrudRestController.injector)(FilterCrudRestController.post)

# Register hook for get_all
before_render(FilterCrudRestController.before_get_all)(FilterCrudRestController.get_all)
# Register hook for new
before_render(FilterCrudRestController.before_new)(FilterCrudRestController.new)
# Register hook for edit
before_render(FilterCrudRestController.before_edit)(FilterCrudRestController.edit)
<commit_msg>Use more intelligent WidgetSelector for TextFields<commit_after># -*- coding: utf-8 -*-
'''
Created on 15.04.2012

@author: moschlar
'''
#
## SAUCE - System for AUtomated Code Evaluation
## Copyright (C) 2013 Moritz Schlarb
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## 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 Affero General Public License for more details.
##
## You should have received a copy of the GNU Affero General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import sys
import logging

import inspect
from itertools import groupby
from webhelpers.html.builder import literal

from tg import expose, tmpl_context as c, request, flash, lurl, abort
from tg.decorators import before_validate, before_call, before_render,\
    cached_property, override_template, with_trailing_slash
from tg.controllers.tgcontroller import TGController
from tgext.crud import CrudRestController, EasyCrudRestController
from tgext.crud.controller import CrudRestControllerHelpers

from sauce.model import DBSession

import tw2.bootstrap.forms as twb
import tw2.jqplugins.chosen.widgets as twjc
import sprox.widgets.tw2widgets.widgets as sw
from sauce.widgets.datagrid import JSSortableDataGrid

from sprox.sa.widgetselector import SAWidgetSelector
from sauce.controllers.crc.provider import FilterSAORMSelector
from sprox.fillerbase import TableFiller, AddFormFiller, EditFormFiller
from sprox.formbase import AddRecordForm, EditableForm

import transaction
from sqlalchemy.exc import IntegrityError, DatabaseError, ProgrammingError
errors = (IntegrityError, DatabaseError, ProgrammingError)

__all__ = ['FilterCrudRestController']

log = logging.getLogger(__name__)

#--------------------------------------------------------------------------------

class ChosenPropertyMultipleSelectField(twjc.ChosenMultipleSelectField, sw.PropertyMultipleSelectField):

    def _validate(self, value, state=None):
        # Fix inspired by twf.MultipleSelectionField
        if value and not isinstance(value, (list, tuple)):
            value = [value]
        return super(ChosenPropertyMultipleSelectField, self)._validate(value, state)

class ChosenPropertySingleSelectField(twjc.ChosenSingleSelectField, sw.PropertySingleSelectField):
    pass

class MyWidgetSelector(SAWidgetSelector):
    text_field_limit = 256
    default_multiple_select_field_widget_type = ChosenPropertyMultipleSelectField
    default_single_select_field_widget_type = ChosenPropertySingleSelectField

    def __init__(self, *args, **kw):
        super(MyWidgetSelector, self).__init__(*args, **kw)
#        self.default_widgets.update({sqlat.DateTime: twb.CalendarDateTimePicker})

    def select(self, field):
        widget = super(MyWidgetSelector, self).select(field)
        if issubclass(widget, sw.TextArea) \
            and hasattr(field.type, 'length') \
            and (field.type.length is None or field.type.length < self.text_field_limit):
            widget = twb.TextField
        return widget

#--------------------------------------------------------------------------------

class CrudIndexController(TGController):

    def __init__(self, *args, **kw):
        super(CrudIndexController, self).__init__(*args, **kw)
        self.helpers = CrudRestControllerHelpers()

    def _before(self, *args, **kw):
        c.title = self.title
        c.menu_items = self.menu_items
        #c.kept_params = self._kept_params()
        c.crud_helpers = self.helpers
        #c.crud_style = self.style

    @with_trailing_slash
    @expose('sauce.templates.crc.index')
    def index(self):
        return dict(page='event')

#--------------------------------------------------------------------------------

class FilterCrudRestController(EasyCrudRestController):
    '''Generic base class for CrudRestControllers with filters'''

    def __init__(self, query_modifier=None, query_modifiers={},
                 menu_items={}, inject={},
                 allow_new=True, allow_edit=True, allow_delete=True,
                 **kw):
        '''Initialize FilteredCrudRestController with given options

        Arguments:

        ``query_modifier``:
            A callable that may modify the base query from the model entity
        ``query_modifiers``:
            A dict of callable that may modify the relationship query from the model entity
            the keys are the remote side classes
        ``menu_items``:
            A dict of menu_items for ``EasyCrudRestController``
        ``inject``:
            A dict of values to inject into POST requests before validation
        ``allow_new``:
            Whether the "New <Entity>" link shall be displayed on get_all
            and the url /<entity/new will be accesible
        ``allow_edit``:
            Whether the "Edit" link shall be displayed in the actions column
            on get_all and the url /<entity/<id>/delete will be accesible
        ``allow_delete``:
            Whether the "Delete" link shall be displayed in the actions column
            on get_all and the url /<entity/<id>/delete will be accesible
        '''

        self.inject = inject

        self.allow_new = allow_new
        self.allow_edit = allow_edit
        self.allow_delete = allow_delete

#        if not hasattr(self, 'table'):
#            class Table(JSSortableTableBase):
#                __entity__ = self.model
#            self.table = Table(DBSession)

        # To effectively disable pagination and fix issues with tgext.crud.util.SmartPaginationCollection
        if not hasattr(self, 'table_filler'):
            class MyTableFiller(TableFiller):
                __entity__ = self.model
                __actions__ = self.custom_actions
                __provider_type_selector_type__ = FilterSAORMSelector
            self.table_filler = MyTableFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_edit and not hasattr(self, 'edit_form'):
            class EditForm(EditableForm):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.edit_form = EditForm(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_edit and not hasattr(self, 'edit_filler'):
            class EditFiller(EditFormFiller):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.edit_filler = EditFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_new and not hasattr(self, 'new_form'):
            class NewForm(AddRecordForm):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.new_form = NewForm(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        if self.allow_new and not hasattr(self, 'new_filler'):
            class NewFiller(AddFormFiller):
                __entity__ = self.model
                __provider_type_selector_type__ = FilterSAORMSelector
            self.new_filler = NewFiller(DBSession,
                query_modifier=query_modifier, query_modifiers=query_modifiers)

        self.__table_options__['__base_widget_type__'] = JSSortableDataGrid
        if '__base_widget_args__' in self.__table_options__:
            if 'headers' in self.__table_options__['__base_widget_args__']:
                self.__table_options__['__base_widget_args__']['headers'].update({0: {'sorter': False}})
            else:
                self.__table_options__['__base_widget_args__'].update({'headers': {0: {'sorter': False}}})
        else:
            self.__table_options__['__base_widget_args__'] = {'headers': {0: {'sorter': False}}}

        self.__form_options__['__base_widget_type__'] = twb.HorizontalForm
        self.__form_options__['__widget_selector__'] = MyWidgetSelector()

        # Since DBSession is a scopedsession we don't need to pass it around,
        # so we just use the imported DBSession here
        super(FilterCrudRestController, self).__init__(DBSession, menu_items)

    def _adapt_menu_items(self, menu_items):
        '''Overwrite from CrudRestController to preserve ordering'''
        adapted_menu_items = type(menu_items)()

        for link, model in menu_items.iteritems():
            if inspect.isclass(model):
                adapted_menu_items[link + 's'] = model.__name__
            else:
                adapted_menu_items[link] = model
        return adapted_menu_items

    def custom_actions(self, obj):
        ''''Display bootstrap-styled action fields respecting the allow_* properties'''
        result = []
        count = 0
        try:
            result.append(u''
                u'')
            count += 1
        except:
            pass
        try:
            primary_fields = self.table_filler.__provider__.get_primary_fields(self.table_filler.__entity__)
            pklist = u'/'.join(map(lambda x: unicode(getattr(obj, x)), primary_fields))
            result.append(u''
                u'')
        except:
            pass
        if self.allow_delete:
            result.append(
                u''
                u'  '
                u'' % (obj.id))
        return literal('
'
            % (len(result) * 30) + ''.join(result) + '
')

    def _before(self, *args, **kw):
        super(FilterCrudRestController, self)._before(*args, **kw)
        try:
            c.menu_item = self.menu_item
        except:
            c.menu_item = self.model.__name__

    @expose('sauce.templates.crc.get_delete')
    def get_delete(self, *args, **kw):
        '''This is the code that creates a confirm_delete page'''
        if not self.allow_delete:
            abort(403)
        pks = self.provider.get_primary_fields(self.model)
        kw, d = {}, {}
        for i, pk in  enumerate(pks):
            kw[pk] = args[i]
        for i, arg in enumerate(args):
            d[pks[i]] = arg

        obj = self.provider.delete(self.model, d)
        deps = u'
'
        for k, g in groupby(sorted(o for o in DBSession.deleted if o != obj), lambda x: type(x)):
            deps += u'
' + unicode(k.__name__) + u'
'
            deps += u'
' + u', '.join(sorted(unicode(o) for o in g)) + u'
'
        deps += u'
'

        transaction.doom()

        #obj = self.edit_filler.__provider__.get_obj(self.model, params=kw, fields=self.edit_filler.__fields__)
        pklist = u'/'.join(map(lambda x: unicode(getattr(obj, x)), pks))

        return dict(obj=obj,
            model=self.model.__name__,
            deps=deps,
            pk_count=len(pks), pklist=pklist)

    @staticmethod
    def before_get_all(remainder, params, output):
        # Disable pagination for get_all
        output['value_list'].page_count = 0
        #output['value_list'] = output['value_list'].original_collection
        output['value_list'] = output['value_list'].collection
        c.paginators = []

        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.get_all,
            'mako:sauce.templates.crc.get_all')

        # And respect __search_fields__ as long as tgext.crud doesn't use them
        s = request.controller_state.controller
        if hasattr(s.table, '__search_fields__'):
            output['headers'] = []
            for field in s.table.__search_fields__:
                if isinstance(field, tuple):
                    output['headers'].append((field[0], field[1]))
                else:
                    output['headers'].append((field, field))

        for allow in ('allow_new', 'allow_edit', 'allow_delete'):
            setattr(c, allow, getattr(s, allow, True))

    @staticmethod
    def before_new(remainder, params, output):
        s = request.controller_state.controller
        if not getattr(s, 'allow_new', True):
            abort(403)
        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.new,
            'mako:sauce.templates.crc.new')

    @staticmethod
    def before_edit(remainder, params, output):
        s = request.controller_state.controller
        if not getattr(s, 'allow_edit', True):
            abort(403)
        # Use my bootstrap-enabled template
        override_template(FilterCrudRestController.edit,
            'mako:sauce.templates.crc.edit')

    @cached_property
    def mount_point(self):
        return '.'

    @staticmethod
    def injector(remainder, params):
        '''Injects the objects from self.inject into params

        self.inject has to be a dictionary of key, object pairs
        '''
        # Get currently dispatched controller instance
        # Does not work, only returns last statically dispatch controller,
        # but we use _lookup in EventsController
        #s = dispatched_controller()
        s = request.controller_state.controller

        for i in getattr(s, 'inject', []):
            params[i] = s.inject[i]

# Register injection hook for POST requests
before_validate(FilterCrudRestController.injector)(FilterCrudRestController.post)

# Register hook for get_all
before_render(FilterCrudRestController.before_get_all)(FilterCrudRestController.get_all)
# Register hook for new
before_render(FilterCrudRestController.before_new)(FilterCrudRestController.new)
# Register hook for edit
before_render(FilterCrudRestController.before_edit)(FilterCrudRestController.edit)
<|endoftext|>


<commit_before><commit_msg>fix a few things<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env python
"""
Test of shake with zero bond length.

"""

from simtk import openmm
from simtk import unit
from simtk.openmm import app
import copy
import numpy as np
from openmmtools import testsystems

# Set conditions for simulation.
# Roughly corresponds to conditions from http://www.cstl.nist.gov/srs/LJ_PURE/mc.htm
nparticles = 500
mass = 39.9 * unit.amu
sigma = 3.4 * unit.angstrom
epsilon = 0.238 * unit.kilocalories_per_mole
#reduced_density = 0.860     # reduced_density = density * (sigma**3)
reduced_density = 0.960     # reduced_density = density * (sigma**3)
reduced_temperature = 0.850 # reduced_temperature = kB * temperature / epsilon
reduced_pressure = 1.2660   # reduced_pressure = pressure * (sigma**3) / epsilon

platform_name = 'CPU'    # OpenMM platform name to use for simulation
platform = openmm.Platform.getPlatformByName(platform_name)

r0 = 2.0**(1./6.) * sigma   # minimum potential distance for Lennard-Jones interaction
characteristic_timescale = unit.sqrt((mass * r0**2) / (72 * epsilon)) # characteristic timescale for bound Lennard-Jones interaction
                                                            # http://borisv.lk.net/matsc597c-1997/simulations/Lecture5/node3.html
timestep = 0.01 * characteristic_timescale # integrator timestep

# From http://www.cstl.nist.gov/srs/LJ_PURE/md.htm
#characteristic_timescale = unit.sqrt(mass * sigma**2 / epsilon)
#timestep = 0.05 * characteristic_timescale

print "characteristic timescale = %.3f ps" % (characteristic_timescale / unit.picoseconds)
print "timestep = %.12f ps" % (timestep / unit.picoseconds)

collision_rate = 5.0 / unit.picoseconds # collision rate for Langevin thermostat
barostat_frequency = 25 # number of steps between barostat updates

# Set parameters for number of simulation replicates, number of iterations per simulation, and number of steps per iteration.
nreplicates = 100
niterations = 10000
nsteps_per_iteration = 25

# Compute real units.
kB = unit.BOLTZMANN_CONSTANT_kB * unit.AVOGADRO_CONSTANT_NA
density = reduced_density / (sigma**3)
temperature = reduced_temperature * epsilon / kB
pressure = reduced_pressure * epsilon / (sigma**3)
kT = kB * temperature

# Create the Lennard-Jones fluid.
testsystem = testsystems.LennardJonesFluid(nparticles=nparticles, mass=mass, sigma=sigma, epsilon=epsilon, reduced_density=reduced_density)

# Move two particles on top of each other.
print "Modifying positions..."
positions = testsystem.positions
positions[1,:] = positions[0,:]
print positions

# Add exclusion
master_system = testsystem.system
print "Adding exclusion..."
forces = { master_system.getForce(index).__class__.__name__ : master_system.getForce(index) for index in range(master_system.getNumForces()) }
force = forces['NonbondedForce']
chargeProd = 0.0 * unit.elementary_charge**2
sigma = 1.0 * unit.angstroms
epsilon = 0.0 * unit.kilocalories_per_mole
force.addException(0, 1, chargeProd, sigma, epsilon)

# Add constraint.
distance = 0.0 * unit.angstroms
master_system.addConstraint(0, 1, distance)

# Construct initial positions by minimization.
print "Minimizing to obtain initial positions..."
integrator = openmm.LangevinIntegrator(temperature, collision_rate, timestep)
context = openmm.Context(master_system, integrator)
context.setPositions(positions)
openmm.LocalEnergyMinimizer.minimize(context)
state = context.getState(getPositions=True)
initial_positions = state.getPositions(asNumpy=True)
del context, integrator, state

# Run replicates of the simulation.
for replicate in range(nreplicates):
    # Make a new copy of the system.
    print "Making a deep copy of the system..."
    system = copy.deepcopy(master_system)

    # Add a barostat to the system.
    # NOTE: This is added to a new copy of the system to ensure barostat random number seeds are unique.
    print "Adding barostat..."
    barostat = openmm.MonteCarloBarostat(pressure, temperature, barostat_frequency)
    system.addForce(barostat)

    # Create integrator
    print "Creating LangevinIntegrator..."
    integrator = openmm.LangevinIntegrator(temperature, collision_rate, timestep)

    # Create context.
    print "Creating Context..."
    context = openmm.Context(system, integrator, platform)

    # Set initial conditions.
    print "Setting initial positions..."
    context.setPositions(initial_positions)
    print "Setting initial velocities appropriate for temperature..."
    context.setVelocitiesToTemperature(temperature)

    # Record initial data.
    state = context.getState(getEnergy=True)
    reduced_volume = state.getPeriodicBoxVolume() / (nparticles * sigma**3)
    reduced_density = 1.0 / reduced_volume
    reduced_potential = state.getPotentialEnergy() / kT
    print "replicate %5d / %5d : initial                 : density %8.3f | potential %8.3f" % (replicate, nreplicates, reduced_density, reduced_potential)

    # Run simulation.
    for iteration in range(niterations):
        # Integrate the simulation.
        integrator.step(nsteps_per_iteration)

        # Record data.
        state = context.getState(getEnergy=True)
        reduced_volume = state.getPeriodicBoxVolume() / (nparticles * sigma**3)
        reduced_density = 1.0 / reduced_volume
        reduced_potential = state.getPotentialEnergy() / kT

        if ((iteration + 1) % 100) == 0:
            print "replicate %5d / %5d : iteration %5d / %5d : density %8.3f | potential %8.3f" % (replicate, nreplicates, iteration+1, niterations, reduced_density, reduced_potential)

    # Clean up.
    del context, integrator

    print ""

<commit_msg>Removed accidentally added file.<commit_after><|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import

__version__ = '0.8.2'

from .formatters import (
    format_as_html,
    format_html_styles,
    format_as_text,
    format_as_dict,
)
from .explain import explain_weights, explain_prediction
from .sklearn import explain_weights_sklearn, explain_prediction_sklearn
from .transform import transform_feature_names

try:
    from .ipython import show_weights, show_prediction
except ImportError:
    pass  # IPython is not installed

try:
    from .formatters.as_dataframe import (
        explain_weights_df, explain_weights_dfs,
        explain_prediction_df, explain_prediction_dfs,
        format_as_dataframe, format_as_dataframes,
    )
except ImportError:
    pass  # pandas not available

try:
    from .lightning import (
        explain_prediction_lightning,
        explain_weights_lightning
    )
except ImportError as e:
    # lightning is not available
    pass

try:
    from .sklearn_crfsuite import (
        explain_weights_sklearn_crfsuite
    )
except ImportError as e:
    # sklearn-crfsuite is not available
    pass

try:
    from .xgboost import (
        explain_weights_xgboost,
        explain_prediction_xgboost
    )
except ImportError:
    # xgboost is not available
    pass
except Exception as e:
    if e.__class__.__name__ == 'XGBoostLibraryNotFound':
        # improperly installed xgboost
        pass
    else:
        raise

try:
    from .lightgbm import (
        explain_weights_lightgbm,
        explain_prediction_lightgbm
    )
except ImportError:
    # lightgbm is not available
    pass<commit_msg>Catch improperly installed LightGBM import exceptions<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import

__version__ = '0.8.2'

from .formatters import (
    format_as_html,
    format_html_styles,
    format_as_text,
    format_as_dict,
)
from .explain import explain_weights, explain_prediction
from .sklearn import explain_weights_sklearn, explain_prediction_sklearn
from .transform import transform_feature_names

try:
    from .ipython import show_weights, show_prediction
except ImportError:
    pass  # IPython is not installed

try:
    from .formatters.as_dataframe import (
        explain_weights_df, explain_weights_dfs,
        explain_prediction_df, explain_prediction_dfs,
        format_as_dataframe, format_as_dataframes,
    )
except ImportError:
    pass  # pandas not available

try:
    from .lightning import (
        explain_prediction_lightning,
        explain_weights_lightning
    )
except ImportError as e:
    # lightning is not available
    pass

try:
    from .sklearn_crfsuite import (
        explain_weights_sklearn_crfsuite
    )
except ImportError as e:
    # sklearn-crfsuite is not available
    pass

try:
    from .xgboost import (
        explain_weights_xgboost,
        explain_prediction_xgboost
    )
except ImportError:
    # xgboost is not available
    pass
except Exception as e:
    if e.__class__.__name__ == 'XGBoostLibraryNotFound':
        # improperly installed xgboost
        pass
    else:
        raise

try:
    from .lightgbm import (
        explain_weights_lightgbm,
        explain_prediction_lightgbm
    )
except ImportError:
    # lightgbm is not available
    pass
except OSError:
    # improperly installed lightgbm
    pass
except Exception as e:
    if e.__class__.__name__ == 'LightGBMError':
        # improperly installed lightgbm
        pass
    else:
        raise<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import numpy as np

class DE:
    def __init__(self, fobj, bounds, mutation=(0.5, 1.0), crossover=0.7, maxiters=1000,
                 self_adaptive=False, popsize=None, seed=None):
        self.adaptive = self_adaptive
        # Indicates the number of extra parameters in an individual that are not used for evaluating
        # If extra_params = d, discards the last d elements from an individual prior to evaluation.
        self.extra_params = 0
        # If self-adaptive, include mutation and crossover as two new variables
        bnd = list(bounds)
        if self_adaptive:
            # TODO: Use the provided mutation values for the bounds
            bnd.extend([(0, 1)] * 2)
            self.extra_params = 2
        B = np.asarray(bnd).T
        self._MIN = B[0]
        self._MAX = B[1]
        self._DIFF = np.fabs(self._MAX - self._MIN)
        self.dims = len(bnd)
        self.crs = crossover
        self.fobj = fobj
        self.maxiters = maxiters
        self.mutation = mutation
        if popsize is None:
            self.popsize = self.dims * 15
        else:
            self.popsize = popsize
        # Initialize random state
        if seed is None:
            self.rnd = np.random.RandomState()
        elif isinstance(seed, np.random.RandomState):
            self.rnd = seed
        else:
            self.rnd = np.random.RandomState(seed)
        # Default functions
        self.crossover = getattr(self, '_binomial_crossover')
        self.mutate = getattr(self, '_rand1')
        self.repair = getattr(self, '_random_repair')
        self.init = getattr(self, '_random_init')

    def _sample(self, exclude_index, P, size):
        idx = [i for i in range(len(P)) if i != exclude_index]
        selected = np.random.choice(idx, size, replace=False)
        return P[selected]

    def _eval_population(self, P):
        # Denormalize population matrix to obtain the scaled parameters
        PD = self._denorm(P)
        if self.extra_params > 0:
            PD = PD[:, :-self.extra_params]
        return [self.fobj(ind) for ind in PD]

    def _eval(self, ind):
        p = self._denorm(ind)
        if self.extra_params > 0:
            p = p[:-self.extra_params]
        return self.fobj(p)

    def _rand1(self, target, P, mutation_factor):
        a, b, c = self._sample(target, P, 3)
        return a + mutation_factor * (b - c)

    def __iter__(self):
        # Initialize a random population of solutions
        P = self.init()
        fitness = self._eval_population(P)
        best_fitness = min(fitness)
        best_idx = np.argmin(fitness)
        while True:
            # Apply dithering on each iteration
            f = np.random.uniform(min(self.mutation), max(self.mutation))
            crs = self.crs
            for i in range(self.popsize):
                target = P[i]
                if self.adaptive:
                    # Denormalize and read the values for the mutation and crossover
                    dt = self._denorm(target)
                    f, crs = dt[-2:]
                # Create a mutant using a base vector
                mutant = self.mutate(i, P, f)
                # Repair the individual if a gene is out of bounds
                z = self.repair(self.crossover(target, mutant, crs))
                new_fitness = self._eval(z)
                if new_fitness < best_fitness:
                    best_fitness = new_fitness
                    best_idx = i
                if new_fitness < fitness[i]:
                    # The new solution is better, replace
                    P[i] = z
                    fitness[i] = new_fitness
            yield P, fitness, best_idx

    def iterator(self, denormalize=True):
        for P, fitness, idx in self:
            pop = self._denorm(P) if denormalize else P
            yield pop, fitness, idx

    def solve(self, show_progress=False):
        if show_progress:
            from tqdm import tqdm
            iterator = tqdm(self, total=self.maxiters, desc='Optimizing (DE)')
        else:
            iterator = self
        step = 0
        for P, fitness, idx in iterator:
            step += 1
            if step > self.maxiters:
                if show_progress:
                    iterator.n = self.maxiters
                    iterator.refresh()
                    iterator.close()
                return self._denorm(P[idx]), fitness[idx]

    def _denorm(self, P):
        return self._MIN + P * self._DIFF

    def _binomial_crossover(self, target, mutant, probability):
        z = np.copy(target)
        n = len(z)
        k = self.rnd.randint(0, n)
        for i in range(n):
            if self.rnd.uniform() <= probability or i == k:
                # transfer gene from mutant
                z[i] = mutant[i]
        return z

    def _random_repair(self, x):
        for i in range(len(x)):
            if x[i] < 0 or x[i] > 1:
                x[i] = self.rnd.uniform()
        return x

    def _bound_repair(self, x):
        return np.clip(x, 0, 1)

    def _lhs_init(self):
        pass

    def _random_init(self):
        return self.rnd.rand(self.popsize, self.dims)

class PDE(DE):
    def __init__(self, fobj, bounds, mutation=(0.5, 1.0), crossover=0.7,
                 maxiters=1000, self_adaptive=False, popsize=None, seed=None, processes=None, chunksize=None):
        super().__init__(fobj, bounds, mutation, crossover, maxiters, self_adaptive, popsize, seed)
        from multiprocessing import Pool
        self.pool = Pool(processes=processes)
        self.chunksize = chunksize

    def __iter__(self):
        # Initialize a random population of solutions
        P = self.init()
        fitness = self._eval_population(P)
        best_fitness = min(fitness)
        best_idx = np.argmin(fitness)
        crs = self.crs
        while True:
            # Apply dithering on each iteration
            f = np.random.uniform(min(self.mutation), max(self.mutation))
            # Create mutants
            mutants = []
            for i in range(self.popsize):
                target = P[i]
                if self.adaptive:
                    # Denormalize and read the values for the mutation and crossover
                    dt = self._denorm(target)
                    f, crs = dt[-2:]
                # Create a mutant using a base vector
                mutant = self.mutate(i, P, f)
                # Repair the individual if a gene is out of bounds
                z = self.repair(self.crossover(target, mutant, crs))
                mutants.append(z)
            # Evaluate in parallel
            new_fitness = self._eval_population(mutants)
            # Replace if better
            for i in range(self.popsize):
                if new_fitness[i] < fitness[i]:
                    P[i] = mutants[i]
                    fitness[i] = new_fitness[i]
                if new_fitness[i] < best_fitness:
                    best_fitness = new_fitness[i]
                    best_idx = i
            yield P, fitness, best_idx

    def _eval_population(self, P):
        # Denormalize population matrix to obtain the scaled parameters
        PD = self._denorm(P)
        return list(self.pool.map(self.fobj, PD, chunksize=self.chunksize))
<commit_msg>Add name param to DE/PDE<commit_after># -*- coding: utf-8 -*-
import numpy as np

class DE:
    def __init__(self, fobj, bounds, mutation=(0.5, 1.0), crossover=0.7, maxiters=1000,
                 self_adaptive=False, popsize=None, seed=None):
        self.adaptive = self_adaptive
        # Indicates the number of extra parameters in an individual that are not used for evaluating
        # If extra_params = d, discards the last d elements from an individual prior to evaluation.
        self.extra_params = 0
        # If self-adaptive, include mutation and crossover as two new variables
        bnd = list(bounds)
        if self_adaptive:
            # TODO: Use the provided mutation values for the bounds
            bnd.extend([(0, 1)] * 2)
            self.extra_params = 2
        B = np.asarray(bnd).T
        self._MIN = B[0]
        self._MAX = B[1]
        self._DIFF = np.fabs(self._MAX - self._MIN)
        self.dims = len(bnd)
        self.crs = crossover
        self.fobj = fobj
        self.maxiters = maxiters
        self.mutation = mutation
        if popsize is None:
            self.popsize = self.dims * 15
        else:
            self.popsize = popsize
        # Initialize random state
        if seed is None:
            self.rnd = np.random.RandomState()
        elif isinstance(seed, np.random.RandomState):
            self.rnd = seed
        else:
            self.rnd = np.random.RandomState(seed)
        # Default functions
        self.crossover = getattr(self, '_binomial_crossover')
        self.mutate = getattr(self, '_rand1')
        self.repair = getattr(self, '_random_repair')
        self.init = getattr(self, '_random_init')
        self.name = 'DE'

    def _sample(self, exclude_index, P, size):
        idx = [i for i in range(len(P)) if i != exclude_index]
        selected = np.random.choice(idx, size, replace=False)
        return P[selected]

    def _eval_population(self, P):
        # Denormalize population matrix to obtain the scaled parameters
        PD = self._denorm(P)
        if self.extra_params > 0:
            PD = PD[:, :-self.extra_params]
        return [self.fobj(ind) for ind in PD]

    def _eval(self, ind):
        p = self._denorm(ind)
        if self.extra_params > 0:
            p = p[:-self.extra_params]
        return self.fobj(p)

    def _rand1(self, target, P, mutation_factor):
        a, b, c = self._sample(target, P, 3)
        return a + mutation_factor * (b - c)

    def __iter__(self):
        # Initialize a random population of solutions
        P = self.init()
        fitness = self._eval_population(P)
        best_fitness = min(fitness)
        best_idx = np.argmin(fitness)
        while True:
            # Apply dithering on each iteration
            f = np.random.uniform(min(self.mutation), max(self.mutation))
            crs = self.crs
            for i in range(self.popsize):
                target = P[i]
                if self.adaptive:
                    # Denormalize and read the values for the mutation and crossover
                    dt = self._denorm(target)
                    f, crs = dt[-2:]
                # Create a mutant using a base vector
                mutant = self.mutate(i, P, f)
                # Repair the individual if a gene is out of bounds
                z = self.repair(self.crossover(target, mutant, crs))
                new_fitness = self._eval(z)
                if new_fitness < best_fitness:
                    best_fitness = new_fitness
                    best_idx = i
                if new_fitness < fitness[i]:
                    # The new solution is better, replace
                    P[i] = z
                    fitness[i] = new_fitness
            yield P, fitness, best_idx

    def iterator(self, denormalize=True):
        for P, fitness, idx in self:
            pop = self._denorm(P) if denormalize else P
            yield pop, fitness, idx

    def solve(self, show_progress=False):
        if show_progress:
            from tqdm import tqdm
            iterator = tqdm(self, total=self.maxiters, desc='Optimizing ({0})'.format(self.name))
        else:
            iterator = self
        step = 0
        for P, fitness, idx in iterator:
            step += 1
            if step > self.maxiters:
                if show_progress:
                    iterator.n = self.maxiters
                    iterator.refresh()
                    iterator.close()
                return self._denorm(P[idx]), fitness[idx]

    def _denorm(self, P):
        return self._MIN + P * self._DIFF

    def _binomial_crossover(self, target, mutant, probability):
        z = np.copy(target)
        n = len(z)
        k = self.rnd.randint(0, n)
        for i in range(n):
            if self.rnd.uniform() <= probability or i == k:
                # transfer gene from mutant
                z[i] = mutant[i]
        return z

    def _random_repair(self, x):
        for i in range(len(x)):
            if x[i] < 0 or x[i] > 1:
                x[i] = self.rnd.uniform()
        return x

    def _bound_repair(self, x):
        return np.clip(x, 0, 1)

    def _lhs_init(self):
        pass

    def _random_init(self):
        return self.rnd.rand(self.popsize, self.dims)

class PDE(DE):
    def __init__(self, fobj, bounds, mutation=(0.5, 1.0), crossover=0.7,
                 maxiters=1000, self_adaptive=False, popsize=None, seed=None, processes=None, chunksize=None):
        super().__init__(fobj, bounds, mutation, crossover, maxiters, self_adaptive, popsize, seed)
        from multiprocessing import Pool
        self.pool = Pool(processes=processes)
        self.chunksize = chunksize
        self.name = 'Parallel DE'

    def __iter__(self):
        # Initialize a random population of solutions
        P = self.init()
        fitness = self._eval_population(P)
        best_fitness = min(fitness)
        best_idx = np.argmin(fitness)
        crs = self.crs
        while True:
            # Apply dithering on each iteration
            f = np.random.uniform(min(self.mutation), max(self.mutation))
            # Create mutants
            mutants = []
            for i in range(self.popsize):
                target = P[i]
                if self.adaptive:
                    # Denormalize and read the values for the mutation and crossover
                    dt = self._denorm(target)
                    f, crs = dt[-2:]
                # Create a mutant using a base vector
                mutant = self.mutate(i, P, f)
                # Repair the individual if a gene is out of bounds
                z = self.repair(self.crossover(target, mutant, crs))
                mutants.append(z)
            # Evaluate in parallel
            new_fitness = self._eval_population(mutants)
            # Replace if better
            for i in range(self.popsize):
                if new_fitness[i] < fitness[i]:
                    P[i] = mutants[i]
                    fitness[i] = new_fitness[i]
                if new_fitness[i] < best_fitness:
                    best_fitness = new_fitness[i]
                    best_idx = i
            yield P, fitness, best_idx

    def _eval_population(self, P):
        # Denormalize population matrix to obtain the scaled parameters
        PD = self._denorm(P)
        return list(self.pool.map(self.fobj, PD, chunksize=self.chunksize))
<|endoftext|>