def console_logger(level='WARNING'):
    """
    *Setup and return a console logger*

    **Key Arguments**

    - ``level`` -- the level of logging required

    **Return**

    - ``logger`` -- the console logger

    **Usage**

    ```python
    from fundamentals import logs
    log = logs.console_logger(
        level="DEBUG"
    )
    log.debug("Testing console logger")
    ```

    """
    import logging
    import logging.config
    import yaml
    try:
        yaml.warnings({'YAMLLoadWarning': False})
    except:
        pass
    loggerConfig = """
  version: 1
  formatters:
      console_style:
          format: '* %(asctime)s - %(levelname)s: %(pathname)s:%(funcName)s:%(lineno)d > %(message)s'
          datefmt: '%H:%M:%S'
  handlers:
      console:
          class: logging.StreamHandler
          level: """ + level + """
          formatter: console_style
          stream: ext://sys.stdout
  root:
      level: """ + level + """
      handlers: [console]"""
    logging.config.dictConfig(yaml.load(loggerConfig))
    logger = logging.getLogger(__name__)
    return logger


@classmethod
def get_from_queryset(cls, queryset, path_fragment):
    """
        Called by containing QuerySetResource to filter the QuerySet down
        to a single item -- represented by this ModelResource
        """
    attr, type_ = cls.published_key
    kwargs = dict()
    kwargs[attr] = type_(path_fragment)
    return queryset.get(**kwargs)


def out_of_china(lng, lat):
    """
    判断是否在国内，不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)


def dict_from_cookiejar(cj):
    """Returns a key/value dictionary from a CookieJar.

    :param cj: CookieJar object to extract cookies from.
    """
    cookie_dict = {}
    for cookie in cj:
        cookie_dict[cookie.name] = cookie.value
    return cookie_dict


def check_var(variable, allowed_range, default=None, logger=None):
    """Check if a given variable (string, number etc.) is "allowed."""
    if variable not in allowed_range:
        logger.warning(str(variable) + ' is not a valid choice of ' + str(
            list(allowed_range.keys())) +
            '. Instead, the default value was used: ' + default)
        variable = default
    return variable


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def mergeUnitCompare(a, b):
    """
    _mergeUnitCompare_

    Compare two merge units.  They will be sorted first by run ID and then by
    lumi ID.
    """
    if a['run'] > b['run']:
        return 1
    elif a['run'] == b['run']:
        if a['lumi'] > b['lumi']:
            return 1
        elif a['lumi'] == b['lumi']:
            return 0
        else:
            return -1
    else:
        return -1


def hash_array(array):
    """
    Hash an array for dictionary or set based lookup

    Parameters
    ----------
    array : np.ndarray
       The integer array to hash

    Returns
    ------
    key : integer
       The hash value of the array
    """
    return hash(array.tostring())


def geopotential_to_geometric(h, r0):
    """ Converts from given geopotential altitude to geometric one.

    Parameters
    ----------
    h: ~astropy.units.Quanity
        Geopotential altitude.
    r0: ~astropy.units.Quantity
        Planet/Natural satellite radius.

    Returns
    -------
    z: ~astropy.units.Quantity
        Geometric altitude.
    """
    z = r0 * h / (r0 - h)
    return z


def get_max_value_key(dic):
    """Fast method to get key for maximum value in dict."""
    v = list(dic.values())
    k = list(dic.keys())
    return k[v.index(max(v))]


def getCatalog():
    """Returns catalog of glossary"""


@classmethod
def is_token_authenticated(cls, handler):
    """Returns True if handler has been token authenticated. Otherwise, False.

        Login with a token is used to signal certain things, such as:

        - permit access to REST API
        - xsrf protection
        - skip origin-checks for scripts
        """
    if getattr(handler, '_user_id', None) is None:
        handler.get_current_user()
    return getattr(handler, '_token_authenticated', False)


def SetDefaultDData(dType, histoName, NShkl=0, NDij=0):
    """Create an initial Histogram dictionary

    Author: Jackson O'Donnell (jacksonhodonnell .at. gmail.com)
    """
    if dType in ['SXC', 'SNC']:
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, True],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]},
            'Extinction': ['Lorentzian', 'None', {'Tbar': 0.1, 'Cos2TM':
            0.955, 'Eg': [1e-10, False], 'Es': [1e-10, False], 'Ep': [1e-10,
            False]}], 'Flack': [0.0, False]}
    elif dType == 'SNT':
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, True],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]},
            'Extinction': ['Lorentzian', 'None', {'Eg': [1e-10, False],
            'Es': [1e-10, False], 'Ep': [1e-10, False]}]}
    elif 'P' in dType:
        return {'Histogram': histoName, 'Show': False, 'Scale': [1.0, False
            ], 'Pref.Ori.': ['MD', 1.0, False, [0, 0, 1], 0, {}, [], 0.1],
            'Size': ['isotropic', [1.0, 1.0, 1.0], [False, False, False], [
            0, 0, 1], [1.0, 1.0, 1.0, 0.0, 0.0, 0.0], 6 * [False]],
            'Mustrain': ['isotropic', [1000.0, 1000.0, 1.0], [False, False,
            False], [0, 0, 1], NShkl * [0.01], NShkl * [False]], 'HStrain':
            [NDij * [0.0], NDij * [False]], 'Extinction': [0.0, False],
            'Babinet': {'BabA': [0.0, False], 'BabU': [0.0, False]}}


def macshim():
    """Shim to run 32-bit on 64-bit mac as a sub-process"""
    import subprocess, sys
    subprocess.call([sys.argv[0] + '32'] + sys.argv[1:], env={
        'VERSIONER_PYTHON_PREFER_32_BIT': 'yes'})


@staticmethod
def __b(value):
    """
        Because Hg Lib is setup to only work with binary encoded strings(8 bit ASCII) and is TERRIBLE at sanitizing
        its inputs, this function is necessary to do that for it.  This also makes unicode out of the question for
        HG repos.
        :param value: A value to be binarized.
        :return:
        """
    if isinstance(value, bytes):
        return value
    return str(value).encode('latin-1')


def has_option(namespace, name: str):
    """Returns True if argparse.Namespace has an option."""
    return name in vars(namespace)


def cosh(data=None, out=None, name=None, **kwargs):
    """Returns the hyperbolic cosine  of the input array, computed element-wise.

    .. math::
       cosh(x) = 0.5\\times(exp(x) + exp(-x))

    The storage type of ``cosh`` output is always dense

    Defined in src/operator/tensor/elemwise_unary_op_trig.cc:L351

    Parameters
    ----------
    data : NDArray
        The input array.

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


@classmethod
def is_datasource_for(cls, data, header, **kwargs):
    """Determines if header corresponds to an TRACE image"""
    return header.get('instrume') == 'TRACE'


@staticmethod
def concat(x, y):
    """
        Concatenates two lists.

        Arguments:
        x -- the list to order first
        y -- the list to order second
        """
    return x + y


def linexor(listoflists, columnlist, valuelist):
    """
