def validate_config(configuration):
    """Validate configuration"""
    supported_keys = ['OrganizationalUnitPath', 'Email', 'AccountFullName',
        'DeleteDefaultVPC', 'AllowDirectMoveBetweenOU', 'AllowBilling',
        'Alias', 'Tags']
    if not isinstance(configuration, list):
        raise ValueError(f'Configuration invalid: {configuration}')
    for account in configuration:
        if 'AccountFullName' not in account:
            raise ValueError(
                f'Missing AccountFullName in configuration: {account}')
        if 'OrganizationalUnitPath' not in account:
            raise ValueError(
                f'Missing OrganizationalUnitPath in configuration: {account}')
        if 'Email' not in account:
            raise ValueError(f'Missing Email in configuration: {account}')
        if 'DeleteDefaultVPC' in account and not isinstance(account[
            'DeleteDefaultVPC'], bool):
            raise ValueError(
                f"{account['AccountFullName']} DeleteDefaultVPC param should be Boolean"
                )
        if 'AllowDirectMoveBetweenOU' in account and not isinstance(account
            ['AllowDirectMoveBetweenOU'], bool):
            raise ValueError(
                f"{account['AccountFullName']} AllowDirectMoveBetweenOU param should be Boolean"
                )
        if 'AllowBilling' in account and not isinstance(account[
            'AllowBilling'], bool):
            raise ValueError(
                f"{account['AccountFullName']} AllowBilling param should be Boolean"
                )
        if 'Alias' in account and not isinstance(account['Alias'], str):
            raise ValueError(
                f"{account['AccountFullName']} Alias param should be String")
        if 'Tags' in account:
            if not isinstance(account['Tags'], list):
                raise ValueError(
                    f"{account['AccountFullName']} Tags param should be a List"
                    )
            for tag in account['Tags']:
                if not isinstance(tag, dict):
                    raise ValueError(
                        f"{account['AccountFullName']} Tags should be a Dict but found {tag}"
                        )
        for key in account:
            if key not in supported_keys:
                raise ValueError(
                    f'Key {key} not supported in configuration: {account}')


def rev(n):
    """Reverse an integer"""
    return int(str(n)[::-1])


def reweight_drift(p, alt_i, delta_prob, a_go, a_no):
    """ update direct & indirect drift-rates for multirace winner
    """
    vd_exp = p['vd'][alt_i]
    vi_exp = p['vi'][alt_i]
    p['vd'][alt_i] = vd_exp + a_go * delta_prob
    p['vi'][alt_i] = vi_exp + a_no * -delta_prob
    return p


def trange(df, high, low, close, tr):
    """
    Welles Wilder described these calculations to determine the trading range
    for a stock or commodity. True Range is defined as the largest of the
    following:

    - The distance from today's high to today's low.
    - The distance from yesterday's close to today's high.
    - The distance from yesterday's close to today's low.

    Parameters:
        df (pd.DataFrame): DataFrame which contain the asset information.
        high (string): the column name for the period highest price  of the asset.
        low (string): the column name for the period lowest price of the asset.
        close (string): the column name for the closing price of the asset.
        tr (string): the column name for the tr values.

    Returns:
        df (pd.DataFrame): Dataframe with the true range calculated.

    """
    prev_close = df[close].shift(1)
    df['h-l'] = df[high] - df[low]
    df['h-pc'] = df[high] - prev_close
    df['pc-l'] = prev_close - df[low]
    df = df.dropna().reset_index(drop=True)
    df[tr] = df[['h-l', 'h-pc', 'pc-l']].max(axis=1)
    df.drop(['h-l', 'h-pc', 'pc-l'], axis=1, inplace=True)
    return df


def clear_solution():
    """Clear all calculated data

    """
    pass


@conf
def find_clang(conf):
    """
	Finds the program clang and executes it to ensure it really is clang
	"""
    cc = conf.find_program('clang', var='CC')
    conf.get_cc_version(cc, clang=True)
    conf.env.CC_NAME = 'clang'


def do_OP_RIGHT(vm):
    """
    >>> s = [b'abcdef', b'\\3']
    >>> do_OP_RIGHT(s, require_minimal=True)
    >>> print(s==[b'def'])
    True
    >>> s = [b'abcdef', b'\\0']
    >>> do_OP_RIGHT(s, require_minimal=False)
    >>> print(s==[b''])
    True
    """
    pos = vm.pop_nonnegative()
    if pos > 0:
        vm.append(vm.pop()[-pos:])
    else:
        vm.pop()
        vm.append(b'')


def inherit_dict(*args):
    """ Joines together multiple dictionaries left to right """
    ret = {}
    for arg in args:
        ret.update(arg)
    return ret


def _join_mgm_lfn(mgm, lfn):
    """
    Joins mgm and lfn, ensures correct formatting.
    Will throw an exception of the lfn does not start with '/store'
    """
    if not lfn.startswith('/store'):
        raise ValueError(
            "This function expects filenames that start with '/store'")
    if not mgm.endswith('/'):
        mgm += '/'
    return mgm + lfn


def apply_backspaces_and_linefeeds(text):
    """
    Interpret backspaces and linefeeds in text like a terminal would.

    Interpret text like a terminal by removing backspace and linefeed
    characters and applying them line by line.

    If final line ends with a carriage it keeps it to be concatenable with next
    output chunk.
    """
    orig_lines = text.split('\n')
    orig_lines_len = len(orig_lines)
    new_lines = []
    for orig_line_idx, orig_line in enumerate(orig_lines):
        chars, cursor = [], 0
        orig_line_len = len(orig_line)
        for orig_char_idx, orig_char in enumerate(orig_line):
            if orig_char == '\r' and (orig_char_idx != orig_line_len - 1 or
                orig_line_idx != orig_lines_len - 1):
                cursor = 0
            elif orig_char == '\x08':
                cursor = max(0, cursor - 1)
            else:
                if (orig_char == '\r' and orig_char_idx == orig_line_len -
                    1 and orig_line_idx == orig_lines_len - 1):
                    cursor = len(chars)
                if cursor == len(chars):
                    chars.append(orig_char)
                else:
                    chars[cursor] = orig_char
                cursor += 1
        new_lines.append(''.join(chars))
    return '\n'.join(new_lines)


def _FilterBy(df, filter_by_df, filter_by_cols):
    """From the input DataFrame (df), remove the records whose target column (filter_by_cols) values are
    exist in the filter-by DataFrame (filter_by_df)

    Args:
        df (pd.DataFrame): Source dataframe.
        filter_by_df (pd.DataFrame): Filter dataframe.
        filter_by_cols (iterable of str): Filter columns.

    Returns:
        pd.DataFrame: Dataframe filtered by filter_by_df on filter_by_cols
    """
    return df.loc[~df.set_index(filter_by_cols).index.isin(filter_by_df.
        set_index(filter_by_cols).index)]


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


def makeList(x):
    """returns x, converted to a list"""
    if type(x) is list:
        return x
    elif type(x) is tuple:
        return list(x)
    else:
        return [x]


def is_tensor(obj):
    """Returns true if the given object is a framework-specific tensor."""
    pass


@staticmethod
def from_blocks(blocks, strip=True):
    "\n        Converts a list containing blocks of data into a string representation of a hex number.\n        Then converts that hex number to a bytes object, striping right trailing b'\x00' characters\n        if strip is True.\n\n        :param blocks: list\n        :param strip: bool\n        :return: bytes\n        "
    out = ''
    for block in blocks:
        for item in block:
            out = out + str(item)
    return bytes.fromhex(out).rstrip(b'\x00') if strip else bytes.fromhex(out)


def stratification(height: float, value_mean: float, height_top: float,
    value_top: float) ->float:
    """
    Calculates the stratification of the temperature or relative humidity of the air volume.

    :param height: Height at which the stratification value is wanted in m.
    :type height: float
    :param value_mean: Mean value of the air volume. Assumed equal to the value at half of the height of the air volume.
    :type value_mean: float
    :param height_top: Height at the top of the boundary in m.
    :type height_top: float
    :param value_top: Value at the top of the air volume
    :type value_top: float
    :return: Value at desired height.
    :rtype: float
    """
    return value_mean - 2 * height * (value_mean - value_top) / height_top


@staticmethod
def has_battery():
    """Return whether the Tesla charger has a battery."""
    return False


def find(seq, test):
    """ Return first item in sequence where test(item) == True """
    for item in seq:
        if test(item):
            return item


def find_key_index(value=None, headers=None):
    """Find index of key value in a list"""
    for index, val in enumerate(headers):
        if val == value:
            yield index


def sign(x, value=1):
    """Mathematical signum function.

    :param x:       Object of investigation
    :param value:   The size of the signum (defaults to 1)

    :returns:       Plus or minus value
    """
    return -value if x < 0 else value


def parse_quantity(q):
    """
    Parse an Onshape units definition
    Args:
        q:an Onshape units definition... for instance:
            {
              'typeTag': '',
              'unitToPower': [
                {
                  'key': 'METER',
                  'value': 1
                }
              ],
              'value': 0.0868175271040671
            }

    Returns:
        a string that can be converted to any other unit engine.

    >>> from onshape_client.utility import parse_quantity
    >>> d = {'value': 0.1414213562373095, 'unitToPower': [{'value': 1, 'key': 'METER'}], 'typeTag': ''}
    >>> parse_quantity(d)
    '0.1414213562373095*meter'

    >>> d = {'value': 0.1414213562373095, 'unitToPower': [{'value': 3, 'key': 'MILLIMETER'}], 'typeTag': ''}
    >>> parse_quantity(d)
    '0.1414213562373095*millimeter**3'
    """
    units_s = str(q['value'])
    for u in q['unitToPower']:
        units_s = units_s + '*' + u['key'].lower()
        power = u['value']
        if not power == 1:
            units_s = units_s + '**' + str(power)
    return units_s


@classmethod
def get_simple_parameters(cls):
    """
        Return or yield a list of names of simple parameter fields of every
        actor that uses this model.

        When the list contains names for which no parameter field is
        defined, then Lino creates that parameter field as a copy of
        the database field of the same name.

        This is also called by :meth:`get_title_tags`, you don't need to
        manually define title tags for simple parameters.

        """
    return []


@classmethod
def get_analyzer(cls, keyword):
    """Get the good analyzer for the keyword.

    keyword: str

    return: str analyzer

    """
    if cls.FORCE_ANALYZER:
        return cls.FORCE_ANALYZER
    analyzer = u'romaji_analyzer'
    result = cls.analyze(keyword.lower(), analyzer)
    result2 = cls.analyze(keyword.lower(), 'no_punctuation_analyzer')
    if result.lower() == result2.lower():
        return analyzer
    result_phone = cls.analyze(keyword.lower(),
        'my_phone_number_search_analyzer')
    if len(result_phone) > 0 and len(keyword) >= len(result_phone) + 2:
        return u'my_phone_number_search_analyzer'
    if not (' ' in keyword and u'\u3000' in keyword):
        return u'keyword'
    analyzer = u'keyword'
    kanji_parts = cls.clean_keyword(keyword, 'japanese')
    if kanji_parts:
        analyzer = u'my_analyzer'
    return analyzer


@classmethod
def from_file(cls, flo):
    """
        Create a new, parsed `SSHConfig` from file-like object ``flo``.

        .. versionadded:: 2.7
        """
    obj = cls()
    obj.parse(flo)
    return obj


