<commit_before># pyenchant
#
# Copyright (C) 2004-2008 Ryan Kelly
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# In addition, as a special exception, you are
# given permission to link the code of this program with
# non-LGPL Spelling Provider libraries (eg: a MSFT Office
# spell checker backend) and distribute linked combinations including
# the two.  You must obey the GNU Lesser General Public License in all
# respects for all of the code used other than said providers.  If you modify
# this file, you may extend this exception to your version of the
# file, but you are not obligated to do so.  If you do not wish to
# do so, delete this exception statement from your version.
#
"""

    enchant.utils:    Misc utilities for the enchant package

    This module provides miscellaneous utilities for use with the
    enchant spellchecking package.  Currently available functionality
    includes:

        * string/unicode compatibility wrappers
        * functions for dealing with locale/language settings
        * ability to list supporting data files (win32 only)

"""

import os
import sys

from enchant.errors import *

# Attempt to access local language information
try:
    import locale
except ImportError:
    locale = None

#
#  Unicode/Bytes compatabilty wrappers.
#
#  These allow us to support both Python 2.x and Python 3.x from
#  the same codebase.
#
#  We provide explicit type objects "bytes" and "unicode" that can be
#  used to construct instances of the appropriate type.  The class
#  "EnchantStr" derives from the default "str" type and implements the
#  necessary logic for encoding/decoding as strings are passed into
#  the underlying C library (where they must always be utf-8 encoded
#  byte strings).
#

try:
    unicode = unicode
except NameError:
    str = str
    unicode = str
    bytes = bytes
    basestring = (str,bytes)
else:
    str = str
    unicode = unicode
    bytes = str
    basestring = basestring

def raw_unicode(raw):
    """Make a unicode string from a raw string.

    This function takes a string containing unicode escape characters,
    and returns the corresponding unicode string.  Useful for writing
    unicode string literals in your python source while being upwards-
    compatible with Python 3.  For example, instead of doing this:

      s = u"hello\u2149"  # syntax error in Python 3

    Or this:

      s = "hello\u2149"   # not what you want in Python 2.x

    You can do this:

      s = raw_unicode(r"hello\u2149")  # works everywhere!

    """
    return raw.encode("ascii").decode("unicode-escape")

class EnchantStr(str):
    """String subclass for interfacing with enchant C library.

    This class encapsulates the logic for interfacing between python native
    string/unicode objects and the underlying enchant library, which expects
    all strings to be UTF-8 character arrays.  It is a subclass of the
    default string class 'str' - on Python 2.x that makes it an ascii string,
    on Python 3.x it is a unicode object.

    Initialise it with a string or unicode object, and use the encode() method
    to obtain an object suitable for passing to the underlying C library.
    When strings are read back into python, use decode(s) to translate them
    back into the appropriate python-level string type.

    This allows us to following the common Python 2.x idiom of returning
    unicode when unicode is passed in, and byte strings otherwise.  It also
    lets the interface be upwards-compatible with Python 3, in which string
    objects are unicode by default.
    """

    def __new__(cls,value):
        """EnchantStr data constructor.

        This method records whether the initial string was unicode, then
        simply passes it along to the default string constructor.
        """
        if type(value) is unicode:
            was_unicode = True
            if str is not unicode:
                value = value.encode("utf-8")
        else:
            was_unicode = False
            if str is not bytes:
                raise Error("Don't pass bytestrings to pyenchant")
        self = str.__new__(cls,value)
        self._was_unicode = was_unicode
        return self

    def encode(self):
        """Encode this string into a form usable by the enchant C library."""
        if str is unicode:
          return str.encode(self,"utf-8")
        else:
          return self

    def decode(self,value):
        """Decode a string returned by the enchant C library."""
        if self._was_unicode:
          if str is unicode:
            # TODO: why does ctypes convert c_char_p to str(),
            #       rather than to bytes()?
            return value.encode().decode("utf-8")
          else:
            return value.decode("utf-8")
        else:
          return value

def get_default_language(default=None):
    """Determine the user's default language, if possible.

    This function uses the 'locale' module to try to determine
    the user's preferred language.  The return value is as
    follows:

        * if a locale is available for the LC_MESSAGES category,
          that language is used
        * if a default locale is available, that language is used
        * if the keyword argument <default> is given, it is used
        * None

    Note that determining the user's language is in general only
    possible if they have set the necessary environment variables
    on their system.
    """
    try:
        import locale
        tag = locale.getlocale()[0]
        if tag is None:
            tag = locale.getdefaultlocale()[0]
            if tag is None:
                raise Error("No default language available")
        return tag
    except:
        pass
    return default
get_default_language._DOC_ERRORS = ["LC"]

def get_resource_filename(resname):
    """Get the absolute path to the named resource file.

    This serves widely the same purpose as pkg_resources.resource_filename(),
    but tries to avoid loading pkg_resources unless we're actually in
    an egg.
    """
    path = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(path,resname)
    if os.path.exists(path):
        return path
    if hasattr(sys, "frozen"):
        exe_dir = os.path.dirname(unicode(sys.executable,sys.getfilesystemencoding()))
        path = os.path.join(exe_dir, resname)
        if os.path.exists(path):
            return path
    else:
        import pkg_resources
        return pkg_resources.resource_filename("enchant",resname)
    raise Error("Could not locate resource '%s'" % (resname,))

def win32_data_files():
    """Get list of supporting data files, for use with setup.py

    This function returns a list of the supporting data files available
    to the running version of PyEnchant.  This is in the format expected
    by the data_files argument of the distutils setup function.  It's
    very useful, for example, for including the data files in an executable
    produced by py2exe.

    Only really tested on the win32 platform (it's the only platform for
    which we ship our own supporting data files)
    """
    #  Include the main enchant DLL
    libEnchant = get_resource_filename("libenchant.dll")
    mainDir = os.path.dirname(libEnchant)
    dataFiles = [('',[libEnchant])]
    #  And some specific supporting DLLs
    for dll in os.listdir(mainDir):
        if not dll.endswith(".dll"):
            continue
        for prefix in ("iconv","intl","libglib","libgmodule"):
            if dll.startswith(prefix):
                break
        else:
            continue
        dataFiles[0][1].append(os.path.join(mainDir,dll))
    #  And anything found in the supporting data directories
    dataDirs = ("share/enchant/myspell","share/enchant/ispell","lib/enchant")
    for dataDir in dataDirs:
        files = []
        fullDir = os.path.join(mainDir,os.path.normpath(dataDir))
        for fn in os.listdir(fullDir):
            fullFn = os.path.join(fullDir,fn)
            if os.path.isfile(fullFn):
                files.append(fullFn)
        dataFiles.append((dataDir,files))
    return dataFiles
win32_data_files._DOC_ERRORS = ["py","py","exe"]

<commit_msg>add raw_bytes function<commit_after># pyenchant
#
# Copyright (C) 2004-2008 Ryan Kelly
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# In addition, as a special exception, you are
# given permission to link the code of this program with
# non-LGPL Spelling Provider libraries (eg: a MSFT Office
# spell checker backend) and distribute linked combinations including
# the two.  You must obey the GNU Lesser General Public License in all
# respects for all of the code used other than said providers.  If you modify
# this file, you may extend this exception to your version of the
# file, but you are not obligated to do so.  If you do not wish to
# do so, delete this exception statement from your version.
#
"""

    enchant.utils:    Misc utilities for the enchant package

    This module provides miscellaneous utilities for use with the
    enchant spellchecking package.  Currently available functionality
    includes:

        * string/unicode compatibility wrappers
        * functions for dealing with locale/language settings
        * ability to list supporting data files (win32 only)

"""

import os
import sys
import codecs

from enchant.errors import *

# Attempt to access local language information
try:
    import locale
except ImportError:
    locale = None

