def validate_output_transform(x, y, y_pred):
    """A transform to format the output of the supervised evaluator before calculating the metric

    Args:
        x (:obj:`torch.Tensor`): the input to the model
        y (:obj:`torch.Tensor`): the output of the model
        y_pred (:obj:`torch.Tensor`): the ground truth labels

    Returns:
        (:obj:`torch.Tensor`, :obj:`torch.Tensor`): model predictions and ground truths reformatted
    """
    output = y_pred
    labels = y
    B, V, C = output.shape
    B_labels, V_labels, C_labels = labels.shape
    output = output.view(B * V, C)
    labels = labels.view(B_labels * V_labels, C_labels)
    return output, labels


def box_intersect(box1, box2):
    """
    Return intersection box two (bounding) boxes.

    If the boxes don't intersect (0,0,0,0) is returned.

    :param (x,y,w,h) box1: First box with x,y specifying the left upper corner.
    :param (x,y,w,h) box2: Second bounding box.
    :return: Intersection box
    :rtype: (x,y,w,h)
    """
    x1 = max(box1[0], box2[0])
    y1 = max(box1[1], box2[1])
    x2 = min(box1[0] + box1[2], box2[0] + box2[2])
    y2 = min(box1[1] + box1[3], box2[1] + box2[3])
    w, h = x2 - x1, y2 - y1
    return (x1, y1, w, h) if w > 0 and h > 0 else (0, 0, 0, 0)


@classmethod
def is_valid_header(cls, name, value=None):
    """Check whether the field name, and optionally the value, make
        a valid HTTP header.
        """
    valid_name = name and name.lower() not in cls._reserved_headers and bool(
        cls._valid_header_re.match(name))
    valid_value = not cls._disallowed_control_codes_re.search(value
        ) if value else True
    return valid_name & valid_value


@classmethod
def get_user_by_email(cls, email):
    """Case insensitive search"""
    return cls.user_model().objects.get(email__iexact=email)


@classmethod
def get_config_opts(cls):
    """Defines the configuration options to be associated to this loadable

        :return: A list of configuration options relative to this Loadable
        :rtype: list of :class:`oslo_config.cfg.Opt` instances
        """
    return []


def get_item_properties(item, fields, mixed_case_fields=[], formatters={}):
    """Return a tuple containing the item properties.

    :param item: a single item resource (e.g. Server, Tenant, etc)
    :param fields: tuple of strings with the desired field names
    :param mixed_case_fields: tuple of field names to preserve case
    :param formatters: dictionary mapping field names to callables
        to format the values
    """
    row = []
    for field in fields:
        if field in formatters:
            row.append(formatters[field](item))
        else:
            if field in mixed_case_fields:
                field_name = field.replace(' ', '_')
            else:
                field_name = field.lower().replace(' ', '_')
            if not hasattr(item, field_name) and (isinstance(item, dict) and
                field_name in item):
                data = item[field_name]
            else:
                data = getattr(item, field_name, '')
            if data is None:
                data = ''
            row.append(data)
    return tuple(row)


def compose_title(projects, data):
    """ Compose the projects JSON file only with the projects name

    :param projects: projects.json
    :param data: eclipse JSON with the origin format
    :return: projects.json with titles
    """
    for project in data:
        projects[project] = {'meta': {'title': data[project]['title']}}
    return projects


def select_similar_region():
    """Select similar face regions to the current selection

    """
    pass


def toInt(node):
    """ Convert node value to python int.
    """
    node.value = int(node.value)


def KK_RC11_fit(params, w, t_values):
    """
    Kramers-Kronig Function: -RC-

    Kristian B. Knudsen (kknu@berkeley.edu / kristianbknudsen@gmail.com)
    """
    Rs = params['Rs']
    R1 = params['R1']
    R2 = params['R2']
    R3 = params['R3']
    R4 = params['R4']
    R5 = params['R5']
    R6 = params['R6']
    R7 = params['R7']
    R8 = params['R8']
    R9 = params['R9']
    R10 = params['R10']
    R11 = params['R11']
    return Rs + R1 / (1 + w * 1.0j * t_values[0]) + R2 / (1 + w * 1.0j *
        t_values[1]) + R3 / (1 + w * 1.0j * t_values[2]) + R4 / (1 + w *
        1.0j * t_values[3]) + R5 / (1 + w * 1.0j * t_values[4]) + R6 / (1 +
        w * 1.0j * t_values[5]) + R7 / (1 + w * 1.0j * t_values[6]) + R8 / (
        1 + w * 1.0j * t_values[7]) + R9 / (1 + w * 1.0j * t_values[8]
        ) + R10 / (1 + w * 1.0j * t_values[9]) + R11 / (1 + w * 1.0j *
        t_values[10])


def check_word_typo(ent, word):
    """
    spell check word
    """
    return not ent.check(word)


def _icon_classes(name):
    """
    Given the name of an icon, return the classes that will render it
    """
    if name.startswith('fa-'):
        return 'fa ' + name
    if name.startswith('glyphicon'):
        return 'glyphicon ' + name
    return name


@staticmethod
def standard(model, **kwargs):
    """
        Create standard model of molecular evolution.

        Parameters
        ----------

         model : str
            Model to create. See list of available models below
         **kwargs:
            Key word arguments to be passed to the model

        **Available models**

        - JC69:

          Jukes-Cantor 1969 model. This model assumes equal frequencies
          of the nucleotides and equal transition rates between nucleotide states.
          For more info, see: Jukes and Cantor (1969).
          Evolution of Protein Molecules. New York: Academic Press. pp. 21-132.
          To create this model, use:

          :code:`mygtr = GTR.standard(model='jc69', mu=<my_mu>, alphabet=<my_alph>)`

          :code:`my_mu` - substitution rate (float)

          :code:`my_alph` - alphabet (str: :code:`'nuc'` or  :code:`'nuc_nogap'`)

        - K80:

          Kimura 1980 model. Assumes equal concentrations across nucleotides, but
          allows different rates between transitions and transversions. The ratio
          of the transversion/transition rates is given by kappa parameter.
          For more info, see
          Kimura (1980),  J. Mol. Evol. 16 (2): 111-120. doi:10.1007/BF01731581.
          Current implementation of the model does not account for the gaps.

          :code:`mygtr = GTR.standard(model='k80', mu=<my_mu>, kappa=<my_kappa>)`

          :code:`mu` - overall substitution rate (float)

          :code:`kappa` - ratio of transversion/transition rates (float)

        - F81:

          Felsenstein 1981 model. Assumes non-equal concentrations across nucleotides,
          but the transition rate between all states is assumed to be equal. See
          Felsenstein (1981), J. Mol. Evol. 17  (6): 368-376. doi:10.1007/BF01734359
          for details.

          :code:`mygtr = GTR.standard(model='F81', mu=<mu>, pi=<pi>, alphabet=<alph>)`

          :code:`mu` -  substitution rate  (float)

          :code:`pi`  - : nucleotide concentrations (numpy.array)

          :code:`alphabet' -  alphabet to use. (:code:`'nuc'` or  :code:`'nuc_nogap'`)

        - HKY85:

          Hasegawa, Kishino and Yano 1985 model. Allows different concentrations of the
          nucleotides (as in F81) + distinguishes between transition/transversion substitutions
          (similar to K80). Link:
          Hasegawa, Kishino, Yano (1985), J. Mol. Evol. 22 (2): 160-174. doi:10.1007/BF02101694

          Current implementation of the model does not account for the gaps

          :code:`mygtr = GTR.standard(model='HKY85', mu=<mu>, pi=<pi>, kappa=<kappa>)`

          :code:`mu` -  substitution rate  (float)

          :code:`pi`  - : nucleotide concentrations (numpy.array)

          :code:`kappa` - ratio of transversion/transition rates (float)

        - T92:

          Tamura 1992 model. Extending Kimura  (1980) model for the case where a
          G+C-content bias exists. Link:
          Tamura K (1992),  Mol.  Biol. Evol. 9 (4): 678-687.  DOI: 10.1093/oxfordjournals.molbev.a040752

          Current implementation of the model does not account for the gaps

          :code:`mygtr = GTR.standard(model='T92', mu=<mu>, pi_GC=<pi_gc>, kappa=<kappa>)`

          :code:`mu` -  substitution rate  (float)

          :code:`pi_GC`  - : relative GC content

          :code:`kappa` - ratio of transversion/transition rates (float)

        - TN93:

          Tamura and Nei 1993. The model distinguishes between the two different types of
          transition: (A <-> G) is allowed to have a different rate to (C<->T).
          Transversions have the same rate. The frequencies of the nucleotides are allowed
          to be different. Link: Tamura, Nei (1993), MolBiol Evol. 10 (3): 512-526.
          DOI:10.1093/oxfordjournals.molbev.a040023

          :code:`mygtr = GTR.standard(model='TN93', mu=<mu>, kappa1=<k1>, kappa2=<k2>)`

          :code:`mu` -  substitution rate  (float)

          :code:`kappa1`  - relative A<-->C, A<-->T, T<-->G and G<-->C rates (float)

          :code:`kappa` - relative C<-->T rate (float)

          .. Note::
                Rate of A<-->G substitution is set to one. All other rates
                (kappa1, kappa2) are specified relative to this rate

        """
    from .nuc_models import JC69, K80, F81, HKY85, T92, TN93
    from .aa_models import JTT92
    if model.lower() in ['jc', 'jc69', 'jukes-cantor', 'jukes-cantor69',
        'jukescantor', 'jukescantor69']:
        model = JC69(**kwargs)
    elif model.lower() in ['k80', 'kimura80', 'kimura1980']:
        model = K80(**kwargs)
    elif model.lower() in ['f81', 'felsenstein81', 'felsenstein1981']:
        model = F81(**kwargs)
    elif model.lower() in ['hky', 'hky85', 'hky1985']:
        model = HKY85(**kwargs)
    elif model.lower() in ['t92', 'tamura92', 'tamura1992']:
        model = T92(**kwargs)
    elif model.lower() in ['tn93', 'tamura_nei_93', 'tamuranei93']:
        model = TN93(**kwargs)
    elif model.lower() in ['jtt', 'jtt92']:
        model = JTT92(**kwargs)
    else:
        raise KeyError(
            "The GTR model '{}' is not in the list of available models.".
            format(model))
    model.mu = kwargs['mu'] if 'mu' in kwargs else 1.0
    return model


def try_enum(cls, val):
    """A function that tries to turn the value into enum ``cls``.

    If it fails it returns the value instead.
    """
    try:
        return cls(val)
    except ValueError:
        return val