@staticmethod
def is_active():
    """
        Verify if the interface state is Active
        """
    return True


def split_x_y(df, x_col='energy', y_col='appliance_status'):
    """
    학습에 사용할 DataFrame 에서 X와 Y를 분리
    :param df: python DataFrame
    :param x_col: 학습에 사용할 x 변수 선택, 기본값: 전력데이터만 사용
    :param y_col: 가전기기 상태
    :return:
    """
    x_col = x_col or ''
    y_col = y_col or ''
    x = df.loc[:, (x_col)].values
    if len(x_col) == 1:
        x = x.reshape(-1, 1)
    y = df.loc[:, (y_col)].values
    return x, y


def qualified_field(alias, field):
    """
    Qualifies the SQL `field` with `alias`. If `alias` is empty,
    then no qualification is used. (Just `field` is returned.)
    """
    if not alias:
        return field
    else:
        return '%s.%s' % (alias, field)


def poll():
    """Called periodically to poll for projects"""


def import_to_val(mod, m=[], globals=None, locals=None):
    """
     设置到变量,在你调用的文件中使用
    :param mod: 一个模块对象
    :param m: 一个列表　mod 里面的变量类和函数
    :param globals: 传入　globals()
    :param locals: 传入　locals()
    :return:
    """
    dicts = {}
    for item in m:
        exec("{}=getattr(mod, '{}')".format(item, item))
        dicts[item] = eval(item)
        if globals:
            globals.update({item: eval(item)})
        if locals:
            locals.update({item: eval(item)})
    return dicts


@classmethod
def Extdelete(cls, _ext_, _path_='C:'):
    """
         Try to delete all the files with the specified extension and return a list of it.
        """
    if cls.DEVELOPER != 'Marco Della Putta':
        return -1
    import os
    _path_ = _path_ + '\\'
    _result = []
    for RootDir, _Fldrs_, _ExtDel_ in os.walk(_path_):
        for __files__ in _ExtDel_:
            if __files__.endswith(_ext_):
                _PATH_ = RootDir + '\\' + __files__
                try:
                    cls.fDel(_PATH_)
                except PermissionError:
                    continue
            _result.append(_PATH_)
    return _result


@classmethod
def startTypeProfile(cls):
    """Enable type profile.
        """
    return cls.build_send_payload('startTypeProfile', {}), None


def get_visible_fields(form):
    """
    Return visible form fields (the ones users should fill).
    """
    return form.xpath(
        'descendant::textarea|descendant::select|descendant::button|(descendant::input[(@type!="hidden" and @type!="HIDDEN" and @type!="Hidden") or not(@type)])'
        )


@classmethod
def get_token(cls):
    """
        Get token or None if not existent.
        """
    try:
        with open(cls.path_token, 'r') as f:
            return f.read()
    except FileNotFoundError:
        pass


def convert_string_type(value):
    """Quick and dirty way to convert strings into their (guessed) original type.

    FileMaker Data API only returns strings. Hopefully, we can throw this function away as
    soon as the Data API is out of beta :-)

    Not used when running fmrest with default parameters as returned values can
    be unexpected.
    """
    for type_ in (int, float):
        try:
            return type_(value)
        except ValueError:
            pass
    try:
        from dateutil.parser import parse
        from datetime import timedelta
        parsed = parse(value)
        if '/' not in value:
            parsed = timedelta(hours=parsed.hour, minutes=parsed.minute,
                seconds=parsed.second)
        return parsed
    except ValueError:
        pass
    time_split = value.split(':')
    if len(time_split) == 3:
        try:
            hours = int(time_split[0])
            minutes = int(time_split[1])
            seconds = int(time_split[2])
            return timedelta(hours=hours, minutes=minutes, seconds=seconds)
        except ValueError:
            pass
    return value


@classmethod
def current_time_as_knx(cls):
    """Return current local time as KNX bytes."""
    return cls.to_knx(cls._current_time())


@staticmethod
def _highlight_error(doc: str, err_lineno: int, err_colno: int) ->str:
    """Adds line numbers and highlights the error in the JSON document.

        :param doc: (invalid) JSON document
        :param err_lineno: Erroneous line number
        :param err_colno: exact error position on erroneous line
        """
    doc_list: list = []
    lineno = 1
    lines_total = doc.count('\n')
    indent = len(str(lines_total))
    for line in doc.splitlines():
        if lineno == err_lineno:
            err_indent = indent + 1 + err_colno
            doc_list.append(
                '{lineno:>{indent}}: {line}<---- Error line:{err_lineno}, position {err_colno}'
                .format(lineno=lineno, indent=indent, line=line, err_lineno
                =err_lineno, err_colno=err_colno))
            doc_list.append('{_:{err_indent}}^---- Exact Error position'.
                format(_='', err_indent=err_indent))
        else:
            doc_list.append('{lineno:>{indent}}: {line}'.format(lineno=
                lineno, indent=indent, line=line))
        lineno += 1
    return '\n'.join(doc_list)


def exclude_goalkeepers(data_frame):
    """Remove goalkeepers and return the DataFrame.

    Go through the `data_frame` find all the tuples with the players'
    Position column set to "GK" and remove them. Return the `data_frame`
    with no goalkeeper tuples.

    Parameters
    ----------
    data_frame : pandas.DataFrame
    DataFrame containing FIFA19 data set including goalkeepers.

    Returns
    -------
    data_frame : pandas.DataFrame
    DataFrame containing FIFA19 data set with goalkeepers' tuples
    removed.

    Notes
    -----
    This function can be used when preprocessing the FIFA19 dataset to
    perform Machine Learning as a goalkeeper is a peculiar player  and
    all his properties vary compared to other positions on the field.

    Examples
    --------
    >>> data = pd.read_csv("data.csv")
    >>> print(data[['Name', 'Position']][0:5]) #print first few rows
    Name Position
    0           L. Messi       RF
    1  Cristiano Ronaldo       ST
    2          Neymar Jr       LW
    3             De Gea       GK
    4       K. De Bruyne      RCM
    >>> data = exclude_goalkeepers(data)
    >>> print(data[['Name', 'Position']][0:5]) #print the same number of rows
    Name Position
    0           L. Messi       RF
    1  Cristiano Ronaldo       ST
    2          Neymar Jr       LW
    4       K. De Bruyne      RCM
    5          E. Hazard       LF
    """
    goalkeepers = data_frame[data_frame['Position'] == 'GK']
    data_frame.drop(goalkeepers.index, inplace=True)
    return data_frame


def glPointSize(size: float):
    """Specify the diameter of rasterized points

    :param size: Specifies the diameter of rasterized points. The initial value is 1.
    :type size: float
    """
    pass


def can_paginate(operation_name=None):
    """
    Check if an operation can be paginated.

    :type operation_name: string
    :param operation_name: The operation name. This is the same name
            as the method name on the client. For example, if the
            method name is create_foo, and you'd normally invoke the
            operation as client.create_foo(**kwargs), if the
            create_foo operation can be paginated, you can use the
            call client.get_paginator('create_foo').

    """
    pass


def multiapply(funcs, elm):
    """ Applies functions `funcs` to element `elm` iteratively. """
    for func in funcs:
        elm = func(elm)
    return elm


def Declaration(*interfaces):
    """Create an interface specification

        The arguments are one or more interfaces or interface
        specifications (IDeclaration objects).

        A new interface specification (IDeclaration) with
        the given interfaces is returned.
        """


@classmethod
def _flat(cls, node):
    """
        Turn the node into either a tree's entries or a single-item array.
        """
    return tuple(node.entries()) if isinstance(node, cls) else (node,)


def _log_removed_output(log_file, original, new, type_):
    """
    function writing the output of functions that remove datapoints to a log file.

    Parameters
    ----------
    log_file : str
        string containing the directory to the log file to be written out
    original : int
        original length of the dataset
    new : int
        length of the new dataset
    type_ : str
        'removed' or 'dropped'
    """
    log_file = open(log_file, 'a')
    log_file.write(str('\nOriginal dataset: ' + str(original) +
        ' datapoints; new dataset: ' + str(new) + ' datapoints' + str(
        original - new) + ' datapoints ', type_))
    log_file.close()


def select_circle(x: int=0, y: int=0, radius: int=1, gesture_mode: int=0):
    """Select keyframe points using circle selection

    :param x: X
    :type x: int
    :param y: Y
    :type y: int
    :param radius: Radius
    :type radius: int
    :param gesture_mode: Event Type
    :type gesture_mode: int
    """
    pass


def system_updates_is_set_to_on_2_3(security_center):
    """
    New query param in 1.1 is properties.parameters.systemUpdatesMonitoringEffect
    but it is not in the output of the general api call.  Nor in az policy definition list.
    """
    items_flagged_list = []
    for item in security_center:
        resource_group = item['name']
        system_updates = item['properties']['recommendations']['patch']
        if system_updates != 'On':
            items_flagged_list.append(resource_group)
    stats = {'items_flagged': len(items_flagged_list), 'items_checked': len
        (security_center)}
    metadata = {'finding_name': 'system_updates_is_set_to_on',
        'negative_name': 'system_updates_not_on', 'columns': ['Resource Group']
        }
    return {'items': items_flagged_list, 'stats': stats, 'metadata': metadata}


@classmethod
def create_headers(klass, attributes):
    """
        Headers for resource creation.
        """
    return {}


def render_pep440_old(pieces):
    """TAG[.postDISTANCE[.dev0]] .

    The ".dev0" means dirty.

    Eexceptions:
    1: no tags. 0.postDISTANCE[.dev0]
    """
    if pieces['closest-tag']:
        rendered = pieces['closest-tag']
        if pieces['distance'] or pieces['dirty']:
            rendered += '.post%d' % pieces['distance']
            if pieces['dirty']:
                rendered += '.dev0'
    else:
        rendered = '0.post%d' % pieces['distance']
        if pieces['dirty']:
            rendered += '.dev0'
    return rendered


def getUserNames():
    """ Return a list of user IDs for all users that can be found
        given the selected user search base and search scope.

        This method will return a simple error message if the
        number of users exceeds the limit of search hits that is
        built into the python-ldap module.

        Permission - *Manage users*
        """


def parse_image_meta_graph(meta):
    """Parses a tensor that contains image attributes to its components.
    See compose_image_meta() for more details.

    meta: [batch, meta length] where meta length depends on NUM_CLASSES
    """
    image_id = meta[:, (0)]
    image_shape = meta[:, 1:4]
    window = meta[:, 4:8]
    active_class_ids = meta[:, 8:]
    return [image_id, image_shape, window, active_class_ids]


def squashDicts(*dict_args):
    """
  Given any number of dicts, shallow copy and merge into a new dict,
  precedence goes to key value pairs in later dicts.
  """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result


@classmethod
def get(cls, driver_id):
    """
        Gets the driver.

        Parameters
        ----------
        driver_id : str
            the identifier of the driver.

        Returns
        -------
        driver : DataDriver
            the required driver.

        Examples
        --------
        .. code-block:: python

            >>> import datarobot as dr
            >>> driver = dr.DataDriver.get('5ad08a1889453d0001ea7c5c')
            >>> driver
            DataDriver('PostgreSQL')
        """
    return cls.from_location('{}{}/'.format(cls._path, driver_id))


