def get_arch(args, apkbuild):
    """
    Get the architecture, that the user wants to run menuconfig on, depending on
    the APKBUILD and on the --arch parameter.

    :param apkbuild: looks like: {"pkgname": "linux-...",
                                  "arch": ["x86_64", "armhf", "aarch64"]}
                     or: {"pkgname": "linux-...", "arch": ["armhf"]}
    """
    pkgname = apkbuild['pkgname']
    if len(apkbuild['arch']) > 1:
        if args.arch is None:
            raise RuntimeError("Package '" + pkgname +
                "' supports multiple architectures, please use '--arch' to specify the desired architecture."
                )
        return args.arch
    if args.arch is None or args.arch == apkbuild['arch'][0]:
        return apkbuild['arch'][0]
    raise RuntimeError("Package '" + pkgname + "' only supports the '" +
        apkbuild['arch'][0] + "' architecture.")


def serialize_fields(obj, fields):
    """
    Put the value of each attribute name in `fields` into a dict and return the dict.

    If a field is callable, it will be called with no arguments.

    e.g.

    class example:
        a = 1
        b = 2

        def c(self):
            return 3

    bag = serialize_fields(example(), ("a", "b", "c"))

    bag == {"a": 1, "b": 2, "c": 3}

    """
    bag = {}
    for name in fields:
        field = getattr(obj, name)
        bag[name] = field() if callable(field) else field
    return bag


def _from_r_alias(obj, r, lat_and_inv=None):
    """
    Alias for instance method that allows the method to be called in a
    multiprocessing pool
    """
    return obj._from_r(r, lat_and_inv=lat_and_inv)


def get_seg_features(string, seg):
    """
    Segment text with pkuseg
    features are represented in bies format
    s donates single word
    将输入句子进行pkuseg分词，然后获取每个词的长度特征
    0 代表为单字，1代表词的开头，2代表词的中间部分，3代表词的结尾
    例如，string=高血糖和血压 高血糖=[1,2,3] 和=[0] 高血压=[1,3] seg_inputs=[1,2,3,0,1,3]
    """
    seg_feature = []
    for word in seg.cut(string):
        if len(word) == 1:
            seg_feature.append(0)
        else:
            tmp = [2] * len(word)
            tmp[0] = 1
            tmp[-1] = 3
            seg_feature.extend(tmp)
    return seg_feature


def svn_parse(url):
    """
    Check if link to a SVN repo seems to be correct. Filter revision
    number
    """
    url_clean, rev = None, None
    if '@' in url:
        url_clean, rev = url.split('@')
    else:
        url_clean = url
    return url_clean, rev


def isdatelike(value):
    """
    Returns whether a given value has a date-like interface
    To support the arrow library, we do not check for instanceof(date, (datetime.date, datetime.datetime))

    Returns
    ------------
    bool
    """
    try:
        value.year, value.month, value.day
        return True
    except:
        return False


def time_to_str(t):
    """ Turns time objects to strings like '08:30' """
    return t.strftime('%H:%M')


def tabpadding(padlen, tabsize=8, offset=0):
    """ Compute some spaces to use a tab padding at an offfset.
  """
    pad = ''
    nexttab = tabsize - offset % tabsize
    while nexttab <= padlen:
        pad += '\t'
        padlen -= nexttab
        nexttab = tabsize
    if padlen > 0:
        pad += '%*s' % (padlen, ' ')
    return pad


def get_includes():
    """
    Returns absolute path to location of fwdpy11 headers
    """
    import os
    import fwdpy11
    return os.path.dirname(fwdpy11.__file__) + '/headers'


def check_gcc():
    """Check that gcc is installed"""
    from sh import which
    shOut = which('gcc')
    if not shOut is None:
        from sh import gcc
        version = str(gcc('--version'))
        return version, True
    else:
        print(
            'ERROR: you must install gcc version 5.1 or above before continuing.'
            )
        return None, False


def mask_dict_password(dictionary, secret='***'):
    """Replace passwords with a secret in a dictionary."""
    d = dictionary.copy()
    for k in d:
        if 'password' in k:
            d[k] = secret
    return d


def line_return_subject_is_valid(line):
    """if we have a valid 'return <object>' statement PS not checking if object is semantically valid"""
    l = line.split()
    if len(l) > 1:
        if l[-2] == 'return':
            return True


def unpad(data):
    """ Unpads data previously padded with `pad`.

    Args:
        data: The data to remove padding from. Must be a `bytearray`. If not previously padded, data may be lost.
    """
    n = data[-1]
    del data[-n:]


def create_orientation(name: str='', use_view: bool=False, use: bool=False,
    overwrite: bool=False):
    """Create transformation orientation from selection

    :param name: Name, Name of the new custom orientation
    :type name: str
    :param use_view: Use View, Use the current view instead of the active object to create the new orientation
    :type use_view: bool
    :param use: Use after creation, Select orientation after its creation
    :type use: bool
    :param overwrite: Overwrite previous, Overwrite previously created orientation with same name
    :type overwrite: bool
    """
    pass


def format_delta(delta, fmt='{hours}:{minutes}'):
    """ Formats timedelta. Allowed variable names are: `days`, `hours`,
    `minutes`, `seconds`.
    """
    hours, rem = divmod(delta.seconds, 3600)
    minutes, seconds = divmod(rem, 60)
    return fmt.format(days=delta.days, hours=hours, minutes=minutes,
        seconds=seconds)


@staticmethod
def from_jacobian(jacobian_point):
    """ A no-op since the point is already jacobian.

        Args:
            jacobian_point (ECPointJacobian): A Jacobian point

        Returns:
            ECPointJacobian: Returns the input arg.
        """
    return jacobian_point


def load_minimal_triangular_mesh():
    """Returns the triangulation of a single triangle

    The data set consists of a list of three vertices at the unit vectors
    of vector space :math:`\\mathbb{R}^3`and a list of a single
    triangle.

    ===================    =
    Number of vertices     3
    Number of triangles    1
    ===================    =

    Parameters
    ----------
    None

    Returns
    -------
    triangulation : dictionary
        Dictionary-like object containing the triangulation of a single
        triangle. The attributes are: 'vertlist', the list of vertices,
        'trilist', the list of triangles.
    """
    return {'vertlist': [[1, 0, 0], [0, 1, 0], [0, 0, 1]], 'trilist': [[0,
        1, 2]]}


def parse_extreme(starter, minim, maxim, mintext, maxtext):
    """
    Check if floor/ceiling value is OK.

    :param starter: Minimum/maximum OS version.
    :type starter: int

    :param minim: Minimum value for starter.
    :type minim: int

    :param maxim: Maximum value for starter.
    :type maxim: int

    :param mintext: What to print if starter < minim.
    :type mintext: str

    :param maxtext: What to print if starter > maxim.
    :type maxtext: str
    """
    okay = False
    if starter < minim:
        print(mintext)
    elif starter > maxim:
        print(maxtext)
    else:
        okay = True
    return okay


@classmethod
def table_name_col(cls):
    """
        Return the name of the metadata column used to store the feature table
        name.
        """
    return 'f_table_name'


def describe_stack_resource(StackName=None, LogicalResourceId=None):
    """
    Returns a description of the specified resource in the specified stack.
    For deleted stacks, DescribeStackResource returns resource information for up to 90 days after the stack has been deleted.
    See also: AWS API Documentation

    :example: response = client.describe_stack_resource(
        StackName='string',
        LogicalResourceId='string'
    )

    :type StackName: string
    :param StackName: [REQUIRED]
            The name or the unique stack ID that is associated with the stack, which are not always interchangeable:
            Running stacks: You can specify either the stack's name or its unique stack ID.
            Deleted stacks: You must specify the unique stack ID.
            Default: There is no default value.

    :type LogicalResourceId: string
    :param LogicalResourceId: [REQUIRED]
            The logical name of the resource as specified in the template.
            Default: There is no default value.

    :rtype: dict
    :return: {
        'StackResourceDetail': {
            'StackName': 'string',
            'StackId': 'string',
            'LogicalResourceId': 'string',
            'PhysicalResourceId': 'string',
            'ResourceType': 'string',
            'LastUpdatedTimestamp': datetime(2015, 1, 1),
            'ResourceStatus': 'CREATE_IN_PROGRESS'|'CREATE_FAILED'|'CREATE_COMPLETE'|'DELETE_IN_PROGRESS'|'DELETE_FAILED'|'DELETE_COMPLETE'|'DELETE_SKIPPED'|'UPDATE_IN_PROGRESS'|'UPDATE_FAILED'|'UPDATE_COMPLETE',
            'ResourceStatusReason': 'string',
            'Description': 'string',
            'Metadata': 'string'
        }
    }

    """
    pass


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 sorted_futures(graph):
    """Returns a sorted, unique list of future imports."""
    f = set()
    for value in graph.values():
        f |= value.futures
    return sorted(f)


def is_transform(func):
    """A simple decorator that marks a function as a "trasform" which allows the transform
    decorator to only reference functions that are specifically intended to transform client
    method call responses.
    """
    func.__is_transform__ = True
    return func


def get_transcripts_from_tree(chrom, start, stop, cds_tree):
    """ Uses cds tree to btain transcript IDs from genomic coordinates

        chrom: (String) Specify chrom to use for transcript search.
        start: (Int) Specify start position to use for transcript search.
        stop: (Int) Specify ending position to use for transcript search
        cds_tree: (Dict) dictionary of IntervalTree() objects containing
            transcript IDs as function of exon coords indexed by chr/contig ID.

        Return value: (set) a set of matching unique transcript IDs.
    """
    transcript_ids = set()
    if chrom not in cds_tree:
        return []
    cds = list(cds_tree[chrom].overlap(start, stop))
    for cd in cds:
        transcript_ids.add(cd.data)
    return list(transcript_ids)


def fromOpenIDRequest(cls, request):
    """Instantiate a Request object from the arguments in a
        C{checkid_*} OpenID message
        """
    self = cls()
    args = request.message.getArgs(self.ns_uri)
    if args == {}:
        return None
    self.parseExtensionArgs(args)
    return self


def prepare_for_fitting(voxels):
    """Return a copy of voxels, prepared for fitting."""
    voxels = voxels.copy()
    for v in voxels:
        if v[0] == 0:
            v[:] = 1
    return voxels


def filter_out_none(dictionary, keys=None):
    """ Filter out items whose value is None.
        If `keys` specified, only return non-None items with matched key.
    """
    ret = dict()
    if 'action' in dictionary:
        ret['action'] = dictionary['action']
    if keys is None:
        keys = []
    for key, value in dictionary.items():
        if value is None or key not in keys:
            continue
        ret[key] = value
    return ret


def feature_constructor(loader, node):
    """Feature (Java enum) is parsed as a String."""
    s = loader.construct_scalar(node)
    return hash(s)


def conv_input_length(output_length, filter_size, border_mode, stride):
    """Determines input length of a convolution given output length.

    # Arguments
        output_length: integer.
        filter_size: integer.
        border_mode: one of "same", "valid", "full".
        stride: integer.

    # Returns
        The input length (integer).
    """
    if output_length is None:
        return None
    assert border_mode in {'same', 'valid', 'full'}
    if border_mode == 'same':
        pad = filter_size // 2
    elif border_mode == 'valid':
        pad = 0
    elif border_mode == 'full':
        pad = filter_size - 1
    return (output_length - 1) * stride - 2 * pad + filter_size