#
#  Unicode/Bytes compatabilty wrappers.
#
#  These allow us to support both Python 2.x and Python 3.x from
#  the same codebase.
#
#  We provide explicit type objects "bytes" and "unicode" that can be
#  used to construct instances of the appropriate type.  The class
#  "EnchantStr" derives from the default "str" type and implements the
#  necessary logic for encoding/decoding as strings are passed into
#  the underlying C library (where they must always be utf-8 encoded
#  byte strings).
#

try:
    unicode = unicode
except NameError:
    str = str
    unicode = str
    bytes = bytes
    basestring = (str,bytes)
else:
    str = str
    unicode = unicode
    bytes = str
    basestring = basestring

def raw_unicode(raw):
    """Make a unicode string from a raw string.

    This function takes a string containing unicode escape characters,
    and returns the corresponding unicode string.  Useful for writing
    unicode string literals in your python source while being upwards-
    compatible with Python 3.  For example, instead of doing this:

      s = u"hello\u2149"  # syntax error in Python 3

    Or this:

      s = "hello\u2149"   # not what you want in Python 2.x

    You can do this:

      s = raw_unicode(r"hello\u2149")  # works everywhere!

    """
    return raw.encode("ascii").decode("unicode-escape")

def raw_bytes(raw):
    """Make a bytes object out of a raw string.

    This is analogous to raw_unicode, but processes byte escape characters
    to produce a bytes object.
    """
    return codecs.escape_decode(raw)[0]

class EnchantStr(str):
    """String subclass for interfacing with enchant C library.

    This class encapsulates the logic for interfacing between python native
    string/unicode objects and the underlying enchant library, which expects
    all strings to be UTF-8 character arrays.  It is a subclass of the
    default string class 'str' - on Python 2.x that makes it an ascii string,
    on Python 3.x it is a unicode object.

    Initialise it with a string or unicode object, and use the encode() method
    to obtain an object suitable for passing to the underlying C library.
    When strings are read back into python, use decode(s) to translate them
    back into the appropriate python-level string type.

    This allows us to following the common Python 2.x idiom of returning
    unicode when unicode is passed in, and byte strings otherwise.  It also
    lets the interface be upwards-compatible with Python 3, in which string
    objects are unicode by default.
    """

    def __new__(cls,value):
        """EnchantStr data constructor.

        This method records whether the initial string was unicode, then
        simply passes it along to the default string constructor.
        """
        if type(value) is unicode:
            was_unicode = True
            if str is not unicode:
                value = value.encode("utf-8")
        else:
            was_unicode = False
            if str is not bytes:
                raise Error("Don't pass bytestrings to pyenchant")
        self = str.__new__(cls,value)
        self._was_unicode = was_unicode
        return self

    def encode(self):
        """Encode this string into a form usable by the enchant C library."""
        if str is unicode:
          return str.encode(self,"utf-8")
        else:
          return self

    def decode(self,value):
        """Decode a string returned by the enchant C library."""
        if self._was_unicode:
          if str is unicode:
            # TODO: why does ctypes convert c_char_p to str(),
            #       rather than to bytes()?
            return value.encode().decode("utf-8")
          else:
            return value.decode("utf-8")
        else:
          return value

def get_default_language(default=None):
    """Determine the user's default language, if possible.

    This function uses the 'locale' module to try to determine
    the user's preferred language.  The return value is as
    follows:

        * if a locale is available for the LC_MESSAGES category,
          that language is used
        * if a default locale is available, that language is used
        * if the keyword argument <default> is given, it is used
        * None

    Note that determining the user's language is in general only
    possible if they have set the necessary environment variables
    on their system.
    """
    try:
        import locale
        tag = locale.getlocale()[0]
        if tag is None:
            tag = locale.getdefaultlocale()[0]
            if tag is None:
                raise Error("No default language available")
        return tag
    except:
        pass
    return default
get_default_language._DOC_ERRORS = ["LC"]

def get_resource_filename(resname):
    """Get the absolute path to the named resource file.

    This serves widely the same purpose as pkg_resources.resource_filename(),
    but tries to avoid loading pkg_resources unless we're actually in
    an egg.
    """
    path = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(path,resname)
    if os.path.exists(path):
        return path
    if hasattr(sys, "frozen"):
        exe_dir = os.path.dirname(unicode(sys.executable,sys.getfilesystemencoding()))
        path = os.path.join(exe_dir, resname)
        if os.path.exists(path):
            return path
    else:
        import pkg_resources
        return pkg_resources.resource_filename("enchant",resname)
    raise Error("Could not locate resource '%s'" % (resname,))

def win32_data_files():
    """Get list of supporting data files, for use with setup.py

    This function returns a list of the supporting data files available
    to the running version of PyEnchant.  This is in the format expected
    by the data_files argument of the distutils setup function.  It's
    very useful, for example, for including the data files in an executable
    produced by py2exe.

    Only really tested on the win32 platform (it's the only platform for
    which we ship our own supporting data files)
    """
    #  Include the main enchant DLL
    libEnchant = get_resource_filename("libenchant.dll")
    mainDir = os.path.dirname(libEnchant)
    dataFiles = [('',[libEnchant])]
    #  And some specific supporting DLLs
    for dll in os.listdir(mainDir):
        if not dll.endswith(".dll"):
            continue
        for prefix in ("iconv","intl","libglib","libgmodule"):
            if dll.startswith(prefix):
                break
        else:
            continue
        dataFiles[0][1].append(os.path.join(mainDir,dll))
    #  And anything found in the supporting data directories
    dataDirs = ("share/enchant/myspell","share/enchant/ispell","lib/enchant")
    for dataDir in dataDirs:
        files = []
        fullDir = os.path.join(mainDir,os.path.normpath(dataDir))
        for fn in os.listdir(fullDir):
            fullFn = os.path.join(fullDir,fn)
            if os.path.isfile(fullFn):
                files.append(fullFn)
        dataFiles.append((dataDir,files))
    return dataFiles
win32_data_files._DOC_ERRORS = ["py","py","exe"]

<|endoftext|>


<commit_before># -*- encoding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
from h2o.utils.compatibility import *  # NOQA

from ..frame import H2OFrame
import h2o
from .model_base import ModelBase
from h2o.utils.typechecks import assert_is_type