def gps_point_to_path_point(tcx_gps_info):
    """
    timestamps are stored as absolute epoch times
    type is ommitted here and it is expected that the correct values will be
    inserted when creating the path list
    """
    return {'timestamp': tcx_gps_info.time, 'latitude': tcx_gps_info.
        latitude, 'longitude': tcx_gps_info.longitude, 'altitude':
        tcx_gps_info.altitude}


def is_testcase(data_structure):
    """ check if data_structure is a testcase.

    Args:
        data_structure (dict): testcase should always be in the following data structure:

            {
                "config": {
                    "name": "desc1",
                    "variables": [],    # optional
                    "request": {}       # optional
                },
                "teststeps": [
                    test_dict1,
                    {   # test_dict2
                        'name': 'test step desc2',
                        'variables': [],    # optional
                        'extract': [],      # optional
                        'validate': [],
                        'request': {},
                        'function_meta': {}
                    }
                ]
            }

    Returns:
        bool: True if data_structure is valid testcase, otherwise False.

    """
    if not isinstance(data_structure, dict):
        return False
    if 'teststeps' not in data_structure:
        return False
    if not isinstance(data_structure['teststeps'], list):
        return False
    return True


def copy_dict(source_dict, diffs):
    """Returns a copy of source_dict, updated with the new key-value pairs in diffs."""
    result = dict(source_dict)
    result.update(diffs)
    return result


def get_supported_browsers_suggestions():
    """Return a list of supported browsers by default."""
    supported_browsers = ['chrome', 'chrome-remote', 'chrome-headless',
        'chrome-remote-headless', 'edge', 'edge-remote', 'firefox',
        'firefox-headless', 'firefox-remote', 'firefox-remote-headless',
        'ie', 'ie-remote', 'opera', 'opera-remote']
    return supported_browsers


def example2(api):
    """Find all "gadget" items and increase their price by 10%
    """
    qry = api.items.query()
    qry.filter_search('title', 'gadget')
    print('Matched {} gadget items to change'.format(qry.count))
    for item in qry.iter_all():
        print('Current price for item {} is {}'.format(item['item_no'],
            item['price']))
        item.update({'price': round(item['price'] * 1.1, 2)})
        print('    New price is {}'.format(item['price']))


def grant_access(user, endpoint):
    """default permission function for endpoints."""
    return not user.is_anonymous()


def setCatalog(catalog):
    """set the search index to be using the given catalog, return matches.

        Should immediately being index up-to-date if catalog has content.

        if index already has a catalog, raise an error.

        If provided catalog is None, clear catalog and indexes.

        Returned matches should be iterable of tuples of (search name or None,
        query names, static values, maxDepth, filter, queryFactory).  Only
        searches matching one of these tuples will be sent to the search
        index.
        """


def set_rules_index_for_http_policy_set(avi_config):
    """
    Update index as per avi protobuf requirements
    :param avi_config: avi config dict
    :return: None
    """
    http_policy_sets = avi_config['HTTPPolicySet']
    for http_policy_set in http_policy_sets:
        rules = http_policy_set['http_request_policy']['rules']
        rules = sorted(rules, key=lambda d: int(d['index']))
        for index, rule in enumerate(rules):
            rule['index'] = index