def get_interface_type(interface):
    """Gets the type of interface
    """
    if interface.upper().startswith('GI'):
        return 'GigabitEthernet'
    elif interface.upper().startswith('TE'):
        return 'TenGigabitEthernet'
    elif interface.upper().startswith('FA'):
        return 'FastEthernet'
    elif interface.upper().startswith('FO'):
        return 'FortyGigabitEthernet'
    elif interface.upper().startswith('LON'):
        return 'LongReachEthernet'
    elif interface.upper().startswith('ET'):
        return 'Ethernet'
    elif interface.upper().startswith('VL'):
        return 'Vlan'
    elif interface.upper().startswith('LO'):
        return 'loopback'
    elif interface.upper().startswith('PO'):
        return 'Port-channel'
    elif interface.upper().startswith('NV'):
        return 'nve'
    elif interface.upper().startswith('TWE'):
        return 'TwentyFiveGigE'
    elif interface.upper().startswith('HU'):
        return 'HundredGigE'
    else:
        return 'unknown'


def _bit_count(value):
    """Returns number of bits set."""
    count = 0
    while value:
        value &= value - 1
        count += 1
    return count


@classmethod
def _fetch_key_signature(cls, tonic, quality):
    """ Returns a list of strings with the note names that make up the scale's key signature. """
    qualified_tonic = tonic + (' MINOR' if 'MINOR' in quality else ' MAJOR')
    key_signature_number = cls._KEY_SIGNATURE_NUMBERS[qualified_tonic]
    return tuple(cls._KEY_SIGNATURES[key_signature_number])


def save_homefile():
    """Make the current file the default .blend file, includes preferences

    """
    pass


@staticmethod
def _get_lib_files_by_alias(map_):
    """
        Get the librairy files by alias char defined.

        :param List[List[Char]] map_: The map to import
        """
    filename_by_alias = {}
    for row in map_:
        line = ''.join(row).rstrip()
        if line.startswith('%!'):
            pieces = line[2:].split(' ')
            filename = pieces[0]
            alias = pieces[1]
            filename_by_alias[alias] = filename
    return filename_by_alias


def get_repo(name, data, type_):
    """
    @param name: resource name
    @param data: rosdoc manifest data
    @param type_: resource type ('stack' or 'package')
    """
    return data.get('repo_name', '')


def auto_index(mcs):
    """Builds all indices, listed in model's Meta class.

           >>> class SomeModel(Model)
           ...     class Meta:
           ...         indices = (
           ...             Index('foo'),
           ...         )

        .. note:: this will result in calls to
                  :meth:`pymongo.collection.Collection.ensure_index`
                  method at import time, so import all your models up
                  front.
        """
    for index in mcs._meta.indices:
        index.ensure(mcs.collection)


def create_logger():
    """Return Neurodocker logger."""
    import logging
    logger = logging.getLogger('neurodocker')
    ch = logging.StreamHandler()
    format_ = '[NEURODOCKER %(asctime)s %(levelname)s]: %(message)s'
    formatter = logging.Formatter(format_)
    ch.setFormatter(formatter)
    logger.addHandler(ch)
    return logger


def get_validation_digit(number):
    """ Calculates the validation digit for the given number. """
    sum = 0
    dvs = [4, 3, 6, 7, 8, 9, 2]
    number = str(number)
    for i in range(0, len(number)):
        sum = (int(number[-1 - i]) * dvs[i] + sum) % 10
    return (10 - sum) % 10


@staticmethod
def is_mergeable(e1, e2):
    """
        Decide if the adjacent elements of the same type e1 and e2 can be
        merged. This can be overriden to honouring distinct classes etc.
        """
    return True


def format_decimal_as_string(value):
    """
    Convert a decimal.Decimal to a fixed point string. Code borrowed from
    Python's moneyfmt recipe.
    https://docs.python.org/2/library/decimal.html#recipes
    """
    sign, digits, exp = value.as_tuple()
    if exp > 0:
        return '%d' % value
    result = []
    digits = list(map(str, digits))
    build, next = result.append, digits.pop
    for i in range(-exp):
        build(next() if digits else '0')
    build('.')
    if not digits:
        build('0')
    while digits:
        build(next())
    if sign:
        build('-')
    return ''.join(reversed(result))


def get_item_not_found_error():
    """
    Return ItemNotFoundError.
    """
    from xmodule.modulestore.exceptions import ItemNotFoundError
    return ItemNotFoundError


def job_assign_filter(instance, field, old_value, new_value):
    """
    A custom setter for the JobState.job.

    .. warning::
        This setter should not exist. job attribute should be read-only. This
        is a temporary kludge to get session restoring over DBus working. Once
        a solution that doesn't involve setting a JobState's job attribute is
        implemented, please remove this awful method.
    """
    return new_value


@classmethod
def construct_array_type(cls):
    """
        Return the array type associated with this dtype.

        Returns
        -------
        type
        """
    raise NotImplementedError


def calculate_custom_fields_support(custom_fields):
    """
    Return a dictionary of `{field_id: set(profiles_that_don't_support_it)}`.
    `custom_fields` should be of the form: {profile_id: [field_definition, ...], ...}
    """
    all_profiles = set(custom_fields.keys())
    custom_fields_sets = {}
    for fields in custom_fields.values():
        for field in fields:
            custom_fields_sets[field['id']] = custom_fields_sets.get(field[
                'id'], all_profiles) - set(field['profiles'])
    return custom_fields_sets


def join_uvs():
    """Transfer UV Maps from active to selected objects (needs matching geometry)

    """
    pass


def isalnum(text):
    """
    Checks if all characters in ``text`` are alphanumeric and there is at least one character

    A character c is alphanumeric if one of the following returns True: :func:`isalpha`,
    :func:`isdecimal`,:func:`isdigit`, or, :func:`isnumeric`.

    :param text: The string to check
    :type text:  ``str``

    :return: True if all characters in ``text`` are alphanumeric and there is at least one character, False otherwise.
    :rtype:  ``bool``
    """
    assert isinstance(text, str), '%s is not a string' % text
    return text.isalnum()


def getWidth(image):
    """ Return width of the image.

	    This includes whitespace.
	    This assumes the image is rectangular.
	"""
    return image.index('\n')


def addSiiToContainer(siiContainer, specfile, siiList):
    """Adds the ``Sii`` elements contained in the siiList to the appropriate
    list in ``siiContainer.container[specfile]``.

    :param siiContainer: instance of :class:`maspy.core.SiiContainer`
    :param specfile: unambiguous identifier of a ms-run file. Is also used as
        a reference to other MasPy file containers.
    :param siiList: a list of ``Sii`` elements imported from any PSM search
        engine results
    """
    for sii in siiList:
        if sii.id not in siiContainer.container[specfile]:
            siiContainer.container[specfile][sii.id] = list()
        siiContainer.container[specfile][sii.id].append(sii)


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

    The ".dev0" means dirty.

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


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

        :param TeamSharingWhitelistSubjectsChangedDetails val:
        :rtype: EventDetails
        """
    return cls('team_sharing_whitelist_subjects_changed_details', val)


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

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

    """
    pass


@classmethod
def collect_dset(cls, h5_file, source_files, gids, dset_in, dset_out=None,
    mem_util_lim=0.7):
    """Collect a single dataset from a list of source files into a final
        output file.

        Parameters
        ----------
        h5_file : str
            Path to h5_file into which dataset is to be collected
        source_files : list
            List of source filepaths.
        gids : list
            list of gids to be collected
        dset_in : str
            Dataset to collect
        dset_out : str
            Dataset into which collected data is to be written
        mem_util_lim : float
            Memory utilization limit (fractional). This sets how many sites
            will be collected at a time.
        """
    dc = cls(h5_file, source_files, gids, dset_in, dset_out=dset_out,
        mem_util_lim=mem_util_lim)
    dc._collect()


def _print_integrate_lp(integrate_lp_stats):
    """Print the contents of the integrate.lp dictionary."""
    images = sorted(integrate_lp_stats.keys())
    for i in images:
        data = integrate_lp_stats[i]
        print('%4d %5.3f %5d %5d %5d %4.2f %6.2f' % (i, data['scale'], data
            ['strong'], data['overloads'], data['rejected'], data['mosaic'],
            data['distance']))


def _common_interval_domain(dom1, dom2):
    """ Determine the interval domain that is common to two interval domains

    Args:
        dom1:  First interval domain
        dom2:  Second interval domain
    Returns:
        Common domain
    """
    return max(dom1[0], dom2[0]), min(dom1[1], dom2[1])


def istest(func):
    """Decorator to mark a function or method as a test
    """
    func.__test__ = True
    return func


def hint_to_endpoint(hint, reactor, update_status):
    """Return (endpoint, hostname), or a Deferred that fires with the
        same, where endpoint is an IStreamClientEndpoint object, and hostname
        is a string (for use in the HTTP headers during negotiation). The
        endpoint, once connected, must be capable of handling .startTLS().
        Hints are strings which always start with 'TYPE:', and handlers are
        registered for specific types (and will not be called with hints of
        other types). update_status() can be called (with a string) to report
        progress, and should typically be set just before waiting for some
        connections step (e.g. connecting to a Tor daemon). Raise
        InvalidHintError (or return a Deferred that errbacks with one) if the
        hint could not be parsed or otherwise turned into an Endpoint. Set an
        attribute named 'foolscap_connection_handler_error' on the exception
        object to have `ConnectionInfo.connectorStatuses()` report that
        string instead of an exception-class -based status message."""


def get_hfac(grid, data):
    """Figure out the correct hfac given array dimensions."""
    hfac = None
    if 'i' in data.dims and 'j' in data.dims and 'hFacC' in grid._ds:
        hfac = grid._ds.hFacC
    if 'i' in data.dims and 'j_g' in data.dims and 'hFacS' in grid._ds:
        hfac = grid._ds.hFacS
    if 'i_g' in data.dims and 'j' in data.dims and 'hFacW' in grid._ds:
        hfac = grid._ds.hFacW
    return hfac


def calculate_corrected_co2_emission(rcb_corrected_co2_emission_value,
    ki_multiplicative, ki_additive, atct_family_correction_factor=1.0):
    """
    Calculates the corrected CO2 emission of the cycle [CO2g/km].

    :param rcb_corrected_co2_emission_value:
        CO2 emission value corrected for RCB [CO2g/km].
    :type rcb_corrected_co2_emission_value: float

    :param ki_multiplicative:
        Multiplicative correction for vehicles with periodically regenerating
        systems [-].
    :type ki_multiplicative: float

    :param ki_additive:
        Additive correction for vehicles with periodically regenerating
        systems [CO2g/km].
    :type ki_multiplicative: float

    :param atct_family_correction_factor:
        Family correction factor for representative regional temperatures [-].
    :type atct_family_correction_factor: float

    :return:
        Corrected CO2 emission value of the cycle [CO2g/km].
    :rtype: float
    """
    v = rcb_corrected_co2_emission_value * ki_multiplicative + ki_additive
    return v * atct_family_correction_factor