class H2OMultinomialModel(ModelBase):

    def _make_model(self):
        return H2OMultinomialModel()

    def confusion_matrix(self, data):
        """
        Returns a confusion matrix based of H2O's default prediction threshold for a dataset.

        :param H2OFrame data: the frame with the prediction results for which the confusion matrix should be extracted.

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> distribution = "multinomial"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> confusion_matrix = gbm.confusion_matrix(train)
        >>> confusion_matrix
        """
        assert_is_type(data, H2OFrame)
        j = h2o.api("POST /3/Predictions/models/%s/frames/%s" % (self._id, data.frame_id))
        return j["model_metrics"][0]["cm"]["table"]

    def hit_ratio_table(self, train=False, valid=False, xval=False):
        """
        Retrieve the Hit Ratios.

        If all are False (default), then return the training metric value.
        If more than one options is set to True, then return a dictionary of metrics where the keys are "train",
        "valid", and "xval".

        :param train: If train is True, then return the hit ratio value for the training data.
        :param valid: If valid is True, then return the hit ratio value for the validation data.
        :param xval:  If xval is True, then return the hit ratio value for the cross validation data.
        :return: The hit ratio for this regression model.

        :example:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> distribution = "multinomial"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> hit_ratio_table = gbm.hit_ratio_table(train=False,
        ...                                       valid=False,
        ...                                       xval=False) # <- Default: return training metrics
        >>> hit_ratio_table
        >>> hit_ratio_table1 = gbm.hit_ratio_table(train=True,
        ...                                        valid=True,
        ...                                        xval=True)
        >>> hit_ratio_table1
        """
        tm = ModelBase._get_metrics(self, train, valid, xval)
        m = {}
        for k, v in zip(list(tm.keys()), list(tm.values())): m[k] = None if v is None else v.hit_ratio_table()
        return list(m.values())[0] if len(m) == 1 else m

    def mean_per_class_error(self, train=False, valid=False, xval=False):
        """
        Retrieve the mean per class error across all classes

        If all are False (default), then return the training metric value.
        If more than one options is set to True, then return a dictionary of metrics where the keys are "train",
        "valid", and "xval".

        :param bool train: If True, return the mean_per_class_error value for the training data.
        :param bool valid: If True, return the mean_per_class_error value for the validation data.
        :param bool xval:  If True, return the mean_per_class_error value for each of the cross-validated splits.

        :returns: The mean_per_class_error values for the specified key(s).

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> distribution = "multinomial"
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3, distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> mean_per_class_error = gbm.mean_per_class_error(train=False,
        ...                                                 valid=False,
        ...                                                 xval=False) # <- Default: return training metric
        >>> mean_per_class_error
        >>> mean_per_class_error1 = gbm.mean_per_class_error(train=True,
        ...                                                  valid=True,
        ...                                                  xval=True)
        >>> mean_per_class_error1
        """
        tm = ModelBase._get_metrics(self, train, valid, xval)
        m = {}
        for k, v in zip(list(tm.keys()), list(tm.values())): m[k] = None if v is None else v.mean_per_class_error()
        return list(m.values())[0] if len(m) == 1 else m

    def plot(self, timestep="AUTO", metric="AUTO", **kwargs):
        """
        Plots training set (and validation set if available) scoring history for an H2OMultinomialModel. The timestep
        and metric arguments are restricted to what is available in its scoring history.

        :param timestep: A unit of measurement for the x-axis. This can be AUTO, duration, or number_of_trees.
        :param metric: A unit of measurement for the y-axis. This can be AUTO, logloss, classification_error, or rmse.

        :returns: A scoring history plot.

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> from h2o.estimators.gbm import H2OGradientBoostingEstimator
        >>> distribution = "multinomial"
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> gbm.plot(metric=AUTO, timestep=AUTO)
        """

        if self._model_json["algo"] in ("deeplearning", "deepwater", "xgboost", "drf", "gbm"):
            if metric == "AUTO":
                metric = "classification_error"
            elif metric not in ("logloss", "classification_error", "rmse"):
                raise ValueError(
                    "metric for H2OMultinomialModel must be one of: AUTO, logloss, classification_error, rmse")

        self._plot(timestep=timestep, metric=metric, **kwargs)
<commit_msg>PUBDEV-6728: updated syntax<commit_after># -*- encoding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
from h2o.utils.compatibility import *  # NOQA

from ..frame import H2OFrame
import h2o
from .model_base import ModelBase
from h2o.utils.typechecks import assert_is_type

class H2OMultinomialModel(ModelBase):

    def _make_model(self):
        return H2OMultinomialModel()

    def confusion_matrix(self, data):
        """
        Returns a confusion matrix based of H2O's default prediction threshold for a dataset.

        :param H2OFrame data: the frame with the prediction results for which the confusion matrix should be extracted.

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> distribution = "multinomial"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> confusion_matrix = gbm.confusion_matrix(train)
        >>> confusion_matrix
        """
        assert_is_type(data, H2OFrame)
        j = h2o.api("POST /3/Predictions/models/%s/frames/%s" % (self._id, data.frame_id))
        return j["model_metrics"][0]["cm"]["table"]

    def hit_ratio_table(self, train=False, valid=False, xval=False):
        """
        Retrieve the Hit Ratios.

        If all are False (default), then return the training metric value.
        If more than one options is set to True, then return a dictionary of metrics where the keys are "train",
        "valid", and "xval".

        :param train: If train is True, then return the hit ratio value for the training data.
        :param valid: If valid is True, then return the hit ratio value for the validation data.
        :param xval:  If xval is True, then return the hit ratio value for the cross validation data.
        :return: The hit ratio for this regression model.

        :example:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> distribution = "multinomial"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> hit_ratio_table = gbm.hit_ratio_table(train=False,
        ...                                       valid=False,
        ...                                       xval=False) # <- Default: return training metrics
        >>> hit_ratio_table
        >>> hit_ratio_table1 = gbm.hit_ratio_table(train=True,
        ...                                        valid=True,
        ...                                        xval=True)
        >>> hit_ratio_table1
        """
        tm = ModelBase._get_metrics(self, train, valid, xval)
        m = {}
        for k, v in zip(list(tm.keys()), list(tm.values())): m[k] = None if v is None else v.hit_ratio_table()
        return list(m.values())[0] if len(m) == 1 else m

    def mean_per_class_error(self, train=False, valid=False, xval=False):
        """
        Retrieve the mean per class error across all classes

        If all are False (default), then return the training metric value.
        If more than one options is set to True, then return a dictionary of metrics where the keys are "train",
        "valid", and "xval".

        :param bool train: If True, return the mean_per_class_error value for the training data.
        :param bool valid: If True, return the mean_per_class_error value for the validation data.
        :param bool xval:  If True, return the mean_per_class_error value for each of the cross-validated splits.

        :returns: The mean_per_class_error values for the specified key(s).

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> distribution = "multinomial"
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3, distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> mean_per_class_error = gbm.mean_per_class_error(train=False,
        ...                                                 valid=False,
        ...                                                 xval=False) # <- Default: return training metric
        >>> mean_per_class_error
        >>> mean_per_class_error1 = gbm.mean_per_class_error(train=True,
        ...                                                  valid=True,
        ...                                                  xval=True)
        >>> mean_per_class_error1
        """
        tm = ModelBase._get_metrics(self, train, valid, xval)
        m = {}
        for k, v in zip(list(tm.keys()), list(tm.values())): m[k] = None if v is None else v.mean_per_class_error()
        return list(m.values())[0] if len(m) == 1 else m

    def plot(self, timestep="AUTO", metric="AUTO", **kwargs):
        """
        Plots training set (and validation set if available) scoring history for an H2OMultinomialModel. The timestep
        and metric arguments are restricted to what is available in its scoring history.

        :param timestep: A unit of measurement for the x-axis. This can be AUTO, duration, or number_of_trees.
        :param metric: A unit of measurement for the y-axis. This can be AUTO, logloss, classification_error, or rmse.

        :returns: A scoring history plot.

        :examples:

        >>> cars = h2o.import_file("https://s3.amazonaws.com/h2o-public-test-data/smalldata/junit/cars_20mpg.csv")
        >>> cars["cylinders"] = cars["cylinders"].asfactor()
        >>> r = cars[0].runif()
        >>> train = cars[r > .2]
        >>> valid = cars[r <= .2]
        >>> response_col = "cylinders"
        >>> predictors = ["displacement","power","weight","acceleration","year"]
        >>> from h2o.estimators.gbm import H2OGradientBoostingEstimator
        >>> distribution = "multinomial"
        >>> gbm = H2OGradientBoostingEstimator(nfolds=3,
        ...                                    distribution=distribution)
        >>> gbm.train(x=predictors,
        ...           y=response_col,
        ...           training_frame=train,
        ...           validation_frame=valid)
        >>> gbm.plot(metric="AUTO", "timestep=AUTO")
        """

        if self._model_json["algo"] in ("deeplearning", "deepwater", "xgboost", "drf", "gbm"):
            if metric == "AUTO":
                metric = "classification_error"
            elif metric not in ("logloss", "classification_error", "rmse"):
                raise ValueError(
                    "metric for H2OMultinomialModel must be one of: AUTO, logloss, classification_error, rmse")

        self._plot(timestep=timestep, metric=metric, **kwargs)
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Copyright 2015 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import argparse
import os
import re
import sys

parser = argparse.ArgumentParser()
parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*')
args = parser.parse_args()