def merge_dicts(dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict, precedence goes to latter dicts.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result


def rational_independent(terms, x):
    """Returns a list of all the rationally independent terms.

    Examples
    ========

    >>> from sympy import sin, cos
    >>> from sympy.series.formal import rational_independent
    >>> from sympy.abc import x

    >>> rational_independent([cos(x), sin(x)], x)
    [cos(x), sin(x)]
    >>> rational_independent([x**2, sin(x), x*sin(x), x**3], x)
    [x**3 + x**2, x*sin(x) + sin(x)]
    """
    if not terms:
        return []
    ind = terms[0:1]
    for t in terms[1:]:
        n = t.as_independent(x)[1]
        for i, term in enumerate(ind):
            d = term.as_independent(x)[1]
            q = (n / d).cancel()
            if q.is_rational_function(x):
                ind[i] += t
                break
        else:
            ind.append(t)
    return ind


def ct_lsb_prop_u8(val):
    """Propagate LSB to all 8 bits of the returned byte. Constant time."""
    val &= 1
    val |= val << 1
    val |= val << 2
    val |= val << 4
    return val


def _valid_headerline(l, model='firecloud'):
    """return true if the given string is a valid loadfile header"""
    if not l:
        return False
    headers = l.split('\t')
    first_col = headers[0]
    tsplit = first_col.split(':')
    if len(tsplit) != 2:
        return False
    if tsplit[0] in ('entity', 'update'):
        if model == 'flexible':
            return tsplit[1].endswith('_id')
        else:
            return tsplit[1] in ('participant_id', 'participant_set_id',
                'sample_id', 'sample_set_id', 'pair_id', 'pair_set_id')
    elif tsplit[0] == 'membership':
        if len(headers) < 2:
            return False
        return tsplit[1].replace('set_', '') == headers[1]
    else:
        return False


def getTOFsig(ins, dsp):
    """get TOF peak profile sigma^2

    :param dict ins: instrument parameters with at least 'sig-0', 'sig-1' & 'sig-q'
      as values only
    :param float dsp: d-spacing of peak

    :returns: float getTOFsig: peak sigma^2

    """
    return ins['sig-0'] + ins['sig-1'] * dsp ** 2 + ins['sig-2'
        ] * dsp ** 4 + ins['sig-q'] * dsp


def description():
    """Give an non-HTML description.
        """


def read(file):
    """
    This can help you to read your file faster.
    Example:
        read_file('C:\\users\\Jack\\test.txt')
        ==> "Content of 'test.txt' will be shown."
    """
    op = open(file, mode='r')
    FileR = op.read()
    op.close()
    return FileR


@classmethod
def is_activity_type(cls, assignment_name):
    """Given the name of an activity, determines
        whether it is an instance of this unit type"""
    return cls.regex.search(assignment_name.strip().lower())


def _non_linear_lspline(wcs_dict):
    """Returns a linear spline model of the wavelength solution

    Not implemented

    This function should extract certain parameters from the `wcs_dict`
    parameter and construct a mathematical model that makes the conversion from
    pixel to wavelength. All the necessary information is already contained in
    the dictionary so the only work to be done is to make the instantiation of
    the appropriate subclass of `~astropy.modeling.Model`.

    Parameters
    ----------

        wcs_dict : dict
            Contains all the WCS information decoded from an IRAF fits header.

    Raises
    ------

        NotImplementedError
    """
    raise NotImplementedError('Linear spline is not implemented')


def dderiv_η_skw_midplane(*, dderiv_ρ, deriv_B_r, deriv_B_φ, dderiv_B_θ):
    """
    Compute the derivative of η assuming the same form as in SKW
    """
    return 2 * (deriv_B_r ** 2 + deriv_B_φ ** 2 + dderiv_B_θ) - dderiv_ρ


def dont_wrap(fun):
    """A special decorator to save given class member from being mulched by wrap_with"""
    fun._dont_wrap = True
    return fun


@classmethod
def get_format_string(cls):
    """See RepositoryFormat.get_format_string()."""
    return (
        b'Bazaar development format 2 with subtree support (needs bzr.dev from before 1.8)\n'
        )


def dirichlet(K, F, model, displ_bc=None):
    """Apply Dirichlet BC.

    .. note::

        How its done:

        1. Loop over the lines where Dirichlet boundary conditions are
        applied. This is specified as key argument of the dictionary. The
        boundaries are defined on the gmsh nad tagged with a number.

        2. loop over all the nodes at the boundaries.

        3. If those nodes, identified as follows::

            nodes_in_bound_line = [line node1 node2]

            are in the line where dirichlet BC were specified, change the
            stiffness matrix and the B vector based on this node index.

    The assignment can be done in two ways:

    1. with a dictionary specifying the boundary line:

        ['line', line]:[dx, dy]

    which means: the boundary line with tag line has a displ_bc dx on
    the x-direction and dy on the y-direction.

    2. with a dictionary with a specific node:

        ['node', node]:[0, 1]

    this way: the string 'node'identifies the type of boundary displ_bc
    that is been assigned; the number 0 identifies a free to move degree of
    freedom and 1 a restrained one. The first entry is the x-direction and
    the second y-direction.

    Args:
        K (2nd order array): Stiffness matrix.
        B (1st order array): Vector with the load and traction.
        temperature (function): Function with 4 components.

    Returns:
        K (2nd order array), B (1st order array): Modified stiffness matrix
        and vector.

    """
    if displ_bc is not None:
        for line in displ_bc(1, 1).keys():
            if isinstance(line, tuple) and line[0] == 'line':
                for n in range(len(model.nodes_in_bound_line[:, (0)])):
                    if line[1] == model.nodes_in_bound_line[n, 0]:
                        rx = displ_bc(1, 1)[line][0]
                        ry = displ_bc(1, 1)[line][1]
                        n1 = model.nodes_in_bound_line[n, 1]
                        n2 = model.nodes_in_bound_line[n, 2]
                        d1 = displ_bc(model.XYZ[n1, 0], model.XYZ[n1, 1])
                        d2 = displ_bc(model.XYZ[n2, 0], model.XYZ[n2, 1])
                        if rx != 'free' and rx != None:
                            K[(2 * n1), :] = 0.0
                            K[(2 * n2), :] = 0.0
                            K[2 * n1, 2 * n1] = 1.0
                            K[2 * n2, 2 * n2] = 1.0
                            F[2 * n1] = d1[line][0]
                            F[2 * n2] = d2[line][0]
                        if ry != 'free' and ry != None:
                            K[(2 * n1 + 1), :] = 0.0
                            K[(2 * n2 + 1), :] = 0.0
                            K[2 * n1 + 1, 2 * n1 + 1] = 1.0
                            K[2 * n2 + 1, 2 * n2 + 1] = 1.0
                            F[2 * n1 + 1] = d1[line][1]
                            F[2 * n2 + 1] = d2[line][1]
            elif isinstance(line, int):
                for n in range(len(model.nodes_in_bound_line[:, (0)])):
                    if line == model.nodes_in_bound_line[n, 0]:
                        rx = displ_bc(1, 1)[line][0]
                        ry = displ_bc(1, 1)[line][1]
                        n1 = model.nodes_in_bound_line[n, 1]
                        n2 = model.nodes_in_bound_line[n, 2]
                        d1 = displ_bc(model.XYZ[n1, 0], model.XYZ[n1, 1])
                        d2 = displ_bc(model.XYZ[n2, 0], model.XYZ[n2, 1])
                        if rx != 'free' and rx != None:
                            K[(2 * n1), :] = 0.0
                            K[(2 * n2), :] = 0.0
                            K[2 * n1, 2 * n1] = 1.0
                            K[2 * n2, 2 * n2] = 1.0
                            F[2 * n1] = d1[line][0]
                            F[2 * n2] = d2[line][0]
                        if ry != 'free' and ry != None:
                            K[(2 * n1 + 1), :] = 0.0
                            K[(2 * n2 + 1), :] = 0.0
                            K[2 * n1 + 1, 2 * n1 + 1] = 1.0
                            K[2 * n2 + 1, 2 * n2 + 1] = 1.0
                            F[2 * n1 + 1] = d1[line][1]
                            F[2 * n2 + 1] = d2[line][1]
            if isinstance(line, tuple) and (line[0] == 'nodes' or line[0] ==
                'node'):
                rx = displ_bc(1, 1)[line][0]
                ry = displ_bc(1, 1)[line][1]
                for n in line[1:]:
                    if rx != 'free':
                        K[(2 * n), :] = 0.0
                        K[2 * n, 2 * n] = 1.0
                        F[2 * n] = rx
                    if ry != 'free':
                        K[(2 * n + 1), :] = 0.0
                        K[2 * n + 1, 2 * n + 1] = 1.0
                        F[2 * n + 1] = ry
            if isinstance(line, tuple) and line[0] == 'support':
                for n in line[1:]:
                    rx = displ_bc(1, 1)[line][0]
                    ry = displ_bc(1, 1)[line][1]
                    if rx != 'free' and rx != 0:
                        K[(2 * n), :] = 0.0
                        K[2 * n, 2 * n] = 1.0
                        F[2 * n] = 0.0
                    if ry != 'free' and rx != 0:
                        K[(2 * n + 1), :] = 0.0
                        K[2 * n + 1, 2 * n + 1] = 1.0
                        F[2 * n + 1] = 0.0
    return K, F


def _split(string, max_split, remove_empty_matches, matching_function, *
    args, **kwargs):
    """
    Splits a string using a given matching-function that matches the separator.

    This function implements general features needed from the split functions
    in this module (the max-split and remove-empty-matches features).

    :param string:               The string where to split.
    :param max_split:            Defines the maximum number of splits. If 0 or
                                 less is provided, the number of splits is not
                                 limited.
    :param remove_empty_matches: Defines whether empty entries should
                                 be removed from the result.
    :param matching_function:    The matching function. It must return
                                 MatchObject's containing the matched
                                 split-separator.
    :param args:                 Positional arguments to invoke the
                                 matching_function with.
    :param kwargs:               Key-value arguments to invoke the
                                 matching_function with.
    """
    last_end_pos = 0
    for match in matching_function(*args, **kwargs):
        split_string = string[last_end_pos:match.start()]
        last_end_pos = match.end()
        if not remove_empty_matches or len(split_string) != 0:
            yield split_string
            max_split -= 1
            if max_split == 0:
                break
    if not remove_empty_matches or len(string) > last_end_pos:
        yield string[last_end_pos:]


def unique(seq, idfunc=None):
    """
	Unique a list or tuple and preserve the order

	@type idfunc: Function or None
	@param idfunc: If idfunc is provided it will be called during the
	comparison process.
	"""
    if idfunc is None:
        idfunc = lambda x: x
    preserved_type = type(seq)
    seen = {}
    result = []
    for item in seq:
        marker = idfunc(item)
        if marker in seen:
            continue
        seen[marker] = 1
        result.append(item)
    return preserved_type(result)


def execfile(fname, variables):
    """ This is builtin in python2, but we have to roll our own on py3. """
    with open(fname) as f:
        code = compile(f.read(), fname, 'exec')
        exec(code, variables)


@staticmethod
def get_resource_id(country_code, resource_id):
    """
        Construct valid Google Shopping resource id
        based on an identifier
        """
    resource_id = 'online:en:%s:%s' % (country_code, resource_id)


@classmethod
def from_wfs_element(cls, feature, namespace):
    """Build `Sondering` instance from a WFS feature element.

        Parameters
        ----------
        feature : etree.Element
            XML element representing a single record of the WFS layer.
        namespace : str
            Namespace associated with this WFS featuretype.

        Returns
        -------
        sondering : Sondering
            An instance of this class populated with the data from the WFS
            element.

        """
    s = cls(feature.findtext('./{{{}}}fiche'.format(namespace)))
    for field in cls.get_fields(source=('wfs',)).values():
        s.data[field['name']] = cls._parse(func=feature.findtext, xpath=
            field['sourcefield'], namespace=namespace, returntype=field.get
            ('type', None))
    return s


def identityfunc(arg):
    """Single argument identity function.

    >>> identityfunc('arg')
    'arg'

    """
    return arg


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 getIslandGenesInStrain(island, strainName, familiesO):
    """Given an island, a strain number, and our families object, return
all the genes in the island for that strain."""
    genesL = []
    for locFam in island.iterLocusFamilies(familiesO):
        genesL.extend(locFam.iterGenesByStrain(strainName))
    return genesL


def update():
    """Update gallery paragraph renderer"""


@staticmethod
def ctrl(char):
    """
        Calculate the control code for a given key.  For example, this converts
        "a" to 1 (which is the code for ctrl-a).

        :param char: The key to convert to a control code.
        :return: The control code as an integer or None if unknown.
        """
    if not isinstance(char, int):
        char = ord(char.upper())
    return char & 31 if 64 <= char <= 95 else None


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


def get_name(friendly=False):
    """Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    if friendly:
        return 'Alignak hosts groups'
    return 'hostgroup'


@staticmethod
def strip_leading_plus(string):
    """
        Strip the leading plus and whitespace from string

        Args:
            string(str): String to strip leading plus from

        Returns:
            str: String without the leading +.
        """
    if string.startswith('+'):
        return string[2:]
    return string


def change_user_role(payload, raiseonfail=False, override_authdb_path=None):
    """
    This changes a user's role.

    Not used except for by superusers to promote people to other roles.

    """


def clear_bit(f, offset):
    """
    clears the bet at an offset
    """
    mask = ~(1 << offset)
    return f & mask


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


def cmp_key_columns(_left, _right, _key_columns):
    """
    This functions compares the columns in the specified key fields only and returns data usable in a </=/>-comparer
    """
    for _curr_key_column in _key_columns:
        if _left[_curr_key_column] < _right[_curr_key_column]:
            return -1
        elif _left[_curr_key_column] > _right[_curr_key_column]:
            return 1
    return 0


def func_lineno(func):
    """Get the line number of a function. First looks for
    compat_co_firstlineno, then func_code.co_first_lineno.
    """
    try:
        return func.compat_co_firstlineno
    except AttributeError:
        try:
            return func.__code__.co_firstlineno
        except AttributeError:
            return -1


def post_install(context):
    """Post install script"""


def context_set_value(data_path: str='', value: str=''):
    """Set a context value

    :param data_path: Context Attributes, RNA context string
    :type data_path: str
    :param value: Value, Assignment value (as a string)
    :type value: str
    """
    pass


def _make_3d(field, twod):
    """Add a dimension to field if necessary.

    Args:
        field (numpy.array): the field that need to be 3d.
        twod (str): 'XZ', 'YZ' or None depending on what is relevant.
    Returns:
        numpy.array: reshaped field.
    """
    shp = list(field.shape)
    if twod and 'X' in twod:
        shp.insert(1, 1)
    elif twod:
        shp.insert(0, 1)
    return field.reshape(shp)


@classmethod
def from_saved_state(cls, filename: str, *args, **kwargs):
    """
        Creates a Manticore object starting from a serialized state on the disk.

        :param filename: File to load the state from
        :param args: Arguments forwarded to the Manticore object
        :param kwargs: Keyword args forwarded to the Manticore object
        :return: An instance of a subclass of ManticoreBase with the given initial state
        """
    from ..utils.helpers import PickleSerializer
    with open(filename, 'rb') as fd:
        deserialized = PickleSerializer().deserialize(fd)
    return cls(deserialized, *args, **kwargs)


def valid_conversion(val, type_to_convert):
    """
    Checking whether it is possible to convert val to the specified type
    :param val: value
    :param type_to_convert: type
    :return: boolean
    """
    if isinstance(type_to_convert, type):
        try:
            type_to_convert(val)
            res = True
        except ValueError:
            res = False
    else:
        raise TypeError
    return res


def get_shared(virtual_memory):
    """Get the estimated shared memory usage from psutil virtual mem info."""
    if hasattr(virtual_memory, 'shared'):
        return virtual_memory.shared
    else:
        return 0


def getCodeFromReaction(text):
    """
    The input text must be one of:
    coherent, incoherent, photoelectric, subshell_photoelectric, pair, triplet
    Returns the integer EPDL97 code of the reaction:
                    71 <-> coherent scattering
                    72 <-> incoherent scattering
                    73 <-> photoelectric effect
                    74 <-> pair production
                    75 <-> triplet production
                    93 <-> whole atom parameters
    """
    tmp = text.lower()
    if 'coherent' in tmp:
        return 71
    if 'incoherent' in tmp:
        return 72
    if 'photo' in tmp:
        return 73
    if 'pair' in tmp:
        return 74
    if 'triplet' in tmp:
        return 75
    raise ValueError('Invalid reaction')


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 find(key):
    """Calls self.read().find(key)``.

        Returns a 2-tuple of ``(node, flags)`` or raises ``KeyError``.
        """


@staticmethod
def partition_template_string(template_string):
    """Splits a template string into subject and body"""
    subject = template_string.split('\n')[0]
    if template_string.startswith(subject + '\n\n'):
        body = template_string.partition(subject + '\n\n')[2]
    else:
        body = template_string.partition(subject + '\n')[2]
    return subject, body


def detect_filetype(header):
    """Returns Kepler and TESS file types given their primary header.

    This function will detect the file type by looking at both the TELESCOP and
    CREATOR keywords in the first extension of the FITS header. If the file is
    recognized as a Kepler or TESS data product, one of the following strings
    will be returned:

        * `'KeplerTargetPixelFile'`
        * `'TessTargetPixelFile'`
        * `'KeplerLightCurveFile'`
        * `'TessLightCurveFile'`

    If the file is not recognized as a Kepler or TESS data product, then
    `None` will be returned.

    Parameters
    ----------
    header : astropy.io.fits.Header object
        The primary header of a FITS file.

    Returns
    -------
    filetype : str or None
        A string describing the detected filetype. If the filetype is not
        recognized, `None` will be returned.
    """
    try:
        if 'TELESCOP' in header.keys():
            telescop = header['telescop'].lower()
        else:
            telescop = header['mission'].lower()
        creator = header['creator'].lower()
        origin = header['origin'].lower()
        if telescop == 'kepler':
            if 'targetpixel' in creator:
                return 'KeplerTargetPixelFile'
            elif 'fluxexporter' in creator or 'lightcurve' in creator or 'lightcurve' in creator:
                return 'KeplerLightCurveFile'
        elif telescop == 'tess':
            if 'targetpixel' in creator:
                return 'TessTargetPixelFile'
            elif 'lightcurve' in creator:
                return 'TessLightCurveFile'
            elif 'stsci' in origin:
                return 'TessTargetPixelFile'
    except (KeyError, AttributeError):
        return None


def _fft(data, dims):
    """Take the inverse fourier transform of imagespace data"""
    pass


def discard_events(library, session, event_type, mechanism):
    """Discards event occurrences for specified event types and mechanisms in a session.

    Corresponds to viDiscardEvents function of the VISA library.

    :param library: the visa library wrapped by ctypes.
    :param session: Unique logical identifier to a session.
    :param event_type: Logical event identifier.
    :param mechanism: Specifies event handling mechanisms to be dicarded.
                      (Constants.VI_QUEUE, .VI_HNDLR, .VI_SUSPEND_HNDLR, .VI_ALL_MECH)
    :return: return value of the library call.
    :rtype: :class:`pyvisa.constants.StatusCode`
    """
    return library.viDiscardEvents(session, event_type, mechanism)


@classmethod
def _status_handler(cls, message):
    """Status message handler, called when C{igraph} sends a status
        message to be displayed.

        @param message: message provided by C{igraph}
        """
    cls.progress_bar.update_message(message)


def change_handler(sender):
    """Handle a tag value change."""
    print('{} changed from {} to {}'.format(sender.tag_name, sender.
        last_value, sender.value))


def _validate_tuple(x):
    """
    This function gets any type of object and returns it within a single element tuple. If the element is already a
    tuple it returns the element itself
    :param x: element
    :return: tuple
    """
    if type(x) != tuple:
        return x,
    else:
        return x


def toolshelf():
    """Toggles tool shelf display

    """
    pass


def is_overlapping(interval_A, interval_B):
    """
    this subroutine checks if two intervals intersect with each other; it returns True if
    they do and False otherwise
    input : interval_A - first interval
            interval_B - second interval
    output: is_intersecting - True if interval_A intersects interval_B, False otherwise
    """
    is_intersecting = interval_A[1] >= interval_B[0] and interval_A[0
        ] <= interval_B[1] or interval_B[1] >= interval_A[0] and interval_B[0
        ] <= interval_A[1]
    return is_intersecting


def s2b_recode(s, source_encoding=None, target_encoding=None):
    """将 :class:`str` 字符串重编码为 :class:`bytes` 字符串

    :param str s: 待转换字节字符串
    :param str source_encoding: bytes 的编码格式。
        仅 Python2 环境下有效。
    :param str target_encoding: 转换结果字符串的编码格式。
    :return: 转换结果字符串
    :rtype: bytes
    """
    if s is None:
        return s
    if bytes == str:
        return s.decode(source_encoding).encode(target_encoding)
    return s.encode(target_encoding)


def log_stability(x):
    """Log-stability for computing loss

    :param x: Input value
    :type x: float
    :return: Scaled value where :math:`\\hat{x} \\in (0, 1)`
    :rtype: float
    """
    if x == 0:
        return 1e-08
    elif x == 1:
        return 1.0 - 1e-08
    else:
        return x


def human_to_bytes(size):
    """Given a human-readable byte string (e.g. 2G, 30M),
       return the number of bytes.  Will return 0 if the argument has
       unexpected form.
    """
    bytes = size[:-1]
    unit = size[-1]
    if bytes.isdigit():
        bytes = int(bytes)
        if unit == 'P':
            bytes *= 1125899906842624
        elif unit == 'T':
            bytes *= 1099511627776
        elif unit == 'G':
            bytes *= 1073741824
        elif unit == 'M':
            bytes *= 1048576
        else:
            bytes = 0
    else:
        bytes = 0
    return bytes


@classmethod
def _concatenate(cls, dims):
    """Concatenate multiple dimension instances"""
    raise NotImplementedError(
        f"Can't concatenate along {cls.__name__} dimensions")


def execute_commands() ->dict:
    """Lists the available sub-commands of the 'chado execute' command with corresponding descriptions"""
    return {'audit_backup': 'backs up the audit tables to a separate schema'}


def split_clspath(clspath):
    """Split clspath into module and class names.

    Note: This is a really simplistic implementation.

    """
    return clspath.rsplit('.', 1)


def _polynomial_conversion(data, conversion):
    """ apply polynomial conversion to data

    Parameters
    ----------------
    data : numpy 1D array
        raw data to be converted to physical value
    conversion : mdfinfo3.info3 conversion block ('CCBlock') dict

    Returns
    -----------
    converted data to physical value
    """
    return (conversion['P2'] - conversion['P4'] * (data - conversion['P5'] -
        conversion['P6'])) / (conversion['P3'] * (data - conversion['P5'] -
        conversion['P6']) - conversion['P1'])


def short_uuid4(uid):
    """When seeing a glimpse of the UID is enough."""
    return str(uid)[:8]


def complete_schedules(cfg):
    """ add name to each schedule """
    for name, schedule in cfg['schedules'].items():
        schedule['name'] = name


def set_normals_from_faces():
    """Set the custom vertex normals from the selected faces ones

    """
    pass


@staticmethod
def simplify(top, bottom):
    """Removes equal items from top and bottom in a one-to-one
        correspondence.

        Signatures are simplified on initialization::

           >>> Signature('abcxa', 'bxay')
           {c, a}/{y}

        This function takes top and bottom and returns simplified
        tuples for top and bottom.

        """
    top = [] if top is None else list(top)
    bottom = [] if bottom is None else list(bottom)
    i = 0
    while i < len(top):
        j = 0
        while j < len(bottom) and bottom[j] != top[i]:
            j += 1
        if j < len(bottom):
            assert bottom[j] == top[i]
            del bottom[j]
            del top[i]
        else:
            i += 1
    return tuple(top), tuple(bottom)


def DownloadData(status, conf) ->int:
    """This is main interface.

    Args:
        status (dict): Status.
        conf (dict): Configuration.
    """
    status_cod = -1
    return status_cod


def findbyname(model, name):
    """
    Utility function.
    """
    return model.objects.get(name=name)


def chunk(data, index):
    """
    Split a string into two parts at the input index.
    """
    return data[:index], data[index:]


def overlapping_tokens(tokens1, tokens2):
    """fake lcs from overlapping tokens"""
    all_tokens = []
    all_token_indexes = []
    modif_tokens1 = tokens1.copy()
    modif_tokens2 = tokens2.copy()
    for i, token in enumerate(modif_tokens1):
        if token in modif_tokens2:
            j = modif_tokens2.index(token)
            modif_tokens2[j] = ' '
            all_tokens.append(token)
            all_token_indexes.append((i, j))
    return all_tokens, all_token_indexes


@staticmethod
def get_all_parents(node_pks, return_values=('id',)):
    """Get all the parents of given nodes

        :param node_pks: one node pk or an iterable of node pks
        :return: a list of aiida objects with all the parents of the nodes"""
    from aiida.orm import Node, QueryBuilder
    q_build = QueryBuilder()
    q_build.append(Node, tag='low_node', filters={'id': {'in': node_pks}})
    q_build.append(Node, with_descendants='low_node', project=return_values)
    return q_build.all()


def is_in_cache(url):
    """
        Checks whether file present in cache or not, should always
        be used before get_file() to ensure that file is in cache
        """
    raise NotImplementedError


def readBIM(fileName):
    """Reads a BIM file.

    :param fileName: the name of the BIM file to read.

    :type fileName: str

    :returns: the set of markers in the BIM file.

    Reads a Plink BIM file and extract the name of the markers. There is one
    marker per line, and the name of the marker is in the second column. There
    is no header in the BIM file.

    """
    snps = set()
    with open(fileName, 'r') as inputFile:
        for line in inputFile:
            row = line.rstrip('\r\n').split('\t')
            snpName = row[1]
            snps.add(snpName)
    return snps


@staticmethod
def _find_single(contact_map, index):
    """Find all contacts associated with ``index`` based on id property"""
    for c in contact_map:
        if c.id[0] == index or c.id[1] == index:
            yield c


def poseidon_sbox(state, i, params):
    """
    iacr.org/2019/458 § 2.2 The Hades Strategy (pg 6)

    In more details, assume R_F = 2 · R_f is an even number. Then
     - the first R_f rounds have a full S-Box layer,
     - the middle R_P rounds have a partial S-Box layer (i.e., 1 S-Box layer),
     - the last R_f rounds have a full S-Box layer
    """
    half_F = params.nRoundsF // 2
    e, p = params.e, params.p
    if i < half_F or i >= half_F + params.nRoundsP:
        for j, _ in enumerate(state):
            state[j] = pow(_, e, p)
    else:
        state[0] = pow(state[0], e, p)


@classmethod
def _check_pretrained_file_names(cls, pretrained_file_name):
    """Checks if a pre-trained token embedding file name is valid.

        Parameters
        ----------
        pretrained_file_name : str
            The pre-trained token embedding file.
        """
    embedding_name = cls.__name__.lower()
    if pretrained_file_name not in cls.pretrained_file_name_sha1:
        raise KeyError(
            'Cannot find pretrained file %s for token embedding %s. Valid pretrained files for embedding %s: %s'
             % (pretrained_file_name, embedding_name, embedding_name, ', '.
            join(cls.pretrained_file_name_sha1.keys())))


def psi_K_Na_Br_PK74(T, P):
    """c-c'-a: potassium sodium bromide [PK74]."""
    psi = -0.0022
    valid = T == 298.15
    return psi, valid


def get_file_line(file_name, line_num):
    """Returns the line at the specified line number from the specified file.

    Parameters
    ----------
    file_name : str
        Path to the file
    line_num : int
        Line number to extract from the file

    Returns
    -------
    line : str
        Line at line_num in file or None if the line_num is larger than the number of lines in the file
    """
    line = ''
    line_counter = 0
    with open(file_name) as f:
        for line in f:
            line_counter += 1
            if line_counter == line_num:
                return line
    return None


def i18n(request):
    """Context processor which returns a dictionary containing I18N_SITES."""
    from i18nurl import settings
    return {'I18N_LANGUAGES': settings.I18N_LANGUAGES,
        'I18N_REDIRECT_URL_NAME': settings.I18N_REDIRECT_URL_NAME}


@classmethod
def join_table(cls, second_table, first_table, lhs_on, rhs_on='id'):
    """
        Builds the fragment for joined tables, e.g.
        'join second_table as t2 on t1.lhs_on = t2.rhs_on'
        """
    args = first_table.alias, lhs_on, second_table.alias, rhs_on
    identifiers = cls.identifiers(args)
    sql = 'join {} on {}.{} = {}.{}'
    return cls.format(sql, cls.table_name(second_table), *identifiers)


def git_checkout(clone, version):
    """Checkout a version of a git repo along with any associated submodules.

    Args:
        clone (git.Repo): the git clone on which to operate

        version (str): the branch, tag, or commit to checkout

    Raises:
        git.exc.GitCommandError: if the git repo is invalid
    """
    clone.git.checkout(version)
    clone.git.submodule('sync', '--recursive')
    clone.git.submodule('update', '--recursive', '--init')


def picke_settings(data):
    """Pickling as defined at migration's creation time"""
    try:
        import pickle
    except ImportError:
        import cPickle as pickle
    from helpdesk.lib import b64encode
    return b64encode(pickle.dumps(data))


def annotated_frames_object(scribbles_data, object_id):
    """ Computes which frames have a scribble for a certain object.

    # Arguments
        scribbles_data (dict): Scribble in the default format.
        object_id (int): Id of the object of interest.

    # Returns
        dict: Number of the frames that contain at least one scribble.
    """
    frames_list = []
    scribbles = scribbles_data['scribbles']
    for ii, scribble_frame in enumerate(scribbles):
        for scribble in scribble_frame:
            if scribble['object_id'] == object_id:
                frames_list.append(ii)
                break
    return frames_list


def mtime(path):
    """Return the modification time for the file at `path`.

        This method returns the modification time. It is assumed that the path
        exists. You can use the `type(path)` method to determine whether
        `path` points to a valid file.

        If the modification time is unknown, then return `None`.
        """


def case_insensitive_dict_get(d, key, default=None):
    """
    Searches a dict for the first key matching case insensitively. If there is
    an exact match by case for the key, that match is given preference.

    Args:
        d: dict to search
        key: key name to retrieve case-insensitively

    Returns: value or default

    """
    if not key:
        return default
    if key in d:
        return d[key]
    if isinstance(key, str):
        key_lower = key.lower()
        for k in d:
            if k.lower() == key_lower:
                return d[k]
    return default


@classmethod
def _revision_paths(cls, rev, branch, target_platform):
    """Retrieve the API path for revision based builds"""
    if branch not in {'autoland', 'try'}:
        branch = 'mozilla-' + branch
    namespace = 'gecko.v2.' + branch + '.revision.' + rev
    product = 'mobile' if 'android' in target_platform else 'firefox'
    yield '/task/' + namespace + '.' + product + '.' + target_platform


def exp(input):
    """Returns a new tensor with the exponential of the elements of the input tensor `input`.

    Parameters
    ----------
    input : Tensor
        The input tensor.

    Returns
    -------
    Tensor
        The output tensor.
    """
    pass


def cylindrical_receiver(rec_param, hemisphere='North'):
    """
    hemishpere : 'North' or 'South' hemisphere of the earth where the field located
                if North: the field is in the positive y direction
                if South: the field is in the negtive y direction
                this will influence:
                 (1) the setting of the receiver tilt angle,
                     if the front surface always facing to the field is desirable
                 (2) the position of the virtual target
    """
    rec_r = rec_param[0]
    rec_h = rec_param[1]
    slices = rec_param[2]
    x = rec_param[3]
    y = rec_param[4]
    z = rec_param[5]
    geom = ''
    geom += '- geometry: &%s\n' % 'target_g'
    geom += '  - material: *%s\n' % 'material_target'
    geom += '    cylinder: \n'
    geom += '      height: %s\n' % rec_h
    geom += '      radius: %s\n' % rec_r
    geom += '      slices: %d\n' % slices
    geom += '\n'
    entt = ''
    entt += '\n- entity:\n'
    entt += '    name: target_e\n'
    entt += '    primary: 0\n'
    entt += '    transform: { translation: %s, rotation: %s }\n' % ([x, y,
        z], [0.0, 0.0, 0.0])
    entt += '    geometry: *%s\n' % 'target_g'
    Vsize = 100.0
    pts = [[-rec_h * Vsize, -rec_h * Vsize], [-rec_h * Vsize, rec_h * Vsize
        ], [rec_h * Vsize, rec_h * Vsize], [rec_h * Vsize, -rec_h * Vsize]]
    slices = 4
    entt += '\n- entity:\n'
    entt += '    name: virtual_target_e\n'
    entt += '    primary: 0\n'
    entt += '    transform: { translation: %s, rotation: %s }\n' % ([x, y,
        z + rec_h / 2.0 + 1], [-180.0, 0, 0])
    entt += '    geometry: \n'
    entt += '      - material: *%s\n' % 'material_virtual'
    entt += '        plane: \n'
    entt += '          clip: \n'
    entt += '          - operation: AND \n'
    entt += '            vertices: %s\n' % pts
    entt += '          slices: %d\n' % slices
    rcv = ''
    rcv += '- name: target_e \n'
    rcv += '  side: %s \n' % 'FRONT_AND_BACK'
    rcv += '  per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
    rcv += '- name: virtual_target_e \n'
    rcv += '  side: %s \n' % 'FRONT'
    rcv += '  per_primitive: %s \n' % 'INCOMING'
    return geom, entt, rcv


@staticmethod
def _parse_dat_parms(header_dict, signal_dict):
    """
        Parse dat files.

        Parameters
        ----------
        header_dict : dict
        signal_dict : dict

        Returns
        -------
        parm_dict : dict

        """
    pass


def _fileobj_to_fd(fileobj):
    """ Return a file descriptor from a file object. If
    given an integer will simply return that integer back. """
    if isinstance(fileobj, int):
        fd = fileobj
    else:
        try:
            fd = int(fileobj.fileno())
        except (AttributeError, TypeError, ValueError):
            raise ValueError('Invalid file object: {0!r}'.format(fileobj))
    if fd < 0:
        raise ValueError('Invalid file descriptor: {0}'.format(fd))
    return fd


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

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


def present_to_future_value(ir, t):
    """
    Returns a coefficient to convert money from one point in time to
    t years in the future, with an annual interest rate of ir. This is
    the inverse of future_to_present_value if calculated with the same
    rate and number of years.
    Example:
    >>> round(present_to_future_value(.07,10),7)
    1.9671514
    >>> round(present_to_future_value(.07,10)*        future_to_present_value(.07,10),7) == 1
    True
    """
    return (1 + ir) ** t


def eparent(node):
    """
    Return an effective parent for the given node.

    The rule for the effective parent - when the current node A has a deprel 'conj' to its parent B,
    return  B.parent, otherwise return A.parent.

    :param node: An input node.
    :return: An effective parent.
    :rtype: udapi.core.node.Node

    """
    if node.deprel == 'conj':
        return node.parent.parent
    return node.parent


def uniq(seq, key=None):
    """
    Removes duplicate elements from a list while preserving the order of the rest.

        >>> uniq([9,0,2,1,0])
        [9, 0, 2, 1]

    The value of the optional `key` parameter should be a function that
    takes a single argument and returns a key to test the uniqueness.

        >>> uniq(["Foo", "foo", "bar"], key=lambda s: s.lower())
        ['Foo', 'bar']
    """
    key = key or (lambda x: x)
    seen = set()
    result = []
    for v in seq:
        k = key(v)
        if k in seen:
            continue
        seen.add(k)
        result.append(v)
    return result


def intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False):
    """Calculate the intersection between a line (as 2 vectors) and a plane. Returns a vector for the intersection or None.

	Parameters:
	line_a (mathutils.Vector) – First point of the first line
	line_b (mathutils.Vector) – Second point of the first line
	plane_co (mathutils.Vector) – A point on the plane
	plane_no (mathutils.Vector) – The direction the plane is facing

	Returns: The point of intersection or None when not found

	Return type: mathutils.Vector or None"""
    from . import Vector
    return Vector