def data_disks_are_encrypted_7_3(virtual_machines):
    """
    TODO rather than making a second call here, enrich
    the data during the get_data phase if required.

    Then add the managed disk section commented out section.
    TODO: test this works for encrypted data disks.
    """
    items_flagged_list = []
    items_checked = 0
    for vm in virtual_machines:
        if not vm['storageProfile']['dataDisksEncrypted']:
            for disk in vm['storageProfile']['dataDisks']:
                if disk['managedDisk']:
                    managed = 'True'
                else:
                    managed = 'False'
                items_flagged_list.append((vm['resourceGroup'], vm['name'],
                    disk['name'], managed))
    stats = {'items_flagged': len(items_flagged_list), 'items_checked': len
        (virtual_machines)}
    metadata = {'finding_name': 'data_disks_are_encrypted', 'negative_name':
        '', 'columns': ['Resource Group', 'Name', 'Disk Name', 'Managed']}
    return {'items': items_flagged_list, 'stats': stats, 'metadata': metadata}
    stats = {'items_flagged': len(items_flagged_list), 'items_checked': len
        (virtual_machines)}
    metadata = {'finding_name': 'data_disks_are_encrypted', 'negative_name':
        '', 'columns': ['Resource Group', 'Name', 'Disk Name']}
    return {'items': items_flagged_list, 'stats': stats, 'metadata': metadata}


@classmethod
def get_object(cls, obj, transposed: bool):
    """ these are written transposed """
    if transposed:
        obj = obj.T
    return obj


def _g():
    """used only for getting generator_type"""
    yield from range(1)


@staticmethod
def _conditions_are_true(conditions, media_session_state=None,
    wake_lock_size=None, audio_state=None):
    """Check whether the conditions in ``conditions`` are true.

        Parameters
        ----------
        conditions : dict
            A dictionary of conditions to be checked (see the ``state_detection_rules`` parameter in :class:`~androidtv.basetv.BaseTV`)
        media_session_state : int, None
            The :attr:`media_session_state` property
        wake_lock_size : int, None
            The :attr:`wake_lock_size` property
        audio_state : str, None
            The :attr:`audio_state` property

        Returns
        -------
        bool
            Whether or not all the conditions in ``conditions`` are true

        """
    for key, val in conditions.items():
        if key == 'media_session_state':
            if media_session_state is None or media_session_state != val:
                return False
        elif key == 'wake_lock_size':
            if wake_lock_size is None or wake_lock_size != val:
                return False
        elif key == 'audio_state':
            if audio_state is None or audio_state != val:
                return False
        else:
            return False
    return True


def fromtimestamp(timestamp):
    """Return the local date from a POSIX timestamp (like time.time())

        This may raise ValueError, if the timestamp is out of the range of
        values supported by the platform C localtime() function. It's common
        for this to be restricted to years from 1970 through 2038. Note that
        on non-POSIX systems that include leap seconds in their notion of a
        timestamp, leap seconds are ignored by fromtimestamp().
        """


def unquote(s):
    """Undo the effects of quote(). Based heavily on urllib.parse.unquote()."""
    mychr = chr
    myatoi = int
    list = s.split('_')
    res = [list[0]]
    myappend = res.append
    del list[0]
    for item in list:
        if item[1:2]:
            try:
                myappend(mychr(myatoi(item[:2], 16)) + item[2:])
            except ValueError:
                myappend('_' + item)
        else:
            myappend('_' + item)
    return ''.join(res)


def is_iterable(structure):
    """Check if given structure is either dictionary or list"""
    return isinstance(structure, (list, dict))


def snow_permittivity(rho, fs, m=0.0, fw=9070000000.0):
    """
    Calculate the dielectric permittivity of snow
    Kendra et al. (1998), IEEE

    Parameters
    ---------
    rho:        snow density       (g/cm3)
    fs:         radar frequency     (Hz)
    m:          snow wetness        (%)
    fw:         relaxation frequency of water at 0C

    Output
    ---------
    eps_ds:     snow permittivity
    """
    eps_s = 1.0 + 1.7 * rho + 0.7 * rho ** 2.0
    eps_s += 0.02 * m ** 1.015 + 0.073 * m ** 1.31 / (1 + fs / fw)
    return eps_s


@classmethod
def add(cls, name, value):
    """Add a name-value pair to the enumeration."""
    attr = cls(value)
    attr._name = name
    setattr(cls, name, attr)


@staticmethod
def filter_list_dict_by_dict(list_dict, filter_dict):
    """
        Filter list of dict by filter_dict.
        :param list_dict:
        :param filter_dict:
        :return: Return list of dict match filter_dict
        Ex: list_dict=[{'id': 1, 'v': 11},
                       {'id': 1, 'v': 111},
                       {'id': 2, 'v': 22},
                       {'id': 3, 'v': 33}]
        Case1:
             filter_dict={'id': 1, 'v': 11}
          => return [{'id': 1, 'v': 11}]

        Case2:
             filter_dict={'id': 1}
          => return [{'id': 1, 'v': 11}, {'id': 1, 'v': 111}]
        """
    result_list = []
    for item in list_dict:
        count_match = len(filter_dict.keys())
        count_check = 0
        if set(filter_dict.keys()).issubset(set(item.keys())):
            for k, v in filter_dict.items():
                if v == item[k]:
                    count_check += 1
        if count_check == count_match:
            result_list.append(item)
        else:
            continue
    return result_list


def to_base64(bytes):
    """Encode bytes to base64 encoded string

    :param bytes:

    """
    import base64
    return base64.encodebytes(bytes).decode().rstrip()


def is_vowel_offset(c_offset):
    """
    Is the offset a vowel
    """
    return c_offset >= 4 and c_offset <= 20


def __call__(cls, value, names=None, module=None, type=None, start=1):
    """Either returns an existing member, or creates a new enum class.

        This method is used both when an enum class is given a value to match
        to an enumeration member (i.e. Color(3)) and for the functional API
        (i.e. Color = Enum('Color', names='red green blue')).

        When used for the functional API: `module`, if set, will be stored in
        the new class' __module__ attribute; `type`, if set, will be mixed in
        as the first base class.

        Note: if `module` is not set this routine will attempt to discover the
        calling module by walking the frame stack; if this is unsuccessful
        the resulting class will not be pickleable.

        """
    if names is None:
        return cls.__new__(cls, value)
    return cls._create_(value, names, module=module, type=type, start=start)


def get_dpval(name, varval):
    """
    use this to get the value of a variable during a simulation, as a game
    is progressing, or during simulation setup. This function is only useful
    if you are using the double precision Vensim DLL

    currently not implemented
    """
    raise NotImplementedError


def _convert_priority(p_priority):
    """
    Converts todo.txt priority to an iCalendar priority (RFC 2445).

    Priority A gets priority 1, priority B gets priority 5 and priority C-F get
    priorities 6-9. This scheme makes sure that clients that use "high",
    "medium" and "low" show the correct priority.
    """
    result = 0
    prio_map = {'A': 1, 'B': 5, 'C': 6, 'D': 7, 'E': 8, 'F': 9}
    try:
        result = prio_map[p_priority]
    except KeyError:
        if p_priority:
            result = 9
    return result


def tup_subtract(tuple):
    """
    definition: func(tuple) {...}
    objective : returns the subtraction of all elements in the given tuple
    """
    result = tuple[0]
    for i in range(1, len(tuple), 1):
        result -= tuple[i]
    return result


def uniq_stable(elems):
    """uniq_stable(elems) -> list

    Return from an iterable, a list of all the unique elements in the input,
    but maintaining the order in which they first appear.

    A naive solution to this problem which just makes a dictionary with the
    elements as keys fails to respect the stability condition, since
    dictionaries are unsorted by nature.

    Note: All elements in the input must be hashable.
    """
    unique = []
    unique_set = set()
    for nn in elems:
        if nn not in unique_set:
            unique.append(nn)
            unique_set.add(nn)
    return unique


def callFilterVisible(dropdownInput):
    """Handle visibility of filter input fields and description depending on
    whether a value is selected in the dropdown. Refers to the Second Order Section of the UI.

    Parameters
    ----------
    dropdownInput : :obj:`String`
        Either filter type as a string or "".

    Returns
    -------
    :obj:`Dictionary`
        Dictionary containing CSS style information for Dash.
        Changes 'display' style of filter inputs to either 'none' or 'inline-block'.

    """
    if dropdownInput != '':
        return {'display': 'inline-block'}, {'display': 'inline-block'}, {
            'display': 'inline-block'}
    return {'display': 'none'}, {'display': 'none'}, {'display': 'none'}