# Cargo culted from http://stackoverflow.com/questions/898669/how-can-i-detect-if-a-file-is-binary-non-text-in-python
def is_binary(pathname):
    """Return true if the given filename is binary.
    @raise EnvironmentError: if the file does not exist or cannot be accessed.
    @attention: found @ http://bytes.com/topic/python/answers/21222-determine-file-type-binary-text on 6/08/2010
    @author: Trent Mick <TrentM@ActiveState.com>
    @author: Jorge Orpinel <jorge@orpinel.com>"""
    try:
        with open(pathname, 'r') as f:
            CHUNKSIZE = 1024
            while 1:
                chunk = f.read(CHUNKSIZE)
                if '\0' in chunk: # found null byte
                    return True
                if len(chunk) < CHUNKSIZE:
                    break # done
    except:
        return True

    return False

def get_all_files(rootdir):
    all_files = []
    for root, dirs, files in os.walk(rootdir):
        # don't visit certain dirs
        if 'vendor' in dirs:
            dirs.remove('vendor')
        if 'staging' in dirs:
            dirs.remove('staging')
        if '_output' in dirs:
            dirs.remove('_output')
        if '_gopath' in dirs:
            dirs.remove('_gopath')
        if 'third_party' in dirs:
            dirs.remove('third_party')
        if '.git' in dirs:
            dirs.remove('.git')
        if '.make' in dirs:
            dirs.remove('.make')
        if 'BUILD' in files:
           files.remove('BUILD')

        for name in files:
            pathname = os.path.join(root, name)
            if is_binary(pathname):
                continue
            all_files.append(pathname)
    return all_files

# Collects all the flags used in golang files and verifies the flags do
# not contain underscore. If any flag needs to be excluded from this check,
# need to add that flag in hack/verify-flags/excluded-flags.txt.
def check_underscore_in_flags(rootdir, files):
    # preload the 'known' flags which don't follow the - standard
    pathname = os.path.join(rootdir, "hack/verify-flags/excluded-flags.txt")
    f = open(pathname, 'r')
    excluded_flags = set(f.read().splitlines())
    f.close()

    regexs = [ re.compile('Var[P]?\([^,]*, "([^"]*)"'),
               re.compile('.String[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Int[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Bool[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Duration[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.StringSlice[P]?\("([^"]*)",[^,]+,[^)]+\)') ]

    new_excluded_flags = set()
    # walk all the files looking for any flags being declared
    for pathname in files:
        if not pathname.endswith(".go"):
            continue
        f = open(pathname, 'r')
        data = f.read()
        f.close()
        matches = []
        for regex in regexs:
            matches = matches + regex.findall(data)
        for flag in matches:
            if any(x in flag for x in excluded_flags):
                continue
            if "_" in flag:
                new_excluded_flags.add(flag)
    if len(new_excluded_flags) != 0:
        print("Found a flag declared with an _ but which is not explicitly listed as a valid flag name in hack/verify-flags/excluded-flags.txt")
        print("Are you certain this flag should not have been declared with an - instead?")
        l = list(new_excluded_flags)
        l.sort()
        print("%s" % "\n".join(l))
        sys.exit(1)

def main():
    rootdir = os.path.dirname(__file__) + "/../"
    rootdir = os.path.abspath(rootdir)

    if len(args.filenames) > 0:
        files = args.filenames
    else:
        files = get_all_files(rootdir)

    check_underscore_in_flags(rootdir, files)

if __name__ == "__main__":
  sys.exit(main())
<commit_msg>Refactoring: Reduce unnecessary lines<commit_after>#!/usr/bin/env python

# Copyright 2015 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import argparse
import os
import re
import sys

parser = argparse.ArgumentParser()
parser.add_argument("filenames", help="list of files to check, all files if unspecified", nargs='*')
args = parser.parse_args()

# Cargo culted from http://stackoverflow.com/questions/898669/how-can-i-detect-if-a-file-is-binary-non-text-in-python
def is_binary(pathname):
    """Return true if the given filename is binary.
    @raise EnvironmentError: if the file does not exist or cannot be accessed.
    @attention: found @ http://bytes.com/topic/python/answers/21222-determine-file-type-binary-text on 6/08/2010
    @author: Trent Mick <TrentM@ActiveState.com>
    @author: Jorge Orpinel <jorge@orpinel.com>"""
    try:
        with open(pathname, 'r') as f:
            CHUNKSIZE = 1024
            while 1:
                chunk = f.read(CHUNKSIZE)
                if '\0' in chunk: # found null byte
                    return True
                if len(chunk) < CHUNKSIZE:
                    break # done
    except:
        return True

    return False

def get_all_files(rootdir):
    all_files = []
    for root, dirs, files in os.walk(rootdir):
        # don't visit certain dirs
        if 'vendor' in dirs:
            dirs.remove('vendor')
        if 'staging' in dirs:
            dirs.remove('staging')
        if '_output' in dirs:
            dirs.remove('_output')
        if '_gopath' in dirs:
            dirs.remove('_gopath')
        if 'third_party' in dirs:
            dirs.remove('third_party')
        if '.git' in dirs:
            dirs.remove('.git')
        if '.make' in dirs:
            dirs.remove('.make')
        if 'BUILD' in files:
           files.remove('BUILD')

        for name in files:
            pathname = os.path.join(root, name)
            if not is_binary(pathname):
                all_files.append(pathname)
    return all_files

# Collects all the flags used in golang files and verifies the flags do
# not contain underscore. If any flag needs to be excluded from this check,
# need to add that flag in hack/verify-flags/excluded-flags.txt.
def check_underscore_in_flags(rootdir, files):
    # preload the 'known' flags which don't follow the - standard
    pathname = os.path.join(rootdir, "hack/verify-flags/excluded-flags.txt")
    f = open(pathname, 'r')
    excluded_flags = set(f.read().splitlines())
    f.close()

    regexs = [ re.compile('Var[P]?\([^,]*, "([^"]*)"'),
               re.compile('.String[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Int[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Bool[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.Duration[P]?\("([^"]*)",[^,]+,[^)]+\)'),
               re.compile('.StringSlice[P]?\("([^"]*)",[^,]+,[^)]+\)') ]

    new_excluded_flags = set()
    # walk all the files looking for any flags being declared
    for pathname in files:
        if not pathname.endswith(".go"):
            continue
        f = open(pathname, 'r')
        data = f.read()
        f.close()
        matches = []
        for regex in regexs:
            matches = matches + regex.findall(data)
        for flag in matches:
            if any(x in flag for x in excluded_flags):
                continue
            if "_" in flag:
                new_excluded_flags.add(flag)
    if len(new_excluded_flags) != 0:
        print("Found a flag declared with an _ but which is not explicitly listed as a valid flag name in hack/verify-flags/excluded-flags.txt")
        print("Are you certain this flag should not have been declared with an - instead?")
        l = list(new_excluded_flags)
        l.sort()
        print("%s" % "\n".join(l))
        sys.exit(1)

def main():
    rootdir = os.path.dirname(__file__) + "/../"
    rootdir = os.path.abspath(rootdir)

    if len(args.filenames) > 0:
        files = args.filenames
    else:
        files = get_all_files(rootdir)

    check_underscore_in_flags(rootdir, files)

if __name__ == "__main__":
  sys.exit(main())
<|endoftext|>


<commit_before>from django.shortcuts import redirect
from django.db.models import Q
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from django.conf import settings

from mezzanine.pages.views import page as page_view
from mezzanine.pages.models import Page

from widgy.contrib.form_builder.views import HandleFormMixin
from widgy.contrib.widgy_mezzanine import get_widgypage_model
from widgy.models import Node
from widgy.views.base import AuthorizedMixin
from widgy.utils import fancy_import

WidgyPage = get_widgypage_model()

def get_page_from_node(node):
    root_node = node.get_root()
    try:
        # try to find a page that uses this root node
        return WidgyPage.objects.distinct().get(
            Q(root_node__commits__root_node=root_node) | Q(root_node__working_copy=root_node)
        )
    except WidgyPage.DoesNotExist:
        # otherwise, use a fake page
        return WidgyPage(
            titles='restoring page',
            content_model='widgypage',
        )