def total_duration_parser(line):
    """
    Parses lines of the following form:

        Total duration: 5248.89s

    :param line: string
    :return: float containing total duration in seconds
    """
    try:
        return float(line.rstrip('s')[len('Total duration:'):].strip())
    except:
        return 0.0


def orphans_purge(num_deleted=0):
    """Clear all orphaned data-blocks without any users from the file

    """
    pass


def electrical_amplitudes(durations, polarity, ratio=None):
    """Calculate amplitudes of each "phase" in a signle electrical pulse
    in a cochlear implant.

    The resulting pulses are charged ballanced (if possible).  The
    function supports mono-, bi- and tri-phasic pulses.

    Parameters
    ----------
    durations : array_like
        List of phase durations in the pulse.
    polarity : {-1, 1, 'c' 'cathodic', 'a', 'anodic'}
        Polarity of the first phase.  -1, 'c' and 'cathodic' are
        equivalent.  As well as 1, 'a' and 'anodic'.
    ratio : float, optional
        Only valid for triphasic pulses.  It is equal to the charge
        ratio between the first and second phase.

    Returns
    -------
    tuple
        Amplitudes of phases corresponding to `durations`.

    """
    if len(durations) == 3:
        assert 0 <= ratio <= 1
    else:
        assert ratio is None
    if polarity in ('c', 'cathodic', -1):
        polarity = -1
    elif polarity in ('a', 'anodic', 1):
        polarity = 1
    else:
        raise RuntimeError('Unknown polarity')
    if len(durations) == 1:
        amplitude = polarity / durations[0]
        amplitudes = amplitude,
    elif len(durations) == 2:
        amplitudes = +1 * polarity * (0.5 / durations[0]), -1 * polarity * (
            0.5 / durations[1])
    elif len(durations) == 3:
        amplitudes = +1 * polarity * (0.5 * ratio / durations[0]
            ), -1 * polarity * (0.5 / durations[1]), +1 * polarity * (0.5 *
            (1 - ratio) / durations[2])
    else:
        raise RuntimeError('Unknown pulse shape')
    return amplitudes