@classmethod
def _sync_blank_domain(cls, site):
    """Delete associated Alias object for ``site``, if domain is blank."""
    if site.domain:
        raise ValueError('%r has a domain' % site)
    try:
        alias = cls.objects.get(site=site)
    except cls.DoesNotExist:
        pass
    else:
        if not alias.is_canonical:
            raise cls.MultipleObjectsReturned('Other %s still exist for %r' %
                (cls._meta.verbose_name_plural.capitalize(), site))
        alias.delete()


def _inputs_swap_needed(mode, shape1, shape2):
    """
    If in 'valid' mode, returns whether or not the input arrays need to be
    swapped depending on whether `shape1` is at least as large as `shape2` in
    every dimension.

    This is important for some of the correlation and convolution
    implementations in this module, where the larger array input needs to come
    before the smaller array input when operating in this mode.

    Note that if the mode provided is not 'valid', False is immediately
    returned.
    """
    if mode == 'valid':
        ok1, ok2 = True, True
        for d1, d2 in zip(shape1, shape2):
            if not d1 >= d2:
                ok1 = False
            if not d2 >= d1:
                ok2 = False
        if not (ok1 or ok2):
            raise ValueError(
                "For 'valid' mode, one must be at least as large as the other in every dimension"
                )
        return not ok1
    return False


def combine_mappings(known_mappings, partial_mapping):
    """
    Update a collection of mappings.

    Add the mappings from the 'partial_mapping' argument into the
    'known_mappings' collection. Both arguments are collections of mappings
    similar to the output of the :func:`read_mapping_directory` function. They
    are dictionary with 3 levels of keys: the name of the initial force field,
    the name of the target force field, and the name of the block. The values
    in the third level dictionary are tuples of (mapping, weights, extra).

    If a force field appears in 'partial_mapping' that is not in
    'known_mappings', then it is added. For existing pairs of initial and
    target force fields, the blocks are updated and the version in
    'partial_mapping' is kept in priority.

    Parameters
    ----------
    known_mappings: dict
        Collection of mapping to update **in-place**.
    partial_mapping: dict
        Collection of mappings to update from.
    """
    for origin, destinations in partial_mapping.items():
        known_mappings[origin] = known_mappings.get(origin, {})
        for destination, residues in destinations.items():
            known_mappings[origin][destination] = known_mappings[origin].get(
                destination, {})
            for residue, mapping in residues.items():
                known_mappings[origin][destination][residue] = mapping


@classmethod
def get_path(cls, uuid):
    """
            Return the file path of a paste given uuid
        """
    return cls.build_path(uuid[:2], uuid[2:4], uuid)


def delete_bucket_cors(Bucket=None):
    """
    Deletes the cors configuration information set for the bucket.
    See also: AWS API Documentation

    :example: response = client.delete_bucket_cors(
        Bucket='string'
    )

    :type Bucket: string
    :param Bucket: [REQUIRED]

    """
    pass


def _get(obj, name):
    """
    Get the indexable value with given `name` from `obj`, which may be
    a `dict` (or subclass) or a non-dict that has a `__getitem__` method.
    """
    try:
        return dict.__getitem__(obj, name)
    except TypeError:
        if isinstance(obj, dict):
            raise
        return obj[name]


def extract_FC_raw(df, rec):
    """
    Extract the Frequency and Consistency features from transactions df.

    Args:
        df : dataframe with column 'TRANSACTION_DATE' containing the bill payment dates
        rec : Q if quarterly bill, M if monthly bill

    Returns:
        F_raw : average days bet payments minus the expected pattern
        C_raw : standard deviation of the distribution of days bet payments
    """
    df = df.sort_values('TRANSACTION_DATE')
    diff = (df['TRANSACTION_DATE'] - df['TRANSACTION_DATE'].shift(1)).iloc[1:]
    if rec == 'M':
        pattern = 30
    elif rec == 'Q':
        pattern = 90
    F_raw = diff.mean().days - pattern
    C_raw = diff.std().days
    return F_raw, C_raw


def parse_option_dict(options):
    """
    Parse a list of option strings like foo=bar baz=qux and return a dictionary.
    Will raise if keys are repeated.
    """
    ret = {}
    for option_pair in (options or []):
        key, value = option_pair.split('=', 1)
        if key in ret:
            raise ValueError(
                "Multiple values provided for the same key '%s'" % key)
        ret[key] = value
    return ret


def validate_static_routes(value):
    """
    sca1, sca+sca, http://localhost:8002+http://localhost:8002;
    sca2, sca+sca, http://localhost:8003+http://localhost:8003;

    must convert in:

    ((
        'sca1',
        ('sca','sca'),
        ('http://localhost:8002', 'http://localhost:8002'),
    ),
    (
        'sca2',
        ('sca','sca'),
        ('http://localhost:8003', 'http://localhost:8003'),
    ))

    """
    routes = []
    if value:
        value = value.split(';')
        for r in value:
            r = r.strip()
            if r:
                routes.append(r)
        for idx, r in enumerate(routes):
            items = r.split(',')
            v = []
            for it in items:
                it = it.strip()
                if it:
                    v.append(it)
            routes[idx] = v
        for r in routes:
            for idx, field in enumerate(r):
                v = ()
                if not '+' in field:
                    v += field,
                    continue
                items = field.split('+')
                for e in items:
                    e = e.strip()
                    if e:
                        v += e,
                r[idx] = v
    return routes


def num_frames(length, fsize, fshift):
    """Compute number of time frames of spectrogram
    """
    pad = fsize - fshift
    if length % fshift == 0:
        M = (length + pad * 2 - fsize) // fshift + 1
    else:
        M = (length + pad * 2 - fsize) // fshift + 2
    return M


def get_pid_from_file(pidfile_path):
    """Retrieve the PID from the given file, if it exists, None otherwise."""
    try:
        with open(pidfile_path, 'r') as fd:
            pid = fd.read().split()[0]
    except IOError:
        return None
    try:
        pid = int(pid)
    except ValueError:
        return None
    return pid


def millis_offset_between_epochs(reference_epoch, target_epoch):
    """
    Calculates the signed milliseconds delta between the reference unix epoch and the provided target unix epoch
    :param reference_epoch: the unix epoch that the millis offset has to be calculated with respect to
    :type reference_epoch: int
    :param target_epoch: the unix epoch for which the millis offset has to be calculated
    :type target_epoch: int
    :return: int
    """
    assert isinstance(reference_epoch, int)
    assert isinstance(target_epoch, int)
    return (target_epoch - reference_epoch) * 1000


def set_close_exec(fd):
    """Sets the close-on-exec bit (``FD_CLOEXEC``)for a file descriptor."""
    raise NotImplementedError()


def flush_edits():
    """Flush edit data from active editing modes

    """
    pass


def convert_site_dm3_table_intensity(sites_df):
    """
    Convert MagIC site headers to short/readable
    headers for a figure (used by ipmag.sites_extract)
    Intensity data only.

    Parameters
    ----------
    sites_df : pandas DataFrame
        sites information

    Returns
    ---------
    int_df : pandas DataFrame
        intensity site data with easily readable headers
    """
    has_vadms, has_vdms = False, False
    if 'int_abs' not in sites_df:
        sites_df['int_abs'] = None
    if 'int_n_samples' not in sites_df:
        sites_df['int_n_samples'] = None
    int_df = sites_df.copy().dropna(subset=['int_abs'])
    int_df['int_n_samples'] = int_df['int_n_samples'].values.astype('int')
    if len(int_df) > 0:
        int_df['int_abs_uT'] = 1000000.0 * int_df.int_abs.values
        int_df['int_abs_sigma_uT'] = 1000000.0 * int_df.int_abs_sigma.values
        int_df['int_abs_uT'] = int_df['int_abs_uT'].values.astype('int')
        int_df['int_abs_sigma_uT'] = int_df['int_abs_sigma_uT'].values.astype(
            'int')
        int_df['int_abs_sigma_perc'] = int_df['int_abs_sigma_perc'
            ].values.astype('int')
        IntCols = ['Site', 'N', 'B', 'B sigma', 'sigma (%)']
        if 'vadm' in int_df.columns:
            test_vadm = int_df.dropna(subset=['vadm'])
            if len(test_vadm) > 0:
                has_vadms = True
        if 'vdm' in int_df.columns:
            test_vdm = int_df.dropna(subset=['vdm'])
            if len(test_vdm) > 0:
                has_vdms = True
        if has_vadms:
            IntCols.append('VADM')
            IntCols.append('VADM sigma')
        if has_vdms:
            IntCols.append('VDM')
            IntCols.append('VDM sigma')
        if not has_vadms and not has_vdms:
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT',
                'int_abs_sigma_uT', 'int_abs_sigma_perc']]
        if has_vadms and not has_vdms:
            int_df.sort_values(by=['site', 'vadm'], ascending=False,
                inplace=True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)
            int_df['vadm_ZAm2'] = 1e-21 * int_df.vadm.values
            int_df['vadm_sigma_ZAm2'] = 1e-21 * int_df.vadm_sigma.values
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT',
                'int_abs_sigma_uT', 'int_abs_sigma_perc', 'vadm_ZAm2',
                'vadm_ZAm2_sigma']]
        if not has_vadms and has_vdms:
            int_df.sort_values(by=['site', 'vdm'], ascending=False, inplace
                =True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)
            int_df['vdm_ZAm2'] = 1e-21 * int_df.vdm.values()
            int_df['vdm_sigma_ZAm2'] = 1e-21 * int_df.vdm_sigma.values()
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT',
                'int_abs_sigma_uT', 'int_abs_sigma_perc', 'vdm_ZAm2',
                'vdm_ZAm2_sigma']]
        if has_vadms and has_vdms:
            int_df.sort_values(by=['site', 'vadm'], ascending=False,
                inplace=True)
            int_df.drop_duplicates(subset=['int_abs_uT', 'site'], inplace=True)
            int_df['vadm_ZAm2'] = 1e-21 * int_df.vadm.values
            int_df['vadm_sigma_ZAm2'] = 1e-21 * int_df.vadm_sigma.values
            int_df['vdm_ZAm2'] = 1e-21 * int_df.vdm.values
            int_df['vdm_sigma_ZAm2'] = 1e-21 * int_df.vdm_sigma.values
            int_df = int_df[['site', 'int_n_samples', 'int_abs_uT',
                'int_abs_sigma_uT', 'int_abs_sigma_perc', 'vadm_ZAm2',
                'vadm_sigma_ZAm2', 'vdm_ZAm2', 'vdm_sigma_ZAm2']]
        int_df.columns = IntCols
        int_df.sort_values(by=['Site'], inplace=True, ascending=True)
        int_df.fillna(value='', inplace=True)
    return int_df


def line_is_not_comment(line):
    """Is the line a comment? Comments start with '#'
    """
    return not line.startswith('#')