def preprocessing(s):
    """
    Returns string where \\ is replaced by \\\\ so that latex new lines work
    """
    return s.replace('\\\\', '\\\\\\\\')


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

        :param list of [str] val:
        :rtype: UsersSelectorArg
        """
    return cls('external_ids', val)


@staticmethod
def getJavaPackage():
    """ Returns package name String. """
    return 'com.microsoft.ml.spark.featurize.text.TextFeaturizerModel'


def walk(path):
    """
        "Пройти" по пути от текущего домена.

        @param path: путь относительно текущего домена, строка со слэшами
        @type path: C{str}
        @return: Deferred, найденный домен (L{IDomain})
        @rtype: C{twisted.internet.defer.Deferred}
        """


def get_index(x, index):
    """
    Get the element at the index of the list or return None
    >>> example = [1, 2]
    >>> get_index(example, 1)
    1
    >>> get_index(example, 7)
    None
    """
    if len(x) > index:
        return x[index]


def convert_shaders(convert, shaders):
    """ Modify shading code so that we can write code once
    and make it run "everywhere".
    """
    out = []
    if convert == 'es2':
        for isfragment, shader in enumerate(shaders):
            has_version = False
            has_prec_float = False
            has_prec_int = False
            lines = []
            for line in shader.lstrip().splitlines():
                if line.startswith('#version'):
                    has_version = True
                    continue
                if line.startswith('precision '):
                    has_prec_float = has_prec_float or 'float' in line
                    has_prec_int = has_prec_int or 'int' in line
                lines.append(line.rstrip())
            if not has_prec_float:
                lines.insert(has_version, 'precision highp float;')
            if not has_prec_int:
                lines.insert(has_version, 'precision highp int;')
            out.append('\n'.join(lines))
    elif convert == 'desktop':
        for isfragment, shader in enumerate(shaders):
            has_version = False
            lines = []
            for line in shader.lstrip().splitlines():
                has_version = has_version or line.startswith('#version')
                if line.startswith('precision '):
                    line = ''
                for prec in (' highp ', ' mediump ', ' lowp '):
                    line = line.replace(prec, ' ')
                lines.append(line.rstrip())
            if not has_version:
                lines.insert(0, '#version 120\n')
            out.append('\n'.join(lines))
    else:
        raise ValueError('Cannot convert shaders to %r.' % convert)
    return tuple(out)


def manage_beforeDelete(item, container):
    """Gets called before being deleted"""


@classmethod
def retrieve(cls):
    """Retrieves PAKMS credentials."""
    return cls.request(method='get')


@classmethod
def from_arg_kinds(cls, arch, fp_args, ret_fp=False, sizes=None, sp_delta=
    None, func_ty=None):
    """
        Get an instance of the class that will extract floating-point/integral args correctly.

        :param arch:        The Archinfo arch for this CC
        :param fp_args:     A list, with one entry for each argument the function can take. True if the argument is fp,
                            false if it is integral.
        :param ret_fp:      True if the return value for the function is fp.
        :param sizes:       Optional: A list, with one entry for each argument the function can take. Each entry is the
                            size of the corresponding argument in bytes.
        :param sp_delta:    The amount the stack pointer changes over the course of this function - CURRENTLY UNUSED
        :parmm func_ty:     A SimType for the function itself
        """
    basic = cls(arch, sp_delta=sp_delta, func_ty=func_ty)
    basic.args = basic.arg_locs(fp_args, sizes)
    basic.ret_val = basic.fp_return_val if ret_fp else basic.return_val
    return basic


def image_from_mask(mask):
    """
    Convert a binary mask into a PIL image.
    """
    import PIL
    mask_image = PIL.Image.new('1', mask.shape)
    pixels = mask_image.load()
    for i in range(mask_image.size[0]):
        for j in range(mask_image.size[1]):
            pixels[i, j] = int(mask[i, j])
    return mask_image


def is_binary_file(file_obj):
    """
    Returns True if file has non-ASCII characters (> 0x7F, or 127)
    Should work in both Python 2 and 3
    """
    start = file_obj.tell()
    fbytes = file_obj.read(1024)
    file_obj.seek(start)
    is_str = isinstance(fbytes, str)
    for fbyte in fbytes:
        if is_str:
            code = ord(fbyte)
        else:
            code = fbyte
        if code > 127:
            return True
    return False


def is_alive(thread):
    """Helper to determine if a thread is alive (handles none safely)."""
    if not thread:
        return False
    return thread.is_alive()


def _quadrant_gte(quadrant, x, y, x0, y0):
    """Return whether y is further along the ellipse than coord, or equal."""
    if quadrant % 2 == 0:
        if y != y0:
            return y > y0
        else:
            return x <= x0
    elif y != y0:
        return y < y0
    else:
        return x >= x0


def is_iterator(obj) ->bool:
    """
    Check if the object is an iterator.

    For example, lists are considered iterators
    but not strings or datetime objects.

    Parameters
    ----------
    obj : The object to check

    Returns
    -------
    is_iter : bool
        Whether `obj` is an iterator.

    Examples
    --------
    >>> is_iterator([1, 2, 3])
    True
    >>> is_iterator(datetime(2017, 1, 1))
    False
    >>> is_iterator("foo")
    False
    >>> is_iterator(1)
    False
    """
    if not hasattr(obj, '__iter__'):
        return False
    return hasattr(obj, '__next__')


def _human_readable_time_format(fmt):
    """Converts strptime format string into something a little more human readable

    :param fmt: the strptime format string
    :type fmt: str
    :return: the human-readable string
    """
    translation_dict = {'%Y': 'yyyy', '%m': 'mm', '%d': 'dd', '%H': 'HH',
        '%M': 'MM', '%S': 'SS'}
    for k, v in translation_dict.items():
        fmt = fmt.replace(k, v)
    return fmt


@staticmethod
def setup_command_line(parser):
    """Setup the command line options for PTN formula

        Arguments:
        - `parser`: parser to load with options.
        """
    parser.add_argument('N', metavar='<N>', type=int, help='Size of the domain'
        )


def neighbors(start, finish):
    """
    returns the neighbors in finish from start
    assumes both are sorted
    """
    assert finish
    index = 0
    retval = []
    for x in start:
        if x < finish[0]:
            retval.append((None, 0))
            continue
        if x > finish[-1]:
            retval.append((len(finish) - 1, None))
            continue
        try:
            while True:
                if x < finish[index] or x > finish[index + 1]:
                    index += 1
                    continue
                else:
                    break
            retval.append((index, index + 1))
        except IndexError:
            retval.append((len(finish) - 2, len(finish) - 1))
    return retval


def get(isdsAppliance, check_mode=False, force=False):
    """
    Get current date/time settings
    """
    return isdsAppliance.invoke_get('Retrieving current date and time settings'
        , '/time_cfg')


def _get_rank_stats(results):
    """
    Helper function that produces median and m.a.d
    probabilities for each of 2 classes given _cv_proba
    results with reworked columns.
    """
    grouped = results[['class', 'proba']].groupby(['class']).median().rename(
        columns={'proba': 'median'})
    return grouped.join(results[['class', 'proba']].groupby(['class']).mad(
        ).rename(columns={'proba': 'mad'}))


@classmethod
def load(cls, data):
    """Create an object from JSON data.

        Parameters
        ----------
        data : `dict`
            JSON data.

        Returns
        ----------
        `object`
            Created object.

        Raises
        ------
        KeyError
            If `data` does not have the '__class__' key
            or the necessary class is not in the class group.
        """
    ret = cls.classes[data['__class__']]
    data_cls = data['__class__']
    del data['__class__']
    try:
        ret = ret(**data)
    finally:
        data['__class__'] = data_cls
    return ret


@staticmethod
def _get_id_mapping(issue_id):
    """
        Get the Jira value mapping for the ID field.

        :param issue_id: Issue ID
        :return: Jira value mapping for the ID
        """
    return str(issue_id)


def rule_match(state, rules):
    """Find the first rule that matches state."""
    for rule in rules:
        if rule.matches(state):
            return rule


def df_set_diag(df, val, copy=True):
    """
    Sets the diagonal of a dataframe to a value. Diagonal in this case is anything where row label == column label.

    :param df: pd.DataFrame
        DataFrame to modify
    :param val: numeric
        Value to insert into any cells where row label == column label
    :param copy: bool
        Force-copy the dataframe instead of modifying in place
    :return: pd.DataFrame / int
        Return either the modified dataframe (if copied) or the number of cells modified (if changed in-place)
    """
    isect = df.index.intersection(df.columns)
    if copy:
        df = df.copy()
    for i in range(len(isect)):
        df.loc[isect[i], isect[i]] = val
    if copy:
        return df
    else:
        return len(isect)


def submit(file_name, dependencies=None, job=None, args=None, kwds=None):
    """Submit any file with dependencies.

    If your batch system does not handle dependencies, then raise a
    NotImplemented error if dependencies are passed.

    Parameters
    ----------
    file_name : str
        Path to an existing file
    dependencies : list, optional
        List of dependencies
    job : fyrd.job.Job, optional, not required
        A job object for the calling job
    args : list, optional, not required
        A list of additional command line arguments to pass when submitting
    kwds : dict or str, optional, not required
        A dictionary of keyword arguments to parse with options_to_string, or
        a string of option:value,option,option:value,....

    Returns
    -------
    job_id : str
    """
    pass


def adjacency_matrix(graph, types=True, weights=True):
    """
    Adjacency matrix of the graph.

    Parameters
    ----------
    graph : :class:`~nngt.Graph` or subclass
        Network to analyze.
    types : bool, optional (default: True)
        Whether the excitatory/inhibitory type of the connnections should be
        considered (only if the weighing factor is the synaptic strength).
    weights : bool or string, optional (default: True)
        Whether weights should be taken into account; if True, then connections
        are weighed by their synaptic strength, if False, then a binary matrix
        is returned, if `weights` is a string, then the ponderation is the
        correponding value of the edge attribute (e.g. "distance" will return
        an adjacency matrix where each connection is multiplied by its length).

    Returns
    -------
    a :class:`~scipy.sparse.csr_matrix`.
    """
    return graph.adjacency_matrix(types=types, weights=weights)


def title_long(s):
    """
	title_long("str[ing]") -> "string"
	"""
    return s.replace('[', '').replace(']', '')


@classmethod
def set_default(cls, default):
    """ Sets the default crypto suite """
    cls.default = default


def _find(tokens, token, value):
    """Return the position of the last token with the same (token, value)
    pair supplied. The position is the one of the rightmost term.
    """
    for index, token_values in enumerate(reversed(tokens)):
        if (token, value) == token_values[:2]:
            return len(tokens) - index - 1
    raise ValueError('(token, value) pair not found')


@staticmethod
def draw_path(ctx, center_x, center_y, width, height=None):
    """Draws a rhombus on the Cairo context without stroking or
        filling it.

        @see: ShapeDrawer.draw_path"""
    height = height or width
    ctx.move_to(center_x - width / 2, center_y)
    ctx.line_to(center_x, center_y + height / 2)
    ctx.line_to(center_x + width / 2, center_y)
    ctx.line_to(center_x, center_y - height / 2)
    ctx.close_path()


@staticmethod
def ratio_and_percentage(current, total, time_remaining):
    """Returns the progress ratio and percentage."""
    return '{} / {} ({}% completed)'.format(current, total, int(current /
        total * 100))


def bC_CaBOH4_Cl_FW86(T, P):
    """c-a: calcium-borate chloride [FW86]."""
    b0 = 0.12
    b1 = 0
    b2 = 0
    C0 = 0
    C1 = 0
    alph1 = 2
    alph2 = -9
    omega = -9
    valid = T == 298.15
    return b0, b1, b2, C0, C1, alph1, alph2, omega, valid


def p_ExceptionMembers_empty(p):
    """ExceptionMembers : """
    p[0] = []


@classmethod
def _convert_to_number_format(cls, number_format_dict):
    """
        Convert ``number_format_dict`` to an openpyxl v2.1.0 number format
        initializer.

        Parameters
        ----------
        number_format_dict : dict
            A dict with zero or more of the following keys.
                'format_code' : str

        Returns
        -------
        number_format : str
        """
    return number_format_dict['format_code']


def lprint(*args):
    """lprint "Log Print" - print args

    To replace all the print() statements so the can be
    easily dis/enabled

    :Parameters:
    - `*args`: args to print
    """
    return


def disassociate_vpc_cidr_block(AssociationId=None):
    """
    Disassociates a CIDR block from a VPC. Currently, you can disassociate an IPv6 CIDR block only. You must detach or delete all gateways and resources that are associated with the CIDR block before you can disassociate it.
    See also: AWS API Documentation

    :example: response = client.disassociate_vpc_cidr_block(
        AssociationId='string'
    )

    :type AssociationId: string
    :param AssociationId: [REQUIRED]
            The association ID for the CIDR block.

    :rtype: dict
    :return: {
        'VpcId': 'string',
        'Ipv6CidrBlockAssociation': {
            'Ipv6CidrBlock': 'string',
            'Ipv6CidrBlockState': {
                'State': 'associating'|'associated'|'disassociating'|'disassociated'|'failing'|'failed',
                'StatusMessage': 'string'
            },
            'AssociationId': 'string'
        }
    }

    """
    pass


@classmethod
def _enforceSingleInheritance(cls, classname, bases, classdict):
    """Only one base class is allowed for enumerated types."""
    if len(bases) > 1:
        raise TypeError(
            'Multiple inheritance is not allowed with %s, %s.%s' % (cls.
            enum_name, classdict['__module__'], classname))


def render_view_add():
    """Add a render view

    """
    pass


def e2rel(e):
    """turns NER tags into common words"""
    if e == 'MISC':
        return 'entity'
    return e.lower()


def get_order_for(grouping, include_archived=False, alphabetical=False):
    """ Get order for a given grouping
        """


@staticmethod
def _dimensions_to_values(dimensions):
    """
        Replace dimensions specs with their `dimension`
        values, and ignore those without
        """
    values = []
    for dimension in dimensions:
        if isinstance(dimension, dict):
            if 'extractionFn' in dimension:
                values.append(dimension)
            elif 'dimension' in dimension:
                values.append(dimension['dimension'])
        else:
            values.append(dimension)
    return values


def validate_overlap(periods, datetime_range=False):
    """
    Receives a list with DateRange or DateTimeRange and returns True
    if periods overlap.
    This method considers that the end of each period is not inclusive:
    If a period ends in 15/5 and another starts in 15/5, they do not overlap.
    This is the default django-postgresql behaviour:
    https://docs.djangoproject.com/en/dev/ref/contrib/postgres/fields/#daterangefield
    """
    periods.sort()
    no_overlap = [True]
    for each in range(0, len(periods) - 1):
        latest_start = max(periods[each].lower, periods[each + 1].lower)
        earliest_end = min(periods[each].upper, periods[each + 1].upper)
        delta = earliest_end - latest_start
        if datetime_range:
            no_overlap.append(max(0, delta.total_seconds()) == 0)
        else:
            no_overlap.append(max(0, delta.days) == 0)
    return False if all(no_overlap) else True


def decfmt(x, pos):
    """Formatter function for Declination."""
    return u'{:+.0f}°'.format(x)


def stage(hub, name):
    """
    Take the highdata and reconcoile the extend keyword
    """
    high, errors = hub.idem.extend.reconcile(hub.idem.RUNS[name]['high'])
    hub.idem.RUNS[name]['high'] = high
    hub.idem.RUNS[name]['errors'] = errors


def link_seg_products(root='j021737-051344', filter='f140w'):
    """Symlink catalog products from the automatically-generated "ir" products to filenames for a given filter.

    Parameters
    ----------
    root : str
        Rootname of the mosaic images.

    filter : str
        Filter name.

    """
    import os
    os.system('ln -s {0}-ir_seg.fits {0}-{1}_seg.fits'.format(root, filter))
    os.system('ln -s {0}-ir.cat {0}-{1}.cat'.format(root, filter))


def mean(float_list):
    """Calcul and return the mean for the given list of numbers (float and int).

	If the list is emmpty or None, return None.
	Else, the value returned is a float."""
    if float_list is None or not float_list:
        return None
    if len(float_list) == 1:
        return float_list[0]
    sum = 0
    for number in float_list:
        sum += float(number)
    return sum / len(float_list)


def _reshape_to_n_steps(raw_mat, num_steps):
    """
    Reshapes provided data from (positions * step, bin) to (positions, step * bin).
    Use this to restructure data back to its original form after parallel computing

    Parameters
    --------------
    raw_mat : 2D numpy array
        Data organized as (positions * step, bin)
    num_steps : unsigned int
         Number of spectroscopic steps per pixel (eg - UDVS steps)

    Returns
    ---------------
    two_d : 2D numpy array
        Data rearranged as (positions, step * bin)
    """
    num_bins = raw_mat.shape[1]
    num_pos = int(raw_mat.shape[0] / num_steps)
    one_d = raw_mat
    one_d = one_d.reshape(num_bins * num_steps * num_pos)
    two_d = one_d.reshape((num_pos, num_steps * num_bins))
    return two_d


def write(bytes):
    """Write some bytes to this file.
        """


def __new__(cls, *args, attr=None, prefix=''):
    """Call list constructor."""
    return super().__new__(cls)


def label_encoder(df):
    """Label Encodingto
    Args:
        - df: DataFrame
    Return:
        - df: DataFrame
            - 옹호 = 1, 부정 = -1, 중립 = 0"""
    df['평가'].replace('옹호', 1, inplace=True)
    df['평가'].replace('부정', -1, inplace=True)
    df['평가'].replace('중립', 0, inplace=True)
    return df


def _assert_section(config, name):
    """Make sure that a section exists in the config file."""
    if name not in config.sections():
        raise RuntimeError('Missing the section [{}] in the config file.'.
            format(name))


def resolve_name(name):
    """Resolve a name like ``module.object`` to an object and return it.

    Raise `ImportError` if the module or name is not found.
    """
    parts = name.split('.')
    cursor = len(parts) - 1
    module_name = parts[:cursor]
    attr_name = parts[-1]
    while cursor > 0:
        try:
            ret = __import__('.'.join(module_name), fromlist=[attr_name])
            break
        except ImportError:
            if cursor == 0:
                raise
            cursor -= 1
            module_name = parts[:cursor]
            attr_name = parts[cursor]
            ret = ''
    for part in parts[cursor:]:
        try:
            ret = getattr(ret, part)
        except AttributeError:
            raise ImportError(name)
    return ret


def _resolve_nat_element(element_or_ip_address):
    """
    NAT elements can be referenced by either IP address or as type
    Element. Resolve that to the right dict structure for the rule

    :param str,Element element_or_ip_address: Element or IP string
    :rtype: dict
    """
    try:
        src = {'element': element_or_ip_address.href}
    except AttributeError:
        src = {'ip_descriptor': element_or_ip_address}
    return src


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 true(symbol):
    """A rule that matches everything"""
    return True


@staticmethod
def p_comment_definition(p):
    """comment_definition : char_string
                              | comment_network_node
                              | comment_message
                              | comment_signal
                              | comment_environment_variable"""
    p[0] = p[1]


@classmethod
def CanNavigatePrev(cls):
    """Are there previous cached navigation positions?
        @param cls: Class
        @return: bool

        """
    return cls._poscache.HasPrevious()


@staticmethod
def parse(name):
    """
        Parse a name with the given convention into a tuple of "words".

        For example, an input of 'on_navigation_panel__left_down' would result
        in an output of `('navigation_panel', 'left_down')`.

        Returns `None` if there is no match.
        """
    if not name.startswith('on_'):
        return None
    cleaned_name = name[3:]
    words = tuple(cleaned_name.split('__'))
    return words


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

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

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

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


@classmethod
def get(cls, object_id):
    """
        Retrieve object with object_id and return
        :param object_id: Id to retrieve
        :return: Object after retrieve
        """
    obj = cls({cls.ID_PROPERTY: object_id}, cls.resource)
    obj.retrieve()
    return obj


def forward(apps, schema_editor):
    """Empty forward method."""
    pass


def avg_ttm_3y(df):
    """
    Calculate 3-year averages from TTM financial data, which has 4 data-points
    per year, and each data-points covers the Trailing Twelve Months.

    This is different from using a rolling average on TTM data, which
    over-weighs the most recent quarters in the average.

    This function should only be used on DataFrames for a single stock.
    Use :obj:`~simfin.utils.apply` with this function on DataFrames for
    multiple stocks.

    :param df:
        Pandas DataFrame with TTM financial data sorted ascendingly by date.

    :return:
        Pandas DataFrame with 3-year averages.
    """
    return 1.0 / 3.0 * (df + df.shift(4) + df.shift(8))


def actionzone(modifier: int=0):
    """Handle area action zones for mouse actions/gestures

    :param modifier: Modifier, Modifier state
    :type modifier: int
    """
    pass


def get_n_rows(data):
    """Get the number of rows/documents in ``data``."""
    return data.index.shape[0]


@staticmethod
def staticclassattribute(function):
    """Return given function as a staticmethod, handle None as None.

        This allows storing the function as a class attribute.
        """
    return staticmethod(function) if function is not None else None


def int_enum(cls, val):
    """Get int enum value.

    Parameters
    ----------
    cls : `type`
        Int enum class.
    val : `int` or `str`
        Name or value.

    Returns
    -------
    `IntEnum`

    Raises
    ------
    ValueError
    """
    if isinstance(val, str):
        val = val.upper()
        try:
            return getattr(cls, val)
        except AttributeError:
            raise ValueError('{0}.{1}'.format(cls, val))
    return cls(val)


@classmethod
def create_statusfile(cls, statusfile):
    """Creates the status file required by all load balancing workers.

        Parameters
        ----------
        statusfile : str
            Filename of the status file.
        """
    with open(statusfile, 'w') as f:
        f.write('0')
        f.flush()


def ack(messageid, transactionid=None):
    """STOMP acknowledge command.

    Acknowledge receipt of a specific message from the server.

    messageid:
        This is the id of the message we are acknowledging,
        what else could it be? ;)

    transactionid:
        This is the id that all actions in this transaction
        will have. If this is not given then a random UUID
        will be generated for this.

    """
    header = 'message-id: %s' % messageid
    if transactionid:
        header = 'message-id: %s\ntransaction: %s' % (messageid, transactionid)
    return 'ACK\n%s\n\n\x00\n' % header


@staticmethod
def format_time(seconds):
    """
        Converts seconds into seconds, minutes:seconds, or
        hours:minutes.seconds as appropriate.
        """
    try:
        minutes, seconds = divmod(float(seconds), 60)
        hours, minutes = divmod(minutes, 60)
        return_value = int(hours), int(minutes), float(seconds)
        if hours:
            return '{0:d}:{1:0>2d}:{2:0>6.3f}'.format(*return_value)
        elif minutes:
            return '{1:d}:{2:0>6.3f}'.format(*return_value)
        else:
            return '{2:.3f}'.format(*return_value)
    except (TypeError, ValueError):
        return ''


def validate_output_attrs(l_out_attrs, l_columns, r_out_attrs, r_columns):
    """Check if the output attributes exist in the original tables."""
    if l_out_attrs:
        for attr in l_out_attrs:
            if attr not in l_columns:
                raise AssertionError("output attribute '" + attr +
                    "' not found in left table")
    if r_out_attrs:
        for attr in r_out_attrs:
            if attr not in r_columns:
                raise AssertionError("output attribute '" + attr +
                    "' not found in right table")
    return True


@staticmethod
def is_convertible(value):
    """Return True if value can be converted to a float."""
    try:
        float(value)
        return True
    except ValueError:
        return False
    except TypeError:
        return False


@staticmethod
def TSP(chromosome, matrix):
    """
		Specific to Travelling Salesman Problem
		Calculates fitness score of a chromosome as sum of distances between each adjacent city in given chromosome

		Parameters :
		-----------
		chromosome : list
					Sequence of cities to be visited in order
		matrix : 2D list
					Gives distances between cities

		Returns :
		----------
		Fitness score

		"""
    total = 0
    for i in range(len(chromosome) - 1):
        total += matrix[chromosome[i]][chromosome[i + 1]]
    return total


def _drop_protected_attrs(model_class, values):
    """Removed protected attributes from values dictionary using the models
    __protected_attributes__ field.
    """
    for attr in model_class.__protected_attributes__:
        if attr in values:
            del values[attr]


def qn_to_qubo(expr):
    """Convert Sympy's expr to QUBO.

    Args:
        expr: Sympy's quadratic expression with variable `q0`, `q1`, ...
    Returns:
        [[float]]: Returns QUBO matrix.
    """
    try:
        import sympy
    except ImportError:
        raise ImportError('This function requires sympy. Please install it.')
    assert type(expr) == sympy.Add
    to_i = lambda s: int(str(s)[1:])
    max_i = max(map(to_i, expr.free_symbols)) + 1
    qubo = [([0.0] * max_i) for _ in range(max_i)]
    for arg in expr.args:
        syms = arg.free_symbols
        assert len(syms) <= 2
        if len(syms) == 2:
            assert type(arg) == sympy.Mul
            i, j = list(map(to_i, syms))
            if i > j:
                i, j = j, i
            if i == j:
                if len(arg.args) == 2:
                    qubo[i][i] = float(arg.args[0])
                elif len(arg.args) == 1:
                    qubo[i][i] = 1.0
                else:
                    raise ValueError(f'Too many args! arg.args = {arg.args}')
                continue
            if len(arg.args) == 3:
                qubo[i][j] = float(arg.args[0])
            elif len(arg.args) == 2:
                qubo[i][j]
        if len(syms) == 1:
            if len(arg.args) == 2:
                assert type(arg) == sympy.Mul
                i = to_i(next(iter(syms)))
                qubo[i][i] = float(arg.args[0])
            elif len(arg.args) == 1:
                qubo[i][i] = 1.0
            else:
                raise ValueError(f'Too many args! arg.args = {arg.args}')
    return qubo


def reset(cls):
    """
        Resets/clears the class's registry so that new isntances will be
        constructed for further calls to `cls`.
        """
    cls._instances.clear()


def LOWU32(i):
    """Return the low-order 32 bits of an int, as a non-negative int."""
    return i & 4294967295


def is_selected(datum):
    """Is this datum selected (note that a missing 'select' key implicitly means
    it should be selected.
    """
    return datum.get('select', True)


def clean_itemlist(itemlist):
    """
    Does lower-casing, de-duplication and alphabeting sorting.
    """
    cleaned_itemlist = []
    for item in itemlist:
        if type(item) == list:
            item = ' '.join(item)
        item = item.lower()
        cleaned_itemlist.append(item)
    return sorted(list(set(cleaned_itemlist)))


@classmethod
def first_or_new(cls, **attributes):
    """
        Get the first record matching the attributes or instantiate it.

        :param attributes: The instance attributes
        :type attributes: dict

        :return: The new instance
        :rtype: Model
        """
    instance = cls().new_query_without_scopes().where(attributes).first()
    if instance is not None:
        return instance
    return cls(**attributes)


def get_key():
    """Returns a string which is used for storing the state in the
        dictstorage.
        """


def capture(func):
    """Return the printed output of func().

    `func` should be a function without arguments that produces output with
    print statements.

    >>> def foo():
    ...     print('hello world!')
    ...
    >>> 'hello' in capture(foo)  # foo, not foo()
    True
    >>> capture(lambda: pprint(2/x, use_unicode=False))
    '2\\n-\\nx\\n'

    """
    from io import StringIO
    import sys
    stdout = sys.stdout
    sys.stdout = file = StringIO()
    try:
        func()
    finally:
        sys.stdout = stdout
    return file.getvalue()


@classmethod
def AddArguments(cls, argument_group):
    """Adds command line arguments to an argument group.

    This function takes an argument parser or an argument group object and adds
    to it all the command line arguments this helper supports.

    Args:
      argument_group (argparse._ArgumentGroup|argparse.ArgumentParser):
          argparse group.
    """
    argument_group.add_argument('--date-filter', '--date_filter', action=
        'append', type=str, dest='date_filters', metavar='TYPE_START_END',
        default=[], help=
        'Filter based on file entry date and time ranges. This parameter is formatted as "TIME_VALUE,START_DATE_TIME,END_DATE_TIME" where TIME_VALUE defines which file entry timestamp the filter applies to e.g. atime, ctime, crtime, bkup, etc. START_DATE_TIME and END_DATE_TIME define respectively the start and end of the date time range. A date time range requires at minimum start or end to time of the boundary and END defines the end time. Both timestamps be set. The date time values are formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and timezone offset are optional. The default timezone is UTC. E.g. "atime, 2013-01-01 23:12:14, 2013-02-23". This parameter can be repeated as needed to add additional date boundaries, e.g. once for atime, once for crtime, etc.'
        )


def crop(clip, x1=None, y1=None, x2=None, y2=None, width=None, height=None,
    x_center=None, y_center=None):
    """
    Returns a new clip in which just a rectangular subregion of the
    original clip is conserved. x1,y1 indicates the top left corner and
    x2,y2 is the lower right corner of the croped region.
    All coordinates are in pixels. Float numbers are accepted.

    To crop an arbitrary rectangle:

    >>> crop(clip, x1=50, y1=60, x2=460, y2=275)

    Only remove the part above y=30:

    >>> crop(clip, y1=30)

    Crop a rectangle that starts 10 pixels left and is 200px wide

    >>> crop(clip, x1=10, width=200)

    Crop a rectangle centered in x,y=(300,400), width=50, height=150 :

    >>> crop(clip,  x_center=300 , y_center=400,
                        width=50, height=150)

    Any combination of the above should work, like for this rectangle
    centered in x=300, with explicit y-boundaries:

    >>> crop(x_center=300, width=400, y1=100, y2=600)

    """
    if width and (x1 is not None or x2 is not None):
        if x1 is not None:
            x2 = x1 + width
        else:
            x1 = x2 - width
    if height and (y1 is not None or y2 is not None):
        if y1 is not None:
            y2 = y1 + height
        else:
            y1 = y2 - height
    if x_center:
        x1, x2 = x_center - width / 2, x_center + width / 2
    if y_center:
        y1, y2 = y_center - height / 2, y_center + height / 2
    if x1 is None:
        x1 = 0
    if y1 is None:
        y1 = 0
    if x2 is None:
        x2 = clip.size[0]
    if y2 is None:
        y2 = clip.size[1]
    return clip.fl_image(lambda pic: pic[int(y1):int(y2), int(x1):int(x2)],
        apply_to=['mask'])


def set_recurrence(recurrence):
    """Set the event recurrence (using a rrule).
        """


def index_run(record_path, keep_json, check_duplicate):
    """
    Convert raw JSON records into sqlite3 DB.

    Normally RASH launches a daemon that takes care of indexing.
    See ``rash daemon --help``.

    """
    from .config import ConfigStore
    from .indexer import Indexer
    cfstore = ConfigStore()
    indexer = Indexer(cfstore, check_duplicate, keep_json, record_path)
    indexer.index_all()


def get_highlighted_code(name, code, type='terminal'):
    """
    If pygments are available on the system
    then returned output is colored. Otherwise
    unchanged content is returned.
    """
    import logging
    try:
        import pygments
        pygments
    except ImportError:
        return code
    from pygments import highlight
    from pygments.lexers import guess_lexer_for_filename, ClassNotFound
    from pygments.formatters import TerminalFormatter
    try:
        lexer = guess_lexer_for_filename(name, code)
        formatter = TerminalFormatter()
        content = highlight(code, lexer, formatter)
    except ClassNotFound:
        logging.debug("Couldn't guess Lexer, will not use pygments.")
        content = code
    return content


def get_distance(pos1, pos2):
    """
    Given two X, Y, Z centers in format from output of get_center() function
    using standard three dimensional distance formula:

    square root (X^2 + Y^2 + Z^2)

    :param pos1: string of format 'X, Y, Z' Where X, Y, Z are numbers
    :param pos2: string of format 'X, Y, Z' Where X, Y, Z are numbers
    :return: distance as a float
    """
    _dist_0 = float(pos1.split(',')[0]) - float(pos2.split(',')[0])
    _dist_1 = float(pos1.split(',')[1]) - float(pos2.split(',')[1])
    _dist_2 = float(pos1.split(',')[2]) - float(pos2.split(',')[2])
    return (_dist_0 ** 2 + _dist_1 ** 2 + _dist_2 ** 2) ** 0.5


@staticmethod
def get_append_item(obj_ref, fk_item_name, fk_obj_list):
    """Generate the proper item to append to the newly built object."""
    if 'key' in fk_obj_list.values() and 'value' in fk_obj_list.values():
        append_item = {'key_id': obj_ref.__data__['key'], 'value_id':
            obj_ref.__data__['value']}
    else:
        append_item = obj_ref.__data__[fk_item_name
            ] if fk_item_name in obj_ref.__data__ else None
    return append_item


def sanitizer(name):
    """
    Sanitizes a string supposed to be an entity name. That is,
    invalid characters like slashes are substituted with underscores.

    :param name: A string representing the name.

    :returns: The sanitized name.
    :rtype: str
    """
    return name.replace('/', '_')


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


@classmethod
def input_named(cls, name):
    """Returns an XPath to find an HTML <input> with the given name."""
    return '//input[@name="%s"]' % name


def axis(name=None, cols=None, values=None, units=None):
    """Convenience function for generating axis descriptions when defining MetaArrays"""
    ax = {}
    cNameOrder = ['name', 'units', 'title']
    if name is not None:
        ax['name'] = name
    if values is not None:
        ax['values'] = values
    if units is not None:
        ax['units'] = units
    if cols is not None:
        ax['cols'] = []
        for c in cols:
            if type(c) != list and type(c) != tuple:
                c = [c]
            col = {}
            for i in range(0, len(c)):
                col[cNameOrder[i]] = c[i]
            ax['cols'].append(col)
    return ax


def static_assert(output, expression, message):
    """Writes a C++ compile-time assertion expression to a file.
    :param output: the output stream.
    :param expression: the expression to check.
    :param message: the string literal that will appear if the expression evaluates to
        false.
    """
    print('static_assert(%s, "%s");' % (expression, message), file=output)


def topic_tuple_overlap(topictups):
    """
    Return an overlap measure over 3 topic distributions

    :param topictups: a list of 3 tuples, each tuple contains word-probability information
    :return: overlap measure given by product of probabilities of words overlapping across all
        three tuples
    """
    topic_dicts = {}, {}, {}
    for i, topictup in enumerate(topictups):
        for tup in topictup:
            topic_dicts[i][tup[0]] = tup[1]
    overlap = 0.0
    for word in topic_dicts[0]:
        try:
            overlap += topic_dicts[0][word] * topic_dicts[1][word
                ] * topic_dicts[2][word]
        except KeyError:
            continue
    return overlap


@classmethod
def base_url(klass, space_id, resource_id=None, **kwargs):
    """
        Returns the URI for the environment.
        """
    return 'spaces/{0}/environments/{1}'.format(space_id, resource_id)


def move_angle_to_angle(theta1, theta2, p):
    """
    Move a number towards another number (here, the numbers were angles).
    args:
        theta1: The first number
        theta2: The second number
        p: The extent of movement. 1 means full movement.
    """
    return theta1 + (theta2 - theta1) * p


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 leading_empty_lines(lines):
    """Remove leading empty lines

    If the leading lines are empty or contain only whitespace, they will be
    removed.
    """
    if not lines:
        return lines
    for i, line in enumerate(lines):
        if line and not line.isspace():
            return lines[i:]
    return lines


def find_mdf(df):
    """
    Finds the median destructive field for AF demag data
    Parameters
    __________
        df : dataframe of measurements
    Returns
    ______
        mdf : median destructive field
    """
    mdf_df = df[df.meas_norm <= 0.5]
    mdf_high = mdf_df.treat_ac_field_mT.values[0]
    mdf_df = df[df.meas_norm >= 0.5]
    mdf_low = mdf_df.treat_ac_field_mT.values[-1]
    mdf = int(0.5 * (mdf_high + mdf_low))
    return mdf


def _convert_single_instance_to_multi(instance_shap_values):
    """Convert a single shap values instance to multi-instance form.

    :param instance_shap_values: The shap values calculated for a new instance.
    :type instance_shap_values: np.array or list
    :return: The instance converted to multi-instance form.
    :rtype np.array or list
    """
    classification = isinstance(instance_shap_values, list)
    if classification:
        shap_values = instance_shap_values
        for i in range(len(shap_values)):
            shap_values[i] = shap_values[i].reshape(1, -1)
    else:
        shap_values = instance_shap_values
    return shap_values


def triangle_coordinates(i, j, k):
    """
    Computes coordinates of the constituent triangles of a triangulation for the
    simplex. These triangules are parallel to the lower axis on the lower side.

    Parameters
    ----------
    i,j,k: enumeration of the desired triangle

    Returns
    -------
    A numpy array of coordinates of the hexagon (unprojected)
    """
    return [(i, j, k), (i + 1, j, k - 1), (i, j + 1, k - 1)]


def set_word_info(nafWord, word, offset):
    """
    Adds all information that is deducted from the word form to the new token
    :param nafWord: Cwf() object for new NAF token
    :param word: FoLiA token
    :param offset: offset of word
    :return: offset updated with word length and space if applicable
    """
    nafWord.set_offset(str(offset))
    text = word.text()
    wLength = len(text)
    nafWord.set_length(str(wLength))
    nafWord.set_text(text)
    offset += wLength
    if word.space:
        offset += 1
    return offset


def check_metric(actual, prediction, metric, round=4):
    """
    reserved for docstring
    """
    import numpy as np
    if metric == 'accuracy':
        from sklearn import metrics
        result = metrics.accuracy_score(actual, prediction)
        result = result.round(round)
    elif metric == 'recall':
        from sklearn import metrics
        result = metrics.recall_score(actual, prediction)
        result = result.round(round)
    elif metric == 'precision':
        from sklearn import metrics
        result = metrics.precision_score(actual, prediction)
        result = result.round(round)
    elif metric == 'f1':
        from sklearn import metrics
        result = metrics.f1_score(actual, prediction)
        result = result.round(round)
    elif metric == 'kappa':
        from sklearn import metrics
        result = metrics.cohen_kappa_score(actual, prediction)
        result = result.round(round)
    elif metric == 'auc':
        from sklearn import metrics
        result = metrics.roc_auc_score(actual, prediction)
        result = result.round(round)
    elif metric == 'mae':
        from sklearn import metrics
        result = metrics.mean_absolute_error(actual, prediction)
        result = result.round(round)
    elif metric == 'mse':
        from sklearn import metrics
        result = metrics.mean_squared_error(actual, prediction)
        result = result.round(round)
    elif metric == 'rmse':
        from sklearn import metrics
        result = metrics.mean_squared_error(actual, prediction)
        result = np.sqrt(result)
        result = result.round(round)
    elif metric == 'r2':
        from sklearn import metrics
        result = metrics.r2_score(actual, prediction)
        result = result.round(round)
    elif metric == 'rmsle':
        result = np.sqrt(np.mean(np.power(np.log(np.array(abs(prediction)) +
            1) - np.log(np.array(abs(actual)) + 1), 2)))
        result = result.round(round)
    elif metric == 'mape':
        mask = actual != 0
        result = (np.fabs(actual - prediction) / actual)[mask].mean()
        result = result.round(round)
    return result


def notModified(published, request, response, etag=None, lastModified=None):
    """Return a ``304 NOT MODIFIED`` response. Modifies the response (status)
    and returns an empty body to indicate the request should be interrupted.

    ``etag`` is an ETag to set on the response
    ``lastModified`` is the last modified date to set on the response

    Both ``etag`` and ``lastModified`` are optional.
    """
    if etag is not None:
        response.setHeader('ETag', etag, literal=1)
    if response.getHeader('Last-Modified'):
        del response.headers['last-modified']
    if response.getHeader('Expires'):
        del response.headers['expires']
    if response.getHeader('Cache-Control'):
        del response.headers['cache-control']
    response.setStatus(304)
    return u''


def parse_chunks(chunks):
    """Parse chunks and extract information on individual streams."""
    streams = []
    for chunk in chunks:
        if chunk['tag'] == 2:
            streams.append(dict(stream_id=chunk['stream_id'], name=chunk.
                get('name'), type=chunk.get('type'), source_id=chunk.get(
                'source_id'), created_at=chunk.get('created_at'), uid=chunk
                .get('uid'), session_id=chunk.get('session_id'), hostname=
                chunk.get('hostname'), channel_count=int(chunk[
                'channel_count']), channel_format=chunk['channel_format'],
                nominal_srate=float(chunk['nominal_srate'])))
    return streams


def gen_url_regex(resource):
    """ URL regex for resource class generator. """
    if resource._meta.parent:
        yield resource._meta.parent._meta.url_regex.rstrip('/$').lstrip('^')
    for p in resource._meta.url_params:
        yield '%(name)s/(?P<%(name)s>[^/]+)' % dict(name=p)
    if resource._meta.prefix:
        yield resource._meta.prefix
    yield '%(name)s/(?P<%(name)s>[^/]+)?' % dict(name=resource._meta.name)


def select_less(use_face_step: bool=True):
    """Deselect vertices, edges or faces at the boundary of each selection region

    :param use_face_step: Face Step, Connected faces (instead of edges)
    :type use_face_step: bool
    """
    pass


@classmethod
def tetragonal(cls, a, c, lattice_type='P'):
    """Factory for tetragonal lattices

        :param a: unit cell length
        :param c: unit cell length
        """
    a = float(a)
    self = cls(a, a, float(c), 90, 90, 90, lattice='tetragonal',
        lattice_type=lattice_type)
    return self


@classmethod
def get_entry_name(cls, entry):
    """
        get entry name as string from XML node entry

        :param entry: XML node entry
        :return: unique entry name
        """
    name = entry.find('./name').text
    return name


def suggested_schedule_changes(schedule, override_timeseries,
    total_number_of_days):
    """
    There are at least two types of schedule change suggestions: those that result in the static analysis of the schedule
    (what the total scheduled off time is) and those that result from the use of the space.
    """
    from optimization_checks import check_total_off_times_for_days_of_week, check_switch_events_with_schedule_per_day
    res = []
    res += check_total_off_times_for_days_of_week(schedule)
    res += check_switch_events_with_schedule_per_day(schedule,
        override_timeseries, total_number_of_days)
    return res


def add_auth_arguments(parser, usr_required=False):
    """ Add 'user' and 'password' arguments
    :param user_required: set 'user' argument as required or not  """
    parser.add_argument('-u', '--user', dest='username', required=usr_required)
    parser.add_argument('-p', '--password', dest='password')


@classmethod
def init_by_id(cls, _id):
    """Load task by its ID"""


@classmethod
def get_tryton_state(cls, name):
    """Get the tryton state corresponding to the prestashop state
        as per the predefined logic
        This method currently expects the value of name to be in US English.

        :param name: Name of the PS state

        :returns: A dictionary of tryton state and shipment and invoice methods
        """
    if name in ('Shipped', 'Delivered'):
        return {'order_state': 'shipment.sent', 'invoice_method': 'manual',
            'shipment_method': 'manual'}
    elif name == 'Canceled':
        return {'order_state': 'sale.cancel', 'invoice_method': 'manual',
            'shipment_method': 'manual'}
    elif name in ('Payment accepted', 'Payment remotely accepted'):
        return {'order_state': 'sale.processing', 'invoice_method': 'order',
            'shipment_method': 'invoice'}
    elif name == 'Preparation in progress':
        return {'order_state': 'sale.processing', 'invoice_method': 'order',
            'shipment_method': 'order'}
    else:
        return {'order_state': 'sale.confirmed', 'invoice_method': 'order',
            'shipment_method': 'order'}


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

    The ".dev0" means dirty.

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


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


def find(function, iterable):
    """ Returns the first item in the list for which function(item) is True, None otherwise.
    """
    for x in iterable:
        if function(x):
            return x


@classmethod
def delete(cls, keys, pipe=None):
    """
        Delete one or more keys from the Struct namespace.

        This is a class method and unlike the `clear` method,
        can be invoked without instantiating a Struct.

        :param keys: the names of the keys to remove from the keyspace
        :param pipe: Pipeline, NestedPipeline, or None
        :return: None
        """
    with cls._pipe(pipe) as pipe:
        core = cls.core(pipe)
        core.delete(*keys)


def tris_convert_to_quads(face_threshold: float=0.698132, shape_threshold:
    float=0.698132, uvs: bool=False, vcols: bool=False, seam: bool=False,
    sharp: bool=False, materials: bool=False):
    """Join triangles into quads

    :param face_threshold: Max Face Angle, Face angle limit
    :type face_threshold: float
    :param shape_threshold: Max Shape Angle, Shape angle limit
    :type shape_threshold: float
    :param uvs: Compare UVs
    :type uvs: bool
    :param vcols: Compare VCols
    :type vcols: bool
    :param seam: Compare Seam
    :type seam: bool
    :param sharp: Compare Sharp
    :type sharp: bool
    :param materials: Compare Materials
    :type materials: bool
    """
    pass


def unpack_nested_exception(error):
    """
        If exception are stacked, return the first one

        :param error: A python exception with possible exception embeded within
        :return: A python exception with no exception embeded within
    """
    i = 0
    while True:
        if error.args[i:]:
            if isinstance(error.args[i], Exception):
                error = error.args[i]
                i = 0
            else:
                i += 1
        else:
            break
    return error


def nfc_encode(string):
    """
    把包含直接信息的字符串转成nfc模块可识别的数组
    """
    if len(string) > 16:
        return None
    else:
        result = []
        for i in range(len(string)):
            result.append(ord(string[i]))
        return result


def resource_listdir(resource_name):
    """List of resource names in the directory (like ``os.listdir()``)"""


def clear_file(file_path):
    """Erase the contents of the file located at `file_path`

    Parameters
    ----------
    file_path: String
        The path of the file whose contents should be cleared out"""
    clear_target = open(file_path, 'w')
    clear_target.truncate()
    clear_target.close()


def registerSynch(synch):
    """Register an `ISynchronizer`.

        Synchronizers are notified about some major events in a transaction's
        life.  See `ISynchronizer` for details.

        If a synchronizer registers while there is an active
        transaction, its ``newTransaction`` method will be called with the
        active transaction.
        """


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

        :param ShowcaseEditCommentDetails val:
        :rtype: EventDetails
        """
    return cls('showcase_edit_comment_details', val)


def all_steps(simulation):
    """make a switch for each section if it does not have one"""
    nsec = simulation.root.input.solver.sections.nsec
    if simulation.root.input.model.connections.nswitches < nsec:
        simulation.root.input.model.connections.nswitches = nsec
        connections = simulation.root.input.model.connections
        for i in range(nsec):
            switch_name = 'switch_%03d' % i
            if switch_name in connections:
                continue
            else:
                switch_name_prev = 'switch_%03d' % (i - 1)
                connections[switch_name] = connections[switch_name_prev].copy()
                connections[switch_name].section = i


def format_bytes(bytes):
    """
    Format a bytes value into something more readable
    """
    bytes = float(bytes)
    if bytes >= 1073741824:
        gigabytes = bytes / 1073741824
        size = '%.2fGB' % gigabytes
    elif bytes >= 1048576:
        megabytes = bytes / 1048576
        size = '%.2fMB' % megabytes
    elif bytes >= 1024:
        kilobytes = bytes / 1024
        size = '%.2fKB' % kilobytes
    else:
        size = '%.2fB' % bytes
    return size


def _imageLabel(img):
    """Used to generate labels for the :attr:`.VectorOpts.modulateImage`,
    :attr:`.VectorOpts.clipImage`, and other :class:`.Image`-based
    choice properties.
    """
    if img is None:
        return 'None'
    else:
        return img.name


@classmethod
def append_to_run_from_text(cls, r, text):
    """
        Create a "one-shot" ``_RunContentAppender`` instance and use it to
        append the run content elements corresponding to *text* to the
        ``<w:r>`` element *r*.
        """
    appender = cls(r)
    appender.add_text(text)


@classmethod
def on_mapping_not_found(cls, controller):
    """
    Callback function that is triggered, when the mapping of a controller was not found

    :param controller:              the controller that should be mapped
    :type controller:               steuer.Controller
    """
    print('EVENT:' +
        'controller {0}:{1} could not be mapped. Controller name unknown.'.
        format(controller.number, controller.name))


@staticmethod
def is_of(obj, thing_url):
    """This is not the thing you are looking for."""
    return obj.get('@id') == thing_url


def ensure_string_type(obj):
    """
    Parse object passed to the function to `str`.

    If the object is of type `bytes`, it is decoded, otherwise a generic string representation of the object is
    returned.

    Parameters
    ----------
    obj: Any
        object which is to be parsed to `str`

    Returns
    -------
    str_obj: String
    """
    if isinstance(obj, bytes):
        return obj.decode()
    else:
        return str(obj)


def capitalizar_cantidad_compuesto(cantidad, tipo_interes, numero_periodos):
    """
            Capitaliza una cantidad de dinero un determinado número de períodos
            por el metodo compuesto, los cuales han sido pasados en los parámetros.

    """
    cantidad_capitalizada = cantidad * (1 + tipo_interes) ** numero_periodos
    return cantidad_capitalizada


def _np_zeros_like(a):
    """
    Return an array of zeros with the same shape and type as a given array.

    Parameters
    ----------
    a : ndarray
        The shape and data-type of `a` define these same attributes of
        the returned array.

    Returns
    -------
    out : ndarray
        Array of zeros with the same shape and type as `a`.

    Examples
    --------
    >>> x = np.arange(6)
    >>> x = x.reshape((2, 3))
    >>> x
    array([[0., 1., 2.],
           [3., 4., 5.]])
    >>> np.zeros_like(x)
    array([[0., 0., 0.],
           [0., 0., 0.]])
    >>> y = np.arange(3, dtype=float)
    >>> y
    array([0., 1., 2.], dtype=float64)
    >>>
    >>> np.zeros_like(y)
    array([0., 0., 0.], dtype=float64)
    """
    pass


@staticmethod
def decode(itemset, table, mapping):
    """Yield sorted (item, variable, value) tuples (one for each item)"""
    attributes = table.domain.attributes
    for item in itemset:
        ivar, ival = mapping[item]
        var = attributes[ivar] if ivar < len(attributes
            ) else table.domain.class_var
        yield item, var, var.values[ival] if var.is_discrete else 0


@classmethod
def _to_list(cls, data):
    """Transform resource data to list.

        A client can send resource or collection in HTTP request. This method
        always converts the top level ``data`` object to a list of resources.

        Args:
            data (dict): Top level JSON ``data`` property.

        Returns:
            tuple: List of attributes
        """
    if not isinstance(data, (list, tuple)):
        return data,
    return tuple(data)


def remove_targets(Rule=None, Ids=None):
    """
    Removes the specified targets from the specified rule. When the rule is triggered, those targets are no longer be invoked.
    When you remove a target, when the associated rule triggers, removed targets might continue to be invoked. Please allow a short period of time for changes to take effect.
    This action can partially fail if too many requests are made at the same time. If that happens, FailedEntryCount is non-zero in the response and each entry in FailedEntries provides the ID of the failed target and the error code.
    See also: AWS API Documentation

    :example: response = client.remove_targets(
        Rule='string',
        Ids=[
            'string',
        ]
    )

    :type Rule: string
    :param Rule: [REQUIRED]
            The name of the rule.

    :type Ids: list
    :param Ids: [REQUIRED]
            The IDs of the targets to remove from the rule.
            (string) --

    :rtype: dict
    :return: {
        'FailedEntryCount': 123,
        'FailedEntries': [
            {
                'TargetId': 'string',
                'ErrorCode': 'string',
                'ErrorMessage': 'string'
            },
        ]
    }

    """
    pass


def bc(temp):
    """
    Calculate Bolometric Correction Using the Teff from the previous equation.
    This correction is for main sequence stars of the Teff range given above.
    """
    return (-10.07203 + temp * 0.00434733 - temp ** 2 * 6.159563e-07 + temp **
        3 * 2.851201e-11)


@classmethod
def compatible_with_dataset(cls, dataset):
    """Checks if the model is compatible with the dataset
        :param dataset: the dataset
        :type dataset: BaseDatasetWrapper
        :rtype: bool
        """
    return True


def print_heading(title: str) ->None:
    """
    Print a non-breaking heading in the form of ":: The given text".

    :param title: The text to print
    :return: None
    """
    print(f'\x1b[1;34m::\x1b[0m {title}', end='', flush=True)


@classmethod
def supported_filetypes(cls):
    """ Returns a list of supported file extensions.
		"""
    return 'json',


def getgrnam(name):
    """Wrapper function to protect against `grp` not being available
    on Windows
    """
    import grp
    return grp.getgrnam(name)


def bitmask(n: int) ->int:
    """Produces a bitmask of n 1s if n is positive, or n 0s if n is negative."""
    if n >= 0:
        return (1 << n) - 1
    else:
        return -1 << -n


def decode_all(res):
    """decode all results fetched from redis"""
    return list(map(bytes.decode, res))


def wei_to_ether(wei):
    """Convert wei to ether.

    :param wei:
    :return:
    """
    return 1.0 * wei / 10 ** 18


@classmethod
def get(cls, project_id):
    """
        Gets information about a project.

        Parameters
        ----------
        project_id : str
            The identifier of the project you want to load.

        Returns
        -------
        project : Project
            The queried project

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

            import datarobot as dr
            p = dr.Project.get(project_id='54e639a18bd88f08078ca831')
            p.id
            >>>'54e639a18bd88f08078ca831'
            p.project_name
            >>>'Some project name'
        """
    path = '{}{}/'.format(cls._path, project_id)
    return cls.from_location(path, keep_attrs=[
        'advanced_options.default_monotonic_increasing_featurelist_id',
        'advanced_options.default_monotonic_decreasing_featurelist_id'])


def is_tool(name):
    """Check whether `name` is on PATH and marked as executable."""
    from shutil import which
    return which(name) is not None


def n_levels(idx):
    """1 if not MultiIndex else x.levelshape"""
    return len(getattr(idx, 'levels', [1]))


def from_any_pb(pb_type, any_pb):
    """Converts an ``Any`` protobuf to the specified message type.

    Args:
        pb_type (type): the type of the message that any_pb stores an instance
            of.
        any_pb (google.protobuf.any_pb2.Any): the object to be converted.

    Returns:
        pb_type: An instance of the pb_type message.

    Raises:
        TypeError: if the message could not be converted.
    """
    msg = pb_type()
    if callable(getattr(pb_type, 'pb', None)):
        msg_pb = pb_type.pb(msg)
    else:
        msg_pb = msg
    if not any_pb.Unpack(msg_pb):
        raise TypeError('Could not convert {} to {}'.format(any_pb.
            __class__.__name__, pb_type.__name__))
    return msg


def get_feature_names_chem(peplen):
    """
	feature names for the fixed peptide length feature vectors
	"""
    names = []
    names += ['pmz', 'peplen', 'ionnumber', 'ionnumber_rel', 'mean_mz']
    for c in ['mean_{}', 'max_{}', 'min_{}', 'max{}_b', 'min{}_b',
        'max{}_y', 'min{}_y']:
        for b in ['bas', 'heli', 'hydro', 'pI']:
            names.append(c.format(b))
    for c in ['mz', 'bas', 'heli', 'hydro', 'pI']:
        names.append('{}_ion'.format(c))
        names.append('{}_ion_other'.format(c))
        names.append('mean_{}_ion'.format(c))
        names.append('mean_{}_ion_other'.format(c))
    for c in ['plus_cleave{}', 'times_cleave{}', 'minus1_cleave{}',
        'minus2_cleave{}', 'bsum{}', 'ysum{}']:
        for b in ['bas', 'heli', 'hydro', 'pI']:
            names.append(c.format(b))
    for i in range(peplen):
        for c in ['mz', 'bas', 'heli', 'hydro', 'pI']:
            names.append('fix_' + c + '_' + str(i))
    names.append('charge')
    return names


def get_supported_options():
    """This is a stub, and gets filled in at runtime in spell/cli/main.py"""
    raise NotImplementedError()


def config_test():
    """Make sure the configuration is valid.

        :raises .MisconfigurationError: when the config is not in a usable state

        """