Returns the rows of a list of lists where col (from columnlist) = val
(from valuelist) for ANY pair of values (colunmlist[i],valuelist[i[).
One value is required for each column in columnlist.  If only one value
exists for columnlist but multiple values appear in valuelist, the
valuelist values are all assumed to pertain to the same column.

Usage:   linexor (listoflists,columnlist,valuelist)
Returns: the rows of listoflists where columnlist[i]=valuelist[i] for ANY i
"""
    if type(columnlist) not in [list, tuple]:
        columnlist = [columnlist]
    if type(valuelist) not in [list, tuple]:
        valuelist = [valuelist]
    criterion = ''
    if len(columnlist) == 1 and len(valuelist) > 1:
        columnlist = columnlist * len(valuelist)
    for i in range(len(columnlist)):
        if isinstance(valuelist[i], str):
            critval = "'" + valuelist[i] + "'"
        else:
            critval = str(valuelist[i])
        criterion = criterion + ' x[' + str(columnlist[i]
            ) + ']==' + critval + ' or'
    criterion = criterion[0:-2]
    function = 'filter(lambda x: ' + criterion + ',listoflists)'
    lines = eval(function)
    return lines


def _map_relation(c, language='any'):
    """
    Map related concept or collection, leaving out the relations.

    :param c: the concept or collection to map
    :param string language: Language to render the relation's label in
    :rtype: :class:`dict`
    """
    label = c.label(language)
    return {'id': c.id, 'type': c.type, 'uri': c.uri, 'label': label.label if
        label else None}


def assert_list_data(value: list) ->None:
    """Asserts value is list type."""
    assert isinstance(value, list
        ), f'Input value type must be a list. Actual type: {type(value)}, value: {value}'


def _create_flow(function_a, function_b):
    """Generate lambda to be used in formatter flow"""
    return lambda x: function_b(function_a(x))


def _findAllTokensBetweenChars(string, start, end, n=None):
    """Finds the text between (possibly nested) delimiters in a string.
    In case of nested delimiters, only the outermost level is
    returned. It returns a tuple of (idx,token)

    Example::

      _findAllTokensBetweenChars('{foo}bar{zig{zag}}boom', '{', '}')
      --> [(1,'foo'), (9, 'zig{zag}')]

    :param string: (str) the expression to parse
    :param start: (str) the char delimiting the start of a token
    :param end: (str) the char delimiting the end of a token
    :param n: (int or None) If an int is passed, it sets the maximum number
              of tokens to be found

    :return: (list(<int>,<str>)) a list of (idx, token) tuples. The idx is the
    position of the token in `string`
             (tokens d not include the delimiting chars not including the
             brackets)
    """
    if start == end:
        raise ValueError('star_char must be different from end_char')
    if string.count(start) != string.count(end):
        raise ValueError('Non-matching delimiters (%i "%s" vs %i "%s")' %
            string.count(start), start, string.count(end), end)
    tokens = []
    indexes = []
    idx = 0
    rest = string
    while len(tokens) != n:
        s = rest.find(start)
        if s < 0:
            break
        e = rest.find(end) + 1
        while rest[s:e].count(start) != rest[s:e].count(end):
            ne = rest[e:].find(end)
            e = e + 1 + ne
        tokens.append((idx + s, rest[s + 1:e - 1]))
        idx += e
        rest = rest[e:]
    return tokens


def click_hook(player, container):
    """
        The ``player`` a Player's protocol
        The ``container`` is a 0x66 message
        :returns: True if you processed the action and TRANSACTION must be ok
                  You probably will never return True here.
        """
    pass


def _csc_gen_triples(A):
    """Converts a SciPy sparse matrix in **Compressed Sparse Column** format to
    an iterable of weighted edge triples.

    """
    ncols = A.shape[1]
    data, indices, indptr = A.data, A.indices, A.indptr
    for i in range(ncols):
        for j in range(indptr[i], indptr[i + 1]):
            yield indices[j], i, data[j]


def _convert_argmax(builder, node, graph, err):
    """
    convert to CoreML ArgMax Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L4961
    """
    axis = node.attrs.get('axis', 0)
    keepdims = node.attrs.get('keepdims', True)
    builder.add_argmax(name=node.name, input_name=node.inputs[0],
        output_name=node.outputs[0], axis=axis, keepdims=keepdims)


def _conv_int(string):
    """
    Helper function to optimize memory usage.
    """
    if string.isdigit():
        return int(string)
    return string


def _contains_date(format):
    """
    Check if a format contains tokens related to date.

    :param format:
    :type format: str
    :return: True if format contains tokens related to date, false otherwise.
    :rtype: boolean
    """
    part_of_date_tokens = 'aAwdbBmyYjUW'
    for token in part_of_date_tokens:
        if token in format:
            return True
    return False


def strings_equal(s1, s2):
    """
    Timing-attack resistant string comparison.
    Normal comparison using == will short-circuit on the first mismatching
    character. This avoids that by scanning the whole string, though we
    still reveal to a timing attack whether the strings are the same
    length.
    """
    try:
        from hmac import compare_digest
        return compare_digest(s1, s2)
    except ImportError:
        pass
    if len(s1) != len(s2):
        return False
    differences = 0
    for c1, c2 in zip(s1, s2):
        differences |= ord(c1) ^ ord(c2)
    return differences == 0


def createReply(title, text, Creator=None):
    """ Create a reply in the proper place.

        o Returns: HTML (directly or via redirect) # XXX

        o Permission: Reply to item
        """


def dict_to_sequence(d):
    """Returns an internal sequence dictionary update."""
    if hasattr(d, 'items'):
        d = d.items()
    return d


@staticmethod
def positional_to_model(value):
    """Converts a positional argument to a model value"""
    return value


def delete(names):
    """ Remove controlpanel children by names
        """


def check_ranking(ranking, mtable):
    """
    Checks if the ranking is fair in respect to the mtable
    :param ranking:     The ranking to be checked (list of FairScoreDoc)
    :param mtable:      The mtable against to check (list of int)
    :return:            Returns whether the rankings satisfies the mtable
    """
    count_protected = 0
    if len(ranking) != len(mtable):
        raise ValueError(
            'Number of documents in ranking and mtable length must be equal!')
    for i, element in enumerate(ranking):
        count_protected += 1 if element.is_protected else 0
        if count_protected < mtable[i]:
            return False
    return True


@staticmethod
def p_addrtype(p):
    """addrtype : PBYTE
                    | PWORD
                    | PLONG
                    | DIRECT"""
    p[0] = p[1]


def match_items(lines, content_old):
    """Create items for mangled lines.

    This function tries to match the lines in ``lines`` with the items (source
    file references and line numbers) in ``content_old``. The
    ``mangle_docstrings`` function changes the actual docstrings, but doesn't
    keep track of where each line came from. The manging does many operations
    on the original lines, which are hard to track afterwards.

    Many of the line changes come from deleting or inserting blank lines. This
    function tries to match lines by ignoring blank lines. All other changes
    (such as inserting figures or changes in the references) are completely
    ignored, so the generated line numbers will be off if ``mangle_docstrings``
    does anything non-trivial.

    This is a best-effort function and the real fix would be to make
    ``mangle_docstrings`` actually keep track of the ``items`` together with
    the ``lines``.

    Examples
    --------
    >>> lines = ['', 'A', '', 'B', '   ', '', 'C', 'D']
    >>> lines_old = ['a', '', '', 'b', '', 'c']
    >>> items_old = [('file1.py', 0), ('file1.py', 1), ('file1.py', 2),
    ...              ('file2.py', 0), ('file2.py', 1), ('file2.py', 2)]
    >>> content_old = ViewList(lines_old, items=items_old)
    >>> match_items(lines, content_old) # doctest: +NORMALIZE_WHITESPACE
    [('file1.py', 0), ('file1.py', 0), ('file2.py', 0), ('file2.py', 0),
     ('file2.py', 2), ('file2.py', 2), ('file2.py', 2), ('file2.py', 2)]
    >>> # first 2 ``lines`` are matched to 'a', second 2 to 'b', rest to 'c'
    >>> # actual content is completely ignored.

    Notes
    -----
    The algorithm tries to match any line in ``lines`` with one in
    ``lines_old``.  It skips over all empty lines in ``lines_old`` and assigns
    this line number to all lines in ``lines``, unless a non-empty line is
    found in ``lines`` in which case it goes to the next line in ``lines_old``.

    """
    items_new = []
    lines_old = content_old.data
    items_old = content_old.items
    j = 0
    for i, line in enumerate(lines):
        while j < len(lines_old) - 1 and not lines_old[j].strip():
            j += 1
        items_new.append(items_old[j])
        if line.strip() and j < len(lines_old) - 1:
            j += 1
    assert len(items_new) == len(lines)
    return items_new


def PVT(df, price='Close', volume='Volume'):
    """
    Price Volume Trend
    Returns: list of floats = jhta.PVT(df, price='Close', volume='Volume')
    Source: https://www.fmlabs.com/reference/default.htm?url=PVT.htm
    """
    pvt_list = []
    for i in range(len(df[price])):
        pvt = 0
        if i > 0:
            pvt = pvt_list[i - 1] + df[volume][i] * (df[price][i] - df[
                price][i - 1]) / df[price][i - 1]
        pvt_list.append(pvt)
    return pvt_list


def scan_setup_py():
    """Validate the contents of setup.py against Versioneer's expectations."""
    found = set()
    setters = False
    errors = 0
    with open('setup.py', 'r') as f:
        for line in f.readlines():
            if 'import versioneer' in line:
                found.add('import')
            if 'versioneer.get_cmdclass()' in line:
                found.add('cmdclass')
            if 'versioneer.get_version()' in line:
                found.add('get_version')
            if 'versioneer.VCS' in line:
                setters = True
            if 'versioneer.versionfile_source' in line:
                setters = True
    if len(found) != 3:
        print('')
        print('Your setup.py appears to be missing some important items')
        print('(but I might be wrong). Please make sure it has something')
        print('roughly like the following:')
        print('')
        print(' import versioneer')
        print(' setup( version=versioneer.get_version(),')
        print('        cmdclass=versioneer.get_cmdclass(),  ...)')
        print('')
        errors += 1
    if setters:
        print("You should remove lines like 'versioneer.VCS = ' and")
        print("'versioneer.versionfile_source = ' . This configuration")
        print('now lives in setup.cfg, and should be removed from setup.py')
        print('')
        errors += 1
    return errors


def check_for_valid_data_length(image_data, data_to_hide):
    """
    Check if cover image is significantly large enough to encode all the data

    Since we are using the lsb of the cover image to encode the data it takes three pixels to hide one byte of data.
    That is three bits in the R and G values and two bits plus a flag bit in the B value. So we require an image that
    is three times as large as the data we want to hide.
    """
    data_len = len(data_to_hide)
    if data_len == 0:
        raise ValueError('No data was provided to hide')
    if data_len * 3 > len(image_data):
        raise ValueError('The data provided is too large to fit in the image')
    return data_len


def inside(xy):
    """Return True if xy within screen."""
    return -200 < xy.x < 200 and -200 < xy.y < 200


def synonym(noun):
    """
        Provides a synonym for a given noun

        Args:
            noun (str): The noun for the synonym

        Returns:
            A string with the synonym
    """
    print('anche {} si chiama'.format(noun))


@classmethod
def convert(cls, number):
    """Converts an int to a formatted string of this type"""
    return cls.add_format(cls._to_str(number))


def z_base_ohm(vbll_kv, ib_ka=None, sb_mva=None):
    """Returns the base impedance based on the base voltage and either the base current
    or the base power.

    Args:
        vbll_kv: Base voltage in kV.
        sb_mva: Base power in MVA.
        ib_ka: Base current in kA.

    Returns:
        Base impedance in ohms.
    """
    vbll_kv = float(vbll_kv)
    if ib_ka is None and sb_mva is not None:
        sb_mva = float(sb_mva)
        return vbll_kv ** 2 / sb_mva
    elif sb_mva is None and ib_ka is not None:
        ib_ka = float(ib_ka)
        return vbll_kv / (ib_ka * 3 ** 0.5)
    else:
        raise ValueError('You must provide either ib_ka or sb_mva')


@classmethod
def create_from_lambda_arn(cls, client, lambda_arn):
    """Create a LogRetriever from a client and lambda arn.

        :type client: botocore.client.Logs
        :param client: A ``logs`` client.

        :type lambda_arn: str
        :param lambda_arn: The ARN of the lambda function.

        :return: An instance of ``LogRetriever``.

        """
    lambda_name = lambda_arn.split(':')[6]
    log_group_name = '/aws/lambda/%s' % lambda_name
    return cls(client, log_group_name)


def serialize_model_base(obj, fields_method, model_method, fields=None,
    exclude=None, related=None, related_fields=None, parent='',
    use_natural_keys=False, handle_related=lambda x, y: y):
    """ Convert model instances to basic Python data types. """
    fields = fields_method(obj, fields=fields, exclude=exclude)
    related = related or {}
    related_fields = related_fields or {}
    return model_method(obj, fields, related, related_fields, parent,
        use_natural_keys, handle_related)


@staticmethod
def get_elastic_mappings(es_major):
    """Get Elasticsearch mapping.

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
         {
            "dynamic":true,
                "properties": {
                    "data": {
                        "properties": {
                            "details": {
                                "properties": {
                                    "suggested_topics": {
                                        "dynamic": false,
                                        "properties": {
                                            "slug": {
                                                "type": "text",
                                                "index": true
                                            },
                                            "title": {
                                                "type": "text",
                                                "index": true
                                            }
                                        }
                                    }
                                }
                            },
                            "fancy_title": {
                                "type": "text",
                                "index": true
                            },
                            "slug": {
                                "type": "text",
                                "index": true
                            },
                            "title": {
                                "type": "text",
                                "index": true
                            },
                            "post_stream": {
                                "dynamic": false,
                                "properties": {
                                    "posts": {
                                        "properties": {
                                            "cooked": {
                                                "type": "text",
                                                "index": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }
        """
    return {'items': mapping}


def process_origin(data, template):
    """
    Replace {$origin} in template with a serialized $ORIGIN record
    """
    record = ''
    if data is not None:
        record += '$ORIGIN %s' % data
    return template.replace('{$origin}', record)


def getmembers(object, predicate=None):
    """A safe version of inspect.getmembers that handles missing attributes.

    This is useful when there are descriptor based attributes that for
    some reason raise AttributeError even though they exist.  This happens
    in zope.inteface with the __provides__ attribute.
    """
    results = []
    for key in dir(object):
        try:
            value = getattr(object, key)
        except AttributeError:
            pass
        else:
            if not predicate or predicate(value):
                results.append((key, value))
    results.sort()
    return results


@staticmethod
def normaliseer_geslacht_code(geslacht_code: str) ->str:
    """
        Normaliseert een geslachtscode naar 1 (man), 2 (vrouw) of 9 (anders).

        :param str geslacht_code: De geslachtscode.

        :rtype: str
        """
    if geslacht_code.upper() in ('1', 'M'):
        return '1'
    if geslacht_code.upper() in ('2', 'V', 'F'):
        return '2'
    return '9'


@staticmethod
def list_to_string(recipient):
    """
        Format the recipient for the MIMEMultipart() email type.
        If the recipient is a list, then it returns the list as a
        comma separated string.
        example: input=['you@here.com', 'her@there.com']
                 output='you@there.com, her@there.com'
        """
    if recipient:
        if isinstance(recipient, list):
            return ', '.join(recipient)
        return recipient


@classmethod
def autorenew_deactivate(cls, fqdn):
    """Activate deautorenew"""
    fqdn = fqdn.lower()
    result = cls.call('domain.autorenew.deactivate', fqdn)
    return result


def accuracy_thresh(y_pred, y_true, thresh=0.5, sigmoid=True):
    """Computes accuracy when `y_pred` and `y_true` are the same size."""
    if sigmoid:
        y_pred = y_pred.sigmoid()
    return ((y_pred > thresh).byte() == y_true.byte()).float().mean()


def _display_paste(request, obj):
    """Returns true if the paste button should be displayed.
    """
    return obj.has_permission(request.user, 'add'
        ) and 'clipboard' in request.session.keys()


def _convert_roialign(builder, node, graph, err):
    """
    convert to CoreML CropResize and Pooling Layer:
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L2239
    https://github.com/apple/coremltools/blob/655b3be5cc0d42c3c4fa49f0f0e4a93a26b3e492/mlmodel/format/NeuralNetwork.proto#L1702
    """
    target_height = node.attrs.get('output_height', 1)
    target_width = node.attrs.get('output_width', 1)
    mode = node.attrs.get('mode', 'AVERAGE').upper()
    sampling_ratio = node.attrs.get('sampling_ratio', 0)
    spatial_scale = node.attrs.get('sampling_scale', 1.0)
    if node.inputs[2] in graph.inputs:
        graph.inputs.remove(node.inputs[2])
    builder.add_expand_dims(name=node.name + '_expand_0', input_name=node.
        inputs[0], output_name=node.inputs[0] + '_expanded', axes=[0])
    node.inputs[0] += '_expanded'
    builder.add_expand_dims(name=node.name + '_expand_2', input_name=node.
        inputs[2], output_name=node.inputs[2] + '_expanded', axes=[1])
    node.inputs[2] += '_expanded'
    builder.add_concat_nd(name=node.name + '_concat_indices', input_names=[
        node.inputs[2], node.inputs[1]], output_name=node.inputs[1] +
        '_rois', axis=1)
    node.inputs[1] += '_rois'
    builder.add_expand_dims(name=node.name + '_expand_1', input_name=node.
        inputs[1], output_name=node.inputs[1] + '_expanded', axes=[1, 3, 4])
    node.inputs[1] += '_expanded'
    builder.add_crop_resize(name=node.name + '_crop_resize', input_names=[
        node.inputs[0], node.inputs[1]], output_name=node.outputs[0] +
        '_crop_resized', target_height=target_height * sampling_ratio,
        target_width=target_width * sampling_ratio, mode='ROI_ALIGN_MODE',
        box_indices_mode='CORNERS_WIDTH_FIRST', spatial_scale=spatial_scale)
    builder.add_squeeze(name=node.name + '_squeeze', input_name=node.
        outputs[0] + '_crop_resized', output_name=node.outputs[0] +
        '_crop_resized_squeezed', axes=[1])
    builder.add_pooling(name=node.name + '_pool', height=sampling_ratio,
        width=sampling_ratio, layer_type=mode, input_name=node.outputs[0] +
        '_crop_resized_squeezed', output_name=node.outputs[0],
        stride_height=sampling_ratio, stride_width=sampling_ratio,
        padding_type='VALID')


def upgrade():
    """A no-op migration for marking the Kilo release."""
    pass


@classmethod
def from_knx(cls, raw):
    """Parse/deserialize from KNX/IP raw data."""
    cls.test_bytesarray(raw, 2)
    return raw[0] * 256 + raw[1]


def is_node_parsed(node):
    """Check whether the node has been parsed or still waiting to be parsed."""
    return bool(node.manufacturer_name and node.product_name or node.name)


def beginFlowingFrom(drain, fount):
    """
    To correctly implement drain.flowingFrom you need to do certian things; do
    those things here.

    @param drain: The drain implementing flowingFrom.

    @param fount: The fount flowingFrom was called with.

    @return: L{None}
    """
    if fount is not None:
        outType = fount.outputType
        inType = drain.inputType
        if outType is not None and inType is not None:
            if not inType.isOrExtends(outType):
                raise TypeError(
                    'the output of {fount}, {outType}, is not compatible with the required input type of {drain}, {inType}'
                    .format(inType=inType, outType=outType, fount=fount,
                    drain=drain))
    oldFount = drain.fount
    drain.fount = fount
    if (oldFount is not None and oldFount is not fount and oldFount.drain is
        drain):
        oldFount.flowTo(None)


def cmp(a, b):
    """ trick to get python3 working with cmp """
    return (a > b) - (a < b)


@classmethod
def implement(cls, msg='Please implement'):
    """
        Raises an exception as not implemented
        :param msg: the message to print
        :return:
        """
    print(msg)
    raise NotImplementedError(msg)


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


def demix2(servo1, servo2, gain=0.5):
    """de-mix a mixed servo output"""
    s1 = servo1 - 1500
    s2 = servo2 - 1500
    out1 = (s1 + s2) * gain
    out2 = (s1 - s2) * gain
    return out2 + 1500


@classmethod
def logout(cls, options=None):
    """Wipe credentials"""
    cls.command_sub = 'logout'
    return cls.execute(cls._construct_command(options), output_format='csv')


@classmethod
def count(cls, _search=None, **kwargs):
    """Total number of instances."""
    return cls._apply_filter(**kwargs).count()


def bake_image():
    """Bake image textures of selected objects

    """
    pass


def escapePattern(msg):
    """
    This method escapes regular expression characters in the string.
    And no, this is not re.escape, which would escape many more characters.

    @type msg: string
    @param msg: String that needs to be quoted

    @rtype: string
    @return: Escaped string for use in regular expressions
    """
    escapedStr = msg
    activeChars = ('\\', '[', ']', '{', '}', '(', ')', '*', '+', '?', '^',
        '$', '.', '|')
    for activeChar in activeChars:
        if activeChar in escapedStr:
            escapedStr = escapedStr.replace(activeChar, '\\' + activeChar)
    return escapedStr


def consumeBody():
    """Returns the response body as a string.

        Note that this function can be only requested once, since it is
        constructed from the result.
        """


def sign(x):
    """Sign of a number.  Note only works for single values, not arrays."""
    return -1 if x < 0 else 1


def __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


def get_liked_playlist_id(channel_id):
    """Given a channel_id, returns the user liked playlist id."""
    playlist_id = 'LL' + channel_id[2:]
    return playlist_id


@classmethod
def legal_holds_change_hold_name(cls, val):
    """
        Create an instance of this class set to the
        ``legal_holds_change_hold_name`` tag with value ``val``.

        :param LegalHoldsChangeHoldNameType val:
        :rtype: EventType
        """
    return cls('legal_holds_change_hold_name', val)


def const(x):
    """Return a function that takes any arguments and returns the specified value.

    Parameters
    ----------
    x
        Value to return.

    Returns
    -------
    `function`
    """
    return lambda *args, **kwargs: x


def aa_2(provider):
    """Stop ARTIM timer if running. Close transport connection."""
    provider.timer.stop()
    provider.dul_socket.close()
    provider.dul_socket = None
    return 'Sta1'


def realpath():
    """
        A symbolic-link-free file path that is alias-equivalent to this file
        path.

        @return: a file path.
        """


@staticmethod
def create_edge(node_a, node_b):
    """Creates an edge from a to b - both must be nodes."""
    node_a.outgoing.append(node_b)
    node_b.incoming.append(node_a)


def page_to_offset(params):
    """
    Transforms `page`/`per_page` from `params` to `limit`/`offset` suitable for SQL.

    :param dict params: The dictionary containing `page` and `per_page` values will be added
                        the values `limit` and `offset`.
    """
    if 'page' not in params:
        return
    page = params['page']
    del params['page']
    if 'per_page' in params:
        per_page = params.get('per_page')
        del params['per_page']
    else:
        per_page = params.get('limit', 10)
    params['offset'] = int(per_page) * (int(page) - 1)
    params['limit'] = per_page


def track_color_preset_add(name: str='', remove_active: bool=False):
    """Add or remove a Clip Track Color Preset

    :param name: Name, Name of the preset, used to make the path name
    :type name: str
    :param remove_active: remove_active
    :type remove_active: bool
    """
    pass


def get_shard_number(file_name: str) ->int:
    """Retrieves the shard number from a shard filename."""
    return int(file_name[5:])


def split_h1_string(doc, seps=None, part='1'):
    """Remove unwanted parts from h1 string.

    Headings or titles are often composed of multiple items,
    like 'Murder! - Domestic News - The Local Paper'.
    You want just 'Murder!'.

    Selected items are whitespace stripped.

    :param seps: strings by which heading is separated.
                 if ``None``, default ``' - ', ' : ', ' | '`` is used.

    :param part: which part to select. '1' means first, or index 0.
                 special number '-1' selects last item.

    >>> el = fromstring('
aaa ~ bbb
')
    >>> split_h1_string(el, '~', '2')
    >>> tostring(el)
    '
bbb
'
    >>> el = fromstring('
aaa ~ bbb
')
    >>> split_h1_string(el, '~', '-1')
    >>> tostring(el)
    '
bbb
'
    """
    el = doc.xpath('//h1')[0]
    if seps is None:
        seps = [' - ', ' : ', ' | ']
    if isinstance(seps, str):
        seps = [seps]
    if part == '-1':
        part = '0'
    for sep in seps:
        if sep in el.text:
            el.text = el.text.split(sep)[int(part) - 1].strip()
            break


def getReadGroupString(samtools, inBamVar):
    """Will print the bash command that will extract a given read group string
    from a

    THIS HAS SOME ALTERATIONS FROM THE ORIGINAL AND SHOULD BE TESTED """
    return '$(' + samtools + ' view -H $' + inBamVar + """ 2>> $logFile | grep "@RG"| sed "s:\\t:\\\\t:g"| sed "s:\\t:\\\\t:g\"
"""


def is_indel_len(mut_df):
    """Simply returns a series indicating whether each corresponding mutation
    is an indel.

    Parameters
    ----------
    mut_df : pd.DataFrame
        mutation input file as a dataframe in standard format

    Returns
    -------
    is_indel : pd.Series
        pandas series indicating if mutaitons are indels
    """
    is_indel = (mut_df['Reference_Allele'] == '-') | (mut_df['Tumor_Allele'
        ] == '-')
    return is_indel


def _test_sampdup(t):
    """Check if there are duplicate samples"""
    return t.shape[1] != len(set(t.ids(axis='sample')))


@classmethod
def add_dimension(cls, columns, dimension, dim_pos, values, vdim):
    """
        Adding value dimensions not currently supported by iris interface.
        Adding key dimensions not possible on dense interfaces.
        """
    if not vdim:
        raise Exception('Cannot add key dimension to a dense representation.')
    raise NotImplementedError


def remove_excess_spaces(text):
    """ Removes duplicate spaces from a string """
    return ' '.join(text.split())


def time_now_with_foramt(format='%Y-%m-%d %H:%M:%S'):
    """
    Returning a formatted string of time

    @Args:
    * [format] str, something like %Y-%m-%d %H:%M:%S.%f

    @Returns:
    * [str] the formatted string of time
    """
    import datetime
    return datetime.datetime.now().strftime(format)


@classmethod
def _create_config(cls):
    """
        Creates an ApphookConfig instance

        ``AutoCMSAppMixin.auto_setup['config_fields']`` is used to fill in the data
        of the instance.

        :return: ApphookConfig instance
        """
    return cls.app_config.objects.create(namespace=cls.auto_setup[
        'namespace'], **cls.auto_setup['config_fields'])


def set_value(list_or_dict, key, val, splitval='/'):
    """Sets a value in a possibly nested list or dict object.

    Parameters
    ----------

    key : str
        ``key/to/value``, path like string describing all keys necessary to
        consider to get to the desired value. List indices can also be passed
        here.
    value : object
        Anything you want to put behind :attr:`key`
    list_or_dict : list or dict
        Possibly nested list or dictionary.
    splitval : str
        String that defines the delimiter between keys of the different depth
        levels in :attr:`key`.

    Examples
    --------

    .. code-block:: python

        dol = {"a": [1, 2], "b": {"c": {"d": 1}, "e": 2}}

        # Change existing entry
        set_value(dol, "a/0", 3)
        # {'a': [3, 2], 'b': {'c': {'d': 1}, 'e': 2}}}

        set_value(dol, "b/e", 3)
        # {"a": [3, 2], "b": {"c": {"d": 1}, "e": 3}}

        set_value(dol, "a/1/f", 3)
        # {"a": [3, {"f": 3}], "b": {"c": {"d": 1}, "e": 3}}

        # Append to list
        dol = {"a": [1, 2], "b": {"c": {"d": 1}, "e": 2}}

        set_value(dol, "a/2", 3)
        # {"a": [1, 2, 3], "b": {"c": {"d": 1}, "e": 2}}

        set_value(dol, "a/5", 6)
        # {"a": [1, 2, 3, None, None, 6], "b": {"c": {"d": 1}, "e": 2}}

        # Add key
        dol = {"a": [1, 2], "b": {"c": {"d": 1}, "e": 2}}
        set_value(dol, "f", 3)
        # {"a": [1, 2], "b": {"c": {"d": 1}, "e": 2}, "f": 3}

        set_value(dol, "b/1", 3)
        # {"a": [1, 2], "b": {"c": {"d": 1}, "e": 2, 1: 3}, "f": 3}

        # Raises Error:
        # Appending key to list
        # set_value(dol, 'a/g', 3)  # should raise

        # Fancy Overwriting
        dol = {"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2}

        set_value(dol, "e/f", 3)
        # {"a": [1, 2], "b": {"c": {"d": 1}}, "e": {"f": 3}}

        set_value(dol, "e/f/1/g", 3)
        # {"a": [1, 2], "b": {"c": {"d": 1}}, "e": {"f": [None, {"g": 3}]}}

        # Toplevel new key
        dol = {"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2}
        set_value(dol, "h", 4)
        # {"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2, "h": 4}

        set_value(dol, "i/j/k", 4)
        # {"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2, "h": 4, "i": {"j": {"k": 4}}}

        set_value(dol, "j/0/k", 4)
        # {"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2, "h": 4, "i": {"j": {"k": 4}}, "j": [{"k": 4}], }

        # Toplevel is list new key
        dol = [{"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2}, 2, 3]

        set_value(dol, "0/k", 4)
        # [{"a": [1, 2], "b": {"c": {"d": 1}}, "e": 2, "k": 4}, 2, 3]

        set_value(dol, "0", 1)
        # [1, 2, 3]

    """
    keys = []
    for k in key.split(splitval):
        try:
            newkey = int(k)
        except:
            newkey = k
        keys.append(newkey)
    next_keys = keys[1:] + [None]
    is_leaf = [(False) for k in keys]
    is_leaf[-1] = True
    next_is_leaf = is_leaf[1:] + [None]
    parent = None
    last_key = None
    for key, leaf, next_key, next_leaf in zip(keys, is_leaf, next_keys,
        next_is_leaf):
        if isinstance(key, str):
            if isinstance(list_or_dict, list):
                raise ValueError('Trying to add a key to a list')
            elif not isinstance(list_or_dict, dict) or key not in list_or_dict:
                list_or_dict[key] = {} if isinstance(next_key, str) else []
        elif isinstance(list_or_dict, list):
            if key >= len(list_or_dict):
                n_add = key - len(list_or_dict) + 1
                list_or_dict += [None] * n_add
        elif not isinstance(list_or_dict, dict):
            if parent is None:
                list_or_dict = [None] * (key + 1)
            else:
                parent[last_key] = [None] * (key + 1)
        if leaf:
            list_or_dict[key] = val
        else:
            if not isinstance(list_or_dict[key], (dict, list)):
                list_or_dict[key] = {} if isinstance(next_key, str) else [None
                    ] * (next_key + 1)
            parent = list_or_dict
            last_key = key
            list_or_dict = list_or_dict[key]


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


@classmethod
def from_clang_fixit(cls, fixit, file):
    """
        Creates a Diff object from a given clang fixit and the file contents.

        :param fixit: A cindex.Fixit object.
        :param file:  A list of lines in the file to apply the fixit to.
        :return:      The corresponding Diff object.
        """
    assert isinstance(file, (list, tuple))
    oldvalue = '\n'.join(file[fixit.range.start.line - 1:fixit.range.end.line])
    endindex = fixit.range.end.column - len(file[fixit.range.end.line - 1]) - 1
    newvalue = oldvalue[:fixit.range.start.column - 1
        ] + fixit.value + oldvalue[endindex:]
    new_file = file[:fixit.range.start.line - 1] + type(file)(newvalue.
        splitlines(True)) + file[fixit.range.end.line:]
    return cls.from_string_arrays(file, new_file)


def _extrap_spec(interpval, lower_val, upper_val, lower_thru, upper_thru):
    """Extrapolate using two spectra to parameter at given value.
    Called by :func:`interpolate_spectral_element`.
    Also see :func:`_interp_spec`.

    """
    m = (upper_thru - lower_thru) / (upper_val - lower_val)
    b = lower_thru - m * lower_val
    return m * interpval + b


def find_unassigned_table_cell(table):
    """
    Search through a table and return the first [row, column] pair
    who's value is None.

    Parameters
    ----------
    table : list of lists of str

    Returns
    -------
    list of int
        The row column pair of the None type cell
    """
    for row in range(len(table)):
        for column in range(len(table[row])):
            if table[row][column] is None:
                return row, column
    return row, column


def get_head(name, line, releases):
    """Parses content from:

    https://github.com/PyMySQL/mysqlclient-python/blob/master/HISTORY.md

    Each HEAD line looks like:

        What's new in 1.3.10

    """
    if not line.strip().startswith("What's new in"):
        return False
    return line.strip().rsplit(None, 1)[1]


def __call__(context):
    """Returns a default value for the field."""


def add_to_list_if_not_none(item, list):
    """
    Add a value to a list if it is not None
    :param item: the item to add
    :param list: the list to append it to
    :return: nothing
    """
    if item is not None:
        list.append(item)


def cast_oct(s):
    """Cast a string value to an octal.

    Args:
        s (str): String to cast.

    Returns:
        int: Base 8 integer for provided string.

    """
    return int(s, 8)


def hashPassword(password):
    """
        Returns a hashed version of the password
        """


def seams_from_islands(mark_seams: bool=True, mark_sharp: bool=False):
    """Set mesh seams according to island setup in the UV editor

    :param mark_seams: Mark Seams, Mark boundary edges as seams
    :type mark_seams: bool
    :param mark_sharp: Mark Sharp, Mark boundary edges as sharp
    :type mark_sharp: bool
    """
    pass


def word_count():
    """Return the number of unique terms in the lexicon."""


def updateNams(nams, removed_seqs):
    """
    Takes nams, a list of sequence names in the input file, and removed_seqs,
    a set of sequences which have been removed from the file and subtracts
    the removed sequences from nams while maintaining the order.

    Parameters
    ----------
    nams: list
        A list of sequence names in the input file
    removed_seqs: set
        Set of sequence names to remove

    Returns
    -------
    nams2: list
        A list of sequence names which have not been removed
    """
    nams2 = []
    for nam in nams:
        if nam not in removed_seqs:
            nams2.append(nam)
    return nams2


def format_size(num):
    """Format byte-sizes.

    .. seealso:: http://stackoverflow.com/a/1094933
    """
    for x in ['bytes', 'KB', 'MB', 'GB']:
        if num < 1024.0 and num > -1024.0:
            return '%3.1f%s' % (num, x)
        num /= 1024.0
    return '%3.1f%s' % (num, 'TB')


@classmethod
def range(cls, start, end=None, step=1):
    """Create a Array from range.

        >>> Array.range(2, 10, 2).to_list()
        [2, 4, 6, 8]
        >>> Array.range(3).to_list()
        [0, 1, 2]
        """
    if end is None:
        start, end = 0, start
    return cls(range(start, end, step))


def formula_2005_01_01(foyer_fiscal, period, parameters):
    """
        Investissements dans les DOM-TOM dans le cadre d'une entreprise.
        """
    f7ur = foyer_fiscal('f7ur', period)
    f7oz = foyer_fiscal('f7oz', period)
    f7pz = foyer_fiscal('f7pz', period)
    f7qz = foyer_fiscal('f7qz_2012', period)
    f7rz = foyer_fiscal('f7rz_2010', period)
    return f7ur + f7oz + f7pz + f7qz + f7rz


def permalink(mlist, msg):
    """Return the url to the message in the archive.

        This url points directly to the message in the archive.  This method
        only calculates the url, it does not actually archive the message.

        If the archiver is not web-accessible, return None.

        :param mlist: The IMailingList object.
        :param msg: The message object.
        :returns: The url string or None if the message's archive url cannot
            be calculated.
        """


def is_maximal_matching(G, matching):
    """Determines whether the given set of edges is a maximal matching.

    A matching is a subset of edges in which no node occurs more than
    once. The cardinality of a matching is the number of matched edges.
    A maximal matching is one where one cannot add any more edges
    without violating the matching rule.

    Parameters
    ----------
    G : NetworkX graph
        The graph on which to check the maximal matching.

    edges : iterable
        A iterable of edges.

    Returns
    -------
    is_matching : bool
        True if the given edges are a maximal matching.

    Example
    -------
    This example checks two sets of edges, both derived from a
    single Chimera unit cell, for a matching. The first set (a matching) is
    a subset of the second, which was found using the `min_maximal_matching()`
    function.

    >>> import dwave_networkx as dnx
    >>> G = dnx.chimera_graph(1, 1, 4)
    >>> dnx.is_matching({(0, 4), (2, 7)})
    True
    >>> dnx.is_maximal_matching(G,{(0, 4), (2, 7)})
    False
    >>> dnx.is_maximal_matching(G,{(0, 4), (1, 5), (2, 7), (3, 6)})
    True

    """
    touched_nodes = set().union(*matching)
    if len(touched_nodes) != len(matching) * 2:
        return False
    for u, v in G.edges:
        if u not in touched_nodes and v not in touched_nodes:
            return False
    return True


def subject():
    """Content subject.
        """


@classmethod
def destroy(cls, *ids):
    """Delete the records with the given ids
        :type ids: list
        :param ids: primary key ids of records
        """
    for pk in ids:
        cls.find(pk).delete()
    cls.session.flush()


def cell_has_code(lines):
    """Is there any code in this cell?"""
    for i, line in enumerate(lines):
        stripped_line = line.strip()
        if stripped_line.startswith('#'):
            continue
        if not stripped_line:
            if i > 0 and not lines[i - 1].strip():
                return False
            continue
        return True
    return False


@staticmethod
def get_es_id(page):
    """
        An ID built with the node path and the position of this organization in the taxonomy:
            - P: parent, the organization has children
            - L: leaf, the organization has no children

        For example: a parent organization `P_00010002` and its child `L_000100020001`.
        """
    return '{type:s}-{path:s}'.format(type='L' if page.node.is_leaf() else
        'P', path=page.node.path)


def swap_data():
    """Swap 2 sequencer strips

    """
    pass


def nlmsg_set_src(msg, addr):
    """https://github.com/thom311/libnl/blob/libnl3_2_25/lib/msg.c#L599"""
    msg.nm_src = addr


def get_iter(dictionary):
    """
    Just a wrapper method that handles Python2->Python3 dict iterations
    :param dictionary: (Dict)
    :return: (Dict)
    """
    try:
        return dictionary.iteritems()
    except AttributeError:
        return dictionary.items()


@staticmethod
def percent_vat(code):
    """
        Returns the VAT percent according to code
        :param code:
        :return: float value
        """
    if code == 1:
        return 10.05
    elif code == 2:
        return 21
    elif code == 3:
        return 70


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


def chrome(_os=None, os_bit=None):
    """
    chrome driver info
    :param _os: system
    :param os_bit: system bit
    :return:
    """
    latest_version = '80.0.3987.106'
    base_download = (
        'https://cdn.npm.taobao.org/dist/chromedriver/%s/chromedriver_%s%s.zip'
        )
    download = base_download % (latest_version, _os, os_bit)
    return 'chromedriver', download, latest_version


def error_message(e, message=None, cause=None):
    """
    Formats exception message + cause
    :param e:
    :param message:
    :param cause:
    :return: formatted message, includes cause if any is set
    """
    if message is None and cause is None:
        return None
    elif message is None:
        return '%s, caused by %r' % (e.__class__, cause)
    elif cause is None:
        return message
    else:
        return '%s, caused by %r' % (message, cause)


def _stops_definitions(df):
    """
    Append GTFS definitions for stop columns to stop dataframe

    Parameters
    ----------
    df : pandas:DataFrame
        stops dataframe

    Returns
    -------
    df : pandas.DataFrame
    """
    if 'location_type' in df.columns:
        stops_location_type = {(0): 'stop', (1): 'station', (2):
            'station entrance'}
        df['location_type_desc'] = df['location_type'].map(stops_location_type
            .get)
    if 'wheelchair_boarding' in df.columns:
        stops_wheelchair_boardings = {(0):
            'No accessibility information available for the stop', (1):
            'At least some vehicles at this stop can be boarded by a rider in a wheelchair'
            , (2): 'Wheelchair boarding is not possible at this stop'}
        df['wheelchair_boarding_desc'] = df['wheelchair_boarding'].map(
            stops_wheelchair_boardings.get)
    return df


def get_essential_spdx_tokens():
    """
    Yield essential SPDX tokens.
    """
    yield 'spdx'
    yield 'license'
    yield 'identifier'
    yield 'licenseref'


def sum(input, dim, keepdims=False):
    """Reduce sum the input tensor along the given dim.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    dim : int
        The reduce dim.
    keepdims : bool
        Whether to keep the summed dimension.

    Returns
    -------
    Tensor
        A framework-specific tensor.
    """
    pass


@staticmethod
def _identify_eds_ing(first, second):
    """Find nodes connecting adjacent edges.

        Args:
            first (Edge):
                Edge object representing the first edge.
            second (Edge):
                Edge object representing the second edge.

        Returns:
            tuple[int, int, set[int]]:
                The first two values represent left and right node
                indicies of the new edge. The third value is the new dependence set.
        """
    A = set([first.L, first.R])
    A.update(first.D)
    B = set([second.L, second.R])
    B.update(second.D)
    depend_set = A & B
    left, right = sorted(list(A ^ B))
    return left, right, depend_set


def weightedUnion(c1, c2, weight1=1, weight2=1):
    """Compute the weighted union of c1 and c2.

        If c1 and c2 are None, the output is (0, None).

        If c1 is None and c2 is not None, the output is (weight2, c2).

        If c1 is not None and c2 is None, the output is (weight1, c1).

        Else, and hereafter, c1 is not None and c2 is not None.

        If c1 and c2 are both sets, the output is 1 and the (unweighted)
        union of the sets.

        Else the output is 1 and a Bucket whose keys are the union of c1 and
        c2's keys, and whose values are::

          v1*weight1 + v2*weight2

          where:

            v1 is 0        if the key is not in c1
                  1        if the key is in c1 and c1 is a set
                  c1[key]  if the key is in c1 and c1 is a mapping

            v2 is 0        if the key is not in c2
                  1        if the key is in c2 and c2 is a set
                  c2[key]  if the key is in c2 and c2 is a mapping

        Note that c1 and c2 must be collections.
        """


def Nu_vertical_plate_Churchill(Pr, Gr):
    """Calculates Nusselt number for natural convection around a vertical
    plate according to the Churchill-Chu [1]_ correlation, also presented in
    [2]_. Plate must be isothermal; an alternate expression exists for constant
    heat flux.

    .. math::
        Nu_{L}=\\left[0.825+\\frac{0.387Ra_{L}^{1/6}}
        {[1+(0.492/Pr)^{9/16}]^{8/27}}\\right]^2

    Parameters
    ----------
    Pr : float
        Prandtl number [-]
    Gr : float
        Grashof number [-]

    Returns
    -------
    Nu : float
        Nusselt number with respect to length, [-]

    Notes
    -----
    Although transition from laminar to turbulent is discrete in reality, this
    equation provides a smooth transition in value from laminar to turbulent.
    Checked with the original source.

    Can be applied to vertical cylinders as well, subject to the criteria below:

    .. math::
        \\frac{D}{L}\\ge \\frac{35}{Gr_L^{1/4}}

    Examples
    --------
    From [2]_, Example 9.2, matches:

    >>> Nu_vertical_plate_Churchill(0.69, 2.63E9)
    147.16185223770603

    References
    ----------
    .. [1] Churchill, Stuart W., and Humbert H. S. Chu. "Correlating Equations
       for Laminar and Turbulent Free Convection from a Vertical Plate."
       International Journal of Heat and Mass Transfer 18, no. 11
       (November 1, 1975): 1323-29. doi:10.1016/0017-9310(75)90243-4.
    .. [2] Bergman, Theodore L., Adrienne S. Lavine, Frank P. Incropera, and
       David P. DeWitt. Introduction to Heat Transfer. 6E. Hoboken, NJ:
       Wiley, 2011.
    """
    Ra = Pr * Gr
    term = 0.825 + 0.387 * Ra ** (1 / 6.0) * (1.0 + (Pr / 0.492) ** -0.5625
        ) ** (-8.0 / 27.0)
    return term * term


def unassign(username):
    """
        Given user login name of existing user, remove user from group.
        Raise ValueError if user is not a member of the group.
        """


def my_model(x_1, x_2):
    """
    Represents f from above
    """
    return x_1 ** x_2


@staticmethod
def row_copy(src, dest, dbname, drop=True):
    """
        Copy each row in the collection
        :param src: The source (from) DB name
        :param dest: The destination (to) DB name
        :param dbname:
        :param drop:
        :return:
        """
    db = src.get_database(dbname)
    dbdest = dest.get_database(dbname)
    if drop:
        for collname in dbdest.collection_names():
            if 'system.' not in collname.lower():
                print('Dropping collection ...')
                dbdest.drop_collection(collname)
    print('Running row copy ...')
    progress = 1
    for collname in db.collection_names():
        print('.' * progress)
        progress += 1
        coll = db.get_collection(collname)
        targ = dbdest.get_collection(collname)
        rows = coll.find({})
        for row in rows:
            targ.insert(row)


def list_numbering_start(attrs):
    """extract numbering from list element attributes"""
    if 'start' in attrs:
        return int(attrs['start']) - 1
    else:
        return 0


def iterate(func, x):
    """ Repeatedly apply a function func onto an original input

    Yields x, then func(x), then func(func(x)), then func(func(func(x))), etc..

    >>> def inc(x):  return x + 1
    >>> counter = iterate(inc, 0)
    >>> next(counter)
    0
    >>> next(counter)
    1
    >>> next(counter)
    2

    >>> double = lambda x: x * 2
    >>> powers_of_two = iterate(double, 1)
    >>> next(powers_of_two)
    1
    >>> next(powers_of_two)
    2
    >>> next(powers_of_two)
    4
    >>> next(powers_of_two)
    8
    """
    while True:
        yield x
        x = func(x)


@classmethod
def serialize(cls, value, writer=None):
    """
        Serialize a python object to GraphSON.

        e.g 'P42DT10H5M37S'
        e.g. {'key': value}

        :param value: The python object to serialize.
        :param writer: A graphson serializer for recursive types (Optional)
        """
    serializer = cls.get_serializer(value)
    if serializer:
        return serializer.serialize(value, writer or cls)
    return value


@staticmethod
def get_kernel_function_name(operator_name, neighbourhood_name,
    similarity_measure_name):
    """
        Get the full name of the kernel function to select.

        :param operator_name: Name of the operator.
        :param neighbourhood_name: Name of the neighbourhood.
        :param similarity_measure_name: Name of the similarity measure.
        :rtype: String.
        """
    if neighbourhood_name and similarity_measure_name:
        return '_'.join([operator_name, neighbourhood_name,
            similarity_measure_name])
    return operator_name


@classmethod
def _decode_payload(cls, octets, errors):
    """Called from Record._decode with the PAYLOAD of an NDEF Text
        Record. Returns a new TextRecord instance initialized with the
        decoded data fields. Raises ndef.DecodeError if any of the
        decoding steps failed. All decoding errors are handled 'strict'.

        """
    FLAG = cls._decode_struct('B', octets)
    if FLAG & 63 == 0:
        raise cls._decode_error('language code length can not be zero')
    if FLAG & 63 >= len(octets):
        raise cls._decode_error('language code length exceeds payload')
    UTFX = 'UTF-16' if FLAG >> 7 else 'UTF-8'
    LANG = octets[1:1 + (FLAG & 63)]
    try:
        TEXT = octets[1 + len(LANG):].decode(UTFX)
    except UnicodeDecodeError:
        raise cls._decode_error("can't be decoded as {}".format(UTFX))
    return cls(TEXT, LANG, UTFX)


def add_nodes(graph, nodes):
    """ Add node(s) to graph

    Args:
        graph (Graph): Graph to add node(s) to
        nodes (list): List of nodes

    Returns:
        Graph: Return the modified graph

    """
    for n in nodes:
        if isinstance(n, tuple):
            graph.node(n[0], **n[1])
        else:
            graph.node(n)
    return graph


def p_dictorsetmaker_star_2(p):
    """dictorsetmaker_star : dictorsetmaker_star COMMA test COLON test"""
    keys, values = p[1]
    p[0] = keys + [p[3]], values + [p[5]]


def pytest_keyboard_interrupt(excinfo):
    """ called for keyboard interrupt. """


def fahrToKelv(temp):
    """
    takes a temperature `temp` in fahrenheit and returns it in Kelvin
    """
    kelvin = 5.0 / 9.0 * (temp - 32.0) + 273.15
    return kelvin


def restart(c):
    """
    Restart the Postfix mail service
    """
    c.sudo('systemctl restart postfix.service')


def clear(ren):
    """ Remove all actors from the renderer
    """
    ren.RemoveAllViewProps()


def save_stats(instance, migration, info, remaining):
    """Save migration stats to the database

    :param instance: a nova.objects.Instance
    :param migration: a nova.objects.Migration
    :param info: a nova.virt.libvirt.guest.JobInfo
    :param remaining: percentage data remaining to transfer

    Update the migration and instance objects with
    the latest available migration stats
    """
    migration.memory_total = info.memory_total
    migration.memory_processed = info.memory_processed
    migration.memory_remaining = info.memory_remaining
    migration.disk_total = info.disk_total
    migration.disk_processed = info.disk_processed
    migration.disk_remaining = info.disk_remaining
    migration.save()
    instance.progress = 100 - remaining
    instance.save()


def pad_line(line):
    """Helper function to pad line to 80 characters in case it is shorter"""
    size_of_line = len(line)
    if size_of_line < 80:
        padding = 80 - size_of_line + 1
        line = line.strip('\n') + ' ' * padding + '\n'
    return line[:81]


def _rnn_param_concat(*data, **kwargs):
    """
    This function support variable length of positional input.

    Parameters
    ----------
    data : Symbol[]
        List of arrays to concatenate
    dim : int, optional, default='1'
        the dimension to be concated.

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


def query_recently_bought(ticker, accapi, options):
    """Looking back 30 days for purchases that would cause wash sales"""
    wash_pattern = options.get('wash_pattern', '')
    account_field = options.get('account_field', 'LEAF(account)')
    wash_pattern_sql = 'AND account ~ "{}"'.format(wash_pattern
        ) if wash_pattern else ''
    sql = (
        """
    SELECT
        {account_field} as account,
        date as acquisition_date,
        DATE_ADD(date, 30) as until,
        units(sum(position)) as units,
        cost(sum(position)) as basis
      WHERE
        number > 0 AND
        date >= DATE_ADD(TODAY(), -30) AND
        currency = "{ticker}"
        {wash_pattern_sql}
      GROUP BY {account_field},date,until
      ORDER BY date DESC
      """
        .format(**locals()))
    rtypes, rrows = accapi.query_func(sql)
    return rtypes, rrows


def indices2one_hot(indices, nb_classes):
    """
    Convert an iterable of indices to one-hot encoded list.

    You might also be interested in sklearn.preprocessing.OneHotEncoder

    Parameters
    ----------
    indices : iterable
        iterable of indices
    nb_classes : int
        Number of classes
    dtype : type

    Returns
    -------
    one_hot : list

    Examples
    --------
    >>> indices2one_hot([0, 1, 1], 3)
    [[1, 0, 0], [0, 1, 0], [0, 1, 0]]
    >>> indices2one_hot([0, 1, 1], 2)
    [[1, 0], [0, 1], [0, 1]]
    """
    if nb_classes < 1:
        raise ValueError('nb_classes={}, but positive number expected'.
            format(nb_classes))
    one_hot = []
    for index in indices:
        one_hot.append([0] * nb_classes)
        one_hot[-1][index] = 1
    return one_hot


def createLink(nodeA, nodeB):
    """Create a link between two node objects.

    This function can be empty. Used for optional complex database quieries.

    Parameters:
        nodeA (MgvNode): source node.
        nodeB (MgvNode): destination node.
    """
    return


def getRestPolefigDerv(HKL, Grid, SHCoeff):
    """default doc string

    :param type name: description

    :returns: type name: description

    """
    pass


def get_overlap(a, b):
    """
    get overlap between ranges
    """
    return max(0, min(a[1], b[1]) - max(a[0], b[0]))


def dummy_callback(*_, **__):
    """ A dummy callable. """
    return 1


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


@classmethod
def device_approvals_remove_exception(cls, val):
    """
        Create an instance of this class set to the
        ``device_approvals_remove_exception`` tag with value ``val``.

        :param DeviceApprovalsRemoveExceptionType val:
        :rtype: EventType
        """
    return cls('device_approvals_remove_exception', val)


def p_case_separator(p):
    """case_separator : COLON
                      | SEMI"""
    pass


def read_pod_raw(pod, page_start, npages, raw_bytes):
    """Reads npages number of pages from pod, returns
    initial raw bytes combined with bytes read"""
    if npages < 1:
        raise AttributeError('Number of pages cannot be less than 0')
    if npages > 15:
        raise AttributeError('Number of pages cannot exceed 16 (8192 bytes)')
    page_size = 512
    adr = page_start * page_size
    nbytes = npages * page_size
    response = pod.read_flash(adr, nbytes)
    response = response[4:-2]
    datab = response.encode()
    for i in range(npages):
        start = i * page_size
        end = start + page_size
        raw_bytes = raw_bytes + datab[start:end]
    return raw_bytes


def lower_first(text):
    """Converts the first character of string to lower case.

    Args:
        text (str): String passed in by the user.

    Returns:
        str: String in which the first character is converted to lower case.

    Example:

        >>> lower_first('FRED')
        'fRED'
        >>> lower_first('Foo Bar')
        'foo Bar'
        >>> lower_first('1foobar')
        '1foobar'
        >>> lower_first(';foobar')
        ';foobar'

    .. versionadded:: 4.0.0
    """
    return text[:1].lower() + text[1:]


@classmethod
def validateTagAndValue(cls, tag, value):
    """validate the given tag / value based on the specs in the documentation"""
    if len(tag) == 0:
        raise Exception('Tag may not be empty')
    if len(value) == 0:
        raise Exception('Value for tag "{tag}" may not be empty'.format(tag
            =tag))
    for char in cls.prohibitedTagChars:
        if char in tag:
            raise Exception('Character "{char}" is not allowed in tag "{tag}"'
                .format(char=char, tag=tag))
    if ';' in value:
        raise Exception(
            'Character ";" is not allowed in value "{value}" of tag {tag}'.
            format(value=value, tag=tag))
    if value[0] == '~':
        raise Exception(
            'Tag values are not allowed to start with "~" in tag "{tag}"'.
            format(tag=tag))


def render_pep440_pre(pieces):
    """TAG[.post.devDISTANCE] -- No -dirty.

    Exceptions:
    1: no tags. 0.post.devDISTANCE
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '.post.dev%d' % pieces['distance']
    else:
        rendered = '0.post.dev%d' % pieces['distance']
    return rendered


def load_ssl_context(cert_file, pkey_file):
    """Loads an SSL context from a certificate and private key file."""
    from OpenSSL import SSL
    ctx = SSL.Context(SSL.SSLv23_METHOD)
    ctx.use_certificate_file(cert_file)
    ctx.use_privatekey_file(pkey_file)
    return ctx


def blue(string):
    """foreground color to blue"""
    return '\x1b[34m' + string + '\x1b[0m'


@classmethod
def all_events(cls):
    """
        Return all events that all subclasses have so far registered to publish.
        """
    all_evts = set()
    for cls, evts in cls.__all_events__.items():
        all_evts.update(evts)
    return all_evts


@staticmethod
def _entropy_params_check(metric, error_msg):
    """
        Check the definition of a entropy metric for consistency, this will
        rise an assertion error if any error is met.

        :param metric: Entropy metric in a dict form.
        :type metric: dict
        :param error_msg: Error message to return in case of error.
        :type error_msg: str
        """
    assert metric['metric'] == 'entropy', error_msg
    assert len(metric) == 2 and 'column' in metric, error_msg
    col = metric['column']
    assert type(col) is int or type(col) is str, error_msg


def parse(raw_message):
    """Breaks a message from an IRC server into components.

    Parameters
    ----------
    raw_message: str
        The raw message received from the IRC server.

    Returns
    -------
    nick: str
        The nick name of the sender.
    host: str
        The host of the IRC message (nick!user@host).
    command: str
        The IRC command.
    target: str
        The target to which the message was sent (usually #channel or nick).
    text: str
        The text sent (the last value in `args`).
    args: list
        The arguments in the IRC message.
    """
    host = ''
    if not raw_message:
        raise Exception('Cannot parse an empty message.')
    if raw_message[0] == ':':
        host, raw_message = raw_message[1:].split(' ', 1)
    if raw_message.find(' :') != -1:
        raw_message, trailing = raw_message.split(' :', 1)
        args = raw_message.split()
        args.append(trailing)
    else:
        args = raw_message.split()
    command = args.pop(0)
    nick = host.split('!', 2)[0] if '!' in host else ''
    target = args[0] if len(args) > 0 else ''
    text = args[-1] if len(args) > 0 else ''
    return nick, host, command, target, text, args


def from_bool_to_string(boolean):
    """Convert a bool to a string representation

    :param boolean: bool to convert
    :type boolean: bool
    :return: if boolean '1' ,else '0'
    :rtype: str
    """
    if boolean:
        return '1'
    return '0'


def INDEX_OF_BYTES(string_expression, substring_expression, start=None, end
    =None):
    """
    Searches a string for an occurence of a substring and returns the UTF-8 byte index (zero-based) of the first occurence.
    If the substring is not found, returns -1.
    https://docs.mongodb.com/manual/reference/operator/aggregation/indexOfBytes/
    for more details
    :param string_expression: The string or expression of string
    :param substring_expression: The string or expression of substring
    :param start: An integral number (or expression) that specifies the starting index position for the search.
    :param end: An integral number (or expression) that specifies the ending index position for the search.
    :return: Aggregation operator
    """
    res = [string_expression, substring_expression]
    if start is not None:
        res.append(start)
    if end is not None:
        res.append(end)
    return {'$indexOfBytes': res}


def linefeed2br(s):
    """Convert linefeeds to
 tags.

    Markdown uses
 tags for linebreaks in tables. This
    function allows to convert a text with linebreaks accordingly.

    Args:
        s (str): string to convert

    returns:
        str: a string with
 tags for linefeeds
    """
    r = None
    for line in iter(s.splitlines()):
        if r is None:
            r = line.strip('\n ')
        else:
            r = r + '
' + line.strip('\n ')
    if r is None:
        r = ''
    return r


def get_user(username):
    """ Returns the :py:class:`IUser` with the specified username or None
        """


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


def cdriver2filetype(driver):
    """Convert a connection driver to a file type.

    Args:
        driver (str): The name of the connection driver.

    Returns:
        str: The corresponding file type for the driver.

    """
    _legacy = {'FileInputDriver': 'binary', 'FileOutputDriver': 'binary',
        'AsciiMapInputDriver': 'map', 'AsciiMapOutputDriver': 'map',
        'AsciiFileInputDriver': 'ascii', 'AsciiFileOutputDriver': 'ascii',
        'AsciiTableInputDriver': 'table', 'AsciiTableOutputDriver': 'table',
        'PandasFileInputDriver': 'pandas', 'PandasFileOutputDriver':
        'pandas', 'PickleFileInputDriver': 'pickle',
        'PickleFileOutputDriver': 'pickle', 'PlyFileInputDriver': 'ply',
        'PlyFileOutputDriver': 'ply', 'ObjFileInputDriver': 'obj',
        'ObjFileOutputDriver': 'obj', 'MatInputDriver': 'mat',
        'MatOutputDriver': 'mat'}
    if driver in _legacy:
        return _legacy[driver]
    raise ValueError('%s is not a registered connection driver.' % driver)


def get_instance_snapshots(pageToken=None):
    """
    Returns all instance snapshots for the user's account.
    See also: AWS API Documentation

    :example: response = client.get_instance_snapshots(
        pageToken='string'
    )

    :type pageToken: string
    :param pageToken: A token used for advancing to the next page of results from your get instance snapshots request.

    :rtype: dict
    :return: {
        'instanceSnapshots': [
            {
                'name': 'string',
                'arn': 'string',
                'supportCode': 'string',
                'createdAt': datetime(2015, 1, 1),
                'location': {
                    'availabilityZone': 'string',
                    'regionName': 'us-east-1'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-central-1'|'ap-south-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-northeast-1'|'ap-northeast-2'
                },
                'resourceType': 'Instance'|'StaticIp'|'KeyPair'|'InstanceSnapshot'|'Domain'|'PeeredVpc',
                'state': 'pending'|'error'|'available',
                'progress': 'string',
                'fromInstanceName': 'string',
                'fromInstanceArn': 'string',
                'fromBlueprintId': 'string',
                'fromBundleId': 'string',
                'sizeInGb': 123
            },
        ],
        'nextPageToken': 'string'
    }

    """
    pass


@classmethod
def from_str(cls, line: str) ->'ImageVersionConfig':
    """Instantiate from a configuration line."""
    parts = line.split()
    assert len(parts
        ) == 4, f'The configuration line "{line}" should have 4 parts'
    return cls(format=parts[0], width=parts[1], height=parts[2], name=parts[3])


def get_main_app_sub_parser(parent_parser):
    """
    Creates and adds a sub_parser to parent_parser.
    Returns the sub_parser

    :param parent_parser: Parser to add the sub_parser to
    :type parent_parser: argparse.ArgumentParser
    :return: Sub Parser
    :rtype: argparse.ArgumentParser
    """
    sub_parser = parent_parser.add_subparsers(title='subcommands',
        description='one of these subcommands must be provided', metavar='',
        dest='cmd')
    return sub_parser


def getDiscoItems(requestor, target, nodeIdentifier=''):
    """
        Get contained items for this entity, node.

        @param requestor: The entity the request originated from.
        @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>}
        @param target: The target entity to which the request is made.
        @type target: L{JID<twisted.words.protocols.jabber.jid.JID>}
        @param nodeIdentifier: The optional identifier of the node at this
                               entity to retrieve the identify and features of.
                               The default is C{''}, meaning the root node.
        @type nodeIdentifier: C{unicode}
        """


def Fplan(A, Phi, Fstar, Rp, d, AU=False):
    """
    Planetary flux function

    Parameters
    ----------
    A : float or array-like
        Planetary geometric albedo
    Phi : float
        Planetary phase function
    Fstar : float or array-like
        Stellar flux [W/m**2/um]
    Rp : float
        Planetary radius [Earth radii]
    d : float
        Distance to star [pc]
    AU : bool, optional
        Flag that indicates d is in AU

    Returns
    -------
    Fplan : float or array-like
        Planetary flux [W/m**2/um]
    """
    Re = 6371000.0
    ds = 3.08567e+16
    if AU:
        ds = 149597900000.0
    return A * Phi * Fstar * (Rp * Re / d / ds) ** 2.0


def gcd2(a, b):
    """Greatest common divisor using Euclid's algorithm."""
    while a:
        a, b = b % a, a
    return b


def add_facet_to_object(DirectoryArn=None, SchemaFacet=None,
    ObjectAttributeList=None, ObjectReference=None):
    """
    Adds a new  Facet to an object.
    See also: AWS API Documentation

    :example: response = client.add_facet_to_object(
        DirectoryArn='string',
        SchemaFacet={
            'SchemaArn': 'string',
            'FacetName': 'string'
        },
        ObjectAttributeList=[
            {
                'Key': {
                    'SchemaArn': 'string',
                    'FacetName': 'string',
                    'Name': 'string'
                },
                'Value': {
                    'StringValue': 'string',
                    'BinaryValue': b'bytes',
                    'BooleanValue': True|False,
                    'NumberValue': 'string',
                    'DatetimeValue': datetime(2015, 1, 1)
                }
            },
        ],
        ObjectReference={
            'Selector': 'string'
        }
    )

    :type DirectoryArn: string
    :param DirectoryArn: [REQUIRED]
            The Amazon Resource Name (ARN) that is associated with the Directory where the object resides. For more information, see arns .

    :type SchemaFacet: dict
    :param SchemaFacet: [REQUIRED]
            Identifiers for the facet that you are adding to the object.
            SchemaArn (string) --The ARN of the schema that contains the facet.
            FacetName (string) --The name of the facet.

    :type ObjectAttributeList: list
    :param ObjectAttributeList: Attributes on the facet that you are adding to the object.
            (dict) --The combination of an attribute key and an attribute value.
            Key (dict) -- [REQUIRED]The key of the attribute.
            SchemaArn (string) -- [REQUIRED]The Amazon Resource Name (ARN) of the schema that contains the facet and attribute.
            FacetName (string) -- [REQUIRED]The name of the facet that the attribute exists within.
            Name (string) -- [REQUIRED]The name of the attribute.
            Value (dict) -- [REQUIRED]The value of the attribute.
            StringValue (string) --A string data value.
            BinaryValue (bytes) --A binary data value.
            BooleanValue (boolean) --A Boolean data value.
            NumberValue (string) --A number data value.
            DatetimeValue (datetime) --A date and time value.

    :type ObjectReference: dict
    :param ObjectReference: [REQUIRED]
            A reference to the object you are adding the specified facet to.
            Selector (string) --A path selector supports easy selection of an object by the parent/child links leading to it from the directory root. Use the link names from each parent/child link to construct the path. Path selectors start with a slash (/) and link names are separated by slashes. For more information about paths, see Accessing Objects . You can identify an object in one of the following ways:
            $ObjectIdentifier - An object identifier is an opaque string provided by Amazon Cloud Directory. When creating objects, the system will provide you with the identifier of the created object. An object s identifier is immutable and no two objects will ever share the same object identifier
            /some/path - Identifies the object based on path
            #SomeBatchReference - Identifies the object in a batch call

    :rtype: dict
    :return: {}

    :returns:
    (dict) --

    """
    pass


def get_form_initial(form_class):
    """ Return initial dict for given form class """
    result = {}
    form = form_class()
    for field in form:
        result[field.name] = field.value()
    return result


def stroke_smooth(repeat: int=1, factor: float=0.5, only_selected: bool=
    True, smooth_position: bool=True, smooth_thickness: bool=True,
    smooth_strength: bool=False, smooth_uv: bool=False):
    """Smooth selected strokes

    :param repeat: Repeat
    :type repeat: int
    :param factor: Factor
    :type factor: float
    :param only_selected: Selected Points, Smooth only selected points in the stroke
    :type only_selected: bool
    :param smooth_position: Position
    :type smooth_position: bool
    :param smooth_thickness: Thickness
    :type smooth_thickness: bool
    :param smooth_strength: Strength
    :type smooth_strength: bool
    :param smooth_uv: UV
    :type smooth_uv: bool
    """
    pass


def clean_data(df, n_std=20):
    """Removes any outliers that are further than a chosen
    number of standard deviations from the mean.

    These values are most likely wrongly inputted data,
    and so are forward filled.

    :param df:          A time series
    :type  df:          pd.DataFrame

    :param n_std:       The number of standard deviations from the mean
    :type  n_std:       int

    :return:            The cleaned time series
    :rtype:             pd.DataFrame
    """
    upper = df.price.mean() + n_std * df.price.std()
    lower = df.price.mean() - n_std * df.price.std()
    df.loc[(df.price > upper) | (df.price < lower), 'price'] = None
    if df.price.isnull().sum() > 0:
        print('Rows removed:', df.price.isnull().sum())
    df.ffill(inplace=True)
    df = df[df.index.weekday_name != 'Saturday']
    df = df[df.index.weekday_name != 'Sunday']
    return df


def get_title():
    """Returns the title of the listing (LaTeX).
        """


def total_requests():
    """Returns the total number of requests managed so far by the pool of uWSGI workers.

    :rtype: int
    """
    return 0


def cast_bool(value):
    """
    Convert string to bool

    :param value: string or bool
    :type value: str or bool
    :return: bool
    """
    if value is None:
        return None
    if isinstance(value, bool):
        return value
    return value.lower() in ['true', '1', 't', 'y', 'yes']


@classmethod
def on_start_configuration(cls):
    """
    Callback function that is triggered, when the configuration of all undetected controllers starts
    """
    print('EVENT:' + 'Start configuration of unknown controller types')


@staticmethod
def visible_for_object(object):
    """
        Used when dropdown item is added through provides

        :return whether this item must be shown
        :rtype: bool
        """
    return True


@classmethod
def create(cls, subject, subject_keypair, attributes=None):
    """Creates a certification request.

        :param subject:         certificate subject
        :type  subject:         :class:`VX509Name`
        :param subject_keypair: subject keypair
        :type  subject_keypair: :class:`versile.crypto.VAsymmetricKey`
        :returns:               signed certification request
        :rtype:                 :class:`VX509CertificationRequest`

        *subject_keypair* will be used for signing the certification
        request.

        """
    _create = cls.create_req_info
    req_info = _create(subject=subject, subject_key=subject_keypair.public,
        attributes=attributes)
    return cls.create_from_req_info(req_info=req_info, subject_keypair=
        subject_keypair)


@classmethod
def from_supplier(cls, supplier, ring_cutoff=10, progress=False, annotate=
    True, **kwargs):
    """Construct a scaffoldgraph from a custom Mol supplier

        Parameters
        ----------
        supplier (iterable): A custom supplier of rdkit molecules, it is expected that each molecule
            will be assigned a property '_Name' serving as an identifier for that molecule. To use
            the progress option the supplier must have an associated length.
        ring_cutoff (int): ignore molecules with more rings than this cutoff (default: 10)
        progress (bool): if True show a progress bar to monitor construction progress (default: False)
        annotate: if True write an annotated murcko scaffold SMILES string to each
            molecule edge (molecule --> scaffold)
        kwargs: arguments to pass to the scaffoldgraph __init__
        """
    instance = cls(**kwargs)
    instance._construct(supplier, ring_cutoff=ring_cutoff, progress=
        progress, annotate=annotate)
    return instance


@classmethod
def shared_link_settings_change_expiration(cls, val):
    """
        Create an instance of this class set to the
        ``shared_link_settings_change_expiration`` tag with value ``val``.

        :param SharedLinkSettingsChangeExpirationType val:
        :rtype: EventType
        """
    return cls('shared_link_settings_change_expiration', val)


def trailingslashit(string=''):
    """
    Removes trailing forward slashes and backslashes if they exist.
    """
    return '{}/'.format(string.strip('/\\'))


def get_identity_mail_from_domain_attributes(Identities=None):
    """
    Returns the custom MAIL FROM attributes for a list of identities (email addresses and/or domains).
    This action is throttled at one request per second and can only get custom MAIL FROM attributes for up to 100 identities at a time.
    See also: AWS API Documentation

    Examples
    The following example returns the custom MAIL FROM attributes for an identity:
    Expected Output:

    :example: response = client.get_identity_mail_from_domain_attributes(
        Identities=[
            'string',
        ]
    )

    :type Identities: list
    :param Identities: [REQUIRED]
            A list of one or more identities.
            (string) --

    :rtype: dict
    :return: {
        'MailFromDomainAttributes': {
            'string': {
                'MailFromDomain': 'string',
                'MailFromDomainStatus': 'Pending'|'Success'|'Failed'|'TemporaryFailure',
                'BehaviorOnMXFailure': 'UseDefaultValue'|'RejectMessage'
            }
        }
    }

    """
    pass


@staticmethod
def _get_next_marker_from_response_object(response_object):
    """Get the marker that should be used to retrieve the next page.

        When we've just retrieved the last page, the API is inconsistent about
        what it returns. Some endpoints return "next_marker":"", some return
        "next_marker":null, some don't give any "next_marker" value. In all of
        these cases, this method will return `None`.

        Otherwise, this method returns the string value of the "next_marker"
        field.

        :rtype:
            `unicode` or `None`
        """
    return response_object.get('next_marker') or None


def _fill_genotype_class(alleles, genotype_info_to_fill):
    """Id genotype class (homozygous/heterozygous) and subclass (reference, alt, compound) and store in VCFGenotypeInfo.

    Args:
        alleles (List[str]): Results of splitting the value for the GT (genotype) format tag.
        genotype_info_to_fill (VCFGenotypeInfo): A partially filled VCFGenotypeInfo object.

    Returns:
        VCFGenotypeInfo: The input VCFGenotypeInfo with genotype_subclass_by_class value set.

    """
    genotype_class = 'homozygous'
    genotype_subclass = 'reference'
    alt_subclass_name = 'alt'
    if alleles[0] != alleles[1]:
        genotype_class = 'heterozygous'
        alt_subclass_name = 'compound'
    if '0' not in alleles:
        genotype_subclass = alt_subclass_name
    result = {genotype_class: genotype_subclass}
    genotype_info_to_fill.genotype_subclass_by_class = result
    return result


def convert_by_vocab(vocab, items):
    """Converts a sequence of [tokens|ids] using the vocab."""
    output = []
    for item in items:
        output.append(vocab[item])
    return output


@staticmethod
def playstatus_error(_, exception):
    """Inform about an error and restart push updates."""
    print('An error occurred (restarting): {0}'.format(exception))


@staticmethod
def p_message_id(p):
    """message_id : NUMERIC"""
    p[0] = p[1]


def shrink_sides(image, ts=0, bs=0, ls=0, rs=0):
    """Shrinks/crops the image through shrinking each side of the image.
    params:
        image: A numpy ndarray, which has 2 or 3 dimensions
        ts: An integer, which is the amount to shrink the top side
            of the image
        bs: An integer, which is the amount to shrink the bottom side
            of the image
        ls: An integer, which is the amount to shrink the left side
            of the image
        rs: An integer, which is the amount to shrink the right side
            of the image
    return: A numpy ndarray, which has the same number of dimensions as image
    """
    return image[ts:image.shape[0] - bs, ls:image.shape[1] - rs]


@classmethod
def from_dict(cls, d):
    """Construct a box from the dictionary"""
    return cls(**d)


def FPS(val):
    """FullPersonalNameSubject"""
    return val


def _minus(lhs=None, rhs=None, out=None, name=None, **kwargs):
    """Subtracts arguments element-wise.

    The storage type of ``elemwise_sub`` output depends on storage types of inputs

       - elemwise_sub(row_sparse, row_sparse) = row_sparse
       - elemwise_sub(csr, csr) = csr
       - elemwise_sub(default, csr) = default
       - elemwise_sub(csr, default) = default
       - elemwise_sub(default, rsp) = default
       - elemwise_sub(rsp, default) = default
       - otherwise, ``elemwise_sub`` generates output with default storage

    Parameters
    ----------
    lhs : NDArray
        first input
    rhs : NDArray
        second input

    out : NDArray, optional
        The output NDArray to hold the result.

    Returns
    -------
    out : NDArray or list of NDArrays
        The output of this function.
    """
    return 0,


@classmethod
def ease_in_out(cls, progress=0):
    """Method to calculate transition for easeInOut display.

        Ease in and out is more complex:
            In the first half of the time the transition is applied normally,
            in the second half it is applied reverse.
        """
    if progress <= 0.5:
        return cls.pos(2 * progress) / 2
    else:
        return 2 - cls.pos(2 * (1 - progress)) / 2


def render_git_describe(pieces):
    """TAG[-DISTANCE-gHEX][-dirty].

    Like 'git describe --tags --dirty --always'.

    Exceptions:
    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance']:
            rendered += '-%d-g%s' % (pieces['distance'], pieces['short'])
    else:
        rendered = pieces['short']
    if pieces['dirty']:
        rendered += '-dirty'
    return rendered


def _generate_tensor_contraction_standard(terms, parameters, g_set):
    """
    Generate code for computation of tensor contraction using full
    tensor contraction.
    """
    iadd = format['iadd']
    assign = format['assign']
    element_tensor = format['element tensor']
    geometry_tensor = format['geometry tensor']
    zero = format['float'](0)
    inner_product = format['inner product']
    incremental = False
    epsilon = parameters['epsilon']
    A0, GK, optimized_contraction = terms[0]
    primary_indices = A0.primary_multi_index.indices
    gk_tensor = []
    for j, (A0, GK, optimized_contraction) in enumerate(terms):
        gk_tensor_j = []
        for a in A0.secondary_multi_index.indices:
            gk_tensor_j.append((geometry_tensor(j, a), a))
        gk_tensor.append((gk_tensor_j, j))
    lines = []
    for k, i in enumerate(primary_indices):
        name = element_tensor(k)
        coefficients = []
        entries = []
        for gka, j in gk_tensor:
            A0, GK, optimized_contraction = terms[j]
            for gk, a in gka:
                a0 = A0.A0[tuple(i + a)]
                if abs(a0) < epsilon:
                    continue
                coefficients.append(a0)
                entries.append(gk)
                g_set.add(gk)
        value = inner_product(coefficients, entries)
        value = value or zero
        if incremental:
            lines.append(iadd(name, value))
        else:
            lines.append(assign(name, value))
    return '\n'.join(lines)


def plus_or_dot(pieces):
    """Return a + if we don't already have one, else return a ."""
    if '+' in pieces.get('closest-tag', ''):
        return '.'
    return '+'


def list_gemeente_adapter(obj, request):
    """
    Adapter for rendering a list of
    :class:`crabpy.gateway.crab.Gemeenten` to json.
    """
    return {'id': obj.id, 'niscode': obj.niscode, 'naam': obj.naam}


def getGroupsForPrincipal(principalid):
    """Get groups the given principal belongs to"""


def names_from_url(repo_url):
    """names_from_url will return the username and repo name, given a repo url
    :param repo_url: the full url of the github repo
    """
    if repo_url[-1] == '/':
        repo_url = repo_url[:-1]
    repo_name = repo_url.split('/')[-1]
    user_name = repo_url.split('/')[-2]
    return user_name, repo_name


def squish(l):
    """If list contains only 1 element, return it instead."""
    return l if len(l) > 1 else l[0]


def broadcast_hypot(lhs=None, rhs=None, name=None, attr=None, out=None, **
    kwargs):
    """ Returns the hypotenuse of a right angled triangle, given its "legs"
    with broadcasting.

    It is equivalent to doing :math:`sqrt(x_1^2 + x_2^2)`.

    Example::

       x = [[ 3.,  3.,  3.]]

       y = [[ 4.],
            [ 4.]]

       broadcast_hypot(x, y) = [[ 5.,  5.,  5.],
                                [ 5.,  5.,  5.]]

       z = [[ 0.],
            [ 4.]]

       broadcast_hypot(x, z) = [[ 3.,  3.,  3.],
                                [ 5.,  5.,  5.]]

    Defined in src/operator/tensor/elemwise_binary_broadcast_op_extended.cc:L158

    Parameters
    ----------
    lhs : Symbol
        First input to the function
    rhs : Symbol
        Second input to the function

    name : string, optional.
        Name of the resulting symbol.

    Returns
    -------
    Symbol
        The result symbol.
    """
    return 0,


@classmethod
def get_valid_keys(cls):
    """
        Return a list of valid keys to be passed to the __init__
        """
    return list(cls._default_fields)


@staticmethod
def _from_dataframe(dataframe, default_type='STRING'):
    """
      Infer a BigQuery table schema from a Pandas dataframe. Note that if you don't explicitly set
      the types of the columns in the dataframe, they may be of a type that forces coercion to
      STRING, so even though the fields in the dataframe themselves may be numeric, the type in the
      derived schema may not be. Hence it is prudent to make sure the Pandas dataframe is typed
      correctly.

    Args:
      dataframe: The DataFrame.
      default_type : The default big query type in case the type of the column does not exist in
          the schema. Defaults to 'STRING'.
    Returns:
      A list of dictionaries containing field 'name' and 'type' entries, suitable for use in a
          BigQuery Tables resource schema.
    """
    type_mapping = {'i': 'INTEGER', 'b': 'BOOLEAN', 'f': 'FLOAT', 'O':
        'STRING', 'S': 'STRING', 'U': 'STRING', 'M': 'TIMESTAMP'}
    fields = []
    for column_name, dtype in dataframe.dtypes.iteritems():
        fields.append({'name': column_name, 'type': type_mapping.get(dtype.
            kind, default_type)})
    return fields


def items():
    """invoke call on each mapping to get key, value pairs"""


def bed_to_samtools_intervals(bed):
    """
    Convert bed file to intervals for samtools view

    Parameters
    ----------
    bed : path
        Bed file to convert

    Returns
    -------
    intervals : list
        List of the intervals in the bed file in the format 1:20-200 etc.

    """
    intervals = []
    f = open(bed, 'r')
    line = f.readline().strip()
    while line != '':
        vals = line.split('\t')
        intervals.append('{}:{}-{}'.format(vals[0], vals[1], vals[2]))
        line = f.readline().strip()
    f.close()
    return intervals


def __curses():
    """Try to discover terminal width with curses library."""
    try:
        import curses
        curses.setupterm()
        cr = curses.tigetnum('cols'), curses.tigetnum('lines')
    except Exception:
        return None
    return cr


def isbra(qob):
    """Checks if ``qob`` is in bra form -- an array row.
    """
    return qob.shape[0] == 1 and qob.shape[1] > 1