def extend_path(conn, arguments):
    """
    get the remote environment's env so we can explicitly add the path without
    wiping out everything
    """
    try:
        result = conn.gateway.remote_exec(
            'import os; channel.send(os.environ.copy())')
        env = result.receive()
    except Exception:
        conn.logger.exception(
            'failed to retrieve the remote environment variables')
        env = {}
    path = env.get('PATH', '')
    env['PATH'
        ] = path + '/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin'
    arguments['env'] = env
    return arguments


def start_logging():
    """Set the logging system to log to the (real) `stdout`.  Suitable for
    logging to the console when using a Jupyter notebook, for example.
    """
    import logging, sys
    logger = logging.getLogger('tilemapbase')
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler(sys.__stdout__)
    fmt = logging.Formatter('{asctime} {levelname} {name} - {message}',
        style='{')
    ch.setFormatter(fmt)
    logger.addHandler(ch)


@classmethod
def from_dict(cls, dict_in):
    """Load instance from output of to_dict

        Returns
        -------
        RemoteAnonServer

        """
    return cls(name=dict_in['name'], url=dict_in['url'])


def pipeline_link_color(plug, link):
    """
    Link color and style for graphical display and graphviz graphs.

    Parameters
    ----------
    plug: Plug
        the plug the link belong to
    link: link tuple (5 values)
        link to color

    Returns
    -------
    link_props: tuple
        (color, style, active, weak) where color is a RGB tuple of float values
        (between 0. and 1.), style is a string ("solid", "dotted"), active and
        weak are booleans.
    """
    GRAY_1 = 0.7, 0.7, 0.8
    RED_2 = 0.92, 0.51, 0.12
    active = plug.activated and link[3].activated
    if active:
        color = RED_2
    else:
        color = GRAY_1
    weak = link[4]
    if weak:
        style = 'dotted'
    else:
        style = 'solid'
    return color, style, active, weak


def _get_old_pk(instance, field_name):
    """ Given a model instance & field_name find the true name of the field
    This is needed to support the uncommon scenario where the
    instance's ForeignKey column name may have been overridden
    from the django default behavior of <field_name>_id.
    Using `get_attname` will return whatever the real fields name
    is that has just the foreign key value.
    """
    model_field_name = instance._meta.get_field(field_name).get_attname()
    return getattr(instance, model_field_name)


def id():
    """Get the ID of this reference.
        """


def hsv2rgb_raw(hsv):
    """
    Converts an HSV tuple to RGB. Intended for internal use.
    You should use hsv2rgb_spectrum or hsv2rgb_rainbow instead.
    """
    HSV_SECTION_3 = 64
    h, s, v = hsv
    invsat = 255 - s
    brightness_floor = v * invsat // 256
    color_amplitude = v - brightness_floor
    section = h // HSV_SECTION_3
    offset = h % HSV_SECTION_3
    rampup = offset
    rampdown = HSV_SECTION_3 - 1 - offset
    rampup_amp_adj = rampup * color_amplitude // (256 // 4)
    rampdown_amp_adj = rampdown * color_amplitude // (256 // 4)
    rampup_adj_with_floor = rampup_amp_adj + brightness_floor
    rampdown_adj_with_floor = rampdown_amp_adj + brightness_floor
    r, g, b = 0, 0, 0
    if section:
        if section == 1:
            r = brightness_floor
            g = rampdown_adj_with_floor
            b = rampup_adj_with_floor
        else:
            r = rampup_adj_with_floor
            g = brightness_floor
            b = rampdown_adj_with_floor
    else:
        r = rampdown_adj_with_floor
        g = rampup_adj_with_floor
        b = brightness_floor
    return r, g, b


def unpack(*arg):
    """Unpacks a 2D array. Input must be unpack(*arg.T) for column unpacking and
    unpack(*arg) for row unpacking."""
    return arg


def _dumpArrayToFile(filelike, array):
    """Serializes a 1-dimensional ``numpy.array`` to bytes, writes the bytes to
    the filelike object and returns a dictionary with metadata, necessary to
    restore the ``numpy.array`` from the file.

    :param filelike: can be a file or a file-like object that provides the
        methods ``.write()`` and ``.tell()``.
    :param array: a 1-dimensional ``numpy.array``

    :returns: a metadata dictionary ::
        {'start': start position in the file, 'end': end position in the file,
         'size': size of the array, 'dtype': numpy data type of the array
         }
    """
    bytedata = array.tobytes('C')
    start = filelike.tell()
    end = start + len(bytedata)
    metadata = {'start': start, 'end': end, 'size': array.size, 'dtype':
        array.dtype.name}
    filelike.write(bytedata)
    return metadata


def grabUserData(portal, out):
    """User data is contained in the contentish members so we don't
    need to grab any user data."""
    print >> out, '\nSkipping Member information extraction...'


def _ansible_verbose(verbose_level=1):
    """
    Return an ansible verbose flag for a given Cliff app verbose
    level to pass along desired verbosity intent.
    """
    flag = ''
    if verbose_level > 1:
        flag = '-{}'.format('v' * (verbose_level - 1))
    return flag


def manage_renameObject(id, new_id, REQUEST=None):
    """Rename a particular sub-object"""


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

        :param TeamMemberLogInfo val:
        :rtype: ContextLogInfo
        """
    return cls('team_member', val)


def max_lenght(data_frame, col):
    """returns leghth of fdataframe object"""
    return max(len(data_frame[col].astype(str).min()), len(data_frame[col].
        astype(str).max())) + 1


def extract_all_ss_dssp(in_dssp, path=True):
    """Uses DSSP to extract secondary structure information on every residue.

    Parameters
    ----------
    in_dssp : str
        Path to DSSP file.
    path : bool, optional
        Indicates if pdb is a path or a string.

    Returns
    -------
    dssp_residues : [tuple]
        Each internal list contains:
            [0] int Residue number
            [1] str Secondary structure type
            [2] str Chain identifier
            [3] str Residue type
            [4] float Phi torsion angle
            [5] float Psi torsion angle
            [6] int dssp solvent accessibility
    """
    if path:
        with open(in_dssp, 'r') as inf:
            dssp_out = inf.read()
    else:
        dssp_out = in_dssp[:]
    dssp_residues = []
    active = False
    for line in dssp_out.splitlines():
        if active:
            try:
                res_num = int(line[5:10].strip())
                chain = line[10:12].strip()
                residue = line[13]
                ss_type = line[16]
                phi = float(line[103:109].strip())
                psi = float(line[109:116].strip())
                acc = int(line[35:38].strip())
                dssp_residues.append((res_num, ss_type, chain, residue, phi,
                    psi, acc))
            except ValueError:
                pass
        elif line[2] == '#':
            active = True
    return dssp_residues


def build_img_tag(src, height, width, alt):
    """
    Constructs an IMG tag
    WARNING: There is NO filtering or escaping of ANY characters.
    """
    return '<img height="{0}" width="{1}" src="{2}" alt="{3}"/>'.format(height,
        width, src, alt)


def break_by_timegap(points, timegap=360):
    """Break into trip segments when time recorded between points is
       > timegap variable and group points by segment number in a dictionary"""
    trips = []
    group = 1
    for idx, row in enumerate(points):
        dt = row['timestamp']
        if idx == 0:
            previous_row = row
            period = 0
        else:
            period = int((dt - previous_row['timestamp']).total_seconds())
            if period > timegap:
                group += 1
            previous_row = row
        row['segment_group'] = group
        row['break_period'] = period
        row['note'] = ''
        row['merge_codes'] = []
        trips.append(dict(row))
    segment_groups = {}
    for t in trips:
        segment_groups.setdefault(t['segment_group'], []).append(t)
    return segment_groups


def find_tax_id(lineage, valids, ranks):
    """Return the most taxonomic specific tax_id available for the given
    Series.  If a tax_id is already present in valids then return None.
    """
    lineage = lineage[ranks]
    lineage = lineage[~lineage.isnull()]
    found = lineage.head(n=1)
    key = found.index.values[0]
    value = found.values[0]
    return value if value not in valids[key].unique() else None


@classmethod
def add_global_scope(cls, scope):
    """
        Register a new global scope on the model.

        :param scope: The scope to register
        :type scope: eloquent.orm.scopes.scope.Scope
        """
    if cls not in cls._global_scopes:
        cls._global_scopes[cls] = {}
    cls._global_scopes[cls][scope.__class__] = scope


def ensure_context_attribute_exists(context, name, default_value=None):
    """
    Ensure a behave resource exists as attribute in the behave context.
    If this is not the case, the attribute is created by using the default_value.
    """
    if not hasattr(context, name):
        setattr(context, name, default_value)


def upsert_char(data, newdata, who):
    """
    Similar to upsert_box(), only for a character.
    """
    pass


@classmethod
def from_offset(cls, chunk_type, stream_rdr, offset):
    """
        Return an _IHDRChunk instance containing the image dimensions
        extracted from the IHDR chunk in *stream* at *offset*.
        """
    px_width = stream_rdr.read_long(offset)
    px_height = stream_rdr.read_long(offset, 4)
    return cls(chunk_type, px_width, px_height)


def _check_pyopengl_3D():
    """Helper to ensure users have OpenGL for 3D texture support (for now)"""
    global USE_TEX_3D
    USE_TEX_3D = True
    try:
        import OpenGL.GL as _gl
    except ImportError:
        raise ImportError('PyOpenGL is required for 3D texture support')
    return _gl


def _setup_depot(specs):
    """Setup depot model

    'DEPOT' key added to `specs`
    """
    specs['DEPOT'] = specs['DEPOT_SECTION']


def md5_etag(body=None, set_content_md5=False):
    """ Generate an etag for the response object using an MD5 hash of the
        body (the body parameter, or self.body if not given).  Sets self.etag.
        If set_content_md5 is True sets self.content_md5 as well """


def _isalnumMUTF8(c):
    """Return True if the given UTF-8 encoded character is alphanumeric
    or multibyte.

    Input is not checked!
    """
    return c.isalnum() or len(c.encode('utf-8')) > 1


def check_for_executable(supernova_args, env_vars):
    """
    It's possible that a user might set their custom executable via an
    environment variable.  If we detect one, we should add it to supernova's
    arguments ONLY IF an executable wasn't set on the command line.  The
    command line executable must take priority.
    """
    exe = supernova_args.get('executable', 'default')
    if exe != 'default':
        return supernova_args
    if 'OS_EXECUTABLE' in env_vars.keys():
        supernova_args['executable'] = env_vars['OS_EXECUTABLE']
        return supernova_args
    supernova_args['executable'] = 'nova'
    return supernova_args


def get_cookies_from_headers(headers):
    """Get cookies dict from headers' Set-Cookie"""
    cookies = {}
    cookie_list = None
    for k, v in headers.items():
        if k.lower() == 'set-cookie':
            cookie_list = headers[k].split('\n')
    if cookie_list:
        for line in cookie_list:
            forward, backward = line.split(';', 1)
            key, value = forward.split('=', 1)
            cookies[key] = value
    return cookies