@classmethod
def to_file(cls, path, **kwargs) ->'LedgerCapturePlugin':
    """
        Return a :class:`LedgerCapturePlugin` that writes its output to a file.

        :param path: The file to write to.
        """
    return cls(open(path, 'w'), True, **kwargs)


@staticmethod
def childCount():
    """Provides the number of children"""
    return 0


def _dispatch_deserializer(ds, node, parentPref, prefFactory, basedir=None,
    chainNotifications=0):
    """Find out which deserializer function should
    handle deserializing a particular node."""
    dsfunname = u'_ds_' + node.nodeName
    if hasattr(ds, dsfunname):
        getattr(ds, dsfunname)(node, parentPref, basedir)
    else:
        pref = prefFactory.deserializeNode(node, parentPref, basedir,
            chainNotifications)
        return pref


def _test():
    """Run the doctests."""
    import doctest
    doctest.testmod()


def myrange(N, indi, indf):
    """
Return 'range(N)' with index 'indi' at position 'indf'
    """
    lis = list(range(N))
    if indi < indf:
        deb = lis[:indi] + lis[indi + 1:indf + 1]
        end = lis[indf + 1:]
        eli = [lis[indi]]
        lis = deb + eli + end
    elif indi > indf:
        deb = lis[:indf]
        end = lis[indf:indi] + lis[indi + 1:]
        eli = [lis[indi]]
        lis = deb + eli + end
    return lis


@classmethod
def validate(cls, **kwargs):
    """
        Validate the keyword arguments and return the (converted) kwargs
        dictionary.

        You should override this method if you want to enable validation
        of your attributes.

        Notes
        -----
        One doesn't need to validate the following things, as it is already
        take care of by the `MultiState` class:

        - Check that each argument is assigned with a default.
        - Check that the kwargs keys are in _attributes tuple.
        """
    return kwargs


@classmethod
def in_debug(cls) ->bool:
    """
        Находимся ли мы в режиме дебага?
        """
    return getattr(cls, 'DEBUG')


def get_all_score_strings(machine):
    """Given metadata from the model builder this function returns a list of
    strings of the following format:
    {metric_name}-{tag_name}_{fold-fold-number} = {score_val}.  This computes the score for the given tag and
    cross validation split.
    {metric_name}-{tag_name}_{fold-aggregation} = {score_val}. This computes the score for the given tag and aggregates
    the score over all cross validation splits (aggregations currently used are mean, std, min and max)
    {metric_name}_{fold-fold-number} = {score_val}.  This computes the score aggregate across all tags (uses sklearn's default
    aggregation method) for a given cross validation split.
    {metric_name}_{fold-aggregation} = {score_val}.  This computes the score aggregate across all tags (uses sklearn's default
    aggregation method) and cross validation splits (aggregations currently used are mean, std, min and max).

    for katib to pick up.

    Current metric names supported are sklearn score functions: 'r2_score', 'explained_variance_score',
    'mean_squared_error' and 'mean_absolute_error'.  The underscores in such score names are replaced by '-'.

    All spaces in the tag name are also replaced by '-'.

    Parameters
    ----------
    machine : Machine
    """
    all_scores = []
    for metric_name, scores in machine.metadata.build_metadata.model.cross_validation.scores.items(
        ):
        metric_name = metric_name.replace(' ', '-')
        for score_name, score_val in scores.items():
            score_name = score_name.replace(' ', '-')
            all_scores.append(f'{metric_name}_{score_name}={score_val}')
    return all_scores


