def parse_int(str_num):
    """ Given an integer number, return its value,
    or None if it could not be parsed.
    Allowed formats: DECIMAL, HEXA (0xnnn, $nnnn or nnnnh)
    :param str_num: (string) the number to be parsed
    :return: an integer number or None if it could not be parsedd
    """
    str_num = (str_num or '').strip().upper()
    if not str_num:
        return None
    base = 10
    if str_num.startswith('0X'):
        base = 16
        str_num = str_num[2:]
    if str_num.endswith('H'):
        base = 16
        str_num = str_num[:-1]
    if str_num.startswith('$'):
        base = 16
        str_num = str_num[1:]
    try:
        return int(str_num, base)
    except ValueError:
        return None


def CLEAR(writer, segments):
    """This policy DELETES all existing segments and only writes the new
    segment.
    """
    return []


def removeFromList(list_, *elements):
    """Save as list_.remove(each element) but don't raise an error if
       element is missing.  Modifies 'list_' in place!  Returns None.
    """
    for elm in elements:
        try:
            list_.remove(elm)
        except ValueError:
            pass


def add_source_parent_project_names(project_details_df):
    """
    Join the parent project names to the details for each project.
    :param DataFrame project_details_df: the project details DataFrame
    :return: DataFrame
    """
    temp_df = project_details_df[['source_project_name', 'source_project_id']
        ].copy()
    temp_df.rename(columns={'source_project_name':
        'source_project_parent_name'}, inplace=True)
    project_details_df = project_details_df.merge(temp_df, left_on=
        'source_project_parent_id', right_on='source_project_id', how=
        'left', suffixes=(None, '_delete'))
    return project_details_df.drop(columns=['source_project_id_delete'])


def setPrefix(prefix):
    """Set the name prefix used for the widget

        The widget name is used to identify the widget's data within
        input data.  For example, for HTTP forms, the widget name is
        used for the form key.

        It is acceptable to *reset* the prefix: set it once to read
        values from the request, and again to redraw with a different
        prefix but maintained state.

        """


def dt_1(provider):
    """Send P-DATA-TF PDU."""
    provider.dul_socket.send(provider.primitive.encode())
    provider.primitive = None
    return 'Sta6'


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

        :param MemberSpaceLimitsChangePolicyDetails val:
        :rtype: EventDetails
        """
    return cls('member_space_limits_change_policy_details', val)


@staticmethod
def listen(data):
    """
        * Do something with the data.
        * :param data:
        * :return: url output
        """
    raise NotImplementedError()


def psi_Ca_H_HCO3_HMW84(T, P):
    """c-c'-a: calcium hydrogen bicarbonate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


def get_default_opts(overrides=None):
    """
    Default :term:`opts` used by :func:`lasso()` when constructing its internal :class:`Ranger`.

    :param dict or None overrides:
            Any items to update the default ones.
    """
    opts = {'lax': False, 'verbose': False, 'read': {'on_demand': True}}
    if overrides:
        opts.update(overrides)
    return opts


def draw_default_tail(context):
    """
    Default tail drawer: draw line to the last handle.
    """
    context.cairo.line_to(0, 0)


@classmethod
def set_bot(cls, bot):
    """Change class bot."""
    cls.bot = bot


@classmethod
def create(cls, registered_name, pipeline=None, **kwargs):
    """
        Stateless method to create a new persistable with the desired parameters
        kwargs are passed directly to persistable

        :param registered_name: Class name registered in SimpleML
        :param pipeline: pipeline object
        """
    if pipeline is None:
        pipeline = cls.retrieve_pipeline(**kwargs.pop('pipeline_kwargs', {}))
    new_model = cls.retrieve_from_registry(registered_name)(**kwargs)
    new_model.add_pipeline(pipeline)
    new_model.fit()
    new_model.save()
    return new_model


@classmethod
def edit_form_entry_help_text_extra(cls):
    """For adding the edit link to edit form entry view.

        :return str:
        """
    return (
        """

              {edit_option_html}

                {delete_text}

            <input type="hidden" value="{form_element_position}"
                   name="form-{counter}-position"
                   id="id_form-{counter}-position"
                   class="form-element-position">
            <input type="hidden" value="{form_element_pk}"
                   name="form-{counter}-id" id="id_form-{counter}-id">
            """
        .format(container_class=cls.form_list_container_class,
        edit_option_html='{edit_option_html}', delete_url='{delete_url}',
        delete_option_class=cls.form_delete_form_entry_option_class,
        delete_text='{delete_text}', form_element_position=
        '{form_element_position}', counter='{counter}', form_element_pk=
        '{form_element_pk}'))


def jwt_payload_handler(user):
    """
    A custom JWT Payload Handler that adds certain extra data in
    payload such as: email, mobile, name

    Source: Himanshu Shankar (https://github.com/iamhssingh)
    Parameters
    ----------
    user: get_user_model()

    Returns
    -------
    payload: dict
    """
    import uuid
    from calendar import timegm
    from datetime import datetime
    from rest_framework_jwt.compat import get_username
    from rest_framework_jwt.compat import get_username_field
    from rest_framework_jwt.settings import api_settings
    username_field = get_username_field()
    username = get_username(user)
    payload = {'user_id': user.pk, 'is_admin': user.is_staff, 'exp':
        datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA}
    if hasattr(user, 'email'):
        payload['email'] = user.email
    if hasattr(user, 'mobile'):
        payload['mobile'] = user.mobile
    if hasattr(user, 'name'):
        payload['name'] = user.name
    if isinstance(user.pk, uuid.UUID):
        payload['user_id'] = str(user.pk)
    payload[username_field] = username
    if api_settings.JWT_ALLOW_REFRESH:
        payload['orig_iat'] = timegm(datetime.utcnow().utctimetuple())
    if api_settings.JWT_AUDIENCE is not None:
        payload['aud'] = api_settings.JWT_AUDIENCE
    if api_settings.JWT_ISSUER is not None:
        payload['iss'] = api_settings.JWT_ISSUER
    return payload


def get_zero_vector(numBytes):
    """
    Generates a zero vector of a given size

    :param numBytes:
    :return:
    """
    return bytearray([0] * numBytes).decode('ascii')


def authenticate(request):
    """Identify a principal for a request.

        If a principal can be identified, then return the
        principal. Otherwise, return None.

        The request object is fairly opaque. We may decide
        that it implements some generic request interface.

        .. note::

           Implementation note: It is likely that the component will dispatch
           to another component based on the actual
           request interface. This will allow different
           kinds of requests to be handled correctly.

           For example, a component that authenticates
           based on user names and passwords might request
           an adapter for the request as in::

              getpw = getAdapter(request, context=self)

           The ``context`` keyword argument is used to control
           where the :class:`ILoginPassword` component is searched for.
           This is necessary because requests are placeless.
        """


def select_linked(extend: bool=False):
    """Select bones related to selected ones by parent/child relationships

    :param extend: Extend, Extend selection instead of deselecting everything first
    :type extend: bool
    """
    pass


def size(iterable):
    """
    Returns the length of an iterable.
    Caution: If this iterable is generator, this method would eat up the generator

    params: iterable
        iterable -> list, sequenece, set, dictionary, generator etc

    Examples:
    >>> gen = (i for i in range(0,10))
    >>> _.size(gen)
    >>> 10
    """
    try:
        return len(iterable)
    except TypeError:
        length = 0
        for i in iterable:
            length = length + 1
        return length


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


def count_lines(filename):
    """
    Count the number of lines in a file.
    :param filename:
    :type filename:  str
    :return:
    :rtype: int
    """
    n = 0
    with open(filename, 'rb') as fh:
        for line in fh:
            n += 1
    return n


def models_from_ids(sas, cls, ids):
    """Generator that, given a sequence of IDs, yields model instances.

    Performance is poor. TODO SOMEONE IMPROVE THIS PLEASE
    """
    for id in ids:
        yield sas.query(cls).get(id)


def index_iterator(shape):
    """Iterates over the indexes of a multi-dimensional array of a specified shape.
    The last index changes most rapidly.

    :param shape: sequence of array dimensions
    :return: yields tuples of array indexes
    """
    dim = len(shape)
    idx = [0] * dim
    num_iterations = 1
    for j in range(0, dim):
        num_iterations *= shape[j]
    for iterations in range(num_iterations):
        yield tuple(idx)
        for j in range(dim - 1, -1, -1):
            idx[j] += 1
            if idx[j] < shape[j]:
                break
            idx[j] = 0


@classmethod
def _from_deprecated_string(cls, serialized):
    """ CCXLocators are never deprecated. """
    raise NotImplementedError


@staticmethod
def _get_name_from_dn(dn):
    """
        Get the instance name from the dn

        :param dn: string containing the distinguished name URL
        :return: string containing the name
        """
    name = dn.split('/if-')[1].split('/')[0]
    return name


def parse_json(desc, rows):
    """
    parse records to list, including record as dict
    :param desc: description of table, column name
    :param rows: input records
    :return: a list of dicts
    """
    if len(rows) == 1:
        results = {}
        row = rows[0]
        i = 0
        for u_desc in desc:
            results[u_desc[0]] = str(row[i])
            i += 1
        results = [results]
    else:
        results = []
        for row in rows:
            i = 0
            result = {}
            for u_desc in desc:
                result[u_desc[0]] = str(row[i])
                i += 1
            results.append(result)
    return results


def dotify(name):
    """ Add a dot to the end of the name if it wasn't there.
    """
    if not name.endswith('.'):
        return '%s.' % name
    return name


@classmethod
def register_notification_objects(cls):
    """Register previously decorated notification as normal ovos.
        This is not intended for production use but only for testing and
        document generation purposes.
        """
    for notification_cls in cls.notification_classes:
        cls.register(notification_cls)


@staticmethod
def sort_key(format):
    """ Get a key to sort a format

        Args:
            format (:obj:`Format`): format

        Returns:
            :obj:`tuple`
        """
    return (format.id, format.name, format.version, format.edam_id, format.
        url, format.spec_url, format.mime_type, format.extension, format.
        sed_urn)


def map_vector(x, raster, **kvars):
    """
    Create new GeoRaster, which has its data replaced by x
    Useful to map output of PySal analyses, e.g. spatial autocorrelation values, etc.

    Usage: raster2 = map_vector(x, raster)
    where
        raster: GeoRaster
        x: Numpy array of data with same length as non-missing values in raster,
           i.e., len(x) == np.sum(raster.mask==False)
    """
    y = raster.copy()
    y.raster[y.raster.mask == False] = x
    return y


def set_param(log_level=None, data_dir=None):
    """
    Set mobileDNA parameters.

    :param log_level: new value for log level
    :param data_dir: new data directory
    """
    global LOG_LEVEL
    global DATA_DIR
    if log_level:
        LOG_LEVEL = log_level
    if data_dir:
        DATA_DIR = data_dir