def version_is_compatible(imp_version, version):
    """Determine whether versions are compatible.

    :param imp_version: The version implemented
    :param version: The version requested by an incoming message.
    """
    if imp_version is None:
        return True
    if version is None:
        return False
    version_parts = version.split('.')
    imp_version_parts = imp_version.split('.')
    try:
        rev = version_parts[2]
    except IndexError:
        rev = 0
    try:
        imp_rev = imp_version_parts[2]
    except IndexError:
        imp_rev = 0
    if int(version_parts[0]) != int(imp_version_parts[0]):
        return False
    if int(version_parts[1]) > int(imp_version_parts[1]):
        return False
    if int(version_parts[1]) == int(imp_version_parts[1]) and int(rev) > int(
        imp_rev):
        return False
    return True


def is_contained(a, b):
    """ Check if segment b is fully contained within segment a """
    return b[0] >= a[0] and b[1] <= a[1]


def nothing():
    """ Widget that does nothing forever. """
    while True:
        yield


def nltk_default_pos_tagger(input_dict):
    """
    A tagger that assigns the same tag to every token.

        >>> from nltk.tag.sequential import DefaultTagger
        >>> default_tagger = DefaultTagger('NN')
        >>> default_tagger.tag('This is a test'.split())
        [('This', 'NN'), ('is', 'NN'), ('a', 'NN'), ('test', 'NN')]

    This tagger is recommended as a backoff tagger, in cases where
    a more powerful tagger is unable to assign a tag to the word
    (e.g. because the word was not seen during training).

    :param default_tag: The default tag "%(default)s". Set this to a different tag, such as "NN",
            to change the default tag.

    :returns pos_tagger: A python dictionary containing the POS tagger
        object and its arguments.
    """
    from nltk.tag import DefaultTagger
    return {'pos_tagger': {'function': 'tag_sents', 'object': DefaultTagger
        (input_dict.get('default_tag', '-None-'))}}


def select_prev_item():
    """Select the previous element (using selection order)

    """
    pass


@property
def significand(f):
    """Return the significand (*redundant)."""
    if f.kind == 'subnormal':
        return 0 + f.fraction
    if f.kind == 'normal':
        return 1 + f.fraction
    else:
        return None


def method_to_permcode(method):
    """
    return the django permcode for the specified method

    eg. "POST" => "add"
    """
    method = method.upper()
    if method == 'POST':
        return 'add'
    if method == 'GET':
        return 'view'
    if method == 'PUT' or method == 'UPDATE':
        return 'change'
    if method == 'DELETE':
        return 'delete'
    raise ValueError('Could not derive perm code from method %s' % method)


@staticmethod
def return_field():
    """ Determines which function will be called on selected items """
    return 'ret'


def _is_safe_size(n):
    """
    Is the size of FFT such that FFTPACK can handle it in single precision
    with sufficient accuracy?

    Composite numbers of 2, 3, and 5 are accepted, as FFTPACK has those
    """
    n = int(n)
    if n == 0:
        return True
    for c in (3, 5):
        while n % c == 0:
            n //= c
    return not n & n - 1


def getMissingDataValue(obj):
    """ Returns obj.fill_value or None if obj doesn't have a fill_value property.

        Typically masked arrays have a fill_value and regular Numpy arrays don't.
        If array is None, this funciont returns None, indicating no fill value.

        :param array: None or a numpy array (masked or regular.
        :return: None or value that represents missing data
    """
    if obj is None:
        return None
    else:
        try:
            return obj.fill_value
        except AttributeError:
            return None


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

    Like 'git describe --tags --dirty --always -long'.
    The distance/hash is unconditional.

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


def get_bundle(runner, params=None):
    """ Returns the list of installed Python dependencies
    """
    return {'status': runner.session.post_bundle(runner.runtime_infos) is not
        None}


def exec_file(file, add_params=None):
    """
    Executes a file with the .py extension

    Parameters
    ----------

    **file**: string
        path to the python file

   **add_params**:
        additional parameters that are used in the file that is beeing executed

    Returns
    -------

        Whatever output the executable file outputs
    """
    if add_params is not None:
        exec(open(file).read(), add_params)
    else:
        exec(open(file).read())


def _lovasz_grad(gt_sorted):
    """
    Computes gradient of the Lovasz extension w.r.t sorted errors
    See Alg. 1 in paper
    """
    p = len(gt_sorted)
    gts = gt_sorted.sum()
    intersection = gts - gt_sorted.float().cumsum(0)
    union = gts + (1 - gt_sorted).float().cumsum(0)
    jaccard = 1.0 - intersection / union
    if p > 1:
        jaccard[1:p] = jaccard[1:p] - jaccard[0:-1]
    return jaccard


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 '+'


@staticmethod
def bytes2lane(bb):
    """
        Converts a sequence of byte values to a lane.
        """
    r = 0
    for b in reversed(bb):
        r = r << 8 | b
    return r


def get_current_tid(cursor):
    """
        Returns the highest transaction ID visible to the cursor.

        If there are no transactions, returns 0.
        """


def flatten(iterable):
    """
    Flatten a sequence, returning a sequence of all its items' items.

    For example, `flatten([[1, 2], [3], [4, 'meow']]) == [1, 2, 3, 4, 'meow']`.
    """
    iterator = iter(iterable)
    try:
        return sum(iterator, next(iterator))
    except StopIteration:
        return []


@classmethod
def key_class(cls, algorithm: str):
    """
        Get public key class with algorithm

        :param algorithm: key algorithm
        :return: public key class
        """
    return cls.__key_classes.get(algorithm)


def _make_packet(qualifier, value, time, info, **kwargs):
    """
    where kwargs overrides info
    """
    packet = {'dataset': kwargs.get('dataset', info['dataset']),
        'component': kwargs.get('component', info['component']), 'kind':
        kwargs.get('kind', info['kind']), 'qualifier': qualifier, 'value':
        value, 'time': time}
    return packet


def _measure(line):
    """
    Parse a measure line.

    Parse a measure line. Looks similar to the following: '# Measure BrainSeg, BrainSegVol, Brain Segmentation Volume, 1243340.000000, mm^3'

    Parameters
    ----------
    line: string
        A stats line.

    Returns
    -------
    list of strings
        A list of strings, containing the data on the line. The prefix, '# Measure', is discarded.
    """
    return line[10:].split(', ')


def pop_kwargs(kwargs, names_with_defaults, allow_others=False):
    """
    Internal utility method to extract optional arguments from kwargs.

    :param kwargs:
    :param names_with_defaults:
    :param allow_others: if False (default) then an error will be raised if kwargs still contains something at the end.
    :return:
    """
    all_arguments = []
    for name, default_ in names_with_defaults:
        try:
            val = kwargs.pop(name)
        except KeyError:
            val = default_
        all_arguments.append(val)
    if not allow_others and len(kwargs) > 0:
        raise ValueError('Unsupported arguments: %s' % kwargs)
    if len(names_with_defaults) == 1:
        return all_arguments[0]
    else:
        return all_arguments


@staticmethod
def remove_linebreaks_within_equations(code):
    """Remove line breaks within equations.

        This is not a exhaustive test, but shows how the method works:

        >>> code = 'asdf = \\\\\\n(a\\n+b)'
        >>> from hydpy.cythons.modelutils import FuncConverter
        >>> FuncConverter.remove_linebreaks_within_equations(code)
        'asdf = (a+b)'
        """
    code = code.replace('\\\n', '')
    chars = []
    counter = 0
    for char in code:
        if char in ('(', '[', '{'):
            counter += 1
        elif char in (')', ']', '}'):
            counter -= 1
        if not (counter and char == '\n'):
            chars.append(char)
    return ''.join(chars)


def safe_issubclass(*args):
    """Like issubclass, but will just return False if not a class."""
    try:
        if issubclass(*args):
            return True
    except TypeError:
        pass
    return False


@classmethod
def summary(cls, gid, excl_fpath, gen_fpath, tm_dset, gen_index, excl_dict=
    None, res_class_dset=None, res_class_bin=None, excl_area=0.0081,
    power_density=None, cf_dset='cf_mean-means', lcoe_dset='lcoe_fcr-means',
    resolution=64, exclusion_shape=None, close=False, offshore_flags=None,
    friction_layer=None, args=None, data_layers=None):
    """Get a summary dictionary of a single supply curve point.

        Parameters
        ----------
        gid : int
            gid for supply curve point to analyze.
        excl_fpath : str
            Filepath to exclusions h5.
        gen_fpath : str
            Filepath to .h5 reV generation output results.
        tm_dset : str
            Dataset name in the techmap file containing the
            exclusions-to-resource mapping data.
        gen_index : np.ndarray
            Array of generation gids with array index equal to resource gid.
            Array value is -1 if the resource index was not used in the
            generation run.
        excl_dict : dict | None
            Dictionary of exclusion LayerMask arugments {layer: {kwarg: value}}
            None if excl input is pre-initialized.
        res_class_dset : str | np.ndarray | None
            Dataset in the generation file dictating resource classes.
            Can be pre-extracted resource data in np.ndarray.
            None if no resource classes.
        res_class_bin : list | None
            Two-entry lists dictating the single resource class bin.
            None if no resource classes.
        excl_area : float
            Area of an exclusion cell (square km).
        power_density : float | None | pd.DataFrame
            Constant power density float, None, or opened dataframe with
            (resource) "gid" and "power_density columns".
        cf_dset : str | np.ndarray
            Dataset name from gen containing capacity factor mean values.
            Can be pre-extracted generation output data in np.ndarray.
        lcoe_dset : str | np.ndarray
            Dataset name from gen containing LCOE mean values.
            Can be pre-extracted generation output data in np.ndarray.
        resolution : int | None
            SC resolution, must be input in combination with gid.
        exclusion_shape : tuple
            Shape of the exclusions extent (rows, cols). Inputing this will
            speed things up considerably.
        close : bool
            Flag to close object file handlers on exit.
        offshore_flags : np.ndarray | None
            Array of offshore boolean flags if available from wind generation
            data. None if offshore flag is not available.
        friction_layer : None | FrictionMask
            Friction layer with scalar friction values if valid friction inputs
            were entered. Otherwise, None to not apply friction layer.
        args : tuple | list, optional
            List of summary arguments to include. None defaults to all
            available args defined in the class attr, by default None
        data_layers : dict, optional
            Aggregation data layers. Must be a dictionary keyed by data label
            name. Each value must be another dictionary with "dset", "method",
            and "fpath", by default None

        Returns
        -------
        summary : dict
            Dictionary of summary outputs for this sc point.
        """
    kwargs = {'excl_dict': excl_dict, 'res_class_dset': res_class_dset,
        'res_class_bin': res_class_bin, 'excl_area': excl_area,
        'power_density': power_density, 'cf_dset': cf_dset, 'lcoe_dset':
        lcoe_dset, 'resolution': resolution, 'exclusion_shape':
        exclusion_shape, 'close': close, 'offshore_flags': offshore_flags,
        'friction_layer': friction_layer}
    with cls(gid, excl_fpath, gen_fpath, tm_dset, gen_index, **kwargs
        ) as point:
        summary = point.summarize(args=args, data_layers=data_layers)
    return summary