class PageViewMixin(object):
    def get_page(self):
        try:
            return Page.objects.published(for_user=self.request.user).get(slug=self.kwargs['slug'])
        except (KeyError, Page.DoesNotExist):
            # restoring, use a fake page
            return WidgyPage(
                titles='restoring page',
                content_model='widgypage',
            )

class HandleFormView(HandleFormMixin, PageViewMixin, View):
    def get(self, request, *args, **kwargs):
        # This will raise a KeyError when `from` is for some reason
        # missing. What should it actually do?
        return redirect(request.GET['from'])

    def form_invalid(self, form):
        root_node = self.form_node.get_root()
        page = self.get_page()

        return page_view(self.request, page.slug, extra_context=self.get_context_data(
            form=form,
            page=page,
            root_node_override=root_node,
        ))

handle_form = HandleFormView.as_view()

class PreviewView(AuthorizedMixin, SingleObjectMixin, PageViewMixin, View):
    model = Node
    pk_url_kwarg = 'node_pk'

    def get(self, request, *args, **kwargs):
        node = self.get_object()
        page = self.get_page()

        context = {
            'page': page,
            'root_node_override': node,
            '_current_page': page,
        }

        return page_view(request, page.slug, extra_context=context)

preview = PreviewView.as_view(
    site=fancy_import(settings.WIDGY_MEZZANINE_SITE),
)
<commit_msg>Fix form redirection<commit_after>from django.db.models import Q
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from django.conf import settings
from django.http import (
    HttpResponseBadRequest,
    HttpResponseForbidden,
    HttpResponsePermanentRedirect,
)
from django.utils.http import is_safe_url

from mezzanine.pages.views import page as page_view
from mezzanine.pages.models import Page

from widgy.contrib.form_builder.views import HandleFormMixin
from widgy.contrib.widgy_mezzanine import get_widgypage_model
from widgy.models import Node
from widgy.views.base import AuthorizedMixin
from widgy.utils import fancy_import

WidgyPage = get_widgypage_model()

def get_page_from_node(node):
    root_node = node.get_root()
    try:
        # try to find a page that uses this root node
        return WidgyPage.objects.distinct().get(
            Q(root_node__commits__root_node=root_node) | Q(root_node__working_copy=root_node)
        )
    except WidgyPage.DoesNotExist:
        # otherwise, use a fake page
        return WidgyPage(
            titles='restoring page',
            content_model='widgypage',
        )

class PageViewMixin(object):
    def get_page(self):
        try:
            return Page.objects.published(for_user=self.request.user).get(slug=self.kwargs['slug'])
        except (KeyError, Page.DoesNotExist):
            # restoring, use a fake page
            return WidgyPage(
                titles='restoring page',
                content_model='widgypage',
            )

class HandleFormView(HandleFormMixin, PageViewMixin, View):
    def get(self, request, *args, **kwargs):
        try:
            if not is_safe_url(request.GET['from']):
                return HttpResponseForbidden()
            return HttpResponsePermanentRedirect(request.GET['from'])
        except KeyError:
            return HttpResponseBadRequest()

    def form_invalid(self, form):
        root_node = self.form_node.get_root()
        page = self.get_page()

        return page_view(self.request, page.slug, extra_context=self.get_context_data(
            form=form,
            page=page,
            root_node_override=root_node,
        ))

handle_form = HandleFormView.as_view()

class PreviewView(AuthorizedMixin, SingleObjectMixin, PageViewMixin, View):
    model = Node
    pk_url_kwarg = 'node_pk'

    def get(self, request, *args, **kwargs):
        node = self.get_object()
        page = self.get_page()

        context = {
            'page': page,
            'root_node_override': node,
            '_current_page': page,
        }

        return page_view(request, page.slug, extra_context=context)

preview = PreviewView.as_view(
    site=fancy_import(settings.WIDGY_MEZZANINE_SITE),
)
<|endoftext|>


<commit_before># Copyright (c) 2014 The songbook Team
#
# This program is distributed under the terms of the GNU General
# Public License as published by the Free Software Foundation;
# either version 2 of the License, or any later version.
# For more information, see the file LICENCE.txt

from django.core.management.base import BaseCommand
from django.conf import settings
from songbook_core.plastex import parsetex
import pprint
import git
import os
from generator import models
from django.db import transaction
from django.utils.text import slugify
from django.utils.encoding import smart_text
from django.conf.global_settings import LANGUAGES

def _file_error(error):
    print(error)

@transaction.atomic
class Command(BaseCommand):
    args = ""
    help = "Import song information into db"

    def handle(self, *args, **options):

        repo = git.Repo(settings.SONGS_LIBRARY_DIR)
        gitcmd = repo.git

        for root, _dirs, filenames in os.walk(settings.SONGS_LIBRARY_DIR,
                                             topdown=True,
                                             onerror=_file_error,
                                             followlinks=False):

            for filename in filenames:
                if filename.lower().endswith(".sg"):
                    filepath = os.path.realpath(os.path.join(root, filename))
                    filepath_rel = os.path.relpath(filepath, settings.SONGS_LIBRARY_DIR)
                    try:
                        data = parsetex(filepath)
                        self.stdout.write("Processing " + pprint.pformat(data['titles'][0]))

                        artist_name = smart_text(data['args']['by'], 'utf-8')
                        artist_slug = slugify(artist_name)

                        artist_model, created = models.Artist.objects.get_or_create(slug=artist_slug, defaults={'name': artist_name})
                        if not created:
                            if (artist_model.name != artist_name):
                                self.stderr.write("*** Artist name differs though slugs are equal : "
                                                  + artist_name + " / "
                                                  + artist_model.name)

                        if (len(data['languages']) > 1):
                            self.stderr.write("*** Multiple languages " +
                                              "in song file; we though" +
                                              " only support one. " +
                                              "Picking any.")
                        if (len(data['languages']) > 0):
                            language_name = data["languages"].pop()
                            language_code = next((x for x in LANGUAGES if x[1].lower() == language_name.lower()), ('', ''))[0]
                            if language_code == '':
                                self.stderr.write("*** No code found for language : '" + language_name + "'")

                        song_title = smart_text(data['titles'][0], 'utf-8')
                        song_slug = slugify(song_title)

                        object_hash = gitcmd.hash_object(filepath)

                        song_model, created = models.Song.objects.get_or_create(title=song_title,
                                                                                artist=artist_model,
                                                                                defaults={'title': song_title,
                                                                                'language': language_code,
                                                                                'object_hash': object_hash,
                                                                                'file_path': filepath_rel})
                        if created:
                            if models.Song.objects.filter(slug=song_slug).exists():
                                song_slug += '-' + str(song_model.id)
                            song_model.slug = song_slug

                        else:
                            self.stdout.write("-> Already exists.")
                            if (song_model.title != song_title):
                                self.stderr.write("*** Song names differs though slugs are equal : "
                                                  + song_title + " / "
                                                  + song_model.title)

                        artist_model.save()
                        song_model.save()

                    except IOError as e:
                        self.stderr.write("*** Failed processing file : " + filepath)
                        self.stderr.write("    I/O error({0}): {1}".format(e.errno, e.strerror))
<commit_msg>Pylint<commit_after># Copyright (c) 2014 The songbook Team
#
# This program is distributed under the terms of the GNU General
# Public License as published by the Free Software Foundation;
# either version 2 of the License, or any later version.
# For more information, see the file LICENCE.txt

from django.core.management.base import BaseCommand
from django.conf import settings
from songbook_core.plastex import parsetex
import pprint
import git
import os
from generator.models import Song, Artist
from django.db import transaction
from django.utils.text import slugify
from django.utils.encoding import smart_text
from django.conf.global_settings import LANGUAGES

def _file_error(error):
    print(error)