def calcPolygonRect(pointArray):
    """ receives a point list and returns the rect that contains them as a tupple -> tuple left, top, right, bottom
    """
    l, t, r, b = 10000000, 10000000, -10000000, -10000000
    for n in pointArray:
        if n[0] < l:
            l = n[0]
        if n[0] > r:
            r = n[0]
        if n[1] < t:
            t = n[1]
        if n[1] > b:
            b = n[1]
    return l, t, r, b


def download_db_log_file_portion(DBInstanceIdentifier=None, LogFileName=
    None, Marker=None, NumberOfLines=None):
    """
    Downloads all or a portion of the specified log file, up to 1 MB in size.
    See also: AWS API Documentation

    Examples
    This example lists information for the specified log file for the specified DB instance.
    Expected Output:

    :example: response = client.download_db_log_file_portion(
        DBInstanceIdentifier='string',
        LogFileName='string',
        Marker='string',
        NumberOfLines=123
    )

    :type DBInstanceIdentifier: string
    :param DBInstanceIdentifier: [REQUIRED]
            The customer-assigned name of the DB instance that contains the log files you want to list.
            Constraints:
            Must contain from 1 to 63 alphanumeric characters or hyphens
            First character must be a letter
            Cannot end with a hyphen or contain two consecutive hyphens

    :type LogFileName: string
    :param LogFileName: [REQUIRED]
            The name of the log file to be downloaded.

    :type Marker: string
    :param Marker: The pagination token provided in the previous request or '0'. If the Marker parameter is specified the response includes only records beyond the marker until the end of the file or up to NumberOfLines.

    :type NumberOfLines: integer
    :param NumberOfLines: The number of lines to download. If the number of lines specified results in a file over 1 MB in size, the file will be truncated at 1 MB in size.
            If the NumberOfLines parameter is specified, then the block of lines returned can be from the beginning or the end of the log file, depending on the value of the Marker parameter.
            If neither Marker or NumberOfLines are specified, the entire log file is returned up to a maximum of 10000 lines, starting with the most recent log entries first.
            If NumberOfLines is specified and Marker is not specified, then the most recent lines from the end of the log file are returned.
            If Marker is specified as '0', then the specified number of lines from the beginning of the log file are returned.
            You can download the log file in blocks of lines by specifying the size of the block using the NumberOfLines parameter, and by specifying a value of '0' for the Marker parameter in your first request. Include the Marker value returned in the response as the Marker value for the next request, continuing until the AdditionalDataPending response element returns false.

    :rtype: dict
    :return: {
        'LogFileData': 'string',
        'Marker': 'string',
        'AdditionalDataPending': True|False
    }

    """
    pass


@classmethod
def _get_import_resolver(cls):
    """ method that can be overridden in tests """
    from zope.dottedname.resolve import resolve as resolve_dotted
    return resolve_dotted


def is_task_mutable(context, task):
    """Return True if the task is mutable in this context."""
    if context.is_admin:
        return True
    if context.owner is None:
        return False
    return task.owner == context.owner


def dynamics(state, time, config, intervention=None):
    """Update equations for the HIV simulaton.

    Parameters
    ----------
        state:  np.ndarray, list, or tuple
            State of the dynamics
        time:   float
        config: hiv.Config
            Simulator configuration object that determines the coefficients
        intervantion: hiv.Intervention
            Simulator intervention object that determines when/how to update the
            dynamics.

    Returns
    -------
        ds_dt: list
            Derivative of the dynamics with respect to time

    """
    if intervention and time >= intervention.time:
        config = config.update(intervention)
    (uninfected_T1, infected_T1, uninfected_T2, infected_T2, free_virus,
        immune_response) = state
    delta_uninfected_T1 = config.lambda_1 - config.d_1 * uninfected_T1 - (1 -
        config.epsilon_1) * config.k_1 * free_virus * uninfected_T1
    delta_infected_T1 = ((1 - config.epsilon_1) * config.k_1 * free_virus *
        uninfected_T1 - config.delta * infected_T1 - config.m_1 *
        immune_response * infected_T1)
    delta_uninfected_T2 = config.lambda_2 - config.d_2 * uninfected_T2 - (1 -
        config.f * config.epsilon_1) * config.k_2 * free_virus * uninfected_T2
    delta_infected_T2 = ((1 - config.f * config.epsilon_1) * config.k_2 *
        free_virus * uninfected_T2 - config.delta * infected_T2 - config.
        m_2 * immune_response * infected_T2)
    delta_virus = (1 - config.epsilon_2) * config.N_T * config.delta * (
        infected_T1 + infected_T2) - config.c * free_virus - free_virus * (
        (1.0 - config.epsilon_1) * config.rho_1 * config.k_1 *
        uninfected_T1 + (1.0 - config.f * config.epsilon_1) * config.rho_2 *
        config.k_2 * uninfected_T2)
    delta_immune_response = config.lambda_E + config.b_E * (infected_T1 +
        infected_T2) / (infected_T1 + infected_T2 + config.K_B
        ) * immune_response - config.d_E * (infected_T1 + infected_T2) / (
        infected_T1 + infected_T2 + config.K_D
        ) * immune_response - config.delta_E * immune_response
    ds_dt = [delta_uninfected_T1, delta_infected_T1, delta_uninfected_T2,
        delta_infected_T2, delta_virus, delta_immune_response]
    return ds_dt


def is_negative(k):
    """
    Determines if given k is negative
    :param k:
    :return: bool: True if k is negative, False otherwise
    """
    if k < 0:
        return True
    return False


def administer(request):
    """Provides administaration functions"""
    pass


def twocs_to_int(val, bits):
    """compute the int value of a two compliment int"""
    assert len(bin(val)) - 2 <= bits, (val, bits)
    if val & 1 << bits - 1 != 0:
        val = val - (1 << bits)
    return val


def invertIntervalList(entryList, minValue=0, maxValue=None):
    """
    Given a list of ordinal events, inverts the start and end positions

    e.g. input [(5, 6), (10, 13), (14, 16)]
         output [(0, 5), (6, 10), (13, 14)]
    """
    newEntryList = []
    i = 0
    if minValue is not None:
        if entryList[0][0] > minValue:
            newEntryList.append((minValue, entryList[0][0]))
    while i + 1 < len(entryList):
        newEntryList.append((entryList[i][1], entryList[i + 1][0]))
        i += 1
    if maxValue is not None:
        if entryList[i][1] < maxValue:
            newEntryList.append((entryList[i][1], maxValue))
    return newEntryList


@staticmethod
def _get_example_from_basic_type(type):
    """Get example from the given type.

        Args:
            type: the type you want an example of.

        Returns:
            An array with two example values of the given type.
        """
    if type == 'integer':
        return [42, 24]
    elif type == 'number':
        return [5.5, 5.5]
    elif type == 'string':
        return ['string', 'string2']
    elif type == 'datetime':
        return ['2015-08-28T09:02:57.481Z', '2015-08-28T09:02:57.481Z']
    elif type == 'boolean':
        return [False, True]
    elif type == 'null':
        return ['null', 'null']


@classmethod
def updateDataHook(cls, installLocation):
    """
        An optional hook that an be used to update the downloaded
        data prior to being installed on the host system.
        """


def generate_checks(container, address, check_ports):
    """Generates the check dictionary to pass to consul of the form {'checks': []}"""
    checks = {}
    checks['checks'] = []
    for p in check_ports:
        checks['checks'].append({'id': '{}-port{}'.format(container, p),
            'name': 'Check TCP port {}'.format(p), 'tcp': '{}:{}'.format(
            address, p), 'Interval': '30s', 'timeout': '4s'})
    return checks


def make_covmatrix(sigma_x, sigma_y, rho=0):
    """ create covariance matrix from given standard deviations and normalised correlation rho, vectorized """
    return (sigma_x ** 2, rho * sigma_x * sigma_y), (rho * sigma_x *
        sigma_y, sigma_y ** 2)


def convert_csv_to_list(string):
    """
    Convert Cauma separated single string to list.
    """
    return string.split(',')


def _get_label_info(G, label_name):
    """Get and return information of labels from the input graph

    Parameters
    ----------
    G : Network X graph
    label_name : string
        Name of the target label

    Returns
    ----------
    labels : numpy array, shape = [n_labeled_samples, 2]
        Array of pairs of labeled node ID and label ID
    label_dict : numpy array, shape = [n_classes]
        Array of labels
        i-th element contains the label corresponding label ID `i`
    """
    import numpy as np
    labels = []
    label_to_id = {}
    lid = 0
    for i, n in enumerate(G.nodes(data=True)):
        if label_name in n[1]:
            label = n[1][label_name]
            if label not in label_to_id:
                label_to_id[label] = lid
                lid += 1
            labels.append([i, label_to_id[label]])
    labels = np.array(labels)
    label_dict = np.array([label for label, _ in sorted(label_to_id.items(),
        key=lambda x: x[1])])
    return labels, label_dict


def __callback(pct, msg, data):
    """
    helper function to create a progress bar in function gdalwarp

    Parameters
    ----------
    pct: float
        the percentage progress
    msg: str
        the message to be printed on each progress step
    data
        the data to be modified during each progress step

    Returns
    -------

    """
    percent = int(pct * 100)
    data.update(percent)
    return 1


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


@classmethod
def is_committed(cls):
    """True if this app class was ever committed.

        :return: bool that is ``True`` when the app was committed before.
        """
    return cls.dectate.committed


def duplicate_move(ACTION_OT_duplicate=None, TRANSFORM_OT_transform=None):
    """Make a copy of all selected keyframes and move them

    :param ACTION_OT_duplicate: Duplicate Keyframes, Make a copy of all selected keyframes
    :param TRANSFORM_OT_transform: Transform, Transform selected items by mode type
    """
    pass


def multiply(initial: int=0, number: int=0) ->int:
    """Return product of *intial* and *number*.
    :param initial: Initial value.
    :type initial: int
    :param number: Value to add to initial.
    :type number: int
    :return: Product of initial and number.
    :rtype: int
    """
    return initial * number


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 last_blank(src):
    """Determine if the input source ends in a blank.

    A blank is either a newline or a line consisting of whitespace.

    Parameters
    ----------
    src : string
      A single or multiline string.
    """
    if not src:
        return False
    ll = src.splitlines()[-1]
    return ll == '' or ll.isspace()


def __call__(context):
    """Return a context-bound instance that implements ISource.
        """


def word_wrap(text, linelen=80, indent=0, joinstr='\n'):
    """Return string, word wrapped at linelen."""
    if len(text) < linelen:
        return text
    result = []
    line = []
    llen = -indent
    for word in text.split():
        llen += len(word) + 1
        if llen < linelen:
            line.append(word)
        else:
            result.append(' '.join(line))
            line = [word]
            llen = len(word)
    if line:
        result.append(' '.join(line))
    return joinstr.join(result)