def _is_parsing_required(torrent):
    """Determines if parsing is required.

    Checks the following attributes to determine if parsing is needed:
    - if torrent.invalid is True, skip parsing
    - if torrent.purged is True, skip parsing
    - if len(torrent.media_files) > 0, skip parsing
    """
    parse = True
    if torrent.invalid:
        parse = False
    if torrent.purged:
        parse = False
    if torrent.media_files:
        parse = False
    return parse


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

        :param MicrosoftOfficeAddinChangePolicyDetails val:
        :rtype: EventDetails
        """
    return cls('microsoft_office_addin_change_policy_details', val)


def poly_td(data):
    """
    Polynomial time domain solvent subtraction - Not Implemented
    """
    raise NotImplementedError


def _cells(nb):
    """Yield all cells in an nbformat-insensitive manner"""
    if nb.nbformat < 4:
        for ws in nb.worksheets:
            for cell in ws.cells:
                yield cell
    else:
        for cell in nb.cells:
            yield cell


def rip_move(MESH_OT_rip=None, TRANSFORM_OT_translate=None):
    """Rip polygons and move the result

    :param MESH_OT_rip: Rip, Disconnect vertex or edges from connected geometry
    :param TRANSFORM_OT_translate: Move, Move selected items
    """
    pass


def apple_deployment_target_flag(os_, os_version):
    """compiler flag name which controls deployment target"""
    flag = {'Macos': '-mmacosx-version-min', 'iOS': '-mios-version-min',
        'watchOS': '-mwatchos-version-min', 'tvOS': '-mappletvos-version-min'
        }.get(str(os_))
    if not flag:
        return ''
    return '%s=%s' % (flag, os_version)


def _generate_background(templates, run_options, run_information):
    """Generates the background section of the report.

    Args:
        templates (jinja2.Environment): the jinja2 template environment
        run_options (dict): the run options
        run_information (dict): the run information

    Returns:
        str: a string representation of the "background" section

    """
    section_template = templates.get_template('section_template.tex')
    background = templates.get_template('parts/background.tex')
    return section_template.render(section_name='Background', section_type=
        'section', section_label='sec:background', section_content=
        background.render(**run_information))


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 _check_discrete_args(at, method):
    """
    Checks the arguments for margeff if the exogenous variables are discrete.
    """
    if method in ['dyex', 'eyex']:
        raise ValueError('%s not allowed for discrete variables' % method)
    if at in ['median', 'zero']:
        raise ValueError('%s not allowed for discrete variables' % at)


def num_to_alnum(integer):
    """
    Transform integer to [a-z], [a0-z0]-[a9-z9]

    Parameters
    ----------
    integer : int
        Integer to transform

    Returns
    -------
    a : str
        alpha-numeric representation of the integer
    """
    ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
    if integer < 26:
        return ascii_lowercase[integer]
    else:
        return ascii_lowercase[integer % 25 - 1] + str(integer // 25)


def weight_t(transpositions, max_n):
    """
    Unweighted weighting function for transposition edit operations.
    """
    return len(transpositions)


def network_status(neutron_status):
    """Translate neutron network status.

    :param neutron_status: neutron status
    """
    if neutron_status == 'ACTIVE':
        return 'active'
    else:
        return 'inactive'


def concat_units(var, units, rawstr=False, ucstr=False):
    """Concatenate variable with units in parentheses.

    Parameters
    ----------
    var, units : str
    rawstr, ucstr : bool, optional

    Returns
    -------
    str

    """
    if rawstr:
        return '{} ({})'.format(var, units)
    elif ucstr:
        return u'{} ({})'.format(var, units)
    else:
        return '{} ({})'.format(var, units)


def topk(input, k, dim, descending=True):
    """Return the k largest elements of the given input tensor along the given dimension.

    If descending is False then the k smallest elements are returned.

    Parameters
    ----------
    input : Tensor
        The input tensor.
    k : int
        The number of elements.
    dim : int
        The dim to sort along.
    descending : bool
        Controls whether to return largest/smallest elements.
    """
    pass


@staticmethod
def p_out_measurement_optional_list(p):
    """out_measurement_optional_list : out_measurement_optional
                                         | out_measurement_optional out_measurement_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def color_true_green(val):
    """DataFrame Styler:
    Changes text color to green if value is True
    Ex: style_df = df.style.applymap(color_true_green)
        style_df #to display"""
    color = 'green' if val == True else 'black'
    return f'color: {color}'


def _pad_sequence_fix(attr, kernelDim):
    """Changing onnx's pads sequence to match with mxnet's pad_width
    mxnet: (x1_begin, x1_end, ... , xn_begin, xn_end)
    onnx: (x1_begin, x2_begin, ... , xn_end, xn_end)"""
    new_attr = ()
    if len(attr) % 2 == 0:
        for index in range(int(len(attr) / 2)):
            new_attr = new_attr + attr[index::int(len(attr) / 2)]
        while len(new_attr) < kernelDim * 2:
            new_attr = new_attr + (0, 0)
    return new_attr


def print_warning(text: str) ->None:
    """
    Print the given text in red to indicate a warning.

    :param text: The text to print
    :return: None
    """
    print(f'\x1b[31m{text}\x1b[0m')


def degree(G, nbunch=None, t=None):
    """Return the degree of a node or nodes at time t.

            The node degree is the number of edges adjacent to that node.

            Parameters
            ----------

            G : Graph opject
                DyNetx graph object

            nbunch : iterable container, optional (default=all nodes)
                A container of nodes.  The container will be iterated
                through once.

            t : snapshot id (default=None)
                If None will be returned the degree of nodes on the flattened graph.

            Returns
            -------
            nd : dictionary, or number
                A dictionary with nodes as keys and degree as values or
                a number if a single node is specified.

            Examples
            --------
            >>> G = dn.DynGraph()
            >>> G.add_path([0,1,2,3], t=0)
            >>> dn.degree(G, 0, t=0)
            1
            >>> dn.degree(G, [0,1], t=1)
            {0: 0, 1: 0}
            >>> list(dn.degree(G, [0,1], t=0).values())
            [1, 2]
            """
    return G.degree(nbunch, t)


def flatten_dict_column(df, keys, col_name, add_col_prefix=True):
    """
    Extract the specified Pandas DataFrame dict column ('col_name'), creating new columns from the given keys.
    :param pd.DataFrame df: the Pandas DataFrame whose dict column will be flattened
    :param list keys: the keys of the dict column which will be extracted into new columns
    :param str col_name: the name of the Pandas DataFrame column whose content will be flattened
    :param bool add_col_prefix: adds the original 'col_name' value as a prefix to generated columns if True
    :return: pd.DataFrame
    """
    for key in keys:
        if add_col_prefix is True:
            df[col_name + '_' + key] = df[col_name].apply(lambda col: col[key])
        elif add_col_prefix is False:
            df[key] = df[col_name].apply(lambda col: col[key])
        else:
            raise ValueError(
                "The 'add_col_prefix' value must be set to either True or False."
                )
    df.drop(columns=[col_name], inplace=True)
    return df


def update_package_data(distribution):
    """update build_py options to get package_data changes"""
    build_py = distribution.get_command_obj('build_py')
    build_py.finalize_options()


def utf8Decode(st):
    """Returns utf7 encoded version of imap utf-7 string"""
    return st.decode('utf-8')


def update_order(bet_id, delta_stake, price, expected_selection_reset_count,
    expected_withdrawal_sequence_number, cancel_on_in_running=None,
    cancel_if_selection_reset=None, set_to_be_sp_if_unmatched=None):
    """
    Create an update order to send to exchange.

    :param bet_id: ID of the bet to be updated.
    :type bet_id: int
    :param delta_stake: Amount to change the stake of the bet by.
    :type delta_stake: float
    :param price: Price at which to place bet at.
    :type price: float
    :param expected_selection_reset_count: must match SelectionResetCount value in GetMarketInformation and GetPrices
                                        to ensure state of the market before placing a bet. If not matching server
                                        bet will not be placed and error is raised.
    :type expected_selection_reset_count: int
    :param expected_withdrawal_sequence_number: should match withdrawalSequenceNumber value in GetMarketInformation and
                                             GetPrices. If not matching server then your bet WILL be accepted, but it
                                             will be repriced.
    :type expected_withdrawal_sequence_number: int
    :param cancel_on_in_running: Cancel any unmatched orders when the market changes to an in-running market.
    :type cancel_on_in_running: betdaq_py.enums.Boolean
    :param cancel_if_selection_reset: Cancel any unmatched bets if the selection is reset.
                                   This can occur when the Market is reset (eg a goal is scored).
    :type cancel_if_selection_reset: betdaq_py.enums.Boolean
    :param set_to_be_sp_if_unmatched: whether to set bet to SP when market turns in play if it is unmatched.
    :type set_to_be_sp_if_unmatched: betdaq_py.enums.Boolean
    :return: dictionary of the order information to update on exchange.
    """
    resp = {'_BetId': bet_id, '_DeltaStake': delta_stake, '_Price': price,
        '_ExpectedSelectionResetCount': expected_selection_reset_count,
        '_ExpectedWithdrawalSequenceNumber':
        expected_withdrawal_sequence_number}
    if cancel_on_in_running is not None:
        resp['_CancelOnInRunning'] = cancel_on_in_running
    if cancel_if_selection_reset is not None:
        resp['_CancelIfSelectionReset'] = cancel_if_selection_reset
    if set_to_be_sp_if_unmatched is not None:
        resp['_SetToBeSPIfUnmatched'] = set_to_be_sp_if_unmatched
    return resp


def parse_result(line):
    """
    Parse the result line of a phenomizer request.

    Arguments:
        line (str): A raw output line from phenomizer

    Returns:
         result (dict): A dictionary with the phenomizer info:
             {
                'p_value': float,
                'gene_symbols': list(str),
                'disease_nr': int,
                'disease_source': str,
                'description': str,
                'raw_line': str
             }

    """
    if line.startswith('Problem'):
        raise RuntimeError('Login credentials seems to be wrong')
    result = {'p_value': None, 'gene_symbols': [], 'disease_nr': None,
        'disease_source': None, 'description': None, 'raw_line': line}
    result['raw_line'] = line.rstrip()
    result_line = line.rstrip().split('\t')
    try:
        result['p_value'] = float(result_line[0])
    except ValueError:
        pass
    try:
        medical_litterature = result_line[2].split(':')
        result['disease_source'] = medical_litterature[0]
        result['disease_nr'] = int(medical_litterature[1])
    except IndexError:
        pass
    try:
        description = result_line[3]
        result['description'] = description
    except IndexError:
        pass
    if len(result_line) > 4:
        for gene_symbol in result_line[4].split(','):
            result['gene_symbols'].append(gene_symbol.strip())
    return result


def RemoveMultiLineCommentsFromRange(lines, begin, end):
    """Clears a range of lines for multi-line comments."""
    for i in range(begin, end):
        lines[i] = '/**/'