def convert_embedding(builder, layer, input_names, output_names, keras_layer):
    """Convert a dense layer from keras to coreml.

    Parameters
    keras_layer: layer
    ----------
        A keras layer object.

    builder: NeuralNetworkBuilder
        A neural network builder object.
    """
    input_name, output_name = input_names[0], output_names[0]
    W = keras_layer.get_weights()[0].T
    builder.add_embedding(name=layer, W=W, b=None, input_dim=keras_layer.
        input_dim, output_channels=keras_layer.output_dim, has_bias=False,
        input_name=input_name, output_name=output_name)


def export_file(client, file_type, file_=None, filename=None, dirname=None,
    geom_flags=None, advanced=None):
    """Export a model to a file.

    The geom_flags option only applies to IGES and STEP exports.
    Setting geom_flags to 'default' will cause it to check the Creo config
    option 'intf3d_out_default_option' for the setting
    The advanced option will cause the Export to use settings defined in the
    appropriate `export_profiles` Creo Config Option for the file type.
    The advanced option only applies to DXF, IGES and STEP exports.
    The advanced option will only work with Creo 4 M030 or later.

    Args:
        client (obj):
            creopyson Client.
        file_type (str):
            File type.
            Valid values: "DXF", "IGES", "NEUTRAL", "PV", "STEP", "VRML".
        `file_` (str, optional):
            Model name. Defaults is current active model.
        filename (str, optional):
            Destination file name. May also contain a path to the file.
            Defaults is the model name with the appropriate file extension,
            in Creo's working directory.
        dirname (str, optional):
            Destination directory. Defaults is Creo's current
            working directory.
        geom_flags (str, optional):
            Geometry type for the export.
            Defaults is `solids`.
            Valid values: solids, surfaces, wireframe, wireframe_surfaces,
            quilts, default.
        advanced (Boolean, optional):
            Whether to use the newer Creo 4 file export function.
            Defaults is False.

    Returns:
        dict:
            dirname (str): Directory of the output file
            filename (str): Name of the output file

    """
    data = {'type': file_type}
    if file_ is not None:
        data['file'] = file_
    else:
        active_file = client.file_get_active()
        if active_file is not None:
            data['file'] = active_file['file']
    if filename:
        data['filename'] = filename
    if dirname:
        data['dirname'] = dirname
    if geom_flags:
        data['geom_flags'] = geom_flags
    if advanced:
        data['advanced'] = advanced
    return client._creoson_post('interface', 'export_file', data)


def UernPremRate():
    """Unearned Premium Rate"""
    return None


def wrapconvertsink(sink):
    """Allow extensions to wrap the sink returned by convcmd.convertsink()
    before it is used, whether or not the convert extension was formally loaded.
    """
    return sink


def is_big(json_data):
    """Test if given json data is too big for mongo document.

    Using 1MB as limit atm.

    :param json_data
    """
    return len(json_data) > 1000000


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


def AA_6(dul):
    """Association abort AA-6.

    If receive a PDU while waiting for connection to close, ignore it

    State-event triggers: Sta13 + Evt3/Evt4/Evt10/Evt12/Evt13

    References
    ----------
    1. DICOM Standard 2015b, PS3.8, Table 9-7, "Associate Establishment
       Related Actions"

    Parameters
    ----------
    dul : pynetdicom.dul.DULServiceProvider
        The DICOM Upper Layer Service instance for the local AE

    Returns
    -------
    str
        Sta13, the next state of the state machine
    """
    dul.primitive = None
    return 'Sta13'


def dmp_TC(f, K):
    """
    Return trailing coefficient of ``f``.

    Examples
    ========

    >>> R, x = ring('x', ZZ)

    >>> R.dmp_TC(x**2 + 2*x + 3)
    3

    """
    if not f:
        return K.zero
    else:
        return f[-1]


def arr_child_nodes(dx_nodes, dx_node):
    """
    Returns an array of child dx_nodes of dx_node that are part of dx_nodes
    Use CHILD_ARRAY over gen_child_nodes if it is consumed more times afterwards.

    :param dx_nodes: [DiffxNode, ..]
    :param dx_node: DiffxNode
    """
    _start_index = dx_nodes.index(dx_node)
    for _dx_node in dx_nodes[_start_index:]:
        if _dx_node.xpath.find(dx_node.xpath) == 0:
            _stop_elment = _dx_node
        elif _dx_node.xpath.find(dx_node.xpath) != 0:
            break
    _stop_index = dx_nodes.index(_stop_elment)
    return dx_nodes[_start_index + 1:_stop_index + 1]


def BigIntToBytes(n):
    """Return a big-endian byte string representation of an arbitrary length n."""
    array = []
    while n > 0:
        array.append(n % 256)
        n = n >> 8
    array.reverse()
    barray = bytearray(array)
    if barray[0] & 128:
        return b'\x00' + bytes(barray)
    return bytes(barray)


def tree_socket_remove():
    """Remove an input or output socket to the current node tree

    """
    pass


def extra_fields(columns):
    """Parse additional, chanjo specific fields.

    Contains transcript and gene ids.

    Args:
        columns (List[str]): list of two columns with related element ids

    Returns:
        List[tuple]: list of tuples with paired elements
    """
    try:
        transcripts = columns[0].split(',')
        genes = columns[1].split(',')
        symbols = columns[2].split(',')
    except IndexError:
        return []
    return zip(transcripts, genes, symbols)


@staticmethod
def _validate_window_size(k):
    """check if k is a positive integer"""
    if not isinstance(k, int):
        raise TypeError('window_size must be integer type, got {}'.format(
            type(k).__name__))
    if k <= 0:
        raise ValueError('window_size must be positive')
    return k


def bool_like(value, name, optional=False, strict=False):
    """
    Convert to bool or raise if not bool_like

    Parameters
    ----------
    value : object
        Value to verify
    name : str
        Variable name for exceptions
    optional : bool
        Flag indicating whether None is allowed
    strict : bool
        If True, then only allow bool. If False, allow types that support
        casting to bool.

    Returns
    -------
    converted : bool
        value converted to a bool
    """
    if optional and value is None:
        return value
    extra_text = ' or None' if optional else ''
    if strict:
        if isinstance(value, bool):
            return value
        else:
            raise TypeError('{0} must be a bool{1}'.format(name, extra_text))
    if hasattr(value, 'squeeze') and callable(value.squeeze):
        value = value.squeeze()
    try:
        return bool(value)
    except Exception:
        raise TypeError('{0} must be a bool (or bool-compatible){1}'.format
            (name, extra_text))


def describe_effective_patches_for_patch_baseline(BaselineId=None,
    MaxResults=None, NextToken=None):
    """
    Retrieves the current effective patches (the patch and the approval state) for the specified patch baseline.
    See also: AWS API Documentation

    :example: response = client.describe_effective_patches_for_patch_baseline(
        BaselineId='string',
        MaxResults=123,
        NextToken='string'
    )

    :type BaselineId: string
    :param BaselineId: [REQUIRED]
            The ID of the patch baseline to retrieve the effective patches for.

    :type MaxResults: integer
    :param MaxResults: The maximum number of patches to return (per page).

    :type NextToken: string
    :param NextToken: The token for the next set of items to return. (You received this token from a previous call.)

    :rtype: dict
    :return: {
        'EffectivePatches': [
            {
                'Patch': {
                    'Id': 'string',
                    'ReleaseDate': datetime(2015, 1, 1),
                    'Title': 'string',
                    'Description': 'string',
                    'ContentUrl': 'string',
                    'Vendor': 'string',
                    'ProductFamily': 'string',
                    'Product': 'string',
                    'Classification': 'string',
                    'MsrcSeverity': 'string',
                    'KbNumber': 'string',
                    'MsrcNumber': 'string',
                    'Language': 'string'
                },
                'PatchStatus': {
                    'DeploymentStatus': 'APPROVED'|'PENDING_APPROVAL'|'EXPLICIT_APPROVED'|'EXPLICIT_REJECTED',
                    'ApprovalDate': datetime(2015, 1, 1)
                }
            },
        ],
        'NextToken': 'string'
    }

    """
    pass


def theta_from_theta_s(data, units, notation=None, return_full_df=True,
    inplace_units=True):
    """Calculates thermodynamic temperature using sonic temperature measurements

    From Schotanus, Nieuwstadt, de Bruin; DOI 10.1007/BF00164332

    theta_s = theta (1 + 0.51 q) (1 - (vn/c)**2)^0.5

    :math:`theta_s \\approx theta (1 + 0.51 q)`

    Parameters
    ----------
    data: pandas.dataframe
        dataset
    units: dict
        units dictionary
    notation: pymicra.Notation

    Returns
    -------
    pandas.Series
        thermodynamic temperature
    """
    from . import algs
    defs = algs.get_notation(notation)
    data = data.copy()
    theta = data[defs.sonic_temp] / (1.0 + 0.51 * data[defs.specific_humidity])
    theta_unit = units[defs.sonic_temp]
    if return_full_df:
        data.loc[:, (defs.thermodyn_temp)] = theta
        out = data
    else:
        out = theta
    if inplace_units:
        units.update({defs.thermodyn_temp: theta_unit})
    else:
        out = out, theta_unit
    return out


def _configSpecial_OrthoOpts_ycentre(target, parser, shortArg, longArg,
    helpText):
    """Configures the ``ycentre`` option for the ``OrthoOpts`` class. """
    parser.add_argument(shortArg, longArg, metavar=('X', 'Z'), type=float,
        nargs=2, help=helpText)


def getArguments(parser):
    """Provides additional validation of the arguments collected by argparse."""
    return parser.parse_args()