@staticmethod
def is_camel_case(string: str) ->bool:
    """
        Check if a string is CamelCase.

        :param string: The string in input
        :return: bool
        """
    return '_' not in string


def _setup_input_slicers(a_shape, input_shape):
    """ This function returns two slicers that are to be used to
    copy the data from the input array to the FFTW object internal
    array, which can then be passed to _FFTWWrapper:

    ``(update_input_array_slicer, FFTW_array_slicer)``

    On calls to :class:`~pyfftw.builders._utils._FFTWWrapper` objects,
    the input array is copied in as:

    ``FFTW_array[FFTW_array_slicer] = input_array[update_input_array_slicer]``
    """
    update_input_array_slicer = [slice(None)] * len(a_shape)
    FFTW_array_slicer = [slice(None)] * len(a_shape)
    for axis in range(len(a_shape)):
        if a_shape[axis] > input_shape[axis]:
            update_input_array_slicer[axis] = slice(0, input_shape[axis])
        elif a_shape[axis] < input_shape[axis]:
            FFTW_array_slicer[axis] = slice(0, a_shape[axis])
            update_input_array_slicer[axis] = slice(0, a_shape[axis])
        else:
            update_input_array_slicer[axis] = slice(0, a_shape[axis])
    return tuple(update_input_array_slicer), tuple(FFTW_array_slicer)


def normalize_argument(argument):
    """
    Helps normalize arguments from aaargh that may not be what we want.
    """
    if argument == 'False':
        return False
    elif argument == 'True':
        return True
    elif argument == 'None':
        return None
    else:
        return argument


def replace_by(value, VR, action, default_name='John Doe', default_date=
    '18000101', default_datetime='180001010000.000000', default_time=
    '0000.000000', default_text='anon', default_code='ANON', default_age=
    '000M', default_decimal='0.0', default_integer='0', default_uid='000.000.0'
    ):
    """ Replace a 'value' depending of the input 'action' and the value
    representation 'VR'.

    The following action codes are:

    * D - replace with a non zero length value that may be a dummy value and
      consistent with the VR
    * Z - replace with a zero length value, or a non-zero length value that
      may be a dummy value and consistent with the VR
    * X - remove
    * K - keep (unchanged for non-sequence attributes, cleaned for sequences)
    * C - clean, that is replace with values of similar meaning known not to
      contain identifying information and consistent with the VR
    * U - replace with a non-zero length UID that is internally consistent
      within a set of Instances
    * Z/D - Z unless D is required to maintain IOD conformance (Type 2 versus
      Type 1)
    * X/Z - X unless Z is required to maintain IOD conformance (Type 3 versus
      Type 2)
    * X/D - X unless D is required to maintain IOD conformance (Type 3 versus
      Type 1)
    * X/Z/D - X unless Z or D is required to maintain IOD conformance (Type 3
      versus Type 2 versus Type 1)
    * X/Z/U* - X unless Z or replacement of contained instance UIDs (U) is
      required to maintain IOD conformance (Type 3 versus Type 2 versus Type 1
      sequences containing UID references)

    We use here the PS 3.6 convention.
    """
    if action in ['X', 'X/Z', 'X/D', 'X/Z/D', 'X/Z/U*']:
        return None
    elif action in ['U', 'D', 'Z', 'Z/D']:
        if VR == 'DA':
            return default_date
        elif VR == 'AS':
            return default_age
        elif VR == 'DS':
            return default_decimal
        elif VR == 'DT':
            return default_datetime
        elif VR == 'TM':
            return default_time
        elif VR == 'FL':
            return float(eval(default_decimal))
        elif VR == 'FD':
            return float(eval(default_decimal))
        elif VR in ['IS']:
            return default_integer
        elif VR in ['UL', 'US', 'SS', 'SL']:
            return eval(default_integer)
        elif VR == 'PN':
            return default_name
        elif VR == 'UI':
            return default_uid
        elif VR == 'CS':
            return default_code
        elif VR in ['LO', 'LT', 'ST', 'SH']:
            return default_text
        elif VR in ['OB', 'OW']:
            return default_integer
        else:
            raise Exception(
                "VR '{0}' is not yet supported. Current value is '{1}'.".
                format(VR, value))
    else:
        raise Exception("Action '{0}' is not yet supported.".format(action))


def eot(data, neof=5):
    """
    EOTs, whatever they are.

    Warning
    -------
    Not yet implemented.
    """
    raise NotImplementedError


def makeFlatList(nestedList):
    """중첩리스트를 단일리스트로 변환하는 함수"""
    flatList = []
    for sublist in nestedList:
        for item in sublist:
            flatList.append(item)
    return flatList


def _insert_rst_epilog(c):
    """Insert the rst_epilog variable into the configuration.

    This should be applied after other configurations so that the epilog can
    use other configuration variables.
    """
    c['rst_epilog'] = (
        """
.. |eups-tag| replace:: {eups_tag}
.. |eups-tag-mono| replace:: ``{eups_tag}``
.. |eups-tag-bold| replace:: **{eups_tag}**
    """
        .format(eups_tag=c['release_eups_tag']))
    return c


def Morimoto_Hotta(Re, Pr, Dh, Rm):
    """Calculates Nusselt number for flow inside a spiral heat exchanger of
    spiral mean diameter `Rm` and hydraulic diameter `Dh` according to [1]_,
    also as shown in [2]_ and [3]_.

    .. math::
        Nu = 0.0239\\left(1 + 5.54\\frac{D_h}{R_m}\\right)Re^{0.806}Pr^{0.268}

    .. math::
        D_h = \\frac{2HS}{H+S}

    .. math::
        R_m = \\frac{R_{min} + R_{max}}{2}

    Parameters
    ----------
    Re : float
        Reynolds number with bulk properties, [-]
    Pr : float
        Prandtl number with bulk properties [-]
    Dh : float
        Average hydraulic diameter, [m]
    Rm : float
        Average spiral radius, [m]

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

    Notes
    -----
    [1]_ is in Japanese.

    Examples
    --------
    >>> Morimoto_Hotta(1E5, 5.7, .05, .5)
    634.4879473869859

    References
    ----------
    .. [1] Morimoto, Eiji, and Kazuyuki Hotta. "Study of Geometric Structure
       and Heat Transfer Characteristics of Spiral Plate Heat Exchanger."
       Transactions of the Japan Society of Mechanical Engineers Series B 52,
       no. 474 (1986): 926-33. doi:10.1299/kikaib.52.926.
    .. [2] Bidabadi, M. and Sadaghiani, A. and Azad, A. "Spiral heat exchanger
       optimization using genetic algorithm." Transaction on Mechanical
       Engineering, International Journal of Science and Technology,
       vol. 20, no. 5 (2013): 1445-1454.
       http://www.scientiairanica.com/en/ManuscriptDetail?mid=47.
    .. [3] Turgut, Oğuz Emrah, and Mustafa Turhan Çoban. "Thermal Design of
       Spiral Heat Exchangers and Heat Pipes through Global Best Algorithm."
       Heat and Mass Transfer, July 7, 2016, 1-18.
       doi:10.1007/s00231-016-1861-y.
    """
    return 0.0239 * (1.0 + 5.54 * Dh / Rm) * Re ** 0.806 * Pr ** 0.268


def str_starts_with_any_in_list(string_a, string_list):
    """
    Check if string_a starts with any string the provided list of strings
    """
    for string_b in string_list:
        if string_a.startswith(string_b):
            return True
    return False


@staticmethod
def format_result(input):
    """From: http://stackoverflow.com/questions/13062300/convert-a-dict-to-sorted-dict-in-python
        """
    return {}


def to_nd(df, ndim):
    """
    Give a new shape to an input data by duplicating its column.

    Parameters
    ----------

    df : input data that will be reshape
    ndim : dimension of the new reshape data.

    Returns
    -------

    df_nd : return array reshaped in ndim.

    """
    df_nd = df[:, (None)]
    return df_nd


def tuple_set(value):
    """
    Serializes odml style tuples to a string representation.

    :param value: odml style tuple values.
    :return: string.
    """
    if not value:
        return None
    return '(%s)' % ';'.join(value)


def mergeWithLabels(json, firstField, firstFieldLabel, secondField,
    secondFieldLabel):
    """
    merge two fields of a json into an array of { firstFieldLabel : firstFieldLabel, secondFieldLabel : secondField }
    """
    merged = []
    for i in range(0, len(json[firstField])):
        merged.append({firstFieldLabel: json[firstField][i],
            secondFieldLabel: json[secondField][i]})
    return merged


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'com.microsoft.ml.spark.io.http.SimpleHTTPTransformer'


def divide_vectors_xy(u, v):
    """Element-wise division of two vectors assumed to lie in the XY plane.

    Parameters
    ----------
    u : list
        The XY(Z) components of the first vector.
    v : list
        The XY(Z) components of the second vector.

    Returns
    -------
    list
        Resulting vector in the XY plane.

    Examples
    --------
    >>>

    """
    return [u[0] / v[0], u[1] / v[1], 0.0]


@classmethod
def count(cls, query_filter={}):
    """
        Return the number of items matching the query filter
        :param query_filter: the raw query type as a dict (using the mongo syntax)
        :type query_filter: dict
        :return:
        """
    raise NotImplemented('abstract method')


@staticmethod
def get_primary_membership(entry):
    """
        Construct primary membership from RID to SID (BloodHound 3.0 only)
        """
    try:
        primarygroupid = int(entry['attributes']['primaryGroupID'])
    except (TypeError, KeyError):
        return None
    return '%s-%d' % ('-'.join(entry['attributes']['objectSid'].split('-')[
        :-1]), primarygroupid)


@classmethod
def merge(cls, key, data):
    """Merge two dicts or lists.

        For example:
            - {'a': 1, 'b': 2} + {'a': 42, 'c': 3}  => {'a': 42, 'b': 2, 'c': 3}
            - ['a', 'b', 'c']  + ['a', 'd', 'e']    => ['a', 'b', 'c', 'a', 'd', 'e']

        Args:
            key (str): Key to set (i.e. 'foo' or 'foo.bar.baz' for a deep key)
            data (dict|list): Value to update/extend for key.
        """
    items = cls.get(key)
    if items:
        if isinstance(items, dict):
            items.update(data)
        elif isinstance(items, list):
            items.extend(data)


@classmethod
def _build_tree(cls, node, show_pk=True, max_depth=None, follow_links=(),
    depth=0):
    """Return string with tree."""
    if max_depth is not None and depth > max_depth:
        return None
    children = []
    for entry in sorted(node.get_outgoing(link_type=follow_links).all(),
        key=cls._ctime):
        child_str = cls._build_tree(entry.node, show_pk, follow_links=
            follow_links, max_depth=max_depth, depth=depth + 1)
        if child_str:
            children.append(child_str)
    out_values = []
    if children:
        out_values.append('(')
        out_values.append(', '.join(children))
        out_values.append(')')
    lab = node.__class__.__name__
    if show_pk:
        lab += ' [{}]'.format(node.pk)
    out_values.append(lab)
    return ''.join(out_values)