@transaction.atomic
class Command(BaseCommand):
    args = ""
    help = "Import song information into db"

    def handle(self, *args, **options):

        repo = git.Repo(settings.SONGS_LIBRARY_DIR)
        gitcmd = repo.git

        for root, _dirs, filenames in os.walk(settings.SONGS_LIBRARY_DIR,
                                             topdown=True,
                                             onerror=_file_error,
                                             followlinks=False):

            for filename in filenames:
                if filename.lower().endswith(".sg"):
                    filepath = os.path.realpath(os.path.join(root, filename))
                    filepath_rel = os.path.relpath(filepath,
                                                   settings.SONGS_LIBRARY_DIR)
                    try:
                        data = parsetex(filepath)
                        self.stdout.write("Processing " +
                                          pprint.pformat(data['titles'][0]))

                        artist_name = smart_text(data['args']['by'], 'utf-8')
                        artist_slug = slugify(artist_name)

                        artist_model, created = Artist.objects.get_or_create(
                                                slug=artist_slug,
                                                defaults={'name': artist_name}
                                                )
                        if not created:
                            if (artist_model.name != artist_name):
                                self.stderr.write(
                                    "*** Artist name differs though "
                                    "slugs are equal : "
                                    + artist_name + " / "
                                    + artist_model.name)

                        if (len(data['languages']) > 1):
                            self.stderr.write("*** Multiple languages " +
                                              "in song file; we though" +
                                              " only support one. " +
                                              "Picking any.")
                        if (len(data['languages']) > 0):
                            language_name = data["languages"].pop()
                            language_code = next(
                                        (x for x in LANGUAGES
                                         if x[1].lower() == language_name.lower()
                                         ),
                                        ('', '')
                                         )[0]
                            if language_code == '':
                                self.stderr.write("*** No code found for "
                                        "language : '" + language_name + "'")

                        song_title = smart_text(data['titles'][0], 'utf-8')
                        song_slug = slugify(song_title)

                        object_hash = gitcmd.hash_object(filepath)

                        song_model, created = Song.objects.get_or_create(
                                                title=song_title,
                                                artist=artist_model,
                                                defaults={
                                                'title': song_title,
                                                'language': language_code,
                                                'object_hash': object_hash,
                                                'file_path': filepath_rel})
                        if created:
                            if Song.objects.filter(slug=song_slug).exists():
                                song_slug += '-' + str(song_model.id)
                            song_model.slug = song_slug

                        else:
                            self.stdout.write("-> Already exists.")
                            if (song_model.title != song_title):
                                self.stderr.write(
                                    "*** Song names differs though "
                                    "slugs are equal : "
                                    + song_title + " / "
                                    + song_model.title)

                        artist_model.save()
                        song_model.save()

                    except IOError as e:
                        self.stderr.write("*** Failed processing file : "
                                          + filepath)
                        self.stderr.write("    I/O error({0}): {1}"
                                          .format(e.errno, e.strerror))
<|endoftext|>


<commit_before>__version__ = '1.2.4-dev'
<commit_msg>Rename 1.2.4-dev to 1.3.0-dev; this release includes some new features and deprecations<commit_after>__version__ = '1.3.0-dev'
<|endoftext|>


<commit_before>
import pymel.core as pm
import pymetanode as meta

import pulse
import pulse.nodes

class AimConstrainAction(pulse.BuildAction):

    def validate(self):
        if not self.leader:
            raise pulse.BuildActionError("leader must be set")
        if not self.follower:
            raise pulse.BuildActionError("follower must be set")
        if not self.worldUpObject:
            raise pulse.BuildActionError("worldUpObject must be set")

    def run(self):
        shouldCreateOffset = False
        if self.createFollowerOffset == 0:
            # Always
            shouldCreateOffset = True
        elif self.createFollowerOffset == 1 and self.follower.nodeType() != 'joint':
            # Exclude Joints and the follower is not a joint
            shouldCreateOffset = True

        _follower = self.follower
        if shouldCreateOffset:
            _follower = pulse.nodes.createOffsetTransform(self.follower)

        # create aim constrain
        upTypeStr = [
            'objectrotation',
            'object',
        ][self.worldUpType]
        ac = pm.aimConstraint(
            self.leader, _follower, mo=True,
            aimVector=self.aimVector, upVector=self.upVector,
            worldUpType=upTypeStr, worldUpObject=self.worldUpObject,
            worldUpVector=self.worldUpVector)

        # lockup the constraints
        pulse.nodes.setConstraintLocked(ac, True)

        # create blend
        if self.createBlend:
            pass
<commit_msg>implement aim constrain blend<commit_after>
import pymel.core as pm
import pymetanode as meta

import pulse
import pulse.nodes

class AimConstrainAction(pulse.BuildAction):

    def validate(self):
        if not self.leader:
            raise pulse.BuildActionError("leader must be set")
        if not self.follower:
            raise pulse.BuildActionError("follower must be set")
        if not self.worldUpObject:
            raise pulse.BuildActionError("worldUpObject must be set")

    def run(self):
        shouldCreateOffset = False
        if self.createFollowerOffset == 0:
            # Always
            shouldCreateOffset = True
        elif self.createFollowerOffset == 1 and self.follower.nodeType() != 'joint':
            # Exclude Joints and the follower is not a joint
            shouldCreateOffset = True

        _follower = self.follower
        if shouldCreateOffset:
            _follower = pulse.nodes.createOffsetTransform(self.follower)

        # create blend
        if self.createBlend:
            # create 2 more transforms to represent aiming off/on
            aimOffNode = pm.group(empty=True, p=_follower,
                                  name='%s_aimOff' % self.follower.nodeName())
            aimOnNode = pm.group(empty=True, p=_follower,
                                 name='%s_aimOn' % self.follower.nodeName())

            # move new nodes so they are siblings
            # (originally parented to follower to inherit the same transform)
            aimOffNode.setParent(_follower.getParent())
            aimOnNode.setParent(_follower.getParent())

            # create matrix blend between off and on
            wtAdd = pm.createNode('wtAddMatrix')
            aimOnNode.worldMatrix >> wtAdd.wtMatrix[0].matrixIn
            aimOffNode.worldMatrix >> wtAdd.wtMatrix[1].matrixIn
            pulse.utilnodes.connectMatrix(wtAdd.matrixSum, _follower)

            # create blend attr and connect to matrix blend
            self.follower.addAttr("aimBlend", min=0, max=1, at='double',
                                  defaultValue=1, keyable=1)
            blendAttr = self.follower.attr("aimBlend")
            blendAttr >> wtAdd.wtMatrix[0].weightIn
            pulse.utilnodes.reverse(blendAttr) >> wtAdd.wtMatrix[1].weightIn

            # use aimOn node as new follower for the aim constraint
            _follower = aimOnNode

        # create aim constrain
        upTypeStr = [
            'objectrotation',
            'object',
        ][self.worldUpType]
        ac = pm.aimConstraint(
            self.leader, _follower, mo=False,
            aimVector=self.aimVector, upVector=self.upVector,
            worldUpType=upTypeStr, worldUpObject=self.worldUpObject,
            worldUpVector=self.worldUpVector)

        # lockup the constraints
        pulse.nodes.setConstraintLocked(ac, True)
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Rock uplift along a normal fault.