def load_class(location):
    """ Take a string of the form 'fedmsg.consumers.ircbot:IRCBotConsumer'
    and return the IRCBotConsumer class.
    """
    mod_name, cls_name = location = location.strip().split(':')
    tokens = mod_name.split('.')
    fromlist = '[]'
    if len(tokens) > 1:
        fromlist = '.'.join(tokens[:-1])
    module = __import__(mod_name, fromlist=fromlist)
    try:
        return getattr(module, cls_name)
    except AttributeError:
        raise ImportError('%r not found in %r' % (cls_name, mod_name))


def parse_data_cfg(path):
    """Parses the data configuration file"""
    options = dict()
    options['gpus'] = '0,1,2,3'
    options['num_workers'] = '10'
    with open(path, 'r') as fp:
        lines = fp.readlines()
    for line in lines:
        line = line.strip()
        if line == '' or line.startswith('#'):
            continue
        key, value = line.split('=')
        options[key.strip()] = value.strip()
    return options


@staticmethod
def _fitParseData(x=None, y=None, livetime=None):
    """Parse the input data (MCA and livetime)
        """
    if y is None:
        raise RuntimeError('y keyword argument is mandatory!')
    if hasattr(y, 'info') and hasattr(y, 'data'):
        data = y.data
        mcaIndex = y.info.get('McaIndex', -1)
    else:
        data = y
        mcaIndex = -1
    if x is None:
        if hasattr(y, 'info') and hasattr(y, 'x'):
            x = y.x[0]
    if livetime is None:
        if hasattr(y, 'info'):
            if 'McaLiveTime' in y.info:
                livetime = y.info['McaLiveTime']
    ndim = data.ndim
    if ndim == 0:
        shape = 1, 1
    elif ndim == 1:
        shape = 1, data.size
    else:
        shape = None
    if shape is not None:
        data = data.reshape(shape)
        if livetime is not None:
            livetime = livetime.reshape(shape)
    return x, data, mcaIndex, livetime


@classmethod
def classpath(cls, targets, classpath_products, confs=('default',)):
    """Return the classpath as a list of paths covering all the passed targets.

        :param targets: Targets to build an aggregated classpath for.
        :param ClasspathProducts classpath_products: Product containing classpath elements.
        :param confs: The list of confs for use by this classpath.
        :returns: The classpath as a list of path elements.
        :rtype: list of string
        """
    classpath_iter = cls._classpath_iter(classpath_products.get_for_targets
        (targets), confs=confs)
    return list(classpath_iter)


def string_to_int(s):
    """Convert a string of bytes into an integer, as per X9.62."""
    result = 0
    for c in s:
        if not isinstance(c, int):
            c = ord(c)
        result = 256 * result + c
    return result


@staticmethod
def _shiftOrientationAction(orientingAction, permutingAction, shamt, modulus):
    """
        Multiply an orientation action by a given amount. Apply the permutation
        by that number of times too.

        :param orientingAction: list. A list of amounts to add to each
            element of the 'orientations' list.
        :param permutingAction: list. A list of cycles to apply.
        :param shamt: int. The amount to shift by.
        :param modulus: int. A modulus to apply after addition.
        :return: list. An orienting action that has been shifted.
        """
    ret = dict()
    if shamt < 0:
        for cycle in permutingAction:
            for i in range(len(cycle)):
                s = 0
                for j in range(abs(shamt)):
                    s -= orientingAction.get(cycle[(i + j + 1) % len(cycle)], 0
                        )
                ret[cycle[i]] = s % modulus
    elif shamt > 0:
        for cycle in permutingAction:
            for i in range(len(cycle)):
                s = 0
                for j in range(abs(shamt)):
                    s -= orientingAction.get(cycle[(i - j) % len(cycle)], 0)
                ret[cycle[i]] = s % modulus
    for k in orientingAction:
        if k not in ret:
            delta = orientingAction[k] * shamt % modulus
            if delta:
                ret[k] = delta
    return ret


def calculate_battery_state_of_charge(prev_battery_state_of_charge,
    battery_capacity, delta_time, battery_current, prev_battery_current=None):
    """
    Calculates the state of charge of the battery [%].

    :param prev_battery_state_of_charge:
        Previous state of charge of the battery [%].

        .. note::

            `prev_battery_state_of_charge` = 99 is equivalent to 99%.
    :type prev_battery_state_of_charge: float

    :param battery_capacity:
        Battery capacity [Ah].
    :type battery_capacity: float

    :param delta_time:
        Time step [s].
    :type delta_time: float

    :param battery_current:
        Low voltage battery current [A].
    :type battery_current: float

    :param prev_battery_current:
        Previous low voltage battery current [A].
    :type prev_battery_current: float

    :return:
        State of charge of the battery [%].
    :rtype: float
    """
    if prev_battery_current is None:
        prev_battery_current = battery_current
    c = battery_capacity * 36.0
    b = (battery_current + prev_battery_current) / 2.0 * delta_time
    return min(prev_battery_state_of_charge + b / c, 100.0)


@classmethod
def from_api_json(cls, d):
    """
        Create a :any:`senseBoxSensor` from a :any:`dict`.

        Args:
            d (dict): the dictionary to create the :any:`senseBoxSensor` from

        Returns:
            senseBoxSensor : the senseBox sensor
        """
    sensor = cls()
    sensor.update_from_api_json(d)
    return sensor


@classmethod
def create(cls, **kwargs):
    """Save the dict and return it."""
    my_data = cls.build(**kwargs)
    factory_data = cls.Meta.model.save(my_data)
    if hasattr(cls.Meta.model, 'ALIASES'):
        cls.Meta.model.set_alias()
    return factory_data


@classmethod
def get_supported(cls):
    """Retrieves a list with names of all supproted character sets

        Returns a tuple.
        """
    res = []
    for info in cls.desc:
        if info and info[0] not in res:
            res.append(info[0])
    return tuple(res)


def get_last_tones_from_melody(melody, n_th_last_tone):
    """ gets nth last tone of current melody"""
    melody_len = len(melody)
    if melody_len < n_th_last_tone:
        return []
    return melody[melody_len - n_th_last_tone]


def _reset_warnings():
    """Helper function to reset all warnings. Used by the unit tests."""
    globals()['__warningregistry__'] = None


@classmethod
def from_data(cls, data):
    """Construct a polygon from its data representation.

        Parameters
        ----------
        data : dict
            The data dictionary.

        Returns
        -------
        :class:`compas.geometry.Polygon`
            The constructed polygon.

        Examples
        --------
        >>> polygon = Polygon.from_data({'points': [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 1.0]]})
        >>> polygon.points[0]
        Point(0.000, 0.000, 0.000)
        """
    return cls(data['points'])


def _format(s, *args, **kwargs):
    """Safely format string ``s``.

    Returns ``s.format(*args, **kwargs)`` if no exception is thrown, otherwise
    ``s``.
    """
    try:
        return s.format(*args, **kwargs)
    except (IndexError, KeyError):
        return s


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 call_if_callable(maybe_callable, callable_args=None, callable_kwargs=
    None, else_=lambda x: x):
    """
    If `maybe_callable` is callable then it's called with `*callable_args` and `**callable_kwargs`.
    Else the function `else_` is called with `maybe_callable` as argument. `else_` default is the
    identity function, so when maybe_callable is not callable, the function returns `maybe_callable.`

    .. code-block:: python

        >>> call_if_callable(u'test')
        u'test'
        >>> def add2(x):
        ...     return x + 2
        >>> call_if_callable(add2, [4])
        6
        >>> def add_something(x, something=2)
        ...     return  x + something
        >>> call_if_callable(add_something, [4], {'something': 8})
        12
        >>> def concat_plop(string):
        ...        return u'{0}.plop'.format(string)
        >>> call_if_callable(u'test', else_=concat_plop)
        u'test.plop'

    :param maybe_callable: function to call if callable
    :param callable_args: List of argument to call with `maybe_callable`
    :param callable_kwargs: Dictonary of (key, value) to call with `maybe_callable`
    :param else_: Function to call if maybe_callable is not callable. One parameter supported : `maybe_callable`
    """
    callable_args = callable_args or []
    callable_kwargs = callable_kwargs or {}
    if hasattr(maybe_callable, '__call__'):
        res = maybe_callable(*callable_args, **callable_kwargs)
    else:
        res = else_(maybe_callable)
    return res


def triangle_variance_space(eigenvalues):
    """Compute barycentric coordinates of a point within the explained variance
    space, knowing the PCA eigenvalues

    See Brodu, N., Lague D., 2011. 3D Terrestrial lidar data classification of
    complex natural scenes using a multi-scale dimensionality criterion:
    applications in geomorphology. arXiV:1107.0550v3.

    Extract of C++ code by N. Brodu:

        // Use barycentric coordinates : a for 1D, b for 2D and c for 3D
        // Formula on wikipedia page for barycentric coordinates
        // using directly the triangle in %variance space, they simplify a lot
        //FloatType c = 1 - a - b; // they sum to 1
        a = svalues[0] - svalues[1];
        b = 2 * svalues[0] + 4 * svalues[1] - 2;

    See the wikipedia page
    https://en.wikipedia.org/wiki/Barycentric_coordinate_system    #Conversion_between_barycentric_and_Cartesian_coordinates

    If you project the three normalized eigenvalues on a 2D plane, i.e. (λ1,
    λ2), you get the triangle with these following coordinates:

    (1/3, 1/3), (1/2, 1/2), (1, 0)

    Thus you can build the T matrix and get the barycentric coordinates with
    the T^{-1}(r - r_3) formula.

    Parameters
    ----------
    eigenvalues : numpy.array
        Set of normalized eigenvalues; must be (1, 3)-shaped

    Returns
    -------
    list
        First two barycentric coordinates in the variance space (triangle)
    """
    alpha = eigenvalues[0] - eigenvalues[1]
    beta = 2 * eigenvalues[0] + 4 * eigenvalues[1] - 2
    return [alpha, beta]


@classmethod
def trace_by_json(cls):
    """Trace by writing directly JSON trace points."""
    cls._trace_functions.append(cls.json_trace_func)


def set_prefs(prefs):
    """This function is called before opening the project"""
    prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', '.hg',
        '.svn', '_svn', '.git', '.tox', '.env', 'node_modules',
        'bower_components']
    prefs['save_objectdb'] = True
    prefs['compress_objectdb'] = False
    prefs['automatic_soa'] = True
    prefs['soa_followed_calls'] = 0
    prefs['perform_doa'] = True
    prefs['validate_objectdb'] = True
    prefs['max_history_items'] = 32
    prefs['save_history'] = True
    prefs['compress_history'] = False
    prefs['indent_size'] = 4
    prefs['extension_modules'] = []
    prefs['import_dynload_stdmods'] = True
    prefs['ignore_syntax_errors'] = False
    prefs['ignore_bad_imports'] = False
    prefs['split_imports'] = False
    prefs['sort_imports_alphabetically'] = False


@classmethod
def initialize_options(cls):
    """ Stores options from the config file

        """
    cls.CONFIG_OPTIONS = cls.CFG.get(cls.CONFIG_PATH, return_type=dict)