def _donothing_func(*args, **kwargs):
    """Perform no good and no bad"""
    pass


def format_uptime(uptime_in_seconds):
    """Format number of seconds into human-readable string.

    :param uptime_in_seconds: The server uptime in seconds.
    :returns: A human-readable string representing the uptime.

    >>> uptime = format_uptime('56892')
    >>> print(uptime)
    15 hours 48 min 12 sec
    """
    m, s = divmod(int(uptime_in_seconds), 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    uptime_values = []
    for value, unit in ((d, 'days'), (h, 'hours'), (m, 'min'), (s, 'sec')):
        if value == 0 and not uptime_values:
            continue
        elif value == 1 and unit.endswith('s'):
            unit = unit[:-1]
        uptime_values.append('{0} {1}'.format(value, unit))
    uptime = ' '.join(uptime_values)
    return uptime


def show_sketch(sketchnum, wantscroll, zoompercent, pwindow):
    """
    Use this function to display a model diagram

    currently not implemented
    """
    raise NotImplementedError


@staticmethod
def _get_parent_path_and_child_name(path):
    """Split the path into the parent path and child name.

        For instance, "/a/b/c" -> ("/a/b", "c")
        :param path: the path to split
        :type path: six.string_types
        :return: a tuple in the form (parent path, child name)
        :type: tuple
        """
    last_slash = path.rfind('/')
    parent_path = path[:last_slash]
    child_name = path[last_slash + 1:]
    return parent_path, child_name


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


def _parse_percent(perc):
    """Parse percentile"""
    return float(perc[:-1]) / 100


def within(shape, *bounds, **bounds_map):
    """Build a ``$within`` query.

    This is a convenience function for ``$within`` queries.

    :param shape: The shape of the bounding area.
    :type shape: str.
    :param \\*bounds: Coordinate pairs defining the bounding area.
    :type \\*bounds: \\*args.
    :param \\*\\*bounds_map: Named coordinate pairs defining the bounding area.
    :type \\*\\*bounds_map: \\*\\*kwargs.
    :returns: dict -- the ``$within`` query.
    :raises: :class:`RuntimeError`.

    """
    if bounds and bounds_map:
        raise RuntimeError(
            "Only one of 'bounds' and 'bounds_map' can be provided.")
    bounds = bounds_map or list(bounds)
    query = {'$within': {'${0}'.format(shape): bounds}}
    return query


def collect_filtered(function, iterable, filtered):
    """
    Similar to :func:`filter` but collects filtered elements in ``filtered``.

    Args:
        function (callable): function that returns ``False`` for elements that
            should be filtered
        iterable (iterable): iterable to filter
        filtered (list): list to store filtered elements
    """
    for el in iterable:
        if function(el):
            yield el
        else:
            filtered.append(el)


def _dryrun(submit, returnStdout, returnStderr, returnExitcode, *args):
    """Used by the :func:`run` function when the :attr:`DRY_RUN` flag is
    active.
    """
    if submit:
        return '0',
    results = []
    stderr = ''
    stdout = ' '.join(args)
    if returnStdout:
        results.append(stdout)
    if returnStderr:
        results.append(stderr)
    if returnExitcode:
        results.append(0)
    if len(results) == 1:
        return results[0]
    else:
        return tuple(results)


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 formula_2012_01_01(foyer_fiscal, period, parameters):
    """
        Investissements OUTRE-MER dans le secteur du logement et autres secteurs d’activité
        2012
        TODO: Plafonnement sur la notice
        """
    f7qb = foyer_fiscal('f7qb', period)
    f7qc = foyer_fiscal('f7qc', period)
    f7qd = foyer_fiscal('f7qd', period)
    f7ql = foyer_fiscal('f7ql', period)
    f7qm = foyer_fiscal('f7qm_2012', period)
    f7qt = foyer_fiscal('f7qt_2012', period)
    f7oa = foyer_fiscal('f7oa', period)
    f7ob = foyer_fiscal('f7ob', period)
    f7oc = foyer_fiscal('f7oc', period)
    f7oh = foyer_fiscal('f7oh', period)
    f7oi = foyer_fiscal('f7oi', period)
    f7oj = foyer_fiscal('f7oj', period)
    f7ok = foyer_fiscal('f7ok', period)
    f7ol = foyer_fiscal('f7ol', period)
    f7om = foyer_fiscal('f7om', period)
    f7on = foyer_fiscal('f7on', period)
    f7oo = foyer_fiscal('f7oo', period)
    f7op = foyer_fiscal('f7op_2012', period)
    f7oq = foyer_fiscal('f7oq_2012', period)
    f7or = foyer_fiscal('f7or_2012', period)
    f7os = foyer_fiscal('f7os_2012', period)
    f7ot = foyer_fiscal('f7ot', period)
    f7ou = foyer_fiscal('f7ou', period)
    f7ov = foyer_fiscal('f7ov', period)
    f7ow = foyer_fiscal('f7ow', period)
    return (f7qb + f7qc + f7qd + f7ql + f7qm + f7qt + f7oa + f7ob + f7oc +
        f7oh + f7oi + f7oj + f7ok + f7ol + f7om + f7on + f7oo + f7op + f7oq +
        f7or + f7os + f7ot + f7ou + f7ov + f7ow)


def set_text(text):
    """Set content of the file from the given string.
        """


def json():
    """Returns the form in json format"""


def strip_blank_lines(l):
    """Remove leading and trailing blank lines from a list of lines"""
    while l and not l[0].strip():
        del l[0]
    while l and not l[-1].strip():
        del l[-1]
    return l


@classmethod
def from_tiles(cls, tiles):
    """Compose raster from tiles. return GeoRaster."""
    raise NotImplementedError


def run_one_step_river(time_gap_sec, r_in_q_riv, r_p_rk, r_s_v_riv):
    """
    This function was written by Thibault Hallouin but is largely inspired by the work of Eva Mockler, namely for
    the work published in: Mockler, E., O’Loughlin, F., and Bruen, M.: Understanding hydrological flow paths in
    conceptual catchment models using uncertainty and sensitivity analysis, Computers & Geosciences, 90, 66–77,
    doi:10.1016/j.cageo.2015.08.015, 2016.

    River model * r_ *
    _ Hydrology
    ___ Inputs * in_ *
    _____ r_in_q_riv      flow at inlet [m3/s]
    ___ Parameters * p_ *
    _____ r_p_rk          linear factor k for water where Storage = k.Flow [hours]
    ___ States * s_ *
    _____ r_s_v_riv       volume of water in store [m3]
    ___ Outputs * out_ *
    _____ r_out_q_riv     flow at outlet [m3/s]
    """
    r_p_rk *= 3600.0
    r_out_q_riv = r_s_v_riv / r_p_rk
    r_s_v_h2o_old = r_s_v_riv
    r_s_v_h2o_temp = r_s_v_h2o_old + (r_in_q_riv - r_out_q_riv) * time_gap_sec
    if r_s_v_h2o_temp < 0.0:
        r_out_q_riv = 0.95 * (r_in_q_riv + r_s_v_h2o_old / time_gap_sec)
        r_s_v_riv += (r_in_q_riv - r_out_q_riv) * time_gap_sec
    else:
        r_s_v_riv = r_s_v_h2o_temp
    return r_out_q_riv, r_s_v_riv


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


@staticmethod
def ensure_snippet(snippet, piece_id, part_id, conn, cursor):
    """
        Ensure the given snippet is included
            :param snippet: Snippet instance to store
            :param piece_id: Id of source piece
            :param part_id: Id of source part
            :param conn: Connection to sqlite instance
            :param cursor: Cursor to use
        """
    cursor.execute(
        'SELECT id FROM snippets WHERE piece_id=? AND part_id=? AND offset=?',
        (piece_id, part_id, snippet.offset))
    results = cursor.fetchall()
    if results:
        return results[0][0]
    cursor.execute(
        'INSERT INTO snippets (piece_id, part_id, offset) VALUES (?, ?, ?)',
        (piece_id, part_id, snippet.offset))
    conn.commit()
    return cursor.lastrowid


def set_conversion(this_converter):
    """
    Set conversion rules in the conversion module.
    :param this_converter: The conversion rules
    :type this_converter: :class:`Converter`
    """
    global converter, py2ri, py2ro, ri2ro, ri2py
    converter = this_converter
    py2ri = converter.py2ri
    py2ro = converter.py2ro
    ri2ro = converter.ri2ro
    ri2py = converter.ri2py


def exact_log2(number):
    """Find and return an unsigned integer i >= 0 such that ``number == 2**i``. If
  no such integer exists, this function raises ValueError.

  .. NOTE:
      It essentially answers this question:

      "How many times would you have to multiply 2 into itself to
      get the given number?"

  Taken from PyCrypto.

  :param number:
      Unsigned integer.
  :returns:
      An integer i >= 0 such that number == 2**i.
  """
    num = number
    if num <= 0:
        raise ValueError('Cannot compute logarithm of non-positive integer')
    i = 0
    while num:
        if num & 1 and num != 1:
            raise ValueError('No solution could be found')
        i += 1
        num >>= 1
    i -= 1
    return i


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

        :param str val:
        :rtype: AddSecondaryEmailResult
        """
    return cls('unknown_error', val)


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 SHL(cpu, dest, src):
    """
        The shift logical left.

        The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation.

        :param cpu: current cpu.
        :param dest: destination operand.
        :param src: source operand.
        """
    return cpu.SAL(dest, src)


def get_temp_file_path(file_path):
    """
    Generates a temporary filename.

    :param str file_path: file path prefix
    :returns: appended file path
    :rtype: str
    """
    return file_path + '.tmp'


def drift(data, n=3, **kwargs):
    """The drift forecast for the next point is a linear extrapolation from the previous ``n``
    points in the series.

    Args:
        data (np.array): Observed data, presumed to be ordered in time.
        n (int): period over which to calculate linear model for extrapolation

    Returns:
        float: a single-valued forecast for the next value in the series.
    """
    yi = data[-n]
    yf = data[-1]
    slope = (yf - yi) / (n - 1)
    forecast = yf + slope
    return forecast


@classmethod
def create(cls, *args, **kwargs):
    """
        Инстанцирование класса
        """
    return cls(*args, **kwargs)


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 __toarray(X):
    """ Converts DataFrames to numpy arrays.
    """
    if hasattr(X, 'values'):
        X = X.values
    return X


def entity_to_props(entity):
    """Converts a Datastore Entity into props

    Converts a ndb.Model Entity into its props form. The props form
    contains all of the properties within the entity as a dict. The props
    form also contains a 'kind' that points to the string form
    of the matching class. The `props` form also contains a 'key'
    that contains the entity.key() object.
    """
    d = entity.to_dict()
    if entity.key:
        d['key'] = entity.key
    d['kind'] = entity._get_kind()
    return d


def get_cell_parameters(line):
    """Identify cell parameters from line.

    Read the cell parameters from an appropriate line

    Parameters
    ----------
    line: str
        Line from pdb file.

    Returns
    -------
    array_like float
        the a, b, c cell vectors of the particular timestep
    """
    return [float(line[6:15]), float(line[15:24]), float(line[24:33])]


def _row_to_key(row):
    """
    Ensure the row is lowercase.
    """
    return str(row).lower()


def get_nodeid_full_path(item):
    """Assemble nodeid with full file path."""
    return '{}::{}'.format(str(item.fspath), item.location[2].replace('.',
        '::'))


@classmethod
def from_msg_to_dict(cls, msg):
    """Convert pylint output to a dict.

        From the output of pylint msg, to a dict, where each key
        is a unique error identifier, value is a list of LintOutput
        """
    result = {}
    for line in msg.splitlines():
        obj = cls.from_line(line)
        if obj is None or obj.is_ignored():
            continue
        key = obj.key()
        if key not in result:
            result[key] = []
        result[key].append(obj)
    return result


def __init__(config: dict):
    """
        This should handle configuration (auth, etc.) and set up the
        metadata db connection
        """
    pass


@classmethod
def cql_parameterized_type(cls):
    """
        There is no CQL notation for Composites, so we override this.
        """
    typestring = cls.cass_parameterized_type(full=True)
    return "'%s'" % (typestring,)


def set_footer(embed: 'discord.Embed', client_user=None):
    """
    Set a "Powered by Chicken Nuggets" footer on the given embed.

    Args:
       embed: Embed to add the footer to
       client_user: ``ClientUser`` whose avatar will be added to the footer
    """
    if client_user is None:
        embed.set_footer(text='Powered by Chicken Nuggets')
    else:
        embed.set_footer(text='Powered by Chicken Nuggets', icon_url=
            client_user.avatar_url)


def _internal_ion_fraction_field(field, data):
    """
    Creates the function for a derived field for following the ion_fraction
    of an ion over a dataset when the number density and nuclei_density for
    that field are already defined on disk.  Example: H I ion fraction is
    H I number density / H number density from on-disk fields.
    """
    if isinstance(field.name, tuple):
        ftype = field.name[0]
        field_name = field.name[1]
    else:
        ftype = 'gas'
        field_name = field.name
    field_array = field_name.split('_')
    if len(field_array) == 3:
        ion = field_array[0]
    else:
        ion = '_'.join(field_array[:2])
    atom = field_array[0]
    return data[ftype, '%s_number_density' % ion] / data[ftype,
        '%s_nuclei_density' % atom]


def encode(params, ignoreNoneValues=True):
    """Encode dict of p_params as a string of parameters ready to be
       incorporated into an URL. If p_ignoreNoneValues is True, every entry
       whose value is None is ignored."""
    if not params:
        return params
    r = []
    for name, value in params.items():
        if ignoreNoneValues and value is None:
            continue
        value = value if isinstance(value, str) else str(value)
        r.append('%s=%s' % (name, value))
    return '&'.join(r)


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

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

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


@classmethod
def daikin_to_human(cls, dimension, value):
    """Return converted values from Daikin to Human."""
    return cls.TRANSLATIONS.get(dimension, {}).get(value, str(value))


def getToplevelMessages(start=None, end=None, recent_first=True):
    """Get a list of proxies for all messages that are at the top of a
           thread in order by date, optionally restricted to a specific date
           range and/or sorted by the most recently responded to message."""


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

        :param UserSelectorArg val:
        :rtype: UserAddResult
        """
    return cls('placeholder_user', val)


def cAddVec():
    """
    Return the kernel source for cAddVec.
    """
    R = """
        KERNEL void cAddVec(
        GLOBAL_MEM float2 *a,
        GLOBAL_MEM float2 *b,
        GLOBAL_MEM float2 *dest)
        {const int i = get_global_id(0);
        dest[i]= a[i]+b[i];
        };"""
    return R


def psi_K_CO3_HSO4_HMW84(T, P):
    """c-a-a': potassium carbonate bisulfate [HMW84]."""
    psi = 0.0
    valid = T == 298.15
    return psi, valid


@staticmethod
def get_orbi(data, system):
    """Переменные: data - словарь, собранный из данных filename, system - имя объекта Предназначение: Осуществляет поиск в словаре объекта с именем system."""
    return data.get(system)


def as_list(val):
    """
    Helper function, always returns a list of the input value.

    :param val: the input value.
    :returns: the input value as a list.

    :Example:

    >>> as_list('test')
    ['test']

    >>> as_list(['test1', 'test2'])
    ['test1', 'test2']
    """
    treat_single_value = str
    if isinstance(val, treat_single_value):
        return [val]
    if hasattr(val, '__iter__'):
        return list(val)
    return [val]


def set_default_asset_dest_dir(dest_dir):
    """Set the default destination to copy assets to."""
    global _DEFAULT_ASSET_DEST_DIR
    _DEFAULT_ASSET_DEST_DIR = dest_dir


def sub_section():
    """ subtracts which section so not to overflow """
    global _SECTION
    _SECTION -= 1


def validate_image_col_row(image, col, row):
    """Basic checks for columns and rows values"""
    SPLIT_LIMIT = 99
    try:
        col = int(col)
        row = int(row)
    except:
        raise ValueError(
            'columns and rows values could not be cast to integer.')
    if col < 2:
        raise ValueError(
            'Number of columns must be between 2 and {} (you                           asked for {}).'
            .format(SPLIT_LIMIT, col))
    if row < 2:
        raise ValueError(
            'Number of rows must be between 2 and {} (you                           asked for {}).'
            .format(SPLIT_LIMIT, row))


def process(terms):
    """ Transform each term in terms.

        Return the sequence of transformed terms.
        """


def extract_docstring_summary(docstring):
    """Get the first summary sentence from a docstring.

    Parameters
    ----------
    docstring : `list` of `str`
        Output from `get_docstring`.

    Returns
    -------
    summary : `str`
        The plain-text summary sentence from the docstring.
    """
    summary_lines = []
    for line in docstring:
        if line == '':
            break
        else:
            summary_lines.append(line)
    return ' '.join(summary_lines)


def addToLeft(start, end, strand, chromosomelength, length=20):
    """ adds a specific length to the 5'end of a gene """
    if strand == '+':
        start -= length
        if start <= 0:
            start = 1
    else:
        end += length
        if end > chromosomelength:
            end = chromosomelength
    return start, end


def validate_image(image, number_tiles):
    """Basic sanity checks prior to performing a split."""
    TILE_LIMIT = 99 * 99
    try:
        number_tiles = int(number_tiles)
    except:
        raise ValueError('number_tiles could not be cast to integer.')
    if number_tiles > TILE_LIMIT or number_tiles < 2:
        raise ValueError(
            'Number of tiles must be between 2 and {} (you                           asked for {}).'
            .format(TILE_LIMIT, number_tiles))


@staticmethod
def parent(i):
    """
        Parent will be at math.floor((i - 1) / 2). Since integer division,
        in Python, simulates the floor function, we do not explicity use it
        because the answer will already be rounded down.

        @param i: The index of the node from which the parent index should be calculated.
        @type: C{int}
        @return: The parent index of the node i.
        @rtype: C{int}
        """
    return (i - 1) / 2


@classmethod
def dark_green(cls):
    """A factory method that returns a :class:`Colour` with a value of ``0x1f8b4c``."""
    return cls(2067276)


def latlon_xyz(latitude, longitude, depth, latitude_0, longitude_0,
    latitude_1, latitude_2):
    """Converts latitude and longitude into x y z

    Uses pyproj abd lambert projection to convert the coordinates using a given origin.

    Args
        latitude: float latitude in degrees
        longitude: float longitude in degrees
        depth: float depth in km
        latitude_0: float latitude of origin in degrees
        longitude_0: float longitude of origin in degrees
        latitude_1: float latitude of first standard parallel in degrees
        latitude_2: float latitude of second standard parallel in degrees

    Returns
        (float,float,float): tuple of x, y, z coordinates in km from latitude_0 and longitude_0 origin
    """
    from pyproj import Proj
    p = Proj('+proj=lcc +lat_0=' + str(latitude_0) + ' +lon_0=' + str(
        longitude_0) + ' +lat_1=' + str(latitude_1) + ' +lat_2=' + str(
        latitude_2), ellps='WGS84')
    [x_0, y_0] = p(float(longitude_0), float(latitude_0))
    [x, y] = p(longitude, latitude)
    return (x - x_0) / 1000.0, (y - y_0) / 1000.0, depth


def turbulent_Friend_Metzner(Re, Pr, fd):
    """Calculates internal convection Nusselt number for turbulent flows
    in pipe according to [2]_ as in [1]_.

    .. math::
        Nu = \\frac{(f/8)RePr}{1.2 + 11.8(f/8)^{0.5}(Pr-1)Pr^{-1/3}}

    Parameters
    ----------
    Re : float
        Reynolds number, [-]
    Pr : float
        Prandtl number, [-]
    fd : float
        Darcy friction factor [-]

    Returns
    -------
    Nu : float
        Nusselt number, [-]

    Notes
    -----
    Range according to [1]_ 50 < Pr ≤ 600  and 5*10^4 ≤ Re ≤ 5*10^6.
    The extreme limits on range should be considered!

    Examples
    --------
    >>> turbulent_Friend_Metzner(Re=1E5, Pr=100., fd=0.0185)
    1738.3356262055322

    References
    ----------
    .. [1] Rohsenow, Warren and James Hartnett and Young Cho. Handbook of Heat
       Transfer, 3E. New York: McGraw-Hill, 1998.
    .. [2] Friend, W. L., and A. B. Metzner. “Turbulent Heat Transfer inside
       Tubes and the Analogy among Heat, Mass, and Momentum Transfer.” AIChE
       Journal 4, no. 4 (December 1, 1958): 393-402. doi:10.1002/aic.690040404.
    """
    return fd / 8.0 * Re * Pr / (1.2 + 11.8 * (fd / 8.0) ** 0.5 * (Pr - 1.0
        ) * Pr ** (-1 / 3.0))


@staticmethod
def is_subclass(class_: type, super_class):
    """判断 obj 是否是 cls 的子类"""
    if not class_:
        return False
    if not isinstance(class_, type):
        class_ = type(class_)
    if class_ is super_class:
        return True
    return issubclass(class_, super_class)


@staticmethod
def paired_idx(idx):
    """
        Return the paired index

        Snapshots are stored in pairs (2n, 2n+1) where one is the reversed copy.
        This make storing CVs easier. This function allows to get the paired
        index or the index of snapshot.reversed

        The implementation uses the trick that all you have to do is flip the
        lowest bit that determines even or odd.

        Parameters
        ----------
        idx : int
            the one part of the paired index

        Returns
        -------
        int
            the other part of the paired index
        """
    return idx ^ 1


@classmethod
def getdiag(cls, data):
    """Returns diagonals of matrix """
    raise NotImplementedError


def addHandler(button, handler):
    """Add a new handler for a button."""


def str2bool(v):
    """ Convert string to a boolean value.
    References
    ----------
    https://stackoverflow.com/questions/715417/converting-from-a-string-to-boolean-in-python/715468#715468
    """
    return str(v).lower() in ('yes', 'true', 't', '1')


def get_contact_reachability_status(domainName=None):
    """
    For operations that require confirmation that the email address for the registrant contact is valid, such as registering a new domain, this operation returns information about whether the registrant contact has responded.
    If you want us to resend the email, use the ResendContactReachabilityEmail operation.
    See also: AWS API Documentation

    :example: response = client.get_contact_reachability_status(
        domainName='string'
    )

    :type domainName: string
    :param domainName: The name of the domain for which you want to know whether the registrant contact has confirmed that the email address is valid.

    :rtype: dict
    :return: {
        'domainName': 'string',
        'status': 'PENDING'|'DONE'|'EXPIRED'
    }

    """
    pass


def methods_equivalent(meth1, meth2):
    """Return True if the two methods are the same implementation."""
    return getattr(meth1, '__func__', meth1) is getattr(meth2, '__func__',
        meth2)


def _docstring():
    """Just an empty function with a docstring."""


def error_library_not_loaded(record):
    """Look in a record (output from program) for signs that this died
    due to a missing library."""
    if 'dyld: Library not loaded' in record:
        raise RuntimeError(record)


def actuator_remove(actuator: str='', object: str=''):
    """Remove an actuator from the active object

    :param actuator: Actuator, Name of the actuator to edit
    :type actuator: str
    :param object: Object, Name of the object the actuator belongs to
    :type object: str
    """
    pass


def list_to_tuple(x):
    """ Make tuples out of lists and sets to allow hashing """
    if isinstance(x, list) or isinstance(x, set):
        return tuple(x)
    else:
        return x


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

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

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


def build_node(type: str, name: str, content: str) ->str:
    """
    Wrap up content in to a html node.

    :param type: content type (e.g., doc, section, text, figure)
    :type path: str
    :param name: content name (e.g., the name of the section)
    :type path: str
    :param name: actual content
    :type path: str
    :return: new String with content in html format
    """
    if type == 'doc':
        return f'{content}'
    if type == 'section':
        return f"
{content}
"
    if type == 'text':
        return f"
{content}
"
    if type == 'figure':
        return f""
    raise RuntimeError(f'unknown type')


def get_ckan_error(response):
    """Return the error from a ckan json response, or None."""
    ckan_error = None
    try:
        if not response['success'] and response['error']:
            ckan_error = response['error']
    except TypeError:
        ckan_error = response
    return ckan_error


def raise_expected_got(expected, for_, got, error_type=ValueError):
    """Raise a standardized error message.

    Raise an `error_type` error with the message
        Expected `expected` for `for_`; got `got` instead.
    Or, if `for_` is `None`,
        Expected `expected`; got `got` instead.

    """
    if for_ is not None:
        raise error_type('Expected {} for {}; got {} instead.'.format(
            expected, for_, got))
    else:
        raise error_type('Expected {}; got {} instead.'.format(expected, got))


def collection_hide():
    """Hide the collection in this view layer

    """
    pass


def dimReduction_filter(sel, feature_train, label_train, feature_test,
    p_thrd=0.05):
    """
        This function is used to Univariate Feature Selection:: ANOVA
        """
    from sklearn.feature_selection import f_classif
    f, p = f_classif(feature_train, label_train)
    mask_selected = p < p_thrd
    feature_train = feature_train[:, (mask_selected)]
    feature_test = feature_test[:, (mask_selected)]
    return feature_train, feature_test, mask_selected


def _mobile_str_as_bool(mobile_str):
    """Try converting to an int-bool."""
    return bool(int(mobile_str))


@staticmethod
def add_node_information(graph, key, data):
    """
        Add other information to nodes other than weights for the edges. This
        will be an added key to the dictionary that contains the default graph
        information.

        Parameters
        ----------
        graph : nx.classes.graph.Graph or nx.classes.digraph.DiGraph
            The graph which you would like to add extra information to at
            each node.
        key : str
            The key name of the information you want add.
        data : np.ndarray
            A 2x2 array that utilizes the row x col numbering of the node values
            to allow for easy transcribing of information from the array to the
            the graph node.

        Returns
        -------
        graph : nx.classes.graph.Graph or nx.classes.digraph.DiGraph
            The graph that was passed to the function but now with the
            information desired at each node.

        """
    for node in graph.nodes():
        graph[node][key] = data[node[0], node[1]]
    return graph


def findSourceTokens(source, maxDepth=1, filter=None):
    """As findSources, but returns tokens rather than the objects"""


def compute_redundancy_score(stats, col_name):
    """
    # Attempts to determine the redundancy of the column by taking into account correlation and
    similarity with other columns

    :param stats: The stats extracted up until this point for all columns
    :param col_name: The name of the column we should compute the new stats for
    :return: Dictioanry containing:
        consistency_score: The socre, ranges from 1 to 0, where 1 is lowest quality and 0 is highest quality
    """
    col_stats = stats[col_name]
    redundancy_score = col_stats['similarity_score'] / 1
    return {'redundancy_score': redundancy_score,
        'redundancy_score_description':
        """
        A high value in this score indicates the data in this column is highly redundant for making any sort of prediction, you should make sure that values heavily related to this column are not already expressed in another column (e.g. if this column is a timestamp, make sure you don't have another column representing the exact same time in ISO datetime format).
        The value is based in equal part on the Similarity Score and the Correlation Score.
        """
        }


@staticmethod
def _build_tree(nodes):
    """Builds the tree (forest) data structure based on the list of nodes.

       Tree building works in O(n*log(n)).

       :param nodes: dict of nodes, where each node is a dictionary with fields
                     "parent_id", "trace_id", "info"
       :returns: list of top level ("root") nodes in form of dictionaries,
                 each containing the "info" and "children" fields, where
                 "children" is the list of child nodes ("children" will be
                 empty for leafs)
       """
    tree = []
    for trace_id in nodes:
        node = nodes[trace_id]
        node.setdefault('children', [])
        parent_id = node['parent_id']
        if parent_id in nodes:
            nodes[parent_id].setdefault('children', [])
            nodes[parent_id]['children'].append(node)
        else:
            tree.append(node)
    for trace_id in nodes:
        nodes[trace_id]['children'].sort(key=lambda x: x['info']['started'])
    return sorted(tree, key=lambda x: x['info']['started'])


def get_service_type(f):
    """Retrieves service type from function."""
    return getattr(f, 'service_type', None)


def identify_max_speed_velocity_ratio(velocities, engine_speeds_out,
    idle_engine_speed, stop_velocity):
    """
    Identifies the maximum speed velocity ratio of the gear box [h*RPM/km].

    :param velocities:
        Vehicle velocity [km/h].
    :type velocities: numpy.array

    :param engine_speeds_out:
        Engine speed [RPM].
    :type engine_speeds_out: numpy.array

    :param idle_engine_speed:
        Engine speed idle median and std [RPM].
    :type idle_engine_speed: (float, float)

    :param stop_velocity:
        Maximum velocity to consider the vehicle stopped [km/h].
    :type stop_velocity: float

    :return:
        Maximum speed velocity ratio of the gear box [h*RPM/km].
    :rtype: float
    """
    b = velocities > stop_velocity
    b &= engine_speeds_out > idle_engine_speed[0]
    return max(engine_speeds_out[b] / velocities[b])


def expected(typ, val=None):
    """
    Return an indication of expected input and the position where it was
    expected and not encountered.
    """
    return [('expected', typ, val)]


def layer_option(option, opt, value, parser):
    """
    Callback for `make_option` for the `ogrinspect` `layer_key`
    keyword option which may be an integer or a string.
    """
    try:
        dest = int(value)
    except ValueError:
        dest = value
    setattr(parser.values, option.dest, dest)


def _try_award_special_answer(post, badge, votes_required):
    """Helper for nice and good answer."""
    pid = str(post.id)
    user = post.author
    for user_badge in user._badges:
        if user_badge.badge == badge and user_badge.payload == pid:
            return
    if post.is_answer and post.votes >= votes_required:
        return user, pid


@classmethod
def worldXY(cls):
    """Construct the world XY frame.

        Returns
        -------
        :class:`compas.geometry.Frame`
            The world XY frame.

        Examples
        --------
        >>> frame = Frame.worldXY()
        >>> frame.point
        Point(0.000, 0.000, 0.000)
        >>> frame.xaxis
        Vector(1.000, 0.000, 0.000)
        >>> frame.yaxis
        Vector(0.000, 1.000, 0.000)
        """
    return cls([0, 0, 0], [1, 0, 0], [0, 1, 0])


def _get_value_for_type(type_value, value):
    """ Return the Value depending on the Type """
    if type_value == bool:
        if value.lower() in ['true', '1']:
            return True
        if value.lower() in ['false', '0']:
            return False
        mess = "Waiting for a boolean but value is '%s'." % value
        raise Exception(mess)
    if type_value == list:
        return value.split(' ')
    return value


def _next_pow_two(n):
    """Returns the next power of two greater than or equal to `n`"""
    i = 1
    while i < n:
        i = i << 1
    return i


@classmethod
def _construct(cls):
    """
        Constructor that returns the fluid and flet pair for a dynamic scope
        manager.
        """
    o = cls()
    return o, o._flet


def build_index():
    """Builds index.html given a set of inputs"""
    pass


@classmethod
def rudin_shapiro(cls, n, **kwargs):
    """
        Return the output of :meth:`mvpoly.cube.MVPolyCube.rudin_shapiro`
        converted to other polynomial subclasess.
        """
    from mvpoly.cube import MVPolyCube
    return cls(MVPolyCube.rudin_shapiro(n, **kwargs), **kwargs)


def box(text: str, lang: str='') ->str:
    """Get the given text in a code block.

    Parameters
    ----------
    text : str
        The text to be marked up.
    lang : `str`, optional
        The syntax highlighting language for the codeblock.

    Returns
    -------
    str
        The marked up text.

    """
    ret = '```{}\n{}\n```'.format(lang, text)
    return ret


def smart_map(func, i, *args, **kwargs):
    """
    将单个对象或列表中的每个项传入给定的函数，并返回单个结果或列表结果，类似于 map 函数

    :param func: 传入到的函数
    :param i: 列表或单个对象
    :param args: func 函数所需的 args
    :param kwargs: func 函数所需的 kwargs
    :return: 若传入的为列表，则以列表返回每个结果，反之为单个结果
    """
    if isinstance(i, (list, tuple, set)):
        return list(map(lambda x: func(x, *args, **kwargs), i))
    else:
        return func(i, *args, **kwargs)


@staticmethod
def __get_clusters(compute_environments):
    """
        Parse computeEnvironments object and return a list of ecsClusterArn.

        :param compute_environments: a list of Compute Environments
        :return: a list of ECS clusters
        """
    ecs_clusters = []
    for compute_env in compute_environments:
        ecs_clusters.append(compute_env['ecsClusterArn'])
    return ecs_clusters


@staticmethod
def get_request_id(saved_game_proto, phase_ix, power_name, is_validation_set):
    """ Returns the standardized request id for this game/phase """
    return '%s/%s/%d/%s/%s' % ('train' if not is_validation_set else
        'valid', saved_game_proto.id, phase_ix, saved_game_proto.phases[
        phase_ix].name, power_name)


def factory_key(item):
    """Helper for topological sort of factories.

    :param item: a ``name, factory`` tuple to generate the key for.
    :return: iterable of ``name, factory`` tuples that factory in item
      depends on for construction.
    """
    name, factory = item
    arguments = getattr(factory, 'factory_arguments', None)
    if arguments is None:
        return []
    return arguments.items()


def prune_to_peaks(det_obj2_d_raw, det_matrix, num_doppler_bins,
    reserve_neighbor=False):
    """Reduce the CFAR detected output to local peaks.

    Reduce the detected output to local peaks. If reserveNeighbor is toggled, will also return the larger neighbor. For
    example, given an array [2, 1, 5, 3, 2], default method will return [2, 5] while reserve neighbor will return
    [2, 5, 3]. The neighbor has to be a larger neighbor of the two immediate ones and also be part of the peak. the 1st
    element "1" in the example is not returned because it's smaller than both sides so that it is not part of the peak.

    Args:
        det_obj2_d_raw (np.ndarray): The detected objects structured array which contains the range_idx, doppler_idx,
         peakVal and SNR, etc.
        det_matrix (np.ndarray): Output of doppler FFT with virtual antenna dimensions reduced. It has the shape of
            (num_range_bins, num_doppler_bins).
        num_doppler_bins (int): Number of doppler bins.
        reserve_neighbor (boolean): if toggled, will return both peaks and the larger neighbors.

    Returns:
        cfar_det_obj_index_pruned (np.ndarray): Pruned version of cfar_det_obj_index.
        cfar_det_obj_SNR_pruned (np.ndarray): Pruned version of cfar_det_obj_SNR.
    """
    range_idx = det_obj2_d_raw['rangeIdx']
    doppler_idx = det_obj2_d_raw['dopplerIdx']
    next_idx = doppler_idx + 1
    next_idx[doppler_idx == num_doppler_bins - 1] = 0
    prev_idx = doppler_idx - 1
    prev_idx[doppler_idx == 0] = num_doppler_bins - 1
    prev_val = det_matrix[range_idx, prev_idx]
    current_val = det_matrix[range_idx, doppler_idx]
    next_val = det_matrix[range_idx, next_idx]
    if reserve_neighbor:
        next_next_idx = next_idx + 1
        next_next_idx[next_idx == num_doppler_bins - 1] = 0
        prev_prev_idx = prev_idx - 1
        prev_prev_idx[prev_idx == 0] = num_doppler_bins - 1
        prev_prev_val = det_matrix[range_idx, prev_prev_idx]
        next_next_val = det_matrix[range_idx, next_next_idx]
        is_neighbor_of_peak_next = (current_val > next_next_val) & (current_val
             > prev_val)
        is_neighbor_of_peak_prev = (current_val > prev_prev_val) & (current_val
             > next_val)
        pruned_idx = (current_val > prev_val) & (current_val > next_val
            ) | is_neighbor_of_peak_next | is_neighbor_of_peak_prev
    else:
        pruned_idx = (current_val > prev_val) & (current_val > next_val)
    det_obj2_d_pruned = det_obj2_d_raw[pruned_idx]
    return det_obj2_d_pruned


@classmethod
def load(cls, filename, schema_only=False):
    """
        Load an ARFF File from a file.
        """
    o = open(filename)
    s = o.read()
    a = cls.parse(s, schema_only=schema_only)
    if not schema_only:
        a._filename = filename
    o.close()
    return a


def pathify(path):
    """
    Convert file path from a/b/c syntax to a.b.c syntax
    """
    return path.replace('.py', '').replace('/', '.')


def _decode(geohash, max_coord):
    """Returns a tuple with the coord and the range of the boundary
    defined by the binary geohash."""
    coord = 0
    for c in geohash:
        max_coord /= 2
        coord = coord - max_coord if c == '0' else coord + max_coord
    return coord, max_coord * 2


def hide(unselected: bool=False):
    """Hide selected/unselected Grease Pencil layers

    :param unselected: Unselected, Hide unselected rather than selected layers
    :type unselected: bool
    """
    pass


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 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 unsorted_1d_segment_sum(input, seg_id, n_segs, dim):
    """Computes the sum along segments of a tensor.

    Equivalent to tf.unsorted_segment_sum, but seg_id is required to be a
    1D tensor.

    Parameters
    ----------
    input : Tensor
        The input tensor
    seg_id : 1D Tensor
        The segment IDs whose values are between 0 and n_segs - 1.  Should
        have the same length as input.
    n_segs : int
        Number of distinct segments
    dim : int
        Dimension to sum on

    Returns
    -------
    Tensor
        The result
    """
    pass


@staticmethod
def _print_placholders_in_slide(slide):
    """
        Mainly used for debugging.  Allows us to see what is in a slide which may help track down
        errors in trying to add new elements (e.g. Missing layouts or placholders)

        :param slide:
        :return:
        """
    for shape in slide.placeholders:
        print('%d %s' % (shape.placeholder_format.idx, shape.name))


def list_lambda_attached_secgroups(lambda_aws) ->list:
    """
    List security groups attached to Lambda functions
    """
    lambda_attached_groups = []
    boto_lambda = lambda_aws.list_functions()
    for lambda_obj in boto_lambda['Functions']:
        if 'VpcConfig' in lambda_obj:
            for security_group in lambda_obj['VpcConfig']['SecurityGroupIds']:
                lambda_attached_groups.append(security_group)
    return lambda_attached_groups


def choose_NT(N_max, iffreq=True):
    """ calculates number of time samples required to constrain N_max modes
        --- equation (21) from Sanders & Binney (2014) """
    if iffreq:
        return max(200, 9 * N_max ** 3 / 4)
    else:
        return max(100, N_max ** 3 / 2)


def _export_subcases(hdf5_file, op2_model):
    """exports the subcases to HDF5"""
    subcase_groups = {}
    result_types = op2_model.get_table_types()
    skip_results = ['params', 'gpdt', 'bgpdt', 'eqexin', 'psds']
    for result_type in result_types:
        if result_type in skip_results or result_type.startswith('responses.'):
            continue
        result = op2_model.get_result(result_type)
        if result is None:
            continue
        for key, obj in result.items():
            obj.object_attributes(filter_properties=True)
            subcase_name = 'Subcase=%s' % str(key)
            if '/' in subcase_name:
                name = obj.class_name
                op2_model.log.warning(
                    f"'/' in titles are not supported by HDF5 for {name}; changing to ';'"
                    )
                subcase_name = subcase_name.replace('/', ';')
            if subcase_name in subcase_groups:
                subcase_group = subcase_groups[subcase_name]
            else:
                subcase_group = hdf5_file.create_group(subcase_name)
                subcase_groups[subcase_name] = subcase_group
            result_name = result_type
            result_group = subcase_group.create_group(result_name)
            obj.export_to_hdf5(result_group, op2_model.log)


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 create_filters(filter_dict):
    """
    Converts a dict to a list of boto3 filters. The keys and value of the dict represent
    the Name and Values of a filter, respectively.
    """
    filters = []
    for key in filter_dict.keys():
        filters.append({'Name': key, 'Values': filter_dict[key]})
    return filters


def create_gaussian_prior_for(parameter, mean, std):
    """
	Use for informed variables.
	The Gaussian prior weights by a Gaussian in the parameter. If you
	would like the logarithm of the parameter to be weighted by
	a Gaussian, create a ancillary parameter (see create_jeffreys_prior_for).

	:param parameter: Parameter to create a prior for. E.g. xspowerlaw.mypowerlaw.PhoIndex

	"""
    from . import invgauss
    lo = parameter.min
    hi = parameter.max
    f = invgauss.get_invgauss_func(mean, std)
    return lambda x: max(lo, min(hi, f(x)))


def from_uuid(uuid):
    """Return the string representation of a UUID.

        :param uuid: The UUID to convert.
        :type uuid: UUID
        :return: The string representation of the UUID, as appropriate for the
            API version.  In 3.0 this is the representation of an integer,
            while in 3.1 it is the hex representation.
        :rtype: str
        """


def scroll_page_down(event):
    """
    Scroll page down. (Prefer the cursor at the top of the page, after scrolling.)
    """
    w = event.app.layout.current_window
    b = event.app.current_buffer
    if w and w.render_info:
        line_index = max(w.render_info.last_visible_line(), w.
            vertical_scroll + 1)
        w.vertical_scroll = line_index
        b.cursor_position = b.document.translate_row_col_to_index(line_index, 0
            )
        b.cursor_position += b.document.get_start_of_line_position(
            after_whitespace=True)


@staticmethod
def _string_to_bool(boolean_string):
    """Returns a boolean value of a boolean value string representation
        """
    if boolean_string.lower() == 'true':
        return True
    elif boolean_string.lower() == 'false':
        return False
    else:
        raise ValueError(msg=
            'Passed in boolean string was neither True or False: {0}'.
            format(boolean_string))


@classmethod
def _partition_lines(cls, line, cell):
    """
        Check the code for additional use of %%opts. Enables
        multi-line use of %%opts in a single call to the magic.
        """
    if cell is None:
        return line, cell
    specs, code = [line], []
    for line in cell.splitlines():
        if line.strip().startswith('%%opts'):
            specs.append(line.strip()[7:])
        else:
            code.append(line)
    return ' '.join(specs), '\n'.join(code)


def rgb2psychorgb(rgbgun):
    """Returns a converted RGB gun

    arguments
    rgbgun    -- a (R,G,B) or (R,G,B,A) tuple containing values between 0
               and 255; other values (e.g. 'red' or hex values) may be
               passed as well, but will be returned as they were
    returns
    psyrgb    -- a (R,G,B) tuple containing values between -1 and 1; or
               rgbgun when passed rgbgun was not a tuple or a list
    """
    if type(rgbgun) not in [tuple, list]:
        return rgbgun
    psyrgb = []
    for val in rgbgun:
        psyrgb.append(val / 127.5 - 1)
    return tuple(psyrgb[0:3])


def human_bytes(n):
    """
    Return the number of bytes n in more human readable form.
    """
    if n < 1024:
        return '%d B' % n
    k = n / 1024
    if k < 1024:
        return '%d KB' % round(k)
    m = k / 1024
    if m < 1024:
        return '%.1f MB' % m
    g = m / 1024
    return '%.2f GB' % g


def fsplit(pred, objs):
    """Split a list into two classes according to the predicate."""
    t = []
    f = []
    for obj in objs:
        if pred(obj):
            t.append(obj)
        else:
            f.append(obj)
    return t, f


def query(question, default_answer='', help=''):
    """Ask user a question

    :param question: question text to user
    :param default_answer: any default answering text string
    :param help:  help text string
    :return: stripped answer string
    """
    prompt_txt = '{question} [{default_answer}] '.format(question=question,
        default_answer=default_answer)
    while True:
        answer = input(prompt_txt).strip()
        if answer:
            if answer == '?':
                print(help)
                continue
            else:
                return answer
        else:
            return default_answer


def get_model_fullname(model):
    """
    gets the full name of the model.
    """
    return model.__module__ + '.' + model.__qualname__


def set(name, value):
    """Sets a variable to value

        :param name: string, variable name
        :param value: value of the key
        """


def get_port(socket):
    """Return the port to which a socket is bound."""
    addr, port = socket.getsockname()
    return port


def retrieve(scale, fieldname):
    """Grabs the thumb of the given field from its scale name
        """


def findRelationships(source=None, target=None, maxDepth=1, filter=None):
    """given source, target, or both, iterate over all relationship paths.

        maxDepth is the number of relationships through which the search
        should walk transitively.  It must be a positive integer.

        filter is an optional callable that takes a relationship and returns
        a boolean True value if it should be included, and a False if not.

        If a cycle is found, it is omitted by default.  if includeCycles is
        True, it returns the cycle in an ICircularRelationshipPath and then
        does not continue down the cycle.
        """


def eof():
    """
    Return an indication that the end of the input was reached.
    """
    return [('message', 'end of input')]


def time_complexities():
    """
    Return information on functions
    time complexity
    :return: string
    """
    return 'Time complexity: O(logn)'


def finish():
    """
        Indicate that the response to this request is complete.
        """


def symbol_is_pair(market_symbol: str, base_currency: str=None,
    quote_currency: str=None) ->bool:
    """
    Check if the market symbol is a pair, i.e. that its symbol consists of the base currency and the
    quote currency separated by '/' character. If base_currency and/or quote_currency is passed,
    it also checks that the symbol contains appropriate base and/or quote currency part before
    and after the separating character correspondingly.
    """
    symbol_parts = market_symbol.split('/')
    return len(symbol_parts) == 2 and (symbol_parts[0] == base_currency if
        base_currency else len(symbol_parts[0]) > 0) and (symbol_parts[1] ==
        quote_currency if quote_currency else len(symbol_parts[1]) > 0)


def srstrip(st, subst, require=False):
    """ Strip a substring `subst` from the left of `st` """
    if st.endswith(subst):
        return st[:len(subst)]
    if require:
        raise ValueError('st does not end with subst', st, subst)
    return st


def derive_tenant(url):
    """Derive tenant ID from host

    We consider the standard `subdomain.domain.com` structure to be the
    `tenant_id`.

    There might be multiple applications that are hosted for the subdomain,
    and they may have additional application identifiers at the beginning,
    like 'customers.subdomain.domain.com' or 'backoffice.subdomain.domain.com'.
    In all such cases, we still consider the 3 part structure,
     `subdomain.domain.com`, to be the `tenant_id`.

    """
    from urllib.parse import urlparse
    host = urlparse(url).hostname
    return host


def copy_python_command_button():
    """Copy the Python command matching this button

    """
    pass


def preprocess_display(x, transpose=(1, 2, 0), scale=255.0, offset=0.0):
    """Basic preprocessing that reshapes, transposes, and scales an image"""
    x = (x + offset) * scale
    if transpose is not None:
        x = x.transpose(transpose)
    if x.shape[-1] == 1:
        x = x[..., 0]
    return x.clip(0, 255).astype('uint8')


def find_uts_hlines(ndvar):
    """Find horizontal lines for uts plots (based on contours)

    Parameters
    ----------
    ndvar : NDVar
        Data to be plotted.

    Returns
    -------
    h_lines : iterator
        Iterator over (y, kwa) tuples.
    """
    contours = ndvar.info.get('contours', None)
    if contours:
        for level in sorted(contours):
            args = contours[level]
            if isinstance(args, dict):
                yield level, args.copy()
            else:
                yield level, {'color': args}


def _do_publish(client):
    """Internal function"""
    message = client._userdata.popleft()
    if isinstance(message, dict):
        client.publish(**message)
    elif isinstance(message, (tuple, list)):
        client.publish(*message)
    else:
        raise TypeError('message must be a dict, tuple, or list')


def get_chr_prefix(sam_file):
    """
    Check if chromosomes names contains "chr".
    :param sam_file: SAM file already opened for reading
    :return: chromosome prefix (either 'chr' or '')
    """
    prefix = ''
    for r in sam_file.fetch():
        if not r.is_unmapped:
            if 'chr' in r.reference_name:
                prefix = 'chr'
            else:
                prefix = ''
            break
    return prefix


def show_(*args, **kwargs):
    """show_('x', 'y', z='z') # print names & values of arguments
    values of args and kwargs are expressions to be evaluated in context of the caller
    values of args become names to be displayed
    names of kwargs become names to be displayed
    """
    import miscutils.insp as insp
    from peepshow.core import show as core
    from peepshow.utils import python as utils
    env = utils.caller_gloloc()
    if args or kwargs:
        names = [*args] + [*kwargs.keys()]
        exprs = [*args] + [*kwargs.values()]
        for expr in exprs:
            if not isinstance(expr, str):
                raise TypeError('Each expression must be a string.')
        values = [eval(expr, env.glo, env.loc) for expr in exprs]
    else:
        is_user_var = lambda item: not insp.isaccess(item[0]).special
        user_vars = filter(is_user_var, env.initial.items())
        names, values = zip(*user_vars)
    core.show(names, values)


def get_intersection(u, v, node_presence):
    """
    Get the intersection between the presence of u and v.

    :param u: First Node
    :param v: Second Node
    :param node_presence: Node presence
    :return: Interection
    """
    intersec = []
    for ut0, ut1 in zip(node_presence[u][::2], node_presence[u][1::2]):
        for vt0, vt1 in zip(node_presence[v][::2], node_presence[v][1::2]):
            if ut0 <= vt1 and vt0 <= ut1:
                intersec += [max(ut0, vt0), min(vt1, ut1)]
    return intersec


def _fixencoding(input, encoding, final=False):
    """
    Replace the name of the encoding in the charset rule at the beginning of
    ``input`` with ``encoding``. If ``input`` doesn't starts with a charset
    rule, ``input`` will be returned unmodified.

    If the encoding can't be found yet, ``None`` is returned. ``final``
    specifies whether more data will be available in later calls or not.
    If ``final`` is true, ``_fixencoding()`` will never return ``None``.
    """
    prefix = u'@charset "'
    if len(input) > len(prefix):
        if input.startswith(prefix):
            pos = input.find(u'"', len(prefix))
            if pos >= 0:
                if encoding.replace('_', '-').lower() == 'utf-8-sig':
                    encoding = u'utf-8'
                return prefix + encoding + input[pos:]
        else:
            return input
    elif not prefix.startswith(input) or final:
        return input
    if final:
        return input
    return None


def getbool(conf, key):
    """Emulation of scrapy.Settings;getbool.

    It allows the config to remain agnostic from Scrapy specificities. Not that
    it brings much to the table but that's really cheap to make it so.

    Examples:
        >>> getbool({}, 'foo')
        False
        >>> getbool({'foo': 'no'}, 'foo')
        False
        >>> getbool({'foo': 'yes'}, 'foo')
        True
        >>> getbool({'foo': 'True'}, 'foo')
        True

    """
    return conf.get(key) in [True, 'True', 'true', 'yes', 'y']


def cmd_abor(args):
    """Abort operation. No read access required.
        """


def rotate_to_fieldframe(mdf, yaw=None, pitch=None, roll=None):
    """ Rotates a mdf taken in the sensor basis (x', y', z') to another basis (x, y, z)
        by rotating the fields and the gradients accordingly """
    mdf_rot = mdf.deepcopy()
    mdf_rot.rotate_fields(yaw, pitch, roll)
    mdf_rot.rotate_grads_sensorframe(yaw, pitch, roll)
    return mdf_rot


def test_zoo(archive, compression, cmd, verbosity, interactive):
    """Test a ZOO archive."""
    return [cmd, '-test', archive]


def inverse_mod(a, p):
    """
    Compute the modular inverse of a (mod p)

    :param a:
        An integer

    :param p:
        An integer

    :return:
        An integer
    """
    if a < 0 or p <= a:
        a = a % p
    c, d = a, p
    uc, vc, ud, vd = 1, 0, 0, 1
    while c != 0:
        q, c, d = divmod(d, c) + (c,)
        uc, vc, ud, vd = ud - q * uc, vd - q * vc, uc, vc
    assert d == 1
    if ud > 0:
        return ud
    else:
        return ud + p


def _get_subnational2(node):
    """
    Get the county where the checklist was recorded.

    :param node: the Tag for the body of the Location section.

    :return: the name of the county.

    """
    tag = node.find('h5', class_='obs-loc')
    location = tag.text.split('( Map )')[0]
    county = location.split(',')[-3].strip()
    return county


def _authenticatedUserHasRole(caller, role, instance=None, shortcircuit=False):
    """ Returns true if current user has specified role """
    from AccessControl import getSecurityManager
    user = getSecurityManager().getUser()
    roles = user.getRoles()
    if shortcircuit == True and 'Manager' in roles:
        return True
    if instance:
        roles = user.getRolesInContext(instance)
    if isinstance(role, list):
        for r in role:
            if r in roles:
                return True
        return False
    return role in roles


def isMON_Ox_Blend(name):
    """
    check for MON oxidizer (MON1 to MON40)  48% is theoretical max
    MON15 and MON25 are in standard deck, however can make MON20, MON30 etc. "on-the-fly"
    """
    try:
        noPcent = float(name[3:])
    except:
        return 0
    if name[:3] in ['MON', 'mon']:
        if noPcent > 0.0 and noPcent < 40.0:
            return 1
    return 0


def clamp(lower, value, upper):
    """Given a value and lower/upper bounds, 'clamp' the value so that
    it satisfies lower <= value <= upper."""
    return max(lower, min(value, upper))


def loginfo(message):
    """
    Prefixes '[INFO]' to the message.

    :param message str: message to log.
    """
    print('[INFO ] ' + message)