Landlab component that implements rock uplift by a normal fault. Note that this
component does not make any attempt to advect topography laterally.

 """

import numpy as np
from landlab import Component
from landlab.utils.decorators import use_field_name_or_array

TWO_PI = 2.0*np.pi

@use_field_name_or_array('node')
def _return_surface(grid, surface):
    """
    Private function to return the surface modfy with the normal fault.

    This function exists to take advantange of the 'use_field_name_or_array
    decorator which permits providing the surface as a field name or array.

    Parameters
    ----------
    grid : ModelGrid
    surface : str or ndarray of shape `(n_nodes, )`
    """
    return surface

class NormalFault(Component):
    """NormalFault implements relative rock motion due to a normal fault.

    The fault can have an arbitrary trace given by two points (x1, y1) and
    (x2, y2) in the `fault_trace` input parameter.

    This NormalFault component permits an arbitrary pattern of fault motion.
    The throw rate is provided through the ``fault_throw_rate_through_time``
    parameter.
    """

    _name = 'NormalFault'

    #_cite_as = """ """

    _input_var_names = (
        'topographic__elevation',
    )

    _output_var_names = (
        'topographic__elevation',
    )

    _var_units = {
        'topographic__elevation': 'm',
    }

    _var_mapping = {
        'topographic__elevation': 'node',
    }

    _var_doc = {
        'topographic__elevation': 'elevation of the ground surface'
    }

    def __init__(self, grid, params):
        """
        Instantiation of a NormalFault.

        Parameters
        --------
        grid : ModelGrid
        faulted_surface : str or ndarray of shape `(n_nodes, )`
            Surface that is modified by the NormalFault component. Can be a
            field name or array. Default value is `topographic__elevation`.
        fault_throw_rate_through_time : dict
            Dictionary that specifies the time varying throw rate on the fault.
            Expected format is:
            ``fault_throw_rate_through_time = {time: array, rate: array}
        fault_dip_angle : float
            Dip angle of the fault in degrees.
        fault_trace : dictionary
            Dictionary that specifies the coordinates of two locations on the
            fault trace. Expected format is
            ``fault_trace_dict = {x1: float, y1: float, x2: float, y2: float}``
            where the vector from ``(x1, y1)`` to ``(x2, y2)`` defines the
            strike of the fault trace. The orientation of the fault dip relative
            to the strike follows the right hand rule.
        include_boundaries : boolean, optional
            Flag to indicate if model grid boundaries should be uplifted. If
            set to ``True`` uplifted model grid boundaries will be set to the
            average value of their upstream nodes. Default value is False

         Examples
         --------

         Create a grid on which we will run the normal fault.

         >>> from landlab import RasterModelGrid
         >>> from landlab.components import NormalFault
         >>> grid = RasterModelGrid((5, 4))

        """
        # call the class Normal Fault inherits from
        super(NormalFault, self).__init__(grid)

        # save a reference to the grid
        self._grid = grid

        # get the surface to be faulted
        surface = params.get('faulted_surface', 'topographic__elevation')
        self.z = _return_surface(grid, surface)

        # get the fault throw parameter values from the parameter dictionary
        self.throw_time = np.array(params['fault_through_rate_through_time']['time'])
        self.throw_rate = np.array(params['fault_through_rate_through_time']['rate'])
        self.fault_dip = np.deg2rad(params['fault_dip_angle'])
        self.uplift = self.throw_rate * np.sin(self.fault_dip)

        # Identify in current boundaries will be included
        self.include_boundaries = params.get('include_boundaries', False)

        # Instantiate record of current time.
        self.current_time = 0.0

        # get the fault trace dictionary and use to to calculate where the
        # faulted nodes are located.

        self.fault_trace_dict = params['fault_trace']
        dx = self.fault_trace_dict['x2'] - self.fault_trace_dict['x1']
        dy = self.fault_trace_dict['y2'] - self.fault_trace_dict['y1']
        self.fault_azimuth = np.mod(np.arctan2(dy, dx), TWO_PI)
        self.fault_anti_azimuth = self.fault_azimuth + np.pi

        if dx == 0:
            self.dy_over_dx = 0.0
            self.fault_trace_y_intercept = 0.0
            self.fault_trace_x_intercept = self.fault_trace_dict['x2']
        else:
            self.dy_over_dx = dy/dx
            self.fault_trace_y_intercept = self.fault_trace_dict['y1'] - (self.dy_over_dx * self.fault_trace_dict['x1'])
            self.fault_trace_x_intercept = 0.0

        # select those nodes that are on the correct side of the node
        if self.include_boundaries:
            potential_nodes = np.arange(self._grid.size('node'))
        else:
            potential_nodes = self._grid.core_nodes

        dx_pn = (self._grid.x_of_node[potential_nodes] - self.fault_trace_x_intercept)
        dy_pn = (self._grid.y_of_node[potential_nodes] - self.fault_trace_y_intercept)

        potential_angles = np.mod(np.arctan2(dy_pn, dx_pn), TWO_PI)

        if self.fault_anti_azimuth <= TWO_PI:
            faulted_node_ids = potential_nodes[((potential_angles>self.fault_azimuth) &
                                                  (potential_angles <= (self.fault_anti_azimuth)))]
        else:
            faulted_node_ids = potential_nodes[((potential_angles>self.fault_azimuth) |
                                                  (potential_angles <= np.mod(self.fault_anti_azimuth, TWO_PI)))]

        # faulted_nodes
        self.faulted_nodes = np.zeros(self._grid.size('node'), dtype=bool)
        self.faulted_nodes[faulted_node_ids] = True

    def run_one_step(self, dt):
        """Run_one_step method for NormalFault.

        Parameters
        ----------
        dt : float
            Time increment used to advance the NormalFault component.

        """
        # save z before uplift
        z_before_uplift = self.z.copy()

        # calculate the current uplift rate
        current_uplift_rate = np.interp(self.current_time, self.throw_time, self.throw_rate)

        # uplift the faulted_nodes
        self.z[self.faulted_nodes] += current_uplift_rate * dt

        # if faulted nodes includes boundaries we must do some extra work because
        # landlab components will typically not erode these boundaries. This means
        # they will be uplifted but not eroded.

        if self.include_boundaries:

            #  here our goal is to set faulted boundaries to average of open
            # node faulted neighbors

            # create boolean of the faulted boundary nodes
            faulted_boundaries = self.faulted_nodes.copy()
            faulted_boundaries[self._grid.core_nodes] = False

            core_nodes = np.zeros(self._grid.size('node'), dtype=bool)
            core_nodes[self._grid.core_nodes] = True

            neighbor_is_core = core_nodes[self._grid.neighbors_at_node]
            neighbor_is_faulted = self.faulted_nodes[self._grid.neighbors_at_node]

            neighbor_for_averaging = neighbor_is_faulted&neighbor_is_core

            # Identify nodes that have at least one adjacent node that is both
            # faulted and not a boundary node.
            # average the pre-uplift topography on those adjacent nodes and assign
            # to the boundary node.
            # here we use the pre-uplift elevation because other steps in the model
            # may diminish this topography.

            averaged = neighbor_for_averaging[faulted_boundaries].sum(axis=1) == 1
            if any(averaged):
                averaged_nodes = np.where(faulted_boundaries)[0][np.where(averaged)[0]]
                elevations_to_average =  z_before_uplift[self._grid.neighbors_at_node]
                elevations_to_average[self._grid.neighbors_at_node == -1] = np.nan
                elevations_to_average[neighbor_for_averaging == False] = np.nan
                self.z[averaged_nodes] = np.nanmean(elevations_to_average[averaged_nodes], axis=1)

            # identify any boundary nodes that are not being averaged. This will
            # happen at the corners on RasterModelGrids. Average over adjacent
            # nodes that are faulted. These nodes will be boundary nodes.
            # here we use the current topography as we will have just updated the
            # adjacent nodes in the prior block.
            if any(averaged == False):
                un_averaged_nodes = np.where(faulted_boundaries)[0][np.where(averaged == False)[0]]
                elevations_to_average =  self.z[self._grid.neighbors_at_node]
                elevations_to_average[self._grid.neighbors_at_node == -1] = np.nan
                elevations_to_average[neighbor_is_faulted == False] = np.nan
                self.z[un_averaged_nodes] = np.nanmean(elevations_to_average[un_averaged_nodes], axis=1)

        # increment time
        self.current_time += dt
<commit_msg>I can spell throw<commit_after>#!/usr/bin/env python
"""Rock uplift along a normal fault.