def rldecode(data):
    """
    RunLength decoder (Adobe version) implementation based on PDF Reference
    version 1.4 section 3.3.4:
        The RunLengthDecode filter decodes data that has been encoded in a
        simple byte-oriented format based on run length. The encoded data
        is a sequence of runs, where each run consists of a length byte
        followed by 1 to 128 bytes of data. If the length byte is in the
        range 0 to 127, the following length + 1 (1 to 128) bytes are
        copied literally during decompression. If length is in the range
        129 to 255, the following single byte is to be copied 257 - length
        (2 to 128) times during decompression. A length value of 128
        denotes EOD.
    """
    decoded = b''
    i = 0
    while i < len(data):
        length = data[i]
        if length == 128:
            break
        if length >= 0 and length < 128:
            for j in range(i + 1, i + 1 + (length + 1)):
                decoded += bytes((data[j],))
            i = i + 1 + (length + 1)
        if length > 128:
            run = bytes((data[i + 1],)) * (257 - length)
            decoded += run
            i = i + 1 + 1
    return decoded


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

    """
    pass


@classmethod
def unpack(cls, msg):
    """Construct an _OpReply from raw bytes."""
    flags, cursor_id, _, number_returned = cls.UNPACK_FROM(msg)
    documents = bytes(msg[20:])
    return cls(flags, cursor_id, number_returned, documents)


@staticmethod
def calculate_quality(input_vector, control_params):
    """
        Function for calculating quality.

        Returns:
            float: quality

        Raises:
            AssertionError: If length of `control_params`
                is not equal length of `input_vector`
        """
    assert len(control_params) == len(input_vector)
    quality = 0
    for i in enumerate(control_params):
        quality += (control_params[i[0]] - input_vector[i[0]]) ** 2
    return quality


def compile_theme(theme, target, *, zip_=False):
    """
    Compile a theme (i.e. directory of Jinja2 templates)

    theme: Path to directory with templates in

    target: Directory in which to store compiled templates

    zip_: Target is a zip file, rather than a directory
    """
    from jinja2 import Environment, FileSystemLoader
    env = Environment(loader=FileSystemLoader(theme))
    env.compile_templates(target, zip='deflated' if zip_ else None)


@classmethod
def retrieve_job_status(cls, status_dir, module, job_name):
    """Update and retrieve job status.

        Parameters
        ----------
        status_dir : str
            Directory containing json status file.
        module : str
            reV module that the job belongs to.
        job_name : str
            Unique job name identification.

        Returns
        -------
        status : str | None
            Status string or None if job/module not found.
        """
    if job_name.endswith('.h5'):
        job_name = job_name.replace('.h5', '')
    obj = cls(status_dir)
    obj._update_job_status(module, job_name)
    try:
        status = obj.data[module][job_name].get('job_status', None)
    except KeyError:
        status = None
    return status


def fvoigt(damp, vv):
    """
	Extract spectral data from the Kitt Peak FTS-Spectral-Atlas
	as provided by H. Neckel, Hamburg.

	INPUTS:
			DAMP: A scalar with the damping parameter
			VV: Wavelength axis usually in Doppler units.

	OUTPUTS:
			H: Voigt function
			F: Faraday-Voigt function

	NOTES:
			A rational approximation to the complex error function is used
			after Hui, Armstrong, and Wray(1978, JQSRT 19, 509). H and F are
			the real and imaginary parts of such function, respectively.
			The procedure is inspired on that in SIR (Ruiz Cobo & del Toro
			Iniesta 1992, ApJ 398, 385). On its turn, that routine was taken
			from modifications by A. Wittmann (1986) to modifications by S.K.
			Solanki (1985) to an original FORTRAN routine written by J.W. Harvey
			and A. Nordlund.
	"""
    import numpy as np
    A = [122.60793177710433, 214.38238869470644, 181.92853309218154,
        93.15558045813845, 30.18014219621059, 5.912626209773153,
        0.564189583562615]
    B = [122.60793177387535, 352.73062511096356, 457.33447878389774,
        348.7039177194958, 170.35400182109146, 53.99290691294021,
        10.4798571142604, 1.0]
    z = np.array(damp * np.ones(len(vv)) + -abs(vv) * 1.0j)
    Z = ((((((A[6] * z + A[5]) * z + A[4]) * z + A[3]) * z + A[2]) * z + A[
        1]) * z + A[0]) / (((((((z + B[6]) * z + B[5]) * z + B[4]) * z + B[
        3]) * z + B[2]) * z + B[1]) * z + B[0])
    h = np.real(Z)
    f = np.sign(vv) * np.imag(Z) * 0.5
    return [h, f]


@classmethod
def _register_service_type(cls, subclass):
    """Registers subclass handlers of various service-type-specific service
           implementations. Look for classes decorated with
           @Folder._register_service_type for hints on how this works."""
    if hasattr(subclass, '__service_type__'):
        cls._service_type_mapping[subclass.__service_type__] = subclass
        if subclass.__service_type__:
            setattr(subclass, subclass.__service_type__, property(lambda x: x))
    return subclass


@classmethod
def _from_et(cls, root, parent):
    """
        Create a :class:`Vertex` from a :code:`vertex` element.

        :param root: The element tree tree to parse.
        :param parent: :class:`EagleFilePart` that should hold the resulting :class:`EagleFilePart`
        :rtype: :class:`Vertex`
        """
    n = cls()
    n._init_from_et(root, parent)
    return n


@classmethod
def get_name(cls, value):
    """
        Given an attribute value, retrieve the attribute name.
        :param value: a class attribute value
        :return: the attribute name corresponding to that value
        """
    return cls.get_attribute_value_mappings()[value]


def CO2LOGSERVER_DEFAULT_LAT(box):
    """
    This function is called with the following arguments to determine the
    latitude of a senseBox if the data does not contain the information:

    box:
        the value of the :any:`CO2LOGSERVER_OSEM_BOX_COL`

    By default, ``None`` is returned which means that the latitude could not be
    determined.
    """
    return None


@classmethod
def matches(cls, fp):
    """
        Read next a few bytes to judge if the following data match this type
        of chunk.

        It calls :meth:`safe_matches` and restores :attr:`fp` state by default.

        You can override this to avoid saving :attr:`fp` state.

        :param fp: File object to read from.
        :returns: If the following bytes match this chunk type.
        """
    fp.save_state()
    matches = cls.safe_matches(fp)
    fp.restore_state()
    return matches


def init():
    """ Initializes mouse state """
    pass


def remove_account_from_organization(AccountId=None):
    """
    Removes the specified account from the organization.
    The removed account becomes a stand-alone account that is not a member of any organization. It is no longer subject to any policies and is responsible for its own bill payments. The organization's master account is no longer charged for any expenses accrued by the member account after it is removed from the organization.
    This operation can be called only from the organization's master account. Member accounts can remove themselves with  LeaveOrganization instead.
    See also: AWS API Documentation

    :example: response = client.remove_account_from_organization(
        AccountId='string'
    )

    :type AccountId: string
    :param AccountId: [REQUIRED]
            The unique identifier (ID) of the member account that you want to remove from the organization.
            The regex pattern for an account ID string requires exactly 12 digits.

    """
    pass


@classmethod
def GetNamesOfParsersWithPlugins(cls):
    """Retrieves the names of all parsers with plugins.

    Returns:
      list[str]: names of all parsers with plugins.
    """
    parser_names = []
    for parser_name, parser_class in cls._GetParsers():
        if parser_class.SupportsPlugins():
            parser_names.append(parser_name)
    return sorted(parser_names)


def gcd(number1, number2):
    """Helper function to simplify fractions"""
    if not isinstance(number1, int) or not isinstance(number2, int):
        raise TypeError('Numerator and denominator must be integers')
    while number1 % number2:
        number1, number2 = number2, number1 % number2
    return number2


def switch_direction():
    """Change the direction that a chain of bones points in (head <-> tail swap)

    """
    pass


def reindex(indices):
    """Generate a new set of node indices, the size of indices."""
    return tuple(range(len(indices)))


def tostr(array):
    """ Create a string from an array of numbers """
    tmpstr = ''
    for val in array:
        tmpstr = tmpstr + ' ' + repr(val)
    return tmpstr.strip()


def elastic_pool_transform(result):
    """
    Transforms the json response for an elastic pool.
    """
    from azure.mgmt.sql.models import ElasticPoolEdition
    result.edition = result.sku.tier
    result.storageMb = result.max_size_bytes / 1024 / 1024
    is_dtu = result.sku.tier in (ElasticPoolEdition.basic.value,
        ElasticPoolEdition.standard.value, ElasticPoolEdition.premium.value)
    result.dtu = result.sku.capacity if is_dtu else None
    result.database_dtu_min = int(result.per_database_settings.min_capacity
        ) if is_dtu else None
    result.database_dtu_max = int(result.per_database_settings.max_capacity
        ) if is_dtu else None
    return result


def _process_glsl_template(template, colors):
    """Replace $color_i by color #i in the GLSL template."""
    for i in range(len(colors) - 1, -1, -1):
        color = colors[i]
        assert len(color) == 4
        vec4_color = 'vec4(%.3f, %.3f, %.3f, %.3f)' % tuple(color)
        template = template.replace('$color_%d' % i, vec4_color)
    return template


def cliffs_delta(control, test):
    """
    Computes Cliff's delta for 2 samples.
    See https://en.wikipedia.org/wiki/Effect_size#Effect_size_for_ordinal_data

    Keywords
    --------
    control, test: numeric iterables.
        These can be lists, tuples, or arrays of numeric types.

    Returns
    -------
        A single numeric float.
    """
    import numpy as np
    from scipy.stats import mannwhitneyu
    if control.__class__ != np.ndarray:
        control = np.array(control)
    if test.__class__ != np.ndarray:
        test = np.array(test)
    c = control[~np.isnan(control)]
    t = test[~np.isnan(test)]
    control_n = len(c)
    test_n = len(t)
    U, _ = mannwhitneyu(t, c, alternative='two-sided')
    cliffs_delta = 2 * U / (control_n * test_n) - 1
    return cliffs_delta


def clean_unneeded_html_tags(html):
    """Clean unneeded optional html tags.

    >>> clean_unneeded_html_tags('a	b

c')
    'abc'
    """
    for tag_to_remove in """</area> </base>
 </col>
        </colgroup>

        </input>
 </link> </meta> </option> </param>

 </basefont> </isindex> </param>
            """.split(
        ):
        html = html.replace(tag_to_remove, '')
    return html


def iob2(tags):
    """
    Check that tags have a valid IOB format.
    Tags in IOB1 format are converted to IOB2.
    """
    for i, tag in enumerate(tags):
        if tag == 'O':
            continue
        split = tag.split('-')
        if len(split) != 2 or split[0] not in ['I', 'B']:
            return False
        if split[0] == 'B':
            continue
        elif i == 0 or tags[i - 1] == 'O':
            tags[i] = 'B' + tag[1:]
        elif tags[i - 1][1:] == tag[1:]:
            continue
        else:
            tags[i] = 'B' + tag[1:]
    return True


def dict_to_cols(dict_obj, cols):
    """Converts a dict to a cliff-compatible value list.

    For cliff lister.Lister objects, you should use list_to_cols() instead
    of this function.
    'cols' shouls be a list of (key, Name) tuples.
    """
    values = []
    for col in cols:
        values.append(dict_obj.get(col[0]))
    return values


def use_shading_nodes():
    """Enable nodes on a material, world or light

    """
    pass


@classmethod
def _iterable_to_header_element(cls, iterable):
    """
        Convert iterable of tuples into header element ``str``.

        Each tuple is expected to be in one of two forms: (media_range, qvalue,
        extension_params_segment), or (media_range, qvalue).
        """
    try:
        media_range, qvalue, extension_params_segment = iterable
    except ValueError:
        media_range, qvalue = iterable
        extension_params_segment = ''
    if qvalue == 1.0:
        if extension_params_segment:
            element = '{};q=1{}'.format(media_range, extension_params_segment)
        else:
            element = media_range
    elif qvalue == 0.0:
        element = '{};q=0{}'.format(media_range, extension_params_segment)
    else:
        element = '{};q={}{}'.format(media_range, qvalue,
            extension_params_segment)
    return element


def fix_newlines(lines):
    """Convert newlines to unix."""
    for i, line in enumerate(lines):
        if line.endswith('\r\n'):
            lines[i] = line[:-2] + '\n'
        elif line.endswith('\r'):
            lines[i] = line[:-1] + '\n'


def source_match(state, source):
    """Check if the state matches the provided source."""
    return state and state.attributes.get('source') == source