@classmethod
def from_str(cls, text):
    """ Convert a text representation of a qualified object name into an ObjectName instance

        For example, 'foo.bar', '"foo".bar', '"foo"."bar"', etc. will be converted an object with
        schema 'foo' and object name 'bar'. Double quotes around the schema or object name are
        stripped, but note that we don't do anything with impossible input like 'foo."bar".baz'
        (which is impossible because the object name would include double quotes in it). Instead,
        we let processing proceed and the issue bubble up downstream.
        """
    if '.' not in text:
        return cls(schema=text)
    schema, unqualified_name = text.split('.', 1)
    return cls(schema=schema, unqualified_name=unqualified_name)


@staticmethod
def gain_int_to_db_string(intval):
    """Substract 96 and return the signed value as a string
        """
    if intval - 96 >= 0:
        return '+' + str(intval - 96)
    return str(intval - 96)


def n50(lengths, genome_size=None):
    """
	Return N50 or NG50 value given a list of lengths.

	If the genome_size is not given, it is set to sum(lengths). The resulting
	value is the N50. If it is given, the resulting value is the NG50.

	If genome_size is greater than 2 * sum(lengths), None is returned.
	"""
    if genome_size is None:
        genome_size = sum(lengths)
    lengths = sorted(lengths, reverse=True)
    running_total = 0
    for length in lengths:
        running_total += length
        if running_total >= genome_size * 0.5:
            return length
    return None


def _kernel_ver_linux():
    """Returns kernel version as major, minor, patch tuple."""
    with open('/proc/sys/kernel/osrelease') as f:
        kver = f.readline().split('.')[:3]
        last = len(kver)
        if last == 2:
            kver.append('0')
        last -= 1
        for char in '-_':
            kver[last] = kver[last].split(char)[0]
        try:
            int(kver[last])
        except ValueError:
            kver[last] = 0
        return int(kver[0]), int(kver[1]), int(kver[2])


def is_bus(df):
    """Return if vehicle is a bus, per NHTSA convention."""
    yr = df['YEAR']
    body = df['BODY_TYP']
    return yr.between(1975, 1981) & body.between(25, 29) | yr.between(1982,
        1990) & body.between(30, 39) | (1991 <= yr) & body.between(50, 59)


def _set_grid_column_references(figure, grid):
    """
    Populate *src columns in a figure from uploaded grid

    Parameters
    ----------
    figure: dict
        Figure dict that previously had inline data arrays extracted
    grid: Grid
        Grid that was created by extracting inline data arrays from figure
        using the _extract_grid_from_fig_like function

    Returns
    -------
    None
        Function modifies figure in-place
    """
    from plotly.basedatatypes import BaseFigure
    for col in grid:
        prop_path = BaseFigure._str_to_dict_path(col.name)
        prop_parent = figure
        for prop in prop_path[:-1]:
            prop_parent = prop_parent[prop]
        prop_parent[prop_path[-1] + 'src'] = col.id


def get_xception_filename(key):
    """Rename tensor name to the corresponding Keras layer weight name.
    # Arguments
        key: tensor name in TF (determined by tf.variable_scope)
    """
    filename = str(key)
    filename = filename.replace('/', '_')
    filename = filename.replace('xception_65_', '')
    filename = filename.replace('decoder_', '', 1)
    filename = filename.replace('BatchNorm', 'BN')
    if 'Momentum' in filename:
        return None
    if 'entry_flow' in filename or 'exit_flow' in filename:
        filename = filename.replace('_unit_1_xception_module', '')
    elif 'middle_flow' in filename:
        filename = filename.replace('_block1', '')
        filename = filename.replace('_xception_module', '')
    filename = filename.replace('_weights', '_kernel')
    filename = filename.replace('_biases', '_bias')
    return filename + '.npy'


def load_script(path: str):
    """
    Load script is a convinient method that just reads the content from the file
    and returns it, as of now. But eventually can do validations using PyTorch's
    scirpt compile utility and clean up the input files for user etc
    """
    with open(path, 'rb') as f:
        return f.read()


def match(v1, v2, nomatch=-1, incomparables=None, start=0):
    """
    Return a vector of the positions of (first)
    matches of its first argument in its second.

    Parameters
    ----------
    v1: array-like
        the values to be matched

    v2: array-like
        the values to be matched against

    nomatch: int
        the value to be returned in the case when
        no match is found.

    incomparables: array-like
        a list of values that cannot be matched.
        Any value in v1 matching a value in this list
        is assigned the nomatch value.
    start: int
        type of indexing to use. Most likely 0 or 1
    """
    lookup = {}
    for i, x in enumerate(v2):
        if x not in lookup:
            lookup[x] = i
    if incomparables:
        skip = set(incomparables) if incomparables else set()
        lst = [(lookup[x] + start if x not in skip and x in lookup else
            nomatch) for x in v1]
    else:
        lst = [(lookup[x] + start if x in lookup else nomatch) for x in v1]
    return lst


def _prepare_arg(arg):
    """Return a keyword arg spec (dict)"""
    _arg = {'name': arg.name}
    if arg.annotation != arg.empty:
        try:
            name = str(arg.annotation.__name__)
        except AttributeError:
            name = str(arg.annotation._name)
        _arg['type'] = name
        _arg['annotation'] = arg.annotation
    if arg.empty is not arg.default:
        _arg['default'] = arg.default
    return _arg


def suspend():
    """Suspends handling of current coroutine/green thread and passes control
    to the next async core.

    * http://uwsgi.readthedocs.io/en/latest/Async.html#suspend-resume

    :rtype: bool
    """
    return False


def make_identifier(headername):
    """Make #ifndef identifier that contains uppercase A-Z and digits 0-9"""
    result = ''
    for c in headername.upper():
        if c.isalnum():
            result += c
        else:
            result += '_'
    return result


def update(fun, arr):
    """update all items using function"""
    for val in arr:
        if val.data is not None:
            val.data.update(fun(val))
        else:
            val.update(fun(val))
        yield val


@staticmethod
def join(timeout=None):
    """Join the service once stopped."""


def default(value):
    """
    Given a python object, return the default value
    of that object.

    :param value: The value to get the default of
    :returns: The default value
    """
    return type(value)()


@staticmethod
def p_annotation_optional(p):
    """annotation_optional : annotation_label
                               | annotation_origin
                               | annotation_text"""
    p[0] = p.slice[1].type, p[1]


def _hex(x):
    """Formatting integer as two digit hex value."""
    return '0x{:02X}'.format(x)


def convert_args_to_laid_out_tensors(xs):
    """Convert list elements to laid-out-tensors when possible.

  Args:
    xs: a list
  Returns:
    a list
  """
    ret = []
    for x in xs:
        if hasattr(x, 'to_laid_out_tensor'):
            ret.append(x.to_laid_out_tensor())
        else:
            ret.append(x)
    return ret


def is_minimally_restrictive(identifier):
    """Minimally restrictive: Same as moderately restrictive, but allow arbitrary
    mixtures of scripts"""
    return True


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


@classmethod
def supports_metadata(cls):
    """returns True if this audio type supports MetaData"""
    return True


def chunks(source, length):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(source), length):
        yield source[i:i + length]


def name_plus_version(name):
    """A weird name for a function (I couldn't think of anything better), This
       function adds name by version. name=tcl or tk
       while version=the version of name.
       This function is used for setting required env variables."""
    if name == 'tcl':
        try:
            import tkinter
            tkv = tkinter.TkVersion
        except:
            import Tkinter
            tkv = Tkinter.TkVersion
        finally:
            tkv = str(tkv)
            a = name + tkv
            return a
    elif name == 'tk':
        try:
            import tkinter
            tclv = tkinter.TclVersion
        except:
            import Tkinter
            tclv = Tkinter.TclVersion
        finally:
            tclv = str(tclv)
            a = name + tclv
            return a
    else:
        error = (
            'is not a valid argument for name. Valid arguments are "tcl" or "tk".'
            )
        error = "'" + name + "' " + error
        raise SyntaxError(error)


def _is_descriptor(obj):
    """Returns True if obj is a descriptor, False otherwise.
    From cpython Enum"""
    return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj,
        '__delete__')


def _calculate_meta(meta, bases):
    """Calculate the most derived metaclass."""
    winner = meta
    for base in bases:
        base_meta = type(base)
        if issubclass(winner, base_meta):
            continue
        if issubclass(base_meta, winner):
            winner = base_meta
            continue
        raise TypeError(
            'metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases'
            )
    return winner


def close():
    """Support file-like API"""


def _convert_to_degress(value):
    """
    Helper function to convert the GPS coordinates
    stored in the EXIF to degress in float format
    """
    d0 = value[0][0]
    d1 = value[0][1]
    d = float(d0) / float(d1)
    m0 = value[1][0]
    m1 = value[1][1]
    m = float(m0) / float(m1)
    s0 = value[2][0]
    s1 = value[2][1]
    s = float(s0) / float(s1)
    return d + m / 60.0 + s / 3600.0


def __iter__():
    """Return an iterator which provides the terms from the vocabulary."""


@classmethod
def attr_name_for_column(cls, column_name: str) ->str:
    """Get the class attribute name for a given database column name.

        This is used when setting instance values for :class`Column`'s, and
        allows access to the attribute name, whether the ``column_name`` was
        parsed using the actual database column name, or the attribute name
        (which can be different depending on the ``Column``).

        Example::

            >>> class User(BaseModel):
                    id = Column('_id', primary_key=True)
                    name = Column()

            >>> User.attr_name_for_column('_id')
            'id'
            >>> User.attr_name_for_column('id')
            'id'

        :param column_name:  The database column name to get the attribute name
                             for.
        :raises ValueError:  If no :class:`Column` is found for that column
                             name.

        """
    for attr_name, col in cls._columns():
        if col.key == column_name:
            return attr_name
        elif attr_name == column_name:
            return column_name
    raise ValueError(column_name)


def distinct(l):
    """Builds a new list with all duplicates removed."""
    s = []
    for i in l:
        if i not in s:
            s.append(i)
    return s


def create_lookup_table(windows):
    """Create a lookup table from the given list of windows.

    The returned dict is in the format window title → X window id.
    """
    lookup = {}
    for window in windows:
        name = window.get('name')
        id_ = window.get('window')
        if id_ is None:
            continue
        if name.startswith('i3bar for output'):
            continue
        lookup[name] = id_
    return lookup


def update_combo_box(values_dict, element, element_key, args, attr,
    fun_to_apply):
    """Update a non-paired, independent option like `uniform`.  Function `fun_to_apply`
    is applied to the GUI value to convert it to the type `args` expects."""
    if values_dict is None:
        return
    element_value = values_dict[element_key]
    element_value = fun_to_apply(element_value)
    element.Update(str(element_value))
    setattr(args, attr, element_value)


@classmethod
def from_json(cls, val):
    """ Create a remote file from JSON

        Args:
            val (:obj:`dict`)

        Returns:
            :obj:`RemoteFile`
        """
    return cls(name=val.get('name', None), type=val.get('type', None), size
        =val.get('size', None))


def iter_join(t, join_on='_'):
    """

    Convert an iterabe (``t``) to a string by joining on ``join_on``.

    :param t: any iterable.
    :type t: ``iterable``
    :param join_on: a string to join ``t`` on.
    :type join_on: ``str``
    :return: ``t`` as a string.
    :rtype: ``str``
    """
    return join_on.join(t) if isinstance(t, (list, tuple)) else t