Landlab component that implements rock uplift by a normal fault. Note that this
component does not make any attempt to advect topography laterally.

 """

import numpy as np
from landlab import Component
from landlab.utils.decorators import use_field_name_or_array

TWO_PI = 2.0*np.pi

@use_field_name_or_array('node')
def _return_surface(grid, surface):
    """
    Private function to return the surface modfy with the normal fault.

    This function exists to take advantange of the 'use_field_name_or_array
    decorator which permits providing the surface as a field name or array.

    Parameters
    ----------
    grid : ModelGrid
    surface : str or ndarray of shape `(n_nodes, )`
    """
    return surface

class NormalFault(Component):
    """NormalFault implements relative rock motion due to a normal fault.

    The fault can have an arbitrary trace given by two points (x1, y1) and
    (x2, y2) in the `fault_trace` input parameter.

    This NormalFault component permits an arbitrary pattern of fault motion.
    The throw rate is provided through the ``fault_throw_rate_through_time``
    parameter.
    """

    _name = 'NormalFault'

    #_cite_as = """ """

    _input_var_names = (
        'topographic__elevation',
    )

    _output_var_names = (
        'topographic__elevation',
    )

    _var_units = {
        'topographic__elevation': 'm',
    }

    _var_mapping = {
        'topographic__elevation': 'node',
    }

    _var_doc = {
        'topographic__elevation': 'elevation of the ground surface'
    }

    def __init__(self, grid, params):
        """
        Instantiation of a NormalFault.

        Parameters
        --------
        grid : ModelGrid
        faulted_surface : str or ndarray of shape `(n_nodes, )`
            Surface that is modified by the NormalFault component. Can be a
            field name or array. Default value is `topographic__elevation`.
        fault_throw_rate_through_time : dict
            Dictionary that specifies the time varying throw rate on the fault.
            Expected format is:
            ``fault_throw_rate_through_time = {time: array, rate: array}
        fault_dip_angle : float
            Dip angle of the fault in degrees.
        fault_trace : dictionary
            Dictionary that specifies the coordinates of two locations on the
            fault trace. Expected format is
            ``fault_trace_dict = {x1: float, y1: float, x2: float, y2: float}``
            where the vector from ``(x1, y1)`` to ``(x2, y2)`` defines the
            strike of the fault trace. The orientation of the fault dip relative
            to the strike follows the right hand rule.
        include_boundaries : boolean, optional
            Flag to indicate if model grid boundaries should be uplifted. If
            set to ``True`` uplifted model grid boundaries will be set to the
            average value of their upstream nodes. Default value is False

         Examples
         --------

         Create a grid on which we will run the normal fault.

         >>> from landlab import RasterModelGrid
         >>> from landlab.components import NormalFault
         >>> grid = RasterModelGrid((5, 4))

        """
        # call the class Normal Fault inherits from
        super(NormalFault, self).__init__(grid)

        # save a reference to the grid
        self._grid = grid

        # get the surface to be faulted
        surface = params.get('faulted_surface', 'topographic__elevation')
        self.z = _return_surface(grid, surface)

        # get the fault throw parameter values from the parameter dictionary
        self.throw_time = np.array(params['fault_throw_rate_through_time']['time'])
        self.throw_rate = np.array(params['fault_throw_rate_through_time']['rate'])
        self.fault_dip = np.deg2rad(params['fault_dip_angle'])
        self.uplift = self.throw_rate * np.sin(self.fault_dip)

        # Identify in current boundaries will be included
        self.include_boundaries = params.get('include_boundaries', False)

        # Instantiate record of current time.
        self.current_time = 0.0

        # get the fault trace dictionary and use to to calculate where the
        # faulted nodes are located.

        self.fault_trace_dict = params['fault_trace']
        dx = self.fault_trace_dict['x2'] - self.fault_trace_dict['x1']
        dy = self.fault_trace_dict['y2'] - self.fault_trace_dict['y1']
        self.fault_azimuth = np.mod(np.arctan2(dy, dx), TWO_PI)
        self.fault_anti_azimuth = self.fault_azimuth + np.pi

        if dx == 0:
            self.dy_over_dx = 0.0
            self.fault_trace_y_intercept = 0.0
            self.fault_trace_x_intercept = self.fault_trace_dict['x2']
        else:
            self.dy_over_dx = dy/dx
            self.fault_trace_y_intercept = self.fault_trace_dict['y1'] - (self.dy_over_dx * self.fault_trace_dict['x1'])
            self.fault_trace_x_intercept = 0.0

        # select those nodes that are on the correct side of the node
        if self.include_boundaries:
            potential_nodes = np.arange(self._grid.size('node'))
        else:
            potential_nodes = self._grid.core_nodes

        dx_pn = (self._grid.x_of_node[potential_nodes] - self.fault_trace_x_intercept)
        dy_pn = (self._grid.y_of_node[potential_nodes] - self.fault_trace_y_intercept)

        potential_angles = np.mod(np.arctan2(dy_pn, dx_pn), TWO_PI)

        if self.fault_anti_azimuth <= TWO_PI:
            faulted_node_ids = potential_nodes[((potential_angles>self.fault_azimuth) &
                                                  (potential_angles <= (self.fault_anti_azimuth)))]
        else:
            faulted_node_ids = potential_nodes[((potential_angles>self.fault_azimuth) |
                                                  (potential_angles <= np.mod(self.fault_anti_azimuth, TWO_PI)))]

        # faulted_nodes
        self.faulted_nodes = np.zeros(self._grid.size('node'), dtype=bool)
        self.faulted_nodes[faulted_node_ids] = True

    def run_one_step(self, dt):
        """Run_one_step method for NormalFault.

        Parameters
        ----------
        dt : float
            Time increment used to advance the NormalFault component.

        """
        # save z before uplift
        z_before_uplift = self.z.copy()

        # calculate the current uplift rate
        current_uplift_rate = np.interp(self.current_time, self.throw_time, self.throw_rate)

        # uplift the faulted_nodes
        self.z[self.faulted_nodes] += current_uplift_rate * dt

        # if faulted nodes includes boundaries we must do some extra work because
        # landlab components will typically not erode these boundaries. This means
        # they will be uplifted but not eroded.

        if self.include_boundaries:

            #  here our goal is to set faulted boundaries to average of open
            # node faulted neighbors

            # create boolean of the faulted boundary nodes
            faulted_boundaries = self.faulted_nodes.copy()
            faulted_boundaries[self._grid.core_nodes] = False

            core_nodes = np.zeros(self._grid.size('node'), dtype=bool)
            core_nodes[self._grid.core_nodes] = True

            neighbor_is_core = core_nodes[self._grid.neighbors_at_node]
            neighbor_is_faulted = self.faulted_nodes[self._grid.neighbors_at_node]

            neighbor_for_averaging = neighbor_is_faulted&neighbor_is_core

            # Identify nodes that have at least one adjacent node that is both
            # faulted and not a boundary node.
            # average the pre-uplift topography on those adjacent nodes and assign
            # to the boundary node.
            # here we use the pre-uplift elevation because other steps in the model
            # may diminish this topography.

            averaged = neighbor_for_averaging[faulted_boundaries].sum(axis=1) == 1
            if any(averaged):
                averaged_nodes = np.where(faulted_boundaries)[0][np.where(averaged)[0]]
                elevations_to_average =  z_before_uplift[self._grid.neighbors_at_node]
                elevations_to_average[self._grid.neighbors_at_node == -1] = np.nan
                elevations_to_average[neighbor_for_averaging == False] = np.nan
                self.z[averaged_nodes] = np.nanmean(elevations_to_average[averaged_nodes], axis=1)

            # identify any boundary nodes that are not being averaged. This will
            # happen at the corners on RasterModelGrids. Average over adjacent
            # nodes that are faulted. These nodes will be boundary nodes.
            # here we use the current topography as we will have just updated the
            # adjacent nodes in the prior block.
            if any(averaged == False):
                un_averaged_nodes = np.where(faulted_boundaries)[0][np.where(averaged == False)[0]]
                elevations_to_average =  self.z[self._grid.neighbors_at_node]
                elevations_to_average[self._grid.neighbors_at_node == -1] = np.nan
                elevations_to_average[neighbor_is_faulted == False] = np.nan
                self.z[un_averaged_nodes] = np.nanmean(elevations_to_average[un_averaged_nodes], axis=1)

        # increment time
        self.current_time += dt
<|endoftext|>