def configureSet(request):
    """
        Called when a node configuration change request has been received.

        @param request: The publish-subscribe request.
        @type request: L{wokkel.pubsub.PubSubRequest}
        @return: A deferred that fires with C{None} when the node's
                 configuration has been changed.
        @rtype: L{Deferred<twisted.internet.defer.Deferred>}
        """


def display_arbre(villes, arbre, mult=1, screen=None, pygame=None):
    """
    dessine le graphe de poids minimal dꧩni par arbre
    """
    if mult == 2:
        color = 0, 255, 0
        li = 4
    else:
        li = 1
        color = 0, 0, 255
    for i in range(0, len(villes)):
        for j in arbre[i]:
            v = villes[i][0] * mult, villes[i][1] * mult
            vv = villes[j][0] * mult, villes[j][1] * mult
            pygame.draw.line(screen, color, v, vv, li)


def parse_metaconfig_line(line):
    """ Parses line and return key=value tuple """
    delimiter_pos = line.find('=')
    if delimiter_pos == -1:
        raise ValueError("'=' not found in metaconfig line " + line)
    var_name = line[:delimiter_pos].strip()
    if len(var_name) == 0:
        raise ValueError('variable name not found in metaconfig line ' + line)
    var_expr = line[delimiter_pos + 1:].strip()
    return var_name, var_expr


def value_from_dict(dict_name, key):
    """
    Get a value from a dictionary, return "" if not existing
    :param dict_name:
    :param key:
    :return:
    """
    try:
        return dict_name[key]
    except KeyError:
        return ''


@classmethod
def is_cmp(cls, op):
    """
        Tests whether a binary operation requires comparison between types.
        """
    return op == 'LESSER' or op == 'LESSER_EQUAL'


def collection_objects_select():
    """Select all objects in collection

    """
    pass


@staticmethod
def extract(cls):
    """ Extract the metadata of the given class

            :param cls: the entity class
            :type  cls: type
            :rtype:     passerine.db.metadata.entity.EntityMetadata
        """
    return cls.__tdbm__


def prompt_string(prompt='Enter a value', default=None):
    """Prompt the user for a string and return it"""
    _new = None
    while True:
        try:
            _new = str(input('{}? [{}]: '.format(prompt, str(default))))
            break
        except ValueError:
            print("Sorry, I didn't understand that.")
            continue
        except KeyboardInterrupt:
            break
    return default if _new in [None, ''] else _new


def hold_request(request_type, key, data=None):
    """Hold some data for moderator approval.

        :param request_type: A `RequestType` enum value.
        :param key: The key piece of request data being held.
        :param data: Additional optional data in the form of a dictionary that
            is associated with the held request.
        :return: A unique id for this held request.
        """


def substitute_ng_ids(cl, ng_dict):
    """Substitute node group template ids for node group template names

    If the cluster template contains node group elements with
    node_group_template_id fields that reference node group templates
    by name, substitute the node group template id for the name.
    The name reference is expected to be a string containing a format
    specifier of the form "{name}", for example "{master}"

    :param cl: a cluster template
    :param ng_dict: a dictionary of node group template ids keyed by
                    node group template names
    """
    for ng in cl['node_groups']:
        if 'node_group_template_id' in ng:
            val = ng['node_group_template_id'].format(**ng_dict)
            ng['node_group_template_id'] = val


def convert_values_to_none(event, field_or_field_list, field_values=None):
    """ Changes a field to None. If a field value is specified then only that value will be changed to None

    :param event: A dictionary
    :param field_or_field_list: A single field or list of fields  to convert to None
    :param field_values: The value to convert to None. If specified only these values are converted to None
    :return: An altered dictionary

    Examples:

    .. code-block:: python

        # Example #1
        event = {'a_field': 'a_value'}
        event = convert_values_to_none(event, field_or_field_list='a_field')
        event = {'a_field': None}

        # Example #2
        event = {'a_field': 'a_value',
                'another_field': 'another_value'
        event = convert_values_to_none(event, field_or_field_list=['a_field', 'another_field'])
        event = {'a_field': None,
                'another_field': None}

        # Example #3
        event = {'a_field': 'a_value',
                'another_field': 'another_value'
        event = convert_values_to_none(event, fields=['a_field', 'another_field'], field_values='a_value')
        event = {'a_field': None,
                'another_field': 'another_value'}

        # Example #4
        event = {'a_field': 'a_value',
                'another_field': 'another_value'
        event = convert_values_to_none(event, fields=['a_field', 'another_field'], field_values=['a_value', 'another_value'])
        event = {'a_field': None,
                'another_field': None}

    """
    if type(field_or_field_list) is not list:
        field_or_field_list = [field_or_field_list]
    if field_values is not None:
        if type(field_values) is not list:
            field_values = [field_values]
    for field in field_or_field_list:
        if field in event and field_values is None:
            event[field] = None
        elif field in event and event[field] in field_values:
            event[field] = None
    return event


def format_float_or_int_string(text: str) ->str:
    """Formats a float string like "1.0"."""
    if '.' not in text:
        return text
    before, after = text.split('.')
    return f'{before or 0}.{after or 0}'


def fetch_local_index(path: str) ->str:
    """Fetch CDXJ index contents from a file on local disk."""
    with open(path, 'r') as f:
        return f.read()