def post_feature(gismo, i):
    """
    Feature indice to feature name

    Parameters
    ----------
    gismo: Gismo
        Gismo instance
    i : int
        feature indice

    Returns
    -------
    str
        Feature i from embedding
    """
    return gismo.embedding.features[i]


@staticmethod
def p_measurement_optional_list(p):
    """measurement_optional_list : measurement_optional
                                     | measurement_optional measurement_optional_list"""
    try:
        p[0] = [p[1]] + p[2]
    except IndexError:
        p[0] = [p[1]]


def ext_left(data):
    """
    Extract the left half of spectrum.

    Parameters
    ----------
    data : ndarray
        Array of NMR data.

    Returns
    -------
    ndata : ndarray
        Left half of spectrum.

    """
    return data[(...), 0:int(data.shape[-1] / 2.0)]


def add_signaling_arguments(parser):
    """
    Add signaling method arguments to an argparse.ArgumentParser.
    """
    parser.add_argument('--signaling', '-s', choices=['share-websocket'])
    parser.add_argument('--signaling-host', default='127.0.0.1', help=
        'Signaling server host')
    parser.add_argument('--signaling-port', default=10000, help=
        'Signaling server port')
    parser.add_argument('--secure-signaling', help=
        'Signaling communication is encrypted', action='store_true')


def perimeter_trapezoid(a, b, c, d):
    """
    P = a + b + c + d
    """
    return a + b + c + d


def _extract_ports(port_string):
    """
    Return a dict for translated_value based on a string or int
    value.

    Value could be 80, or '80' or '80-90'.

    Will be returned as {'min_port': 80, 'max_port': 80} or
    {'min_port': 80, 'max_port': 90}

    :rtype: dict
    """
    _ports = str(port_string)
    if '-' in _ports:
        start, end = _ports.split('-')
        return {'min_port': start, 'max_port': end}
    return {'min_port': _ports, 'max_port': _ports}


def get_mids(mids):
    """arranges mid values and emus in list"""
    modified_mids = [[], []]
    measured_emus = mids[0]
    i = 0
    while i < len(mids[1]):
        vals = float(mids[1][i])
        err = float(mids[2][i])
        modified_mids[0].append(vals)
        modified_mids[1].append(err)
        i += 1
    modified_mids.append(measured_emus)
    return modified_mids


def quadgl(ctx, *args, **kwargs):
    """
        Performs Gauss-Legendre quadrature. The call

            quadgl(func, *points, ...)

        is simply a shortcut for:

            quad(func, *points, ..., method=GaussLegendre)

        For example, a single integral and a double integral:

            quadgl(lambda x: exp(cos(x)), [0, 1])
            quadgl(lambda x, y: exp(cos(x+y)), [0, 1], [0, 1])

        See the documentation for quad for information about how points
        arguments and keyword arguments are parsed.

        See documentation for TanhSinh for algorithmic information about
        tanh-sinh quadrature.
        """
    kwargs['method'] = 'gauss-legendre'
    return ctx.quad(*args, **kwargs)


def guessMode(text):
    """Tries to guess the type of the input text, using a quite fast heuristic.

    Returns one of the strings also present as key in the modes dictionary.

    """
    text = text.lstrip()
    if text.startswith(('%', '\\')):
        if '\\version' in text or '\\relative' in text or '\\score' in text:
            return 'lilypond'
        if '\\documentclass' in text or '\\begin{document}' in text:
            return 'latex'
        return 'lilypond'
    if text.startswith('<<'):
        return 'lilypond'
    if text.startswith('<'):
        if 'DOCTYPE book' in text or '<programlisting' in text:
            return 'docbook'
        else:
            return 'html'
    if text.startswith(('#!', ';', '(')):
        return 'scheme'
    if text.startswith('@'):
        return 'texinfo'
    if text.startswith('//'):
        return 'mup'
    s = text.split(None, 1)
    if s and s[0] in ('include', 'score', 'music'):
        return 'mup'
    return 'lilypond'


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 wordCode(node):
    """ Change word node value to Word() expr. """
    expr = repr(node.snippet)
    word = repr(node.value)
    node.value = 'Word(%s, expression=%s)' % (word, expr)


@classmethod
def has_archiving(cls):
    """Returns whether it supports archiving items on the fetch process.

        :returns: this backend supports items archive
        """
    return True


@staticmethod
def _escape_unicode_char_uU(c, ord=ord):
    """
        Escape a Unicode code point using \\uHHHH` (16-bit),
        or `\\UHHHHHHHH` (24-bit) notation.
        """
    n = ord(c)
    if n < 65536:
        return '\\u{0:04x}'.format(n)
    return '\\U{0:08x}'.format(n)


def lambd_CO2_Na_HMW84(T, P):
    """n-c: carbon-dioxide sodium [HMW84]."""
    lambd = 0.1
    valid = T == 298.15
    return lambd, valid


@staticmethod
def get_custom_spec_interface(dhcp, ip=None, mask=None, gateway=None):
    """
        Generates an interface object definition for a
        customization specification :py:func:`get_custom_spec`

        :param dhcp: Whether the virtual machine acquires IP config from
         DHCP. If set to true, parameters ip, subnet dns and gateway will
         be ignored.
        :type dhcp: bool
        :param ip: Specification to obtain a unique IP address
         for this virtual network adapter.
        :type ip: str
        :param mask: Subnet mask for this virtual network adapter.
        :type mask: str
        :param gateway: For a virtual network adapter with a static IP address,
         this data object type contains a list of gateways,
         in order of preference.
        :type gateway: list
        :return:
        """
    interface = dict(dhcp=dhcp)
    if not dhcp:
        fixed_ip = dict(ip=ip, mask=mask, gateway=gateway)
        interface.update(fixed_ip)
    return interface


def _match(property):
    """Triggered for match event type
    :@param property: string
    :@return event_type: string
    """
    event_mapper = {'ForkEvent': 'forked', 'WatchEvent': 'started',
        'CheckRunEvent': 'checked run', 'CommitCommentEvent':
        'committed comment', 'CreateEvent': 'created', 'DeleteEvent':
        'deleted', 'ForkApplyEvent': 'forked apply', 'IssueCommentEvent':
        'issueed comment', 'IssuesEvent': 'iussue', 'LabelEvent': 'lebel',
        'MemberEvent': 'member', 'MembershipEvent': 'membership',
        'MilestoneEvent': 'milestone', 'PullRequestEvent':
        'pulled a request', 'PullRequestReviewEvent': 'review pull request',
        'PullRequestReviewCommentEvent': 'review & comment pull request',
        'RepositoryEvent': 'repo', 'PushEvent': 'pushed',
        'RepositoryVulnerabilityAlertEvent': 'repo sequirity', 'TeamEvent':
        'team', 'TeamAddEvent': 'added team'}
    if property not in event_mapper:
        return ''
    return event_mapper.get(property)


def get_rect(img, bottom, top, left, right, ax, color='r'):
    """
    return a sub-area on a 2D-array img and display the boundaries on a matplotlib axis ax
    """
    ax.axhline(bottom, color=color)
    ax.axhline(top, color=color)
    ax.axvline(left, color=color)
    ax.axvline(right, color=color)
    return img[bottom:top, left:right]


def send(source, queue, shutdown=None):
    """Send records from a source to a queue.

    Parameters
    ----------
    source: :ref:`Record generator <record-generators>`, required
    queue: :class:`queue.Queue`, required
    shutdown: :class:`threading.Event`, optional.
        Set the event to safely stop sending from another thread.
    """
    for record in source:
        queue.put(record)
        if shutdown and shutdown.isSet():
            return
    queue.put(StopIteration)


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 '+'


@classmethod
def from_kibi(cls, value):
    """
        Convert from Kibibytes (KiB) to bytes
        """
    return cls.from_kilo(value, base=1024)


def count_and_log(message, i, total, log_every_n):
    """Print a message to reflect the progress of processing once a while.

    Parameters
    ----------
    message : str
        Message to print.
    i : int
        Current index.
    total : int
        Total count.
    log_every_n : None or int
        Molecule related computation can take a long time for a large dataset and we want
        to learn the progress of processing. This can be done by printing a message whenever
        a batch of ``log_every_n`` molecules have been processed. If None, no messages will
        be printed.
    """
    if log_every_n is not None and (i + 1) % log_every_n == 0:
        print('{} {:d}/{:d}'.format(message, i + 1, total))


def imports_on_separate_lines(logical_line):
    """Place imports on separate lines.

    Okay: import os\\nimport sys
    E401: import sys, os

    Okay: from subprocess import Popen, PIPE
    Okay: from myclas import MyClass
    Okay: from foo.bar.yourclass import YourClass
    Okay: import myclass
    Okay: import foo.bar.yourclass
    """
    line = logical_line
    if line.startswith('import '):
        found = line.find(',')
        if -1 < found and ';' not in line[:found]:
            yield found, 'E401 multiple imports on one line'


@classmethod
def list_supported_networks(cls):
    """Lists all networks supported by nodes returned by this driver

        :return: [String] list of network names
        """
    return cls.SUPPORTED_NETWORKS


@classmethod
def from_config(cls, config):
    """Construct a `ParseContext` from a `FluffConfig`."""
    return cls(dialect=config.get('dialect_obj'), recurse=config.get('recurse')
        )


def d_phi_dxx(x, y):
    """
    second derivative of the orientation angle

    :param x:
    :param y:
    :return:
    """
    return 2 * x * y / (x ** 2 + y ** 2) ** 2


def make_bounds(model_metabolite, minTotal=False):
    """
    Create reaction bounds.
      if minTotal == True then extra bound is added to acomodate for the pseudoreaction
    """
    basis = model_metabolite[3]
    p_basis = model_metabolite[6][0]
    deviation = model_metabolite[4]
    bounds = []
    for i in range(len(basis)):
        base = basis[i]
        dev = deviation[i]
        print('\n\ni', i)
        print('len(model_metabolite)', len(model_metabolite))
        print('len(model_metabolite)', len(model_metabolite[7]))
        lb = model_metabolite[7][i]
        ub = model_metabolite[8][i]
        if base == '' and (dev == '' or not dev.isnumeric()) or base == 'X':
            if lb != '' and ub != '':
                bounds.append((float(lb), float(ub)))
            elif model_metabolite[5][i] != 'R':
                b = 0, p_basis * 15
                bounds.append(b)
            elif model_metabolite[5][i] == 'BR':
                b = -p_basis * 15, p_basis * 15
                bounds.append(b)
            else:
                ubb = p_basis * 5
                b = 0, ubb
                bounds.append(b)
        elif base != '' and dev == '':
            assert float(base), 'Error: basis entry might not be a numeral'
            base = float(base)
            b = base, base
            bounds.append(b)
        elif base != '' and dev != '':
            assert float(base), 'Error: basis entry might not be a numeral'
            base = float(base)
            dev = float(dev)
            assert float(dev), 'Error: deviation entry might not be a numeral'
            b = base - dev, base + dev
            bounds.append(b)
    if minTotal is True:
        bounds.append((0, 5000))
    return bounds