def data_to_result(header, data, data_present):
    """Moves the header and data (if present) into a common object."""
    result = {}
    if header['num_amplifier_channels'] > 0 and data_present:
        result['t_amplifier'] = data['t_amplifier']
    if header['num_aux_input_channels'] > 0 and data_present:
        result['t_aux_input'] = data['t_aux_input']
    if header['num_supply_voltage_channels'] > 0 and data_present:
        result['t_supply_voltage'] = data['t_supply_voltage']
    if header['num_board_adc_channels'] > 0 and data_present:
        result['t_board_adc'] = data['t_board_adc']
    if (header['num_board_dig_in_channels'] > 0 or header[
        'num_board_dig_out_channels'] > 0) and data_present:
        result['t_dig'] = data['t_dig']
    if header['num_temp_sensor_channels'] > 0 and data_present:
        result['t_temp_sensor'] = data['t_temp_sensor']
    if header['num_amplifier_channels'] > 0:
        result['spike_triggers'] = header['spike_triggers']
    result['notes'] = header['notes']
    result['frequency_parameters'] = header['frequency_parameters']
    if header['version']['major'] > 1:
        result['reference_channel'] = header['reference_channel']
    if header['num_amplifier_channels'] > 0:
        result['amplifier_channels'] = header['amplifier_channels']
        if data_present:
            result['amplifier_data'] = data['amplifier_data']
            result['amplifier_data_conversion_factor'] = data[
                'amplifier_data_conversion_factor']
    if header['num_aux_input_channels'] > 0:
        result['aux_input_channels'] = header['aux_input_channels']
        if data_present:
            result['aux_input_data'] = data['aux_input_data']
    if header['num_supply_voltage_channels'] > 0:
        result['supply_voltage_channels'] = header['supply_voltage_channels']
        if data_present:
            result['supply_voltage_data'] = data['supply_voltage_data']
    if header['num_board_adc_channels'] > 0:
        result['board_adc_channels'] = header['board_adc_channels']
        if data_present:
            result['board_adc_data'] = data['board_adc_data']
    if header['num_board_dig_in_channels'] > 0:
        result['board_dig_in_channels'] = header['board_dig_in_channels']
        if data_present:
            result['board_dig_in_data'] = data['board_dig_in_data']
    if header['num_board_dig_out_channels'] > 0:
        result['board_dig_out_channels'] = header['board_dig_out_channels']
        if data_present:
            result['board_dig_out_data'] = data['board_dig_out_data']
    return result


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

        :param SharingChangeFolderJoinPolicyType val:
        :rtype: EventType
        """
    return cls('sharing_change_folder_join_policy', val)


@classmethod
def specification_handlers(cls, master_instance):
    """
        Should return dict {ns => {code: handler}}. Only has sense for (server|both)-direction
          codes. It takes a master broadcast instance to get the handlers from.
        """
    raise NotImplemented


@classmethod
def locate(cls, client=None, **kwargs):
    """Locates nearby atms and create an Atm instance from it.

        Args:
            client (Client): an instance of the API Client
            zip(string): Zip code for ATM locator
            radius(string): radius in miles
            page(integer): Page number
            per_page(integer): Number of atms per page
        Returns:
            Atm: an ATM instance corresponding to the record
        """
    response = client.atms.locate(**kwargs)
    return cls.multiple_from_response(client, response['atms'])


def get_peptide_quant(quantdata, quanttype):
    """Parses lists of quantdata and returns maxvalue from them. Strips NA"""
    parsefnx = {'precur': max}
    quantfloats = []
    for q in quantdata:
        try:
            quantfloats.append(float(q))
        except (TypeError, ValueError):
            pass
    if not quantfloats:
        return 'NA'
    return str(parsefnx[quanttype](quantfloats))


def is_pmp_obj(obj):
    """
    Helper function to determine if the current object matches the structure
    that the library enforices for Pan-MatrixProfiles.

    Parameters
    ----------
    obj : object
        The object to test.

    Returns
    -------
    bool :
        True or false respectively.
    """
    return isinstance(obj, dict) and obj.get('class') == 'PMP'


@staticmethod
def _extract_section(sect_req, elffile, mem=None):
    """
            :sect_req dictionary of section names as strings and SectionRequest objects
            :mem if mem is not null, it serves as an accumulator rather than using the memory
                 in SectionRequests

            :returns nothing
        """
    for nseg, section in enumerate(elffile.iter_sections()):
        request = sect_req.get(section.name, None)
        if request:
            request.set_found(True)
            request.set_sect_properties(section.header.sh_addr, section.
                header.sh_size)
            if mem:
                mem.add_vma(section.header.sh_addr, section.data())
            else:
                request.memory.add_vma(section.header.sh_addr, section.data())


def chunkread(f, size):
    """Generator that reads from file like object. May return less
     data than requested on the last read."""
    c = f.read(size)
    while len(c):
        yield c
        c = f.read(size)


def clean_entry_id(entryid):
    """
    Clean up entry ID.

    :param entryid: Entry ID.
    :type entryid: str
    """
    entryid = str(entryid).lower()
    if entryid is None:
        print('NO SCP SPECIFIED')
        raise SystemExit
    elif not entryid.startswith(('scp-', 'spc-')):
        entryid = 'scp-' + entryid
    return entryid


@classmethod
def fetch_by_id(cls, element_id):
    """Return an object (or None) by its id."""
    return cls.query_by(id=int(element_id)).first()


def save_document(collection, doc):
    """Saves document to given MongoDB collection.

    If document _id already exists, replaces it. Else, inserts it.

    Parameters
    ----------
    collection : mongodb.collection
        Collection to save document to.
    doc : dict
        Document to save.
    """
    if '_id' in doc and collection.find_one({'_id': doc['_id']}):
        collection.replace_one({'_id': doc['_id']}, doc)
    else:
        collection.insert_one(doc)


def move_up():
    """Move selected strips up a track if there’s room

    """
    pass


@classmethod
def check_cache(cls, url):
    """Checks if url already have a response.
        Stop from calling the request method more than once.
        Great for saving mobile data on mobile devices.
        """
    url = url.strip()
    try:
        if url in cls.cache.keys():
            cls.cache[url]['count'] += 1
            return cls.cache[url]['response']
    except MemoryError:
        cls.clear_cache()
    except:
        pass


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


def dumpb(data: str, encoding='utf-8'):
    """
    Convert a string to its netstring representation. Returns a `bytes`
    object.

    """
    payload = data.encode(encoding=encoding)
    return b'%d:%b,' % (len(payload), payload)


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 process_query_string_band(report, element):
    """
    Read from jrxml queryString element and query a datasource.
    :param report: dictionary holding report information
    :param element:
    """
    sql_stmt = element.get('value')
    if sql_stmt is not None:
        sql_stmt = sql_stmt.strip()
        report['field_names'] = report['main_datasource'].execute_query(
            sql_stmt)


def delete_pipeline(Id=None):
    """
    The DeletePipeline operation removes a pipeline.
    You can only delete a pipeline that has never been used or that is not currently in use (doesn't contain any active jobs). If the pipeline is currently in use, DeletePipeline returns an error.
    See also: AWS API Documentation

    :example: response = client.delete_pipeline(
        Id='string'
    )

    :type Id: string
    :param Id: [REQUIRED]
            The identifier of the pipeline that you want to delete.

    :rtype: dict
    :return: {}

    """
    pass


@staticmethod
def attr_doc_inherit(prnt_attr_doc, child_doc):
    """ Merge the docstrings of method or property from parent class and the corresponding
        attribute of its child.

        Parameters
        ----------
        prnt_attr_doc: Union[None, str]
        child_doc: Union[None, str]

        Raises
        ------
        NotImplementedError

        Notes
        -----
        This works for properties, methods, static methods, class methods, and
        decorated methods/properties."""
    raise NotImplementedError


def sdf_count(file_obj):
    """Count the number of molecules in an SDF file.

    Counts the number of times '$$$$' occurs at the start of lines
    in the file.

    Parameters
    ----------
    file_obj: A file-like object

    Returns
    -------
    count: The number of molecules in the file (int)
    """
    return sum(1 for line in file_obj if line[:4] == b'$$$$')


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

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
         {
            "dynamic":true,
                "properties": {
                    "data": {
                        "properties": {
                            "comments": {
                                "properties": {
                                    "comment": {
                                        "type": "text",
                                        "index": true
                                    },
                                    "member": {
                                        "properties": {
                                            "bio": {
                                                "type": "text",
                                                "index": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }
        """
    return {'items': mapping}


def get_protected_properties():
    """
    returns properties never be modified once request is created
    """
    return ['RequestName', '_id']


def Effic_ULdigraph_Disconnected(N, L):
    """
    Smallest possible efficiency of a digraph that is not strongly connected.

    Calculates the smallest possible efficiency that a digraph of arbitrary
    number of nodes N and number of directed arcs L could possibly have.
    When digraphs are allowed to be disconnected, the smallest efficiency any
    digraph could have is E_dUL = density. This is true for any value of
    L <= 1/2 N(N-1), or density <= 1/2. For larger link densities, special
    cases exists for which the smallest efficiency is larger than the density.
    While the configuration of such cases is as today not fully understood,
    the density is an excellent approximation for those cases as well.
    Therefore, this function returns, E_dUL = dens.

    Reference and citation
    ^^^^^^^^^^^^^^^^^^^^^^
    G. Zamora-López & R. Brasselet "Sizing complex networks" Commun Phys 2:144 (2019)

    Parameters
    ----------
    N : integer
        Number of nodes in the digraph.
    L : integer
        Number of undirected edges in the digraph.

    Returns
    -------
    efficiency : float
        The smallest efficiency a digraph could take.

    See Also
    --------
    Pathlen_ULdigraph :
    """
    if N < 2:
        raise ValueError('Network needs at least two nodes, N > 1')
    Ltot = N * (N - 1)
    if L < 0:
        raise ValueError('L does not take negative values')
    if L > int(Ltot):
        raise ValueError('L out of range. max(L) = N*(N-1)')
    efficiency = float(L) / Ltot
    return efficiency


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

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

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

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

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

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

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


def flip4(x, y):
    """ fast, slow to dety, detz"""
    return -x, -y


def split_many(string, delimiters):
    """Behaves str.split but supports tuples of delimiters."""
    delimiters = tuple(delimiters)
    if len(delimiters) < 1:
        return [string]
    final_delimiter = delimiters[0]
    for i in delimiters[1:]:
        string = string.replace(i, final_delimiter)
    return string.split(final_delimiter)


def lag_observations(observations, lag, stride=1):
    """ Create new trajectories that are subsampled at lag but shifted

    Given a trajectory (s0, s1, s2, s3, s4, ...) and lag 3, this function will generate 3 trajectories
    (s0, s3, s6, ...), (s1, s4, s7, ...) and (s2, s5, s8, ...). Use this function in order to parametrize a MLE
    at lag times larger than 1 without discarding data. Do not use this function for Bayesian estimators, where
    data must be given such that subsequent transitions are uncorrelated.

    Parameters
    ----------
    observations : list of int arrays
        observation trajectories
    lag : int
        lag time
    stride : int, default=1
        will return only one trajectory for every stride. Use this for Bayesian analysis.

    """
    obsnew = []
    for obs in observations:
        for shift in range(0, lag, stride):
            obs_lagged = obs[shift:][::lag]
            if len(obs_lagged) > 1:
                obsnew.append(obs_lagged)
    return obsnew


def device_memory_depends(devmem, *objs):
    """Add dependencies to the device memory.

    Mainly used for creating structures that points to other device memory,
    so that the referees are not GC and released.
    """
    depset = getattr(devmem, '_depends_', [])
    depset.extend(objs)


@staticmethod
def is_activate_node():
    """
        Returns true if this node is a ActivateNode. Otherwise return false.

        :rtype: bool
        """
    return False


def remove_alpha_channel(image):
    """
    Converts the Image object (RGBA or ARGB) to RGB. Just passes it through if already RGB.

    :param image: the image object to convert if necessary
    :type image: Image
    :return: the converted object
    :rtype: Image
    """
    if image.mode is 'RGBA' or 'ARGB':
        return image.convert('RGB')
    else:
        return image


@staticmethod
def _for_each_option_group(callback, options):
    """
        Given set of options, call a callback for each option group.

        :param options: List of option groups, or a dict listing options directly.
        :param callable callback: Must accept at least 2 parameters: ``options`` (``dict``), listing options
            in the group, and keyword parameter ``group_name`` (``str``), which is set to group name when
            the ``options`` defines an option group.
        """
    if isinstance(options, dict):
        callback(options)
    elif isinstance(options, (list, tuple)):
        for group in options:
            if isinstance(group, dict):
                callback(group)
            else:
                group_name, group_options = group
                callback(group_options, group_name=group_name)


@classmethod
def _factory(cls, returnsrows, name=None):
    """Base factory method.  Subclasses need to provide this."""
    raise NotImplementedError()


def convert_mass(mass_from, mass_to, log):
    """
    determines the mass, weight, gravity scale factor

    We apply a gravity_scale_mass for any unit not {kg, slug}.
    Then we convert to N.

    So for SI, if we have kg, we have a base unit, and the length is assumed
    to be m, so we have a consistent system and gravity_scale_mass is 1.0.

    For lbm:
       F = m*a
       1 lbf = 1 lbm * 1 ft/s^2
       32 lbf = 1 slug * 32 ft/s^2
       gscale = 1/g
       F = gscale * m * a
       1 lbf = gscale * 1 lbm * 32 ft/s^2
       --> gscale = 1/32

    For slug:
       F = gscale * m * a
       32 lbf = gscale * 1 slug * 32 ft/s^2
       --> gscale = 1

    For slinch:
       F = gscale * m * a
       386 lbf = gscale * 1 slinch * 12*32 in/s^2
       1 slinch = 12 slug
       12 in = 1 ft
       386 lbf = gscale * 12 slug * 32 ft/s^2
       --> gscale = 1

    TODO: slinch/slug not validated

    """
    mass_scale = 1.0
    weight_scale = 1.0
    gravity_scale_mass = 1.0
    gravity_english_ft = 32.174
    slug_to_kg = 14.5939
    slinch_to_kg = 12.0 * slug_to_kg
    lbf_to_newton = 4.4482216152605
    lbm_to_kg = 0.45359237
    if mass_from == 'kg':
        pass
    elif mass_from == 'Mg':
        mass_scale *= 1000.0
        gravity_scale_mass *= 1000.0
    elif mass_from == 'g':
        mass_scale *= 1.0 / 1000.0
        gravity_scale_mass *= 1 / 1000.0
    elif mass_from == 'lbm':
        mass_scale *= lbm_to_kg
        weight_scale *= lbf_to_newton
        gravity_scale_mass /= gravity_english_ft
    elif mass_from == 'slug':
        mass_scale *= slug_to_kg
        weight_scale *= lbf_to_newton
    elif mass_from == 'slinch':
        mass_scale *= slinch_to_kg
        weight_scale *= lbf_to_newton
    else:
        raise NotImplementedError(
            'mass from unit=%r; expected=[g, kg, Mg, lbm, slug, slinch]' %
            mass_from)
    if mass_to == 'kg':
        pass
    elif mass_to == 'Mg':
        mass_scale /= 1000.0
        gravity_scale_mass /= 1000.0
    elif mass_to == 'g':
        mass_scale *= 1000.0
        gravity_scale_mass *= 1000.0
    elif mass_to == 'lbm':
        mass_scale /= lbm_to_kg
        weight_scale /= lbf_to_newton
        gravity_scale_mass *= gravity_english_ft
    elif mass_to == 'slug':
        mass_scale /= slug_to_kg
        weight_scale /= lbf_to_newton
    elif mass_to == 'slinch':
        mass_scale /= slinch_to_kg
        weight_scale /= lbf_to_newton
    else:
        raise NotImplementedError(
            'mass to unit=%r; expected=[g, kg, Mg, lbm, slug, slinch]' %
            mass_to)
    return mass_scale, weight_scale, gravity_scale_mass


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

        :param es_major: major version of Elasticsearch, as string
        :returns:        dictionary with a key, 'items', with the mapping
        """
    mapping = """
        {
            "properties": {
                "content_analyzed": {
                  "type": "text",
                  "index": true
                },
                "tags_analyzed": {
                  "type": "text",
                  "index": true
                }
           }
        } """
    return {'items': mapping}


def get_Union_params(un):
    """Python version independent function to obtain the parameters
    of a typing.Union object.
    Tested with CPython 2.7, 3.5, 3.6 and Jython 2.7.1.
    """
    try:
        return un.__union_params__
    except AttributeError:
        return un.__args__


@classmethod
def view_attributes(cls):
    """Return a list of xpath, attribute name and value"""
    return []


def load_script(browser, url):
    """Ensure that JavaScript at a given URL is available to the browser."""
    if browser.current_url.startswith('file:'):
        url = 'https:' + url
    browser.execute_script(
        """
    var script_tag = document.createElement("script");
    script_tag.setAttribute("type", "text/javascript");
    script_tag.setAttribute("src", arguments[0]);
    document.getElementsByTagName("head")[0].appendChild(script_tag);
    """
        , url)


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 __repr__(A):
    """For `print` and `pprint`"""
    return A.to_str()


def file_data_status(ca_status):
    """
    Verify the CA status based in the existent files.

    :param ca_status: current ``ca_status`` file dictionary:
        ``ownca.utils.ownca_directory``
    :type ca_status: dict, required

    :return: True, False or None
    :rtype: bool/None
    """
    key = ca_status['key']
    cert = ca_status['certificate']
    if key == cert and key is True:
        return True
    elif key != cert and key or cert:
        return False
    else:
        return None


def getModule(modulename, fromPath='tools.pythonpoint.styles'):
    """Get a module containing style declarations.

    Search order is:
        tools/pythonpoint/
        tools/pythonpoint/styles/
        ./
    """
    try:
        exec('from tools.pythonpoint import ' + modulename)
        return eval(modulename)
    except ImportError:
        try:
            exec('from tools.pythonpoint.styles import ' + modulename)
            return eval(modulename)
        except ImportError:
            exec('import ' + modulename)
            return eval(modulename)


def localizeCassetteExon(upExonEnd, downExonStart, extraDomains, notAligned):
    """
    Localizes cassette exon to extracellular domain of protein

    :param upExonEnd: End index of upstream exon in protein AA sequence (float)
    :param downExonStart: Start index of downstream exon in protein AA sequence (float)
    :param extraDomains: List of lists lower bound and upper bound of extracellular/membrane domains (list[list[int, int], ...])
    :param notAligned: Exons that did not align to CDS (str)
    :return: Exons that localize to the extracellular/membrane domain (str)
    """
    exonsMatched = 'N/A'
    if extraDomains:
        for x in extraDomains:
            lowerBound = x[0]
            upperBound = x[1]
            if notAligned == 'Aligned':
                if lowerBound < int(upExonEnd) < int(downExonStart
                    ) < upperBound:
                    exonsMatched = 'Both'
            elif notAligned == 'Downstream':
                if lowerBound < int(upExonEnd) < upperBound:
                    exonsMatched = 'Upstream'
            elif notAligned == 'Upstream':
                if lowerBound < int(downExonStart) < upperBound:
                    exonsMatched = 'Downstream'
    return exonsMatched


def generate_sub_matrices(A, rad, RC, n):
    """
    Generate the sub matrices used in RCF routine
    :param A: Data matrix, length n
    :param rad: radius of RCF filter
    :param RC: np array of length 2r+1 with
    :param n:
    :return: A_sub, RC_sub, lists of same dimensions, sampled according to paper: https://doi.org/10.1366%2F12-06766
    """
    ni = n
    A_sub = []
    RC_sub = []
    for i in range(len(A)):
        if i < rad + 1:
            a_sub = A[:i + rad + 1]
            rc_sub = RC[rad - i:2 * rad + 1]
            A_sub.append(a_sub)
            RC_sub.append(rc_sub)
        elif rad + 1 <= i <= n - (rad + 1):
            a_sub = A[i - rad:i + rad + 1]
            rc_sub = RC
            A_sub.append(a_sub)
            RC_sub.append(rc_sub)
        elif i > n - (rad + 1):
            a_sub = A[i - rad:n + 1]
            rc_sub = RC[:rad + (n - i)]
            A_sub.append(a_sub)
            RC_sub.append(rc_sub)
        else:
            print('something has gone wrong')
            import ipdb
            ipdb.set_trace()
            raise RuntimeError("Something has gone wrong and I don't know why")
    return A_sub, RC_sub


def get_src_master():
    """Return a Collection instance for src_master collection/table"""
    raise NotImplementedError()


def safe_eval(expr, local_var):
    """Eval expr save is expr contains only letters.

    """
    if expr.isalpha():
        return expr
    return eval(expr, globals(), local_var)


def group_routes_by(routes: list, param: str) ->dict:
    """Group routes by parameter.

    Create different groupings to accomodate different templates

    :param routes: routes
    :type routes: list
    :param param: parameter to group by
    :type param: str
    :return: grouped routes
    :rtype: dict
    """
    grouped_routes = {}
    for route in routes:
        grouped_by_param = grouped_routes.get(route[param], [])
        grouped_by_param.append(route)
        grouped_routes[route[param]] = grouped_by_param
    return grouped_routes


def add_row(irow, grid, p1_label, p1_cid_pulldown, p1_x_edit, p1_y_edit,
    p1_z_edit):
    """adds the items to the grid"""
    grid.addWidget(p1_label, irow, 0)
    grid.addWidget(p1_cid_pulldown, irow, 1)
    grid.addWidget(p1_x_edit, irow, 2)
    grid.addWidget(p1_y_edit, irow, 3)
    grid.addWidget(p1_z_edit, irow, 4)


@classmethod
def instantiate_and_register_to_app(cls, flask_app):
    """Build the API object and register to the passed in flask_app.

        This is a simplistic loader that makes assumptions about how the
        blueprint is loaded. Anything beyond defaults should be done
        explicitly via normal instantiation where more values may be passed
        via :meth:`__init__`.

        :returns: :class:`xerox.server.flask.common.APIBase`
        """
    inst = cls()
    flask_app.register_blueprint(inst.blueprint)
    return inst


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


def ocean_s_coordinate_g2(s, eta, depth, depth_c, c):
    """
    Creates a dimensioned version of s-coordinate generic form 2.

    z(n,k,j,i) = eta(n,j,i) + (eta(n,j,i) + depth(j,i)) * S(k,j,i)

    where:
        S(k,j,i) = (depth_c * s(k) + depth(j,i) * C(k)) /
                    (depth_c + depth(j,i))

    """
    S = (depth_c * s + depth * c) / (depth_c + depth)
    return eta + (eta + depth) * S


def etree_write(tree, stream):
    """
    Write XML ElementTree 'root' content into 'stream'.

    :param tree: XML ElementTree object
    :param stream: File or file-like object can write to
    """
    try:
        tree.write(stream, encoding='utf-8', xml_declaration=True)
    except TypeError:
        tree.write(stream, encoding='unicode', xml_declaration=True)


def set_excluded_items(items):
    """Set a list of all excluded items.
        """


@classmethod
def from_data(cls, data):
    """
        Initializes from a sequence of values.
        """
    return cls(*data)


def import_object(name):
    """Imports an object by name.

    import_object('x.y.z') is equivalent to 'from x.y import z'.

    """
    parts = name.split('.')
    m = '.'.join(parts[:-1])
    attr = parts[-1]
    obj = __import__(m, None, None, [attr], 0)
    try:
        return getattr(obj, attr)
    except AttributeError as e:
        raise ImportError("'%s' does not exist in module '%s'" % (attr, m))


def set_array_range(worksheet, itop_row, ileft_col, data):
    """insert a 1d or 2d array starting at given location in provided worksheet.

    Args:
        worksheet: win32 Excel object
        itop_row: top row index (zero based)
        ileft_col: left column index (zero based)
        data: numpy array

    Returns:
        win32 Excel Range object
    """
    if len(data.shape) == 1:
        data = data.reshape(data.shape[0], 1)
    ibottom_row = itop_row + data.shape[0] - 1
    iright_col = ileft_col + data.shape[1] - 1
    xlrange = worksheet.Range(worksheet.Cells(itop_row + 1, ileft_col + 1),
        worksheet.Cells(ibottom_row + 1, iright_col + 1))
    xlrange.Value = data.tolist()
    return xlrange


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

        :param BinderAddSectionDetails val:
        :rtype: EventDetails
        """
    return cls('binder_add_section_details', val)


def untokenize(tokens):
    """
    Converts the output of tokenize.generate_tokens back into a human-readable
    string (that doesn't contain oddly-placed whitespace everywhere).

    **Note:** Unlike tokenize.untokenize(), this function requires the 3rd and
    4th items in each token tuple (though we can use lists *or* tuples).
    """
    out = ''
    last_lineno = -1
    last_col = 0
    for tok in tokens:
        token_string = tok[1]
        start_line, start_col = tok[2]
        end_line, end_col = tok[3]
        if start_line > last_lineno:
            last_col = 0
        if start_col > last_col:
            out += ' ' * (start_col - last_col)
        out += token_string
        last_col = end_col
        last_lineno = end_line
    return out


def pn_from_dataframe(dataframe, data_column, pos_class):
    """
    Function to generate random positive-negative data from any pandas dataframe. It returns the same dataset with a 'y' column containing the positive-negative data.

    REQUIRED

    dataframe: pandas.Dataframe to be extracted to positive-negative.
    data_column: dataframe column to be compared to extract the positive class.
    pos_class: class in the data_column to be considered as positive.

    OPTIONAL

    pos_size: positive rate (if between 0 and 1) or positive literal number (greater than one).
    pos_size will default to 0.8 if no value is specified.
    """
    dataframe = dataframe.sample(frac=1).reset_index(drop=True)
    for index, value in enumerate(dataframe.loc[:, (data_column)]):
        if value == pos_class:
            dataframe.loc[index, 'y'] = 1
        else:
            dataframe.loc[index, 'y'] = -1
    return dataframe


def PS(a, b):
    """return the scalar product of two vetors"""
    return sum(a * b)


def get_schema():
    """Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {'schema': {'schema_version': {'type': 'integer', 'default': 2},
        'name': {'schema_version': 1, 'title': 'Graphite connection name',
        'comment': 'Unique Graphite connection name', 'type': 'string',
        'required': True, 'empty': False, 'unique': True}, 'carbon_address':
        {'schema_version': 1, 'title': 'Carbon daemon address', 'comment':
        '', 'type': 'string', 'required': True, 'empty': False},
        'carbon_port': {'schema_version': 1, 'title': 'Carbon daemon port',
        'comment': '', 'type': 'integer', 'empty': False, 'default': 2004},
        'graphite_address': {'schema_version': 1, 'title':
        'Graphite address', 'comment': '', 'type': 'string', 'required':
        True, 'empty': False}, 'graphite_port': {'schema_version': 1,
        'title': 'Graphite port', 'comment': '', 'type': 'integer', 'empty':
        False, 'default': 8080}, 'prefix': {'schema_version': 1, 'title':
        'Metrics prefix', 'comment':
        'Prefix that will be prepended to the metrics sent to this TS DB.',
        'type': 'string', 'default': ''}, 'realms_prefix': {
        'schema_version': 2, 'title': 'Realms prefix', 'comment':
        'Include the realms prefix for the metrics sent to this TS DB.',
        'type': 'boolean', 'default': True}, 'grafana': {'schema_version':
        1, 'title': 'Grafana relation', 'comment':
        'If set, the Alignak backend will use this Grafana relation for the metrics sent to the Influx DB. It will create/update the Grafana panels accordindgly.'
        , 'type': 'objectid', 'data_relation': {'resource': 'grafana',
        'embeddable': True}, 'nullable': True, 'default': None}, 'statsd':
        {'schema_version': 1, 'title': 'StatsD relation', 'comment':
        'If set, the Alignak backend will use this StatsD relation for the metrics sent to the Influx DB.'
        , 'type': 'objectid', 'data_relation': {'resource': 'statsd',
        'embeddable': True}, 'nullable': True, 'default': None}, '_realm':
        {'schema_version': 1, 'title': 'Realm', 'comment':
        'Realm this element belongs to.', 'type': 'objectid',
        'data_relation': {'resource': 'realm', 'embeddable': True},
        'required': True}, '_sub_realm': {'schema_version': 1, 'title':
        'Sub-realms', 'comment':
        'Is this element visible in the sub-realms of its realm?', 'type':
        'boolean', 'default': True}, '_users_read': {'schema_version': 1,
        'type': 'list', 'schema': {'type': 'objectid', 'data_relation': {
        'resource': 'user', 'embeddable': True}}}, '_users_update': {
        'schema_version': 1, 'type': 'list', 'schema': {'type': 'objectid',
        'data_relation': {'resource': 'user', 'embeddable': True}}},
        '_users_delete': {'schema_version': 1, 'type': 'list', 'schema': {
        'type': 'objectid', 'data_relation': {'resource': 'user',
        'embeddable': True}}}}, 'schema_deleted': {}}


@classmethod
def from_flat(cls, data, dict_type='ndict'):
    """Initialize from a dict keyed by tuples
        Each tuple-element is taken as a key for each level in the NestedDict

        Parameters
        ----------
        data: dict, list
            Dictionary keyed by tuples
        dict_type: ['ndict', 'dict', 'odict']
            Dict-type in string format, for initializing dicts at depth if they
            don't exist yet

        Returns
        -------
        NestedDict
        """
    if isinstance(data, dict):
        iterdata = data.items()
    elif isinstance(data, list):
        iterdata = data
    else:
        raise TypeError('from_flat requires a dict or list, not {}'.format(
            type(data)))
    new_dict = cls()
    for key_list, val in iterdata:
        new_dict.nested_set(key_list, val, dict_type=dict_type)
    return new_dict


def uncached_property(fun):
    """
    Behaves like the builtin :keyword:`@property` decorator, but supports the same assignment logic as ``@fin.cache.property``.
    This method performs **no** caching, but is syntactic sugar.
    """
    return property(fun, wrapper=lambda x: x)


def Dequiv(mas, agents, states):
    """
    Return the set of states of mas that are equivalent to some state in states
    w.r.t. distributed knowledge of agents.

    mas -- a multi-agent system;
    agents -- a set of agents;
    states -- a subset of states of mas.
    """
    return mas.equivalent_states(states, {agents}) & mas.reachable_states


def get_thresholdcurve_data(data, xname, yname):
    """
    Retrieves x and y columns from  of the data generated by the weka.classifiers.evaluation.ThresholdCurve
    class.

    :param data: the threshold curve data
    :type data: Instances
    :param xname: the name of the X column
    :type xname: str
    :param yname: the name of the Y column
    :type yname: str
    :return: tuple of x and y arrays
    :rtype: tuple
    """
    xi = data.attribute_by_name(xname).index
    yi = data.attribute_by_name(yname).index
    x = []
    y = []
    for i in range(data.num_instances):
        inst = data.get_instance(i)
        x.append(inst.get_value(xi))
        y.append(inst.get_value(yi))
    return x, y


def get_instance(instanceName=None):
    """
    Returns information about a specific Amazon Lightsail instance, which is a virtual private server.
    See also: AWS API Documentation

    :example: response = client.get_instance(
        instanceName='string'
    )

    :type instanceName: string
    :param instanceName: [REQUIRED]
            The name of the instance.

    :rtype: dict
    :return: {
        'instance': {
            'name': 'string',
            'arn': 'string',
            'supportCode': 'string',
            'createdAt': datetime(2015, 1, 1),
            'location': {
                'availabilityZone': 'string',
                'regionName': 'us-east-1'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-central-1'|'ap-south-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-northeast-1'|'ap-northeast-2'
            },
            'resourceType': 'Instance'|'StaticIp'|'KeyPair'|'InstanceSnapshot'|'Domain'|'PeeredVpc',
            'blueprintId': 'string',
            'blueprintName': 'string',
            'bundleId': 'string',
            'isStaticIp': True|False,
            'privateIpAddress': 'string',
            'publicIpAddress': 'string',
            'ipv6Address': 'string',
            'hardware': {
                'cpuCount': 123,
                'disks': [
                    {
                        'name': 'string',
                        'arn': 'string',
                        'supportCode': 'string',
                        'createdAt': datetime(2015, 1, 1),
                        'location': {
                            'availabilityZone': 'string',
                            'regionName': 'us-east-1'|'us-west-1'|'us-west-2'|'eu-west-1'|'eu-central-1'|'ap-south-1'|'ap-southeast-1'|'ap-southeast-2'|'ap-northeast-1'|'ap-northeast-2'
                        },
                        'resourceType': 'Instance'|'StaticIp'|'KeyPair'|'InstanceSnapshot'|'Domain'|'PeeredVpc',
                        'sizeInGb': 123,
                        'gbInUse': 123,
                        'isSystemDisk': True|False,
                        'iops': 123,
                        'path': 'string',
                        'attachedTo': 'string',
                        'isAttached': True|False,
                        'attachmentState': 'string'
                    },
                ],
                'ramSizeInGb': ...
            },
            'networking': {
                'monthlyTransfer': {
                    'gbPerMonthAllocated': 123
                },
                'ports': [
                    {
                        'fromPort': 123,
                        'toPort': 123,
                        'protocol': 'tcp'|'all'|'udp',
                        'accessFrom': 'string',
                        'accessType': 'Public'|'Private',
                        'commonName': 'string',
                        'accessDirection': 'inbound'|'outbound'
                    },
                ]
            },
            'state': {
                'code': 123,
                'name': 'string'
            },
            'username': 'string',
            'sshKeyName': 'string'
        }
    }

    """
    pass


def _get_available_monitors(screen_list):
    """Return a list with all the available monitors."""
    res = []
    for screen in screen_list:
        res.append('Screen(%s)' % screen_list.index(screen))
    return res


def ltruncate_int(value, ndigits):
    """Truncate an integer, retaining least significant digits

    Parameters
    ----------
    value : int
      value to truncate
    ndigits : int
      number of digits to keep

    Returns
    -------
    truncated : int
      only the `ndigits` least significant digits from `value`

    Examples
    --------
    >>> ltruncate_int(123, 2)
    23
    >>> ltruncate_int(1234, 5)
    1234
    """
    return int(str(value)[-ndigits:])


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

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

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


def list_update(item, lst, remove=False):
    """ Add or remove item from list, checking first to avoid exceptions. """
    if not remove and item not in lst:
        lst.append(item)
    elif remove and item in lst:
        lst.remove(item)


def yesno(string):
    """Interpret string argument as a boolean.

    May raise `ValueError` if argument cannot be interpreted.
    """
    yes_strings = ['y', 'yes', 'true', '1']
    no_strings = ['n', 'no', 'false', '0']
    if string.lower() in yes_strings:
        return True
    if string.lower() in no_strings:
        return False
    raise ValueError("'{}' is supposed to be one of {}.".format(string,
        ', '.join(["'{}'".format(string) for string in yes_strings +
        no_strings])))


def z_axis(rot):
    """Return the z-axis vector from 3x3 (row major) rotation matrix
	``rot``.

	"""
    return rot[2], rot[5], rot[8]


@staticmethod
def _add_extra_fields(gelf_dict, record):
    """Add extra fields to the given ``gelf_dict``

        However, this does not add additional fields in to ``message_dict``
        that are either duplicated from standard :class:`logging.LogRecord`
        attributes, duplicated from the python logging module source
        (e.g. ``exc_text``), or violate GELF format (i.e. ``id``).

        .. seealso::

            The list of standard :class:`logging.LogRecord` attributes can be
            found at:

                http://docs.python.org/library/logging.html#logrecord-attributes

        :param gelf_dict: Dictionary representing a GELF log.
        :type gelf_dict: dict

        :param record: :class:`logging.LogRecord` to extract extra fields
            from to insert into the given ``gelf_dict``.
        :type record: logging.LogRecord
        """
    skip_list = ('args', 'asctime', 'created', 'exc_info', 'exc_text',
        'filename', 'funcName', 'id', 'levelname', 'levelno', 'lineno',
        'module', 'msecs', 'message', 'msg', 'name', 'pathname', 'process',
        'processName', 'relativeCreated', 'thread', 'threadName')
    for key, value in record.__dict__.items():
        if key not in skip_list and not key.startswith('_'):
            gelf_dict['_%s' % key] = value


@staticmethod
def _from_db_object(volume, db_volume):
    """Converts a database entity to a formal object."""
    for field in volume.fields:
        setattr(volume, field, db_volume[field])
    volume.obj_reset_changes()
    return volume


@classmethod
def get_card_providers(cls, store):
    """Get a list of all credit card providers.
        :param store: a database store
        """
    return store.find(cls)


def __init__(meta_class, class_name, bases, class_dict, **kw_arguments):
    """
        Initialize a new type object.

        Behaves like a class method because type objects are their own
        meta-classes.
        """
    type.__init__(meta_class, class_name, bases, class_dict)


def get_dirs(hub, sub):
    """
    Return a list of directories that contain the modules for this subname
    """
    return sub._dirs


@staticmethod
def predict(params, context):
    """Given a set of parameters and a context, return the resulting sum of square error.

        Parameters
        ----------
        params : list
            1 dimensional array of parameters
        context : dict
            Dictionary of arguments/keyword arguments to pass to functions

        Returns
        -------
        float
        """
    raise NotImplementedError(
        'The `predict` method not implemented. Create a subclass of OptimizerBase with `predict` overridden to use it'
        )


def is_32bytes(instance, attribute, value):
    """
    validator for a 32 byte value
    """
    if not isinstance(value, bytes) or len(value) != 32:
        raise ValueError('must be 32 byte value')


def is_status(byte):
    """Return True if the given byte is a MIDI status byte, False otherwise."""
    return byte & 128 == 128


def describe_instances(StackId=None, LayerId=None, InstanceIds=None):
    """
    Requests a description of a set of instances.
    See also: AWS API Documentation

    :example: response = client.describe_instances(
        StackId='string',
        LayerId='string',
        InstanceIds=[
            'string',
        ]
    )

    :type StackId: string
    :param StackId: A stack ID. If you use this parameter, DescribeInstances returns descriptions of the instances associated with the specified stack.

    :type LayerId: string
    :param LayerId: A layer ID. If you use this parameter, DescribeInstances returns descriptions of the instances associated with the specified layer.

    :type InstanceIds: list
    :param InstanceIds: An array of instance IDs to be described. If you use this parameter, DescribeInstances returns a description of the specified instances. Otherwise, it returns a description of every instance.
            (string) --

    :rtype: dict
    :return: {
        'Instances': [
            {
                'AgentVersion': 'string',
                'AmiId': 'string',
                'Architecture': 'x86_64'|'i386',
                'AutoScalingType': 'load'|'timer',
                'AvailabilityZone': 'string',
                'BlockDeviceMappings': [
                    {
                        'DeviceName': 'string',
                        'NoDevice': 'string',
                        'VirtualName': 'string',
                        'Ebs': {
                            'SnapshotId': 'string',
                            'Iops': 123,
                            'VolumeSize': 123,
                            'VolumeType': 'gp2'|'io1'|'standard',
                            'DeleteOnTermination': True|False
                        }
                    },
                ],
                'CreatedAt': 'string',
                'EbsOptimized': True|False,
                'Ec2InstanceId': 'string',
                'EcsClusterArn': 'string',
                'EcsContainerInstanceArn': 'string',
                'ElasticIp': 'string',
                'Hostname': 'string',
                'InfrastructureClass': 'string',
                'InstallUpdatesOnBoot': True|False,
                'InstanceId': 'string',
                'InstanceProfileArn': 'string',
                'InstanceType': 'string',
                'LastServiceErrorId': 'string',
                'LayerIds': [
                    'string',
                ],
                'Os': 'string',
                'Platform': 'string',
                'PrivateDns': 'string',
                'PrivateIp': 'string',
                'PublicDns': 'string',
                'PublicIp': 'string',
                'RegisteredBy': 'string',
                'ReportedAgentVersion': 'string',
                'ReportedOs': {
                    'Family': 'string',
                    'Name': 'string',
                    'Version': 'string'
                },
                'RootDeviceType': 'ebs'|'instance-store',
                'RootDeviceVolumeId': 'string',
                'SecurityGroupIds': [
                    'string',
                ],
                'SshHostDsaKeyFingerprint': 'string',
                'SshHostRsaKeyFingerprint': 'string',
                'SshKeyName': 'string',
                'StackId': 'string',
                'Status': 'string',
                'SubnetId': 'string',
                'Tenancy': 'string',
                'VirtualizationType': 'paravirtual'|'hvm'
            },
        ]
    }

    :returns:
    (string) --

    """
    pass


def build_endpoint_route_name(cls, method_name, class_name=None):
    """
    Build the route endpoint
    It is recommended to place your views in /views directory, so it can build
    the endpoint from it. If not, it will make the endpoint from the module name
    The main reason for having the views directory, it is explicitly easy
    to see the path of the view

    :param cls: The view class
    :param method_name: The name of the method
    :param class_name: To pass the class name.
    :return: string
    """
    module = cls.__module__.split('views.')[1
        ] if '.views.' in cls.__module__ else cls.__module__.split('.')[-1]
    return '%s.%s:%s' % (module, class_name or cls.__name__, method_name)


def or_filter(filter_predicate_one, filter_predicate_two):
    """Combine two filter predicates with the logical NOT."""
    return lambda properties: filter_predicate_one(properties
        ) or filter_predicate_two(properties)


def sub2ind(array_shape, rows, cols):
    """
    Equivalent to the same-named function in Matlab (Except that Matlab is Fortran-styled indexing)
    Usage:
    In Matlab:
    A = reshape(1:30, 6, [])
    sub2ind(size(A), [2, 4], [1, 3])
    ans = 2    16

    Equivalently, in python:
    >>> mat = np.arange(1, 31).reshape((5, 6))
    >>> ind = sub2ind(mat.shape, np.array([0, 2]), np.array([1, 3]))
    >>> array([ 1, 15])

    Notice that the row and column arrays are swapped, and the indices are 1 less than that in Matlab,
    e.g. [1, 3] => [0, 2]

    :param array_shape:
    :param rows:
    :param cols:
    :return:
    """
    ind = rows * array_shape[1] + cols
    ind[ind < 0] = -1
    ind[ind >= array_shape[0] * array_shape[1]] = -1
    return ind


def CDLLOWSHAS(df, open='Open', low='Low', close='Close'):
    """
    Candle Lower Shadow Size
    Returns: list of floats = jhta.CDLLOWSHAS(df, open='Open', low='Low', close='Close')
    Source: https://www.tradeciety.com/understand-candlesticks-patterns/
    """
    cdl_list = []
    for i in range(len(df[close])):
        body = df[close][i] - df[open][i]
        if body < 0:
            cdl = df[close][i] - df[low][i]
        else:
            cdl = df[open][i] - df[low][i]
        cdl_list.append(cdl)
    return cdl_list


def _jeans_integrand_term2(y, *args):
    """ Second term in the Jeans integrand
    """
    bias_ratio = args[0]
    numerator = bias_ratio
    denominator = y ** 2 * (1 + y) ** 2 * (1 + bias_ratio * y)
    return numerator / denominator


@classmethod
def _get_apic_classes(cls):
    """
        Get the APIC classes used by this acitoolkit class.

        :returns: list of strings containing APIC class names
        """
    resp = ['eqptBoard']
    return resp


def parse_spaces(opts):
    """
    Ensure user-defined spatial references for outputs are correctly parsed.

    Certain options require normalization to a space not explicitly defined by users.
    These spaces will not be included in the final outputs.

    """
    spaces = opts.output_spaces
    if not spaces.references and not spaces.is_cached():
        spaces.add('MNI152NLin2009cAsym')
    if not spaces.is_cached():
        spaces.checkpoint()
    if opts.use_aroma:
        spaces.add(('MNI152NLin6Asym', {'res': '2'}))
    if opts.cifti_output:
        vol_res = '2' if opts.cifti_output == '91k' else '1'
        spaces.add(('fsaverage', {'den': '164k'}))
        spaces.add(('MNI152NLin6Asym', {'res': vol_res}))
    if 'MNI152NLin2009cAsym' not in spaces.get_spaces(nonstandard=False,
        dim=(3,)):
        spaces.add('MNI152NLin2009cAsym')
    return spaces


def __call__():
    """perform the detection."""


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 profiles():
    """This function can also be a variable

    Example:
        profiles = ["profile1", "profile2"]

    """
    import os
    demo_profiles = ['alita', 'lotr', 'test_noexist', 'test_noapps',
        'test_badapps']
    user_profiles = os.getenv('MY_PROFILES', '').split(',')
    return user_profiles + demo_profiles


@classmethod
def set_channel_layout(cls, client, channel_id, layout, layout_id='1'):
    """returns the json layout set.

        layout must be a json string
        """
    path = '/admin/channel%s/layouts/%s' % (channel_id, layout_id)
    extra_headers = {'Content-Type': 'application/json; charset=UTF-8'}
    r = client.post(path=path, data=layout, extra_headers=extra_headers)
    return r.text


def unregister(ob):
    """
        Remove the object from the indexes.

        If the *ob* is not previously registered, this has no effect.

        An :class:`IIdRemovedEvent` is triggered for successful
        unregistrations.

        """


@staticmethod
def findinputslice(coord, sliceshape, sheetshape):
    """
        Gets the matrix indices of a slice within an array of size
        sheetshape from a sliceshape, positioned at coord.
        """
    center_row, center_col = coord
    n_rows, n_cols = sliceshape
    sheet_rows, sheet_cols = sheetshape
    c1 = -min(0, center_col - n_cols / 2)
    r1 = -min(0, center_row - n_rows / 2)
    c2 = -max(-n_cols, center_col - sheet_cols - n_cols / 2)
    r2 = -max(-n_rows, center_row - sheet_rows - n_rows / 2)
    return r1, r2, c1, c2


def convert_adsorption_energy_units(AE):
    """Converts the adsorption energy into units of KJ/mol

    Parameters
    ----------
    AE : array like
        array of adsorption energies

    Returns
    -------
    array like
        array of adsorption energies in units of KJ/mol
    """
    return AE * 96.485 * 1000


def check_attr(attr):
    """
    Checks whether the attr is a class and whether
    it does inherit from Component and whether
    """
    from pybliotecario.components.component_core import Component
    if not isinstance(attr, type):
        return False
    if attr == Component:
        return False
    if issubclass(attr, Component):
        return (not Component.configure_me.__code__ == attr.configure_me.
            __code__)
    return False


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


def removeCallback(service, nodeIdentifier, callback):
    """
        Remove a registered callback URI.

        The returned deferred will fire with a boolean that signals wether or
        not this was the last callback unregistered for this node.

        @param service: The XMPP entity that holds the node.
        @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
        @param nodeIdentifier: The identifier of the publish-subscribe node.
        @type nodeIdentifier: C{unicode}.
        @param callback: The callback URI to be unregistered.
        @type callback: C{str}.
        @rtype: L{Deferred<twisted.internet.defer.Deferred>}
        """


def get_user_name(user_email):
    """
        returns the full name associated with the user_email
        """


def run_command_from_args(args):
    """Run a subcommand with previously parsed arguments in an argparse namespace.

    This function is intended to be used for unit testing.

    Parameters
    ----------
    args : Namespace
        Command line arguments are stored as attributes of a Namespace.
        The args are obtained by calling parse_argument_list().

    Returns
    -------
    Returns 0 on success if it completes with no exceptions.
    """
    return args.func(args)


@staticmethod
def _append_step_results(tx_result: 'TransactionResult', context:
    'IconScoreContext', step_used_details: dict) ->int:
    """
        Appends step usage information to TransactionResult
        """
    final_step_used = sum(step_used_details.values())
    tx_result.step_used = final_step_used
    tx_result.cumulative_step_used = (context.cumulative_step_used +
        final_step_used)
    if final_step_used != step_used_details.get(context.msg.sender, 0):
        tx_result.step_used_details = step_used_details
    return final_step_used


def check_field_exists(data, parameter):
    """Utility to check json field is present."""
    present = False
    if data and parameter:
        fields = parameter.split('.')
        curdata = data
        if fields:
            allfields = True
            for field in fields:
                if curdata:
                    if field in curdata and isinstance(curdata, dict):
                        curdata = curdata[field]
                    else:
                        allfields = False
            if allfields:
                present = True
    return present


def check_detach_disk(num1, num2):
    """Check detach disk result via simple disk number
       comparison
    """
    if num2 < num1:
        return True
    else:
        return False


def float16(val):
    """Convert a 16-bit floating point value to a standard Python float."""
    frac = val & 1023
    exp = val >> 10 & 31
    sign = val >> 15
    if exp:
        value = 2 ** (exp - 16) * (1 + float(frac) / 2 ** 10)
    else:
        value = float(frac) / 2 ** 9
    if sign:
        value *= -1
    return value


def switch(label, key=False):
    """
        overt switch to linked chain configured in external appspace

        @param label: linked chain label
        @param key: linked chain chain key (default: False)
        """


def find_longitude_wrap_start(packed_data_item):
    """
    ONLY WORK OUT THE WRAP START OF THE DATA
    :param packed_data_item:
    :return:
    """
    from iris.exceptions import CoordinateNotFoundError
    try:
        x_points_min = packed_data_item.coord(standard_name='longitude'
            ).points.min()
    except CoordinateNotFoundError:
        x_wrap_start = None
    else:
        x_wrap_start = -180 if x_points_min < 0 else 0
    return x_wrap_start


def generic_find_fk_constraint_name(table, columns, referenced, insp):
    """Utility to find a foreign-key constraint name in alembic migrations"""
    for fk in insp.get_foreign_keys(table):
        if fk['referred_table'] == referenced and set(fk['referred_columns']
            ) == columns:
            return fk['name']


def conv_output_length(input_length, filter_size, padding, stride, dilation=1):
    """Determines output length of a convolution given input length.
    # Arguments
        input_length: integer.
        filter_size: integer.
        padding: one of `"same"`, `"valid"`, `"full"`.
        stride: integer.
        dilation: dilation rate, integer.
    # Returns
        The output length (integer).
    """
    if input_length is None:
        return None
    assert padding in {'same', 'valid', 'full', 'causal'}
    dilated_filter_size = (filter_size - 1) * dilation + 1
    if padding == 'same':
        output_length = input_length
    elif padding == 'valid':
        output_length = input_length - dilated_filter_size + 1
    elif padding == 'causal':
        output_length = input_length
    elif padding == 'full':
        output_length = input_length + dilated_filter_size - 1
    return (output_length + stride - 1) // stride


@classmethod
def register_property_set_type(cls, name, group_yaml_type, estimator_type):
    """(class method) Register new property set type.

        Parameters
        ----------
        name : str
            Name of new property set type.
        group_yaml_type : str
            Name of property set type in the YAML type namespace.
        estimator_type : class
            The provided class is instantiated when an estimate is to be made
            for a particular set of groups.  The constructor should accept the
            following parameters:

                library : :class:`GroupLibrary`
                    library which is to be used to estimate these properties.
                groups : mapping
                    Map from :class:`Group` to int or float specifying counts
                    of each group in the chemical structure.
        """
    if name in cls._property_set_group_yaml_types:
        raise KeyError('Property set %r already registered.' % name)
    cls._property_set_group_yaml_types[name] = group_yaml_type
    cls._property_set_estimator_types[name] = estimator_type


def _add_doc(func, doc):
    """Add documentation to a function."""
    func.__doc__ = doc


def get_schema():
    """Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {'mongo_indexes': {'index_updated': [('_updated', 1)],
        'index_name': [('name', 1)]}, 'schema': {'schema_version': {'type':
        'integer', 'default': 1}, 'imported_from': {'schema_version': 1,
        'title': 'Imported from', 'comment':
        'Item importation source (alignak-backend-import, ...)', 'type':
        'string', 'default': 'unknown'}, 'definition_order': {
        'schema_version': 1, 'title': 'Definition order', 'comment':
        'Priority level if several elements have the same name', 'type':
        'integer', 'default': 100}, 'name': {'schema_version': 1, 'title':
        'Realm name', 'comment': 'Unique realm name', 'type': 'string',
        'required': True, 'empty': False, 'unique': True, 'regex':
        '^[a-zA-Z0-9 \\-_]+$'}, 'alias': {'schema_version': 1, 'title':
        'Alias', 'comment':
        'Element friendly name used by the Web User Interface.', 'type':
        'string', 'default': ''}, 'notes': {'schema_version': 1, 'title':
        'Notes', 'comment':
        'Element notes. Free text to store element information.', 'type':
        'string', 'default': ''}, 'default': {'schema_version': 1, 'title':
        'Default realm', 'comment':
        'This realm is the default realm used when no realm information is provided.'
        , 'type': 'boolean', 'default': False}, 'hosts_critical_threshold':
        {'schema_version': 1, 'type': 'integer', 'min': 0, 'max': 100,
        'default': 5}, 'hosts_warning_threshold': {'schema_version': 1,
        'type': 'integer', 'min': 0, 'max': 100, 'default': 3},
        'services_critical_threshold': {'schema_version': 1, 'type':
        'integer', 'min': 0, 'max': 100, 'default': 5},
        'services_warning_threshold': {'schema_version': 1, 'type':
        'integer', 'min': 0, 'max': 100, 'default': 3},
        'global_critical_threshold': {'schema_version': 1, 'type':
        'integer', 'min': 0, 'max': 100, 'default': 5},
        'global_warning_threshold': {'schema_version': 1, 'type': 'integer',
        'min': 0, 'max': 100, 'default': 3}, '_parent': {'schema_version':
        1, 'title': 'Parent', 'comment':
        'Immediate parent in the hierarchy', 'type': 'objectid',
        'data_relation': {'resource': 'realm', 'embeddable': True},
        'default': None}, '_tree_parents': {'schema_version': 1, 'title':
        'Parents', 'comment': 'List of parents in the hierarchy', 'type':
        'list', 'schema': {'type': 'objectid', 'data_relation': {'resource':
        'realm', 'embeddable': True}}, 'default': []}, '_children': {
        'schema_version': 1, 'title': 'Children', 'comment':
        'List of the immediate children in the hierarchy', 'type': 'list',
        'schema': {'type': 'objectid', 'data_relation': {'resource':
        'realm', 'embeddable': True}}, 'default': []}, '_all_children': {
        'schema_version': 1, 'title': 'Children', 'comment':
        'List of all the children in the hierarchy', 'type': 'list',
        'schema': {'type': 'objectid', 'data_relation': {'resource':
        'realm', 'embeddable': True}}, 'default': []}, '_level': {
        'schema_version': 1, 'title': 'Level', 'comment':
        'Level in the hierarchy', 'type': 'integer', 'default': 0},
        '_users_read': {'schema_version': 1, 'type': 'list', 'schema': {
        'type': 'objectid', 'data_relation': {'resource': 'user',
        'embeddable': True}}}, '_users_update': {'schema_version': 1,
        'type': 'list', 'schema': {'type': 'objectid', 'data_relation': {
        'resource': 'user', 'embeddable': True}}}, '_users_delete': {
        'schema_version': 1, 'type': 'list', 'schema': {'type': 'objectid',
        'data_relation': {'resource': 'user', 'embeddable': True}}}},
        'schema_deleted': {}}


@staticmethod
def _get_ancestry_of(entity):
    """
        Get the ancestry of this entity, beginning from the most abstract and terminating by this entity
        :param entity: The entity
        :return: The ancestry
        """
    ancestors = entity.ancestors()
    result = list(reversed(ancestors))
    result.append(entity)
    return result


def get_session_from_request_assertion(assertion):
    u"""
    Получение ID сессии из запроса на выход (утверждения)

    :param assertion: Утверждение (Assertion, xml)
    :type assertion: etree.ElementTree
    :return: идентификатор сессии
    :rtype: basestring
    """
    session_id = None
    statement = assertion.xpath('//saml2p:LogoutRequest//saml2p:SessionIndex',
        namespaces={'saml2p': 'urn:oasis:names:tc:SAML:2.0:protocol',
        'saml2': 'urn:oasis:names:tc:SAML:2.0:assertion'})
    if len(statement) > 0:
        session_id = statement[0].text
    return session_id


@classmethod
def _get_with_cache(cls, url):
    """ Get resource from either cache or rest
        :returns JSONObject
        """
    try:
        return cls._cache[url]
    except KeyError:
        api = cls(None, None)
        return cls._cache.setdefault(url, api.method(url))


def production_variant(model_name, instance_type, initial_instance_count=1,
    variant_name='AllTraffic', initial_weight=1, accelerator_type=None):
    """Create a production variant description suitable for use in a ``ProductionVariant`` list as
    part of a ``CreateEndpointConfig`` request.

    Args:
        model_name (str): The name of the SageMaker model this production variant references.
        instance_type (str): The EC2 instance type for this production variant. For example,
            'ml.c4.8xlarge'.
        initial_instance_count (int): The initial instance count for this production variant
            (default: 1).
        variant_name (string): The ``VariantName`` of this production variant
            (default: 'AllTraffic').
        initial_weight (int): The relative ``InitialVariantWeight`` of this production variant
            (default: 1).
        accelerator_type (str): Type of Elastic Inference accelerator for this production variant.
            For example, 'ml.eia1.medium'.
            For more information: https://docs.aws.amazon.com/sagemaker/latest/dg/ei.html

    Returns:
        dict[str, str]: An SageMaker ``ProductionVariant`` description
    """
    production_variant_configuration = {'ModelName': model_name,
        'InstanceType': instance_type, 'InitialInstanceCount':
        initial_instance_count, 'VariantName': variant_name,
        'InitialVariantWeight': initial_weight}
    if accelerator_type:
        production_variant_configuration['AcceleratorType'] = accelerator_type
    return production_variant_configuration


def get(isamAppliance, uuid, check_mode=False, force=False):
    """
    Retrieving a single interface
    """
    return isamAppliance.invoke_get('Retrieving a single interface',
        '/net/ifaces/' + uuid)


def compute_address_commandable(address):
    """
    Creates a commandable address, with the checksum appended
    :param address: A list of bytes corresponding to the address or the actual address in question
    :return: A list of bytes corresponding to the address with the checksum appended
    """
    if not isinstance(address, bytearray):
        if isinstance(address, bytes) or isinstance(address, list):
            address = bytearray(address)
        else:
            address = [address >> 24 & 255, address >> 16 & 255, address >>
                8 & 255, address & 255]
    checksum = 0
    for x in address:
        checksum ^= x
    address.append(checksum)
    return address


def get_field_entry_key(node: 'FieldNode') ->str:
    """
    Implements the logic to compute the key of a given field's entry.
    :param node: field node from which to extract the entry key
    :type node: FieldNode
    :return: the field entry key
    :rtype: str
    """
    return node.alias.value if node.alias else node.name.value


@staticmethod
def _create_message(result=None, *args, **kwargs):
    """
        Формирует сообщение для записи в лог
        :param result: результат работы функции
        :param args: любые параметры по порядку
        :param kwargs: любые именованные параметры
        :return:

        """
    message = ''
    if args:
        message += f"args: {str(args).replace(',)', ')')} "
    if kwargs:
        message += f'kwargs: {kwargs}'
    if result:
        message += f' result: {result}'
    return message


def format(msg, leftmargin=0, rightmargin=78):
    """Format a message by inserting line breaks at appropriate places.

    msg is the text of the message.
    leftmargin is the position of the left margin.
    rightmargin is the position of the right margin.

    Return the formatted message.
    """
    curs = leftmargin
    fmsg = ' ' * leftmargin
    for w in msg.split():
        l = len(w)
        if curs != leftmargin and curs + l > rightmargin:
            fmsg = fmsg + '\n' + ' ' * leftmargin
            curs = leftmargin
        if curs > leftmargin:
            fmsg = fmsg + ' '
            curs = curs + 1
        fmsg = fmsg + w
        curs = curs + l
    return fmsg


@classmethod
def required(cls):
    """Return a list of all columns required by the database to create the
        resource.

        :param cls: The Model class to gather attributes from
        :rtype: list
        """
    columns = []
    for column in cls.__table__.columns:
        is_autoincrement = 'int' in str(column.type).lower(
            ) and column.autoincrement
        if (not column.nullable and not column.primary_key or column.
            primary_key and not is_autoincrement):
            columns.append(column.name)
    return columns


def grant_permission_to_principal(permission_id, principal_id):
    """Assert that the permission is allowed for the principal.
        """


def _translate_slice(exp, length):
    """ Given a slice object, return a 3-tuple
        (start, count, step)
        for use with the hyperslab selection routines
    """
    start, stop, step = exp.indices(length)
    if step < 1:
        raise ValueError('Step must be >= 1 (got %d)' % step)
    if stop < start:
        return 0, 0, 1
    count = 1 + (stop - start - 1) // step
    return start, count, step


def love(cs, pc=None, fmt=None):
    """ quicklove command """
    pc = pc or cs.make_plans_connection()
    fmt = fmt or cs.make_formatter()
    cs.hook('pre_search', pc.username, planlove=True)
    results = pc.search_plans(pc.username, planlove=True)
    cs.hook('post_search', results)
    fmt.print_search_results(results)


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


@staticmethod
def _delete_redundant_policy(infra, policy_type):
    """
        Removes redundant policies
        """
    policies = []
    for idx, child in enumerate(infra['infraInfra']['children']):
        if policy_type in child:
            policy_name = child[policy_type]['attributes']['name']
            if policy_name in policies:
                del infra['infraInfra']['children'][idx]
            else:
                policies.append(policy_name)
    return infra


def make_encoding_map(decoding_map):
    """ Creates an encoding map from a decoding map.

        If a target mapping in the decoding map occurs multiple
        times, then that target is mapped to None (undefined mapping),
        causing an exception when encountered by the charmap codec
        during translation.

        One example where this happens is cp875.py which decodes
        multiple character to \\u001a.

    """
    m = {}
    for k, v in decoding_map.items():
        if not v in m:
            m[v] = k
        else:
            m[v] = None
    return m


def _should_use_existing_connection(setup):
    """
    The new connection dispatch approach is used by PyDev when the `multiprocess` option is set,
    the existing connection approach is used by PyCharm when the `multiproc` option is set.
    """
    return setup.get('multiproc', False)


def minimize_stretch(fill_holes: bool=True, blend: float=0.0, iterations: int=0
    ):
    """Reduce UV stretching by relaxing angles

    :param fill_holes: Fill Holes, Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry
    :type fill_holes: bool
    :param blend: Blend, Blend factor between stretch minimized and original
    :type blend: float
    :param iterations: Iterations, Number of iterations to run, 0 is unlimited when run interactively
    :type iterations: int
    """
    pass


def subscript(cube, index, value):
    """Filter cube1 using the index and the value. Return a new cube without the index1 dimension
        Ex.
            cp.subscript(nodo_ejemplo,index_para_ejemplo,"Item 1")
    """
    return cube[index == value]


def unpad(buf, byte=None):
    """Truncate the padded bytes.
    None = autodetect
    """
    if not isinstance(buf, bytes):
        raise TypeError('Buffer must be in bytes')
    if byte is None:
        byte = buf[-1:]
    return buf.rstrip(byte)


def find_tokens(text, tokenizer):
    """Return a generator of `{"token", "character", "target"}` dictionaries by
    tokenizing some text.

    `text` -- `string` -- the text to tokenize

    `tokenizer` -- `regex.Regex` -- the tokenizer to use on the text
                   (supporting `finditer`)

    `return` -- `generator(dict)` -- a generator of tokens, which have keys:

      - `token` -- `int` -- index of the token in the message
      - `character` -- `int` -- index of the first character of the token in
                       the message
      - `target` -- `string` -- the text content of the token itself
    """
    for i, m in enumerate(tokenizer.finditer(text)):
        yield dict(token=i, character=m.span()[0], target=m.group())


def normalize_time(timestamp):
    """Normalize time in arbitrary timezone to UTC naive object."""
    offset = timestamp.utcoffset()
    if offset is None:
        return timestamp
    return timestamp.replace(tzinfo=None) - offset


def apply_weather_correction(enduse, fuel_y, cooling_factor_y,
    heating_factor_y, enduse_space_heating, enduse_space_cooling,
    f_weather_correction):
    """Change fuel demand for heat and cooling service
    depending on changes in HDD and CDD within a region
    (e.g. climate change induced). Change fuel consumption based on
    climate change induced temperature differences

    Arguments
    ----------
    enduse : str
        Enduse
    fuel_y : array
        Yearly fuel per fueltype
    cooling_factor_y : array
        Distribution of fuel within year to days (yd)
    heating_factor_y : array
        Distribution of fuel within year to days (yd)
    enduse_space_heating : list
        Enduses defined as space heating
    enduse_space_cooling : list
        Enduses defined as space cooling
    f_weather_correction : dict
        Correction factors to calculate hdd and cdd
        related extra demands in case a different
        weather station is used

    Return
    ------
    fuel_y : array
        Changed yearly fuel per fueltype

    Note
    ----
    - `cooling_factor_y` and `heating_factor_y` are based on the sum
        over the year. Therefore it is assumed that fuel correlates
        directly with HDD or CDD.
    """
    if enduse in enduse_space_heating:
        fuel_y = fuel_y * f_weather_correction['hdd']
        fuel_y = fuel_y * heating_factor_y
    elif enduse in enduse_space_cooling:
        fuel_y = fuel_y * f_weather_correction['cdd']
        fuel_y = fuel_y * cooling_factor_y
    return fuel_y


@classmethod
def from_code(cls, status_code, **kwargs):
    """ Instantiate one of subclasses by code

            :rtype: type
        """
    for C in cls.__subclasses__():
        if C.status_code == status_code:
            return C(**kwargs)
    return cls(**kwargs)


def _write_log(*msg, end='\n'):
    """Write message to log output, ignoring the verbosity level.
    This is the most basic function.
    Parameters
    ----------
    *msg :
        One or more arguments to be formatted as string. Same behavior as print
        function.
    """
    from .settings import logfile
    if logfile == '':
        print(*msg, end=end)
    else:
        out = ''
        for s in msg:
            out += str(s) + ' '
        with open(logfile, 'a') as f:
            f.write(out + end)


@staticmethod
def _classification_function_two(salary, commission, age, elevel, car,
    zipcode, hvalue, hyears, loan):
    """ classification_function_two

        Parameters
        ----------
        salary: float
            Numeric feature: Salary.

        commission: float
            Numeric feature: Commission.

        age: int
            Numeric feature: Age.

        elevel: int
            Categorical feature: Education level.

        car: int
            Categorical feature: Car maker.

        zipcode; int
            Categorical feature: Zipcode.

        hvalue: flaot
            Numeric feature: Value of the house.

        hyears: float
            Numeric feature: Years house owned.

        loan: float
            Numeric feature: Total amount of loan.

        Returns
        -------
        int
            Returns the sample class label, either 0 or 1.

        """
    if age < 40:
        return 0 if elevel == 0 or elevel == 1 else 1
    elif age < 60:
        return 0 if elevel == 1 or elevel == 2 or elevel == 3 else 1
    else:
        return 0 if (elevel == 2 or elevel == 3) or elevel == 4 else 1


@classmethod
def get_collection_name(cls):
    """ Returns the collection name used by the class.  If the ``config_collection_name``
            attribute is set it is used, otherwise the name of the class is used."""
    if not hasattr(cls, 'config_collection_name'):
        return cls.__name__
    return cls.config_collection_name


def get_link_loops(vert):
    """
    Get loop linked to vertex
    """
    link_loops = []
    for f in vert.link_faces:
        adj_loops = []
        for loop in f.loops:
            if loop.vert == vert:
                l = loop
            else:
                for e in loop.vert.link_edges:
                    if e.other_vert(loop.vert) == vert:
                        adj_loops.append(loop)
        if len(adj_loops) < 2:
            return None
        link_loops.append({'l': l, 'l0': adj_loops[0], 'l1': adj_loops[1]})
    return link_loops


def get_enzyme_reactions(eid, db):
    """
    For a given ec number return associated reaction ids
    :param eid: enzyme id format "EC-x.x.x.x"
    :param db: database dict
    :return:
    """
    erids = []
    if eid[:3] != 'EC-':
        eid = 'EC-{}'.format(eid)
    for rid, react in db['reactions'].items():
        if 'EC-NUMBER' in react and eid in react['EC-NUMBER']:
            erids.append(rid)
    return erids


def get_waypoint_in_distance(waypoint, distance):
    """
    Obtain a waypoint in a given distance from the current actor's location.
    Note: Search is stopped on first intersection.
    @return obtained waypoint and the traveled distance
    """
    traveled_distance = 0
    while not waypoint.is_intersection and traveled_distance < distance:
        waypoint_new = waypoint.next(1.0)[-1]
        traveled_distance += waypoint_new.transform.location.distance(waypoint
            .transform.location)
        waypoint = waypoint_new
    return waypoint, traveled_distance


def prepareLimitsChangedSignal(sourceObj, xRange, yRange, y2Range):
    """See Plot documentation for content of events"""
    return {'event': 'limitsChanged', 'source': id(sourceObj), 'xdata':
        xRange, 'ydata': yRange, 'y2data': y2Range}


def resolve_import(import_path, from_module):
    """Resolves relative imports from a module.
    """
    if not import_path or not import_path.startswith('.'):
        return import_path
    from_module = from_module.split('.')
    dots = 0
    for c in import_path:
        if c == '.':
            dots += 1
        else:
            break
    if dots:
        from_module = from_module[:-dots]
        import_path = import_path[dots:]
    if import_path:
        from_module.append(import_path)
    return '.'.join(from_module)


def get_poly_bounds(poly1):
    """ Find the bounds of the Polygon.

    Parameters
    -------
    poly1 : Polygon
        contour with shapely polygon format

    Returns
    -------
    min_h : int
        minimum y coordinate of polygon
    min_w : int
        minimum x coordinate of polygon
    max_h : int
        maximum y coordinate of polygon
    max_w : int
        maximum x coordinate of polygon

    """
    min_x, min_y, max_x, max_y = poly1.bounds
    min_h, min_w = min_y, min_x
    max_h, max_w = max_y, max_x
    return min_h, min_w, max_h, max_w


def decode_params(string):
    """
    translate string made of 0 1 to resp False True
    """
    b = [True] * len(string)
    for k, s in enumerate(string):
        if s == '0':
            b[k] = False
    return b


def get_default_bias_to_obvious_steps():
    """
    Parameter regarding obvious plays during end-game simulations (not during games)

    [Warning] Important advice: you might want to keep this boolean to False! Otherwise, there is a huge burden of
    computation, which hinders your ability to play with other parameters such as the number of Monte Carlo samples.

    It might sound worth it as the end-game evaluations should be more accurate. However, AI spends most of its
    computation power checking whether each *random* move might be a winning move during end-game simulations, which
    is not a smart way to "think" for an AI. The result is an AI which is less good at the game than it could be.

    AI plays "obvious steps" (one-step win, or one-step win-deny for the opponent), no matter this parameter.
    Only the end-game simulations rely on this parameter.
    """
    bias_to_obvious_steps = True
    return bias_to_obvious_steps


def retrieveSubstitute(history_id, selector, default=None):
    """Return a selected version of an object or a substitute

        Called by the storage if the object to be retrieved was purged.
        Implement the policy in case a client tries to retrieve a purged
        version.

        Return a substitute of ``IVersionData`` type.
        """


def legendre_symbol(a, p):
    """
    Computes the Legendre symbol
    :param a: number
    :param p: prime number
    :return: Returns 1 if `a` has a square root modulo p, -1 otherwise.
    """
    ls = pow(a, (p - 1) // 2, p)
    if ls == p - 1:
        return -1
    return ls


@staticmethod
def module_repr(module):
    """Return repr for the module.

        The method is deprecated.  The import machinery does the job itself.

        """
    return '<module {!r} (built-in)>'.format(module.__name__)


def iterexcept(call, exception, start=None):
    """
    Call function `call` until `exception` is raised.

    from Raymond Hettinger Python Cookbook recipe # 577155
    """
    try:
        if start is not None:
            yield start()
        while 1:
            yield call()
    except exception:
        pass


def filter_headers(data):
    """只设置host content-type 还有x开头的头部.

    :param data(dict): 所有的头部信息.
    :return(dict): 计算进签名的头部.
    """
    headers = {}
    for i in data:
        if i == 'Content-Type' or i == 'Host' or i[0] == 'x' or i[0] == 'X':
            headers[i] = data[i]
    return headers


def add_finder_patterns(matrix, is_micro):
    """    Adds the finder pattern(s) with the separators to the matrix.

    QR Codes get three finder patterns, Micro QR Codes have just one finder
    pattern.

    ISO/IEC 18004:2015(E) -- 6.3.3 Finder pattern (page 16)
    ISO/IEC 18004:2015(E) -- 6.3.4 Separator (page 17)

    :param matrix: The matrix.
    :param bool is_micro: Indicates if the matrix represents a Micro QR Code.
    """
    pattern = (0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 1, 1, 1, 1, 1, 1, 1, 0), (0,
        1, 0, 0, 0, 0, 0, 1, 0), (0, 1, 0, 1, 1, 1, 0, 1, 0), (0, 1, 0, 1,
        1, 1, 0, 1, 0), (0, 1, 0, 1, 1, 1, 0, 1, 0), (0, 1, 0, 0, 0, 0, 0, 1, 0
        ), (0, 1, 1, 1, 1, 1, 1, 1, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0)
    corners = (0, 0), (0, len(matrix) - 8), (-8, 0)
    if is_micro:
        corners = (0, 0),
    finder_range = range(8)
    for i, j in corners:
        offset = 1 if i == 0 else 0
        sepoffset = 0 if j != 0 else 1
        for r in finder_range:
            matrix[i + r][j:j + 8] = pattern[offset + r][sepoffset:
                sepoffset + 8]


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 _union(xval, iunion, ix):
    """helper method for ``filter``"""
    import numpy as np
    if xval:
        if iunion:
            iunion = np.union1d(iunion, ix)
        else:
            pass
    return iunion


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

        :param str val:
        :rtype: MemberSelector
        """
    return cls('dropbox_id', val)


def get_ratio_w_h(ratio):
    """
    returns width and height from string e.g. '1-2' or '4-3' as integer
    """
    w, h = ratio.split('-')
    return float(w), float(h)


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


def store_clip_pos(locus, chr, seq, flag, CLIP_note):
    """
	A data structure store info of soft-clippings.
	It has two hashtables:
		1. key1 is an integer calculated by coordinate / 10000;
		2. key2 is an integer calculated by (coordinate % 10000) / 50.
	"""
    hash_1 = int(locus / 10000)
    mod = locus % 10000
    hash_2 = int(mod / 50)
    element = [locus, seq, flag]
    if hash_1 not in CLIP_note[chr]:
        CLIP_note[chr][hash_1] = dict()
        CLIP_note[chr][hash_1][hash_2] = list()
        CLIP_note[chr][hash_1][hash_2].append(element)
    elif hash_2 not in CLIP_note[chr][hash_1]:
        CLIP_note[chr][hash_1][hash_2] = list()
        CLIP_note[chr][hash_1][hash_2].append(element)
    else:
        CLIP_note[chr][hash_1][hash_2].append(element)


def pristinemethod(func):
    """
    A decorator for handling pristine settings like callables.

    Use it like this::

        from configurations import Configuration, pristinemethod

        class Develop(Configuration):

            @pristinemethod
            def USER_CHECK(user):
                return user.check_perms()

            GROUP_CHECK = pristinemethod(lambda user: user.has_group_access())

    """
    func.pristine = True
    return staticmethod(func)


@classmethod
def bind(cls, ns, location=None):
    """
        Bind a namespace to a schema location (URI).
        This is used for imports that don't specify a schemaLocation.
        @param ns: A namespace-uri.
        @type ns: str
        @param location: The (optional) schema location for the
            namespace.  (default=ns).
        @type location: str
        """
    if location is None:
        location = ns
    cls.locations[ns] = location


def update_ip_set(IPSetId=None, ChangeToken=None, Updates=None):
    """
    Inserts or deletes  IPSetDescriptor objects in an IPSet . For each IPSetDescriptor object, you specify the following values:
    AWS WAF supports /8, /16, /24, and /32 IP address ranges for IPv4, and /24, /32, /48, /56, /64 and /128 for IPv6. For more information about CIDR notation, see the Wikipedia entry Classless Inter-Domain Routing .
    IPv6 addresses can be represented using any of the following formats:
    You use an IPSet to specify which web requests you want to allow or block based on the IP addresses that the requests originated from. For example, if you're receiving a lot of requests from one or a small number of IP addresses and you want to block the requests, you can create an IPSet that specifies those IP addresses, and then configure AWS WAF to block the requests.
    To create and configure an IPSet , perform the following steps:
    When you update an IPSet , you specify the IP addresses that you want to add and/or the IP addresses that you want to delete. If you want to change an IP address, you delete the existing IP address and add the new one.
    For more information about how to use the AWS WAF API to allow or block HTTP requests, see the AWS WAF Developer Guide .
    See also: AWS API Documentation

    Examples
    The following example deletes an IPSetDescriptor object in an IP match set with the ID example1ds3t-46da-4fdb-b8d5-abc321j569j5.
    Expected Output:

    :example: response = client.update_ip_set(
        IPSetId='string',
        ChangeToken='string',
        Updates=[
            {
                'Action': 'INSERT'|'DELETE',
                'IPSetDescriptor': {
                    'Type': 'IPV4'|'IPV6',
                    'Value': 'string'
                }
            },
        ]
    )

    :type IPSetId: string
    :param IPSetId: [REQUIRED]
            The IPSetId of the IPSet that you want to update. IPSetId is returned by CreateIPSet and by ListIPSets .

    :type ChangeToken: string
    :param ChangeToken: [REQUIRED]
            The value returned by the most recent call to GetChangeToken .

    :type Updates: list
    :param Updates: [REQUIRED]
            An array of IPSetUpdate objects that you want to insert into or delete from an IPSet . For more information, see the applicable data types:
            IPSetUpdate : Contains Action and IPSetDescriptor
            IPSetDescriptor : Contains Type and Value
            (dict) --Specifies the type of update to perform to an IPSet with UpdateIPSet .
            Action (string) -- [REQUIRED]Specifies whether to insert or delete an IP address with UpdateIPSet .
            IPSetDescriptor (dict) -- [REQUIRED]The IP address type (IPV4 or IPV6 ) and the IP address range (in CIDR notation) that web requests originate from.
            Type (string) -- [REQUIRED]Specify IPV4 or IPV6 .
            Value (string) -- [REQUIRED]Specify an IPv4 address by using CIDR notation. For example:
            To configure AWS WAF to allow, block, or count requests that originated from the IP address 192.0.2.44, specify 192.0.2.44/32 .
            To configure AWS WAF to allow, block, or count requests that originated from IP addresses from 192.0.2.0 to 192.0.2.255, specify 192.0.2.0/24 .
            For more information about CIDR notation, see the Wikipedia entry Classless Inter-Domain Routing .
            Specify an IPv6 address by using CIDR notation. For example:
            To configure AWS WAF to allow, block, or count requests that originated from the IP address 1111:0000:0000:0000:0000:0000:0000:0111, specify 1111:0000:0000:0000:0000:0000:0000:0111/128 .
            To configure AWS WAF to allow, block, or count requests that originated from IP addresses 1111:0000:0000:0000:0000:0000:0000:0000 to 1111:0000:0000:0000:ffff:ffff:ffff:ffff, specify 1111:0000:0000:0000:0000:0000:0000:0000/64 .

    :rtype: dict
    :return: {
        'ChangeToken': 'string'
    }

    :returns:
    1111:0000:0000:0000:0000:0000:0000:0111/128
    1111:0:0:0:0:0:0:0111/128
    1111::0111/128
    1111::111/128

    """
    pass


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

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


@classmethod
def fromkeys(cls, iterable, value=None):
    """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        """
    d = cls()
    for key in iterable:
        d[key] = value
    return d