text:
'''
Formula objects
===============

A formula is basically a sympy expression for the mean of something of
the form::

   mean = sum([Beta(e)*e for e in expr])

Or, a linear combination of sympy expressions, with each one multiplied
by its own "Beta". The elements of expr can be instances of Term (for a
linear regression formula, they would all be instances of Term). But, in
general, there might be some other parameters (i.e. sympy.Symbol
instances) that are not Terms.

The design matrix is made up of columns that are the derivatives of mean
with respect to everything that is not a Term, evaluted at a recarray
that has field names given by [str(t) for t in self.terms].

For those familiar with R's formula syntax, if we wanted a design matrix
like the following::

    > s.table = read.table("http://www-stat.stanford.edu/~jtaylo/courses/stats191/data/supervisor.table", header=T)
    > d = model.matrix(lm(Y ~ X1*X3, s.table)
    )
    > d
       (Intercept) X1 X3 X1:X3
    1            1 51 39  1989
    2            1 64 54  3456
    3            1 70 69  4830
    4            1 63 47  2961
    5            1 78 66  5148
    6            1 55 44  2420
    7            1 67 56  3752
    8            1 75 55  4125
    9            1 82 67  5494
    10           1 61 47  2867
    11           1 53 58  3074
    12           1 60 39  2340
    13           1 62 42  2604
    14           1 83 45  3735
    15           1 77 72  5544
    16           1 90 72  6480
    17           1 85 69  5865
    18           1 60 75  4500
    19           1 70 57  3990
    20           1 58 54  3132
    21           1 40 34  1360
    22           1 61 62  3782
    23           1 66 50  3300
    24           1 37 58  2146
    25           1 54 48  2592
    26           1 77 63  4851
    27           1 75 74  5550
    28           1 57 45  2565
    29           1 85 71  6035
    30           1 82 59  4838
    attr(,"assign")
    [1] 0 1 2 3
    >

With the Formula, it looks like this:

>>> r = np.rec.array([
...     (43, 51, 30, 39, 61, 92, 45), (63, 64, 51, 54, 63, 73, 47),
...     (71, 70, 68, 69, 76, 86, 48), (61, 63, 45, 47, 54, 84, 35),
...     (81, 78, 56, 66, 71, 83, 47), (43, 55, 49, 44, 54, 49, 34),
...     (58, 67, 42, 56, 66, 68, 35), (71, 75, 50, 55, 70, 66, 41),
...     (72, 82, 72, 67, 71, 83, 31), (67, 61, 45, 47, 62, 80, 41),
...     (64, 53, 53, 58, 58, 67, 34), (67, 60, 47, 39, 59, 74, 41),
...     (69, 62, 57, 42, 55, 63, 25), (68, 83, 83, 45, 59, 77, 35),
...     (77, 77, 54, 72, 79, 77, 46), (81, 90, 50, 72, 60, 54, 36),
...     (74, 85, 64, 69, 79, 79, 63), (65, 60, 65, 75, 55, 80, 60),
...     (65, 70, 46, 57, 75, 85, 46), (50, 58, 68, 54, 64, 78, 52),
...     (50, 40, 33, 34, 43, 64, 33), (64, 61, 52, 62, 66, 80, 41),
...     (53, 66, 52, 50, 63, 80, 37), (40, 37, 42, 58, 50, 57, 49),
...     (63, 54, 42, 48, 66, 75, 33), (66, 77, 66, 63, 88, 76, 72),
...     (78, 75, 58, 74, 80, 78, 49), (48, 57, 44, 45, 51, 83, 38),
...     (85, 85, 71, 71, 77, 74, 55), (82, 82, 39, 59, 64, 78, 39)],
...              dtype=[('y', '<i8'), ('x1', '<i8'), ('x2', '<i8'),
...                     ('x3', '<i8'), ('x4', '<i8'), ('x5', '<i8'),
...                     ('x6', '<i8')])
>>> x1 = Term('x1'); x3 = Term('x3')
>>> f = Formula([x1, x3, x1*x3]) + I
>>> f.mean
_b0*x1 + _b1*x3 + _b2*x1*x3 + _b3

The I is the "intercept" term, I have explicity not used R's default of
adding it to everything.

>>> f.design(r)
array([(51.0, 39.0, 1989.0, 1.0), (64.0, 54.0, 3456.0, 1.0),
       (70.0, 69.0, 4830.0, 1.0), (63.0, 47.0, 2961.0, 1.0),
       (78.0, 66.0, 5148.0, 1.0), (55.0, 44.0, 2420.0, 1.0),
       (67.0, 56.0, 3752.0, 1.0), (75.0, 55.0, 4125.0, 1.0),
       (82.0, 67.0, 5494.0, 1.0), (61.0, 47.0, 2867.0, 1.0),
       (53.0, 58.0, 3074.0, 1.0), (60.0, 39.0, 2340.0, 1.0),
       (62.0, 42.0, 2604.0, 1.0), (83.0, 45.0, 3735.0, 1.0),
       (77.0, 72.0, 5544.0, 1.0), (90.0, 72.0, 6480.0, 1.0),
       (85.0, 69.0, 5865.0, 1.0), (60.0, 75.0, 4500.0, 1.0),
       (70.0, 57.0, 3990.0, 1.0), (58.0, 54.0, 3132.0, 1.0),
       (40.0, 34.0, 1360.0, 1.0), (61.0, 62.0, 3782.0, 1.0),
       (66.0, 50.0, 3300.0, 1.0), (37.0, 58.0, 2146.0, 1.0),
       (54.0, 48.0, 2592.0, 1.0), (77.0, 63.0, 4851.0, 1.0),
       (75.0, 74.0, 5550.0, 1.0), (57.0, 45.0, 2565.0, 1.0),
       (85.0, 71.0, 6035.0, 1.0), (82.0, 59.0, 4838.0, 1.0)],
      dtype=[('x1', '<f8'), ('x3', '<f8'), ('x1*x3', '<f8'), ('1', '<f8')])
'''
from __future__ import print_function
from __future__ import absolute_import

from string import ascii_letters, digits

import numpy as np
from scipy.linalg import pinv

import sympy
from sympy import Dummy, default_sort_key
from sympy.utilities.lambdify import (implemented_function, lambdify)

from nipy.utils.compat3 import to_str

from nipy.algorithms.utils.matrices import matrix_rank, full_rank

@np.deprecate(message = "Please use sympy.Dummy instead of this function")
def make_dummy(name):
    """ Make dummy variable of given name

    Parameters
    ----------
    name : str
        name of dummy variable

    Returns
    -------
    dum : `Dummy` instance

    Notes
    -----
    The interface to Dummy changed between 0.6.7 and 0.7.0, and we used this
    function to keep compatibility. Now we depend on sympy 0.7.0 and this
    function is obsolete.
    """
    return Dummy(name)

def define(*args, **kwargs):
    # Moved to utils module
    import warnings
    from . import utils
    warnings.warn('Please use define function from utils module',
                  DeprecationWarning,
                  stacklevel=2)
    return utils.define(*args, **kwargs)

class Term(sympy.Symbol):
    """A sympy.Symbol type to represent a term an a regression model

    Terms can be added to other sympy expressions with the single
    convention that a term plus itself returns itself.

    It is meant to emulate something on the right hand side of a formula
    in R. In particular, its name can be the name of a field in a
    recarray used to create a design matrix.

    >>> t = Term('x')
    >>> xval = np.array([(3,),(4,),(5,)], np.dtype([('x', np.float)]))
    >>> f = t.formula
    >>> d = f.design(xval)
    >>> print(d.dtype.descr)
    [('x', '<f8')]
    >>> f.design(xval, return_float=True)
    array([ 3.,  4.,  5.])
    """
    # This flag is defined to avoid using isinstance in getterms
    # and getparams.
    _term_flag = True

    def _getformula(self):
        return Formula([self])
    formula = property(_getformula,
                       doc="Return a Formula with only terms=[self].")

    def __add__(self, other):
        if self == other:
            return self
        return sympy.Symbol.__add__(self, other)

# time symbol
T = Term('t')

def terms(names, **kwargs):
    ''' Return list of terms with names given by `names`

    This is just a convenience in defining a set of terms, and is the
    equivalent of ``sympy.symbols`` for defining symbols in sympy.

    We enforce the sympy 0.7.0 behavior of returning symbol "abc" from input
    "abc", rthan than 3 symbols "a", "b", "c".

    Parameters
    ----------
    names : str or sequence of str
       If a single str, can specify multiple ``Term``s with string
       containing space or ',' as separator.
    \\**kwargs : keyword arguments
       keyword arguments as for ``sympy.symbols``

    Returns
    -------
    ts : ``Term`` or tuple
       ``Term`` instance or list of ``Term`` instance objects named from `names`

    Examples
    --------
    >>> terms(('a', 'b', 'c'))
    (a, b, c)
    >>> terms('a, b, c')
    (a, b, c)
    >>> terms('abc')
    abc
    '''
    if 'each_char' in kwargs:
        raise TypeError('deprecated "each_char" kwarg removed in sympy>0.7.3')
    syms = sympy.symbols(names, **kwargs)
    try:
        len(syms)
    except TypeError:
        return Term(syms.name)
    return tuple(Term(s.name) for s in syms)

class FactorTerm(Term):
    """ Boolean Term derived from a Factor.

    Its properties are the same as a Term except that its product with
    itself is itself.
    """
    # This flag is defined to avoid using isinstance in getterms
    _factor_term_flag = True

    def __new__(cls, name, level):
        # Names or levels can be byte strings
        new = Term.__new__(cls, "%s_%s" % (to_str(name), to_str(level)))
        new.level = level
        new.factor_name = name
        return new

    def __mul__(self, other):

        if self == other:
            return self
        else:
            return sympy.Symbol.__mul__(self, other)

class Beta(sympy.symbol.Dummy):
    ''' A symbol tied to a Term `term` '''
    def __new__(cls, name, term):
        new = sympy.symbol.Dummy.__new__(cls, name)
        new._term = term
        return new

def getparams(expression):
    """ Return the parameters of an expression that are not Term
    instances but are instances of sympy.Symbol.

    Examples
    --------
    >>> x, y, z = [Term(l) for l in 'xyz']
    >>> f = Formula([x,y,z])
    >>> getparams(f)
    []
    >>> f.mean
    _b0*x + _b1*y + _b2*z
    >>> getparams(f.mean)
    [_b0, _b1, _b2]
    >>> th = sympy.Symbol('theta')
    >>> f.mean*sympy.exp(th)
    (_b0*x + _b1*y + _b2*z)*exp(theta)
    >>> getparams(f.mean*sympy.exp(th))
    [_b0, _b1, _b2, theta]
    """
    atoms = set([])
    expression = np.array(expression)
    if expression.shape == ():
        expression = expression.reshape((1,))
    if expression.ndim > 1:
        expression = expression.reshape((np.product(expression.shape),))
    for term in expression:
        atoms = atoms.union(sympy.sympify(term).atoms())
    params = []
    for atom in atoms:
        if isinstance(atom, sympy.Symbol) and not is_term(atom):
            params.append(atom)
    params.sort(key=default_sort_key)
    return params

def getterms(expression):
    """ Return the all instances of Term in an expression.

    Examples
    --------
    >>> x, y, z = [Term(l) for l in 'xyz']
    >>> f = Formula([x,y,z])
    >>> getterms(f)
    [x, y, z]
    >>> getterms(f.mean)
    [x, y, z]
    """
    atoms = set([])
    expression = np.array(expression)
    if expression.shape == ():
        expression = expression.reshape((1,))
    if expression.ndim > 1:
        expression = expression.reshape((np.product(expression.shape),))
    for e in expression:
        atoms = atoms.union(e.atoms())
    terms = []
    for atom in atoms:
        if is_term(atom):
            terms.append(atom)
    terms.sort(key=default_sort_key)
    return terms

def make_recarray(rows, names, dtypes=None):
    """ Create recarray from `rows` with field names `names`

    Create a recarray with named columns from a list of rows and names
    for the columns. If dtype is None, the dtype is based on rows if it
    is an np.ndarray, else the data is cast as np.float. If dtypes are
    supplied, it uses the dtypes to create a np.dtype unless rows is an
    np.ndarray, in which case dtypes are ignored

    Parameters
    ----------
    rows: array-like
        Rows that will be turned into an recarray.
    names: sequence
        Sequence of strings - names for the columns.
    dtypes: [str or np.dtype]
        Used to create a np.dtype, can be np.dtypes or string.

    Returns
    -------
    v : np.ndarray

    Examples
    --------
    The following tests depend on machine byte order to pass

    >>> arr = np.array([[3,4 ], [4, 6], [6, 8]])
    >>> make_recarray(arr, ['x', 'y']) #doctest: +ELLIPSIS
    array([[(3, 4)],
           [(4, 6)],
           [(6, 8)]],
          dtype=[('x', '...'), ('y', '...')])
    >>> r = make_recarray(arr, ['w', 'u'])
    >>> make_recarray(r, ['x', 'y']) #doctest: +ELLIPSIS
    array([[(3, 4)],
           [(4, 6)],
           [(6, 8)]],
          dtype=[('x', '...'), ('y', '...')])
    >>> make_recarray([[3, 4], [4, 6], [7, 9]], 'wv', [np.float, np.int]) #doctest: +ELLIPSIS
    array([(3.0, 4), (4.0, 6), (7.0, 9)],
          dtype=[('w', '...'), ('v', '...')])
    """
    # XXX This function is sort of one of convenience
    # Would be nice to use DataArray or something like that
    # to add axis names.
    if isinstance(rows, np.ndarray):
        if rows.dtype.isbuiltin:
            dtype = np.dtype([(n, rows.dtype) for n in names])
        else:
            dtype = np.dtype([(n, d[1]) for n, d in zip(names, rows.dtype.descr)])
        if dtypes is not None:
            raise ValueError('dtypes not used if rows is an ndarray')
        return rows.view(dtype)
    if dtypes is None:
        dtype = np.dtype([(n, np.float) for n in names])
    else:
        dtype = np.dtype([(n, d) for n, d in zip(names, dtypes)])
    nrows = []
    vector = -1
    for r in rows:
        if vector < 0:
            a = np.array(r)
            if a.shape == ():
                vector = True
            else:
                vector = False
        if not vector:
            nrows.append(tuple(r))
        else:
            nrows.append(r)
    if vector:
        if len(names) != 1: # a 'row vector'
            nrows = tuple(nrows)
            return np.array(nrows, dtype)
        else:
            nrows = np.array([(r,) for r in nrows], dtype)
    return np.array(nrows, dtype)

class Formula(object):
    """ A Formula is a model for a mean in a regression model.

    It is often given by a sequence of sympy expressions, with the mean
    model being the sum of each term multiplied by a linear regression
    coefficient.

    The expressions may depend on additional Symbol instances, giving a
    non-linear regression model.
    """
    # This flag is defined for test isformula(obj) instead of isinstance
    _formula_flag = True

    def __init__(self, seq, char = 'b'):
        """
        Parameters
        ----------
        seq : sequence of ``sympy.Basic``
        char : str, optional
            character for regression coefficient
        """
        self._terms = np.asarray(seq)
        self._counter = 0
        self.char = char

    # Properties
    def _getcoefs(self):
        if not hasattr(self, '_coefs'):
            self._coefs = {}
            for term in self.terms:
                self._coefs.setdefault(term, Beta("%s%d" % (self.char, self._counter), term))
                self._counter += 1
        return self._coefs
    coefs = property(_getcoefs, doc='Coefficients in the linear regression formula.')

    def _getterms(self):
        t = self._terms
        # The Rmode flag is meant to emulate R's implicit addition of an
        # intercept to every formula. It currently cannot be changed.
        Rmode = False
        if Rmode:
            if sympy.Number(1) not in self._terms:
                t = np.array(list(t) + [sympy.Number(1)])
        return t
    terms = property(_getterms, doc='Terms in the linear regression formula.')

    def _getmean(self):
        """ Expression for mean

        Expression for the mean, expressed as a linear combination of
        terms, each with dummy variables in front.
        """
        b = [self.coefs[term] for term in self.terms]
        return np.sum(np.array(b)*self.terms)
    mean = property(_getmean, doc="Expression for the mean, expressed "
                    "as a linear combination of terms, each with dummy "
                    "variables in front.")

    def _getdiff(self):
        params = sorted(list(set(getparams(self.mean))), key=default_sort_key)
        return [sympy.diff(self.mean, p).doit() for p in params]
    design_expr = property(_getdiff)

    def _getdtype(self):
        vnames = [str(s) for s in self.design_expr]
        return np.dtype([(n, np.float) for n in vnames])
    dtype = property(_getdtype, doc='The dtype of the design matrix of the Formula.')

    def __repr__(self):
        return "Formula(%r)" % (list(self.terms),)

    def __getitem__(self, key):
        """ Return the term such that str(term) == key.

        Parameters
        ----------
        key : str
            name of term to retrieve

        Returns
        -------
        term : sympy.Expression
        """
        names = [str(t) for t in self.terms]
        try:
            idx = names.index(key)
        except ValueError:
            raise ValueError('term %s not found' % key)
        return self.terms[idx]

    @staticmethod
    def fromrec(rec, keep=[], drop=[]):
        """ Construct Formula from recarray

        For fields with a string-dtype, it is assumed that these are
        qualtiatitve regressors, i.e. Factors.

        Parameters
        ----------
        rec: recarray
            Recarray whose field names will be used to create a formula.
        keep: []
            Field names to explicitly keep, dropping all others.
        drop: []
            Field names to drop.
        """
        f = {}
        for n in rec.dtype.names:
            if rec[n].dtype.kind in 'SOU':
                f[n] = Factor.fromcol(rec[n], n)
            else:
                f[n] = Term(n).formula
        for d in drop:
            del(f[d])
        if keep:
            return np.sum([t for n, t in f.items() if n in keep])
        else:
            return np.sum(list(f.values()))

    def subs(self, old, new):
        """ Perform a sympy substitution on all terms in the Formula

        Returns a new instance of the same class

        Parameters
        ----------
        old : sympy.Basic
           The expression to be changed
        new : sympy.Basic
           The value to change it to.

        Returns
        -------
        newf : Formula

        Examples
        --------
        >>> s, t = [Term(l) for l in 'st']
        >>> f, g = [sympy.Function(l) for l in 'fg']
        >>> form = Formula([f(t),g(s)])
        >>> newform = form.subs(g, sympy.Function('h'))
        >>> newform.terms
        array([f(t), h(s)], dtype=object)
        >>> form.terms
        array([f(t), g(s)], dtype=object)
        """
        return self.__class__([term.subs(old, new) for term in self.terms])

    def __add__(self, other):
        """ New Formula combining terms of `self` with those of `other`.

        Parameters
        ----------
        other : Formula instance
            Object for which ``is_formula(other)`` is True

        Returns
        -------
        added : Formula instance
            Formula combining terms of `self` with terms of `other`

        Examples
        --------
        >>> x, y, z = [Term(l) for l in 'xyz']
        >>> f1 = Formula([x,y,z])
        >>> f2 = Formula([y])+I
        >>> f3=f1+f2
        >>> sorted(f1.terms, key=default_sort_key)
        [x, y, z]
        >>> sorted(f2.terms, key=default_sort_key)
        [1, y]
        >>> sorted(f3.terms, key=default_sort_key)
        [1, x, y, y, z]
        """
        if not is_formula(other):
            raise ValueError('only Formula objects can be added to a Formula')
        f = Formula(np.hstack([self.terms, other.terms]))
        return f

    def __sub__(self, other):
        """ New Formula by deleting terms in `other` from those in `self`

        Create and return a new Formula by deleting terms in `other` from those
        in `self`.

        No exceptions are raised for terms in `other` that do not appear in
        `self`.

        Parameters
        ----------
        other : Formula instance
            Object for which ``is_formula(other)`` is True

        Returns
        -------
        subbed : Formula instance
            Formula with terms of `other` removed from terms of `self`

        Examples
        --------
        >>> x, y, z = [Term(l) for l in 'xyz']
        >>> f1 = Formula([x, y, z])
        >>> f2 = Formula([y]) + I
        >>> f1.mean
        _b0*x + _b1*y + _b2*z
        >>> f2.mean
        _b0*y + _b1
        >>> f3 = f2 - f1
        >>> f3.mean
        _b0
        >>> f4 = f1 - f2
        >>> f4.mean
        _b0*x + _b1*z
        """
        if not is_formula(other):
            raise ValueError(
                'only Formula objects can be subtracted from a Formula')
        # Preserve order of terms in subtraction
        unwanted = set(other.terms)
        d = [term for term in self.terms if term not in unwanted]
        return Formula(d)

    def __array__(self):
        return self.terms

    def _getparams(self):
        return getparams(self.mean)
    params = property(_getparams, doc='The parameters in the Formula.')

    def __mul__(self, other):
        if not is_formula(other):
            raise ValueError('only two Formulas can be multiplied together')
        if is_factor(self):
            if self == other:
                return self
        v = []
        # Compute the pairwise product of each term
        # If either one is a Term, use Term's multiplication
        for sterm in self.terms:
            for oterm in other.terms:
                if is_term(sterm):
                    v.append(Term.__mul__(sterm, oterm))
                elif is_term(oterm):
                    v.append(Term.__mul__(oterm, sterm))
                else:
                    v.append(sterm*oterm)
        terms = sorted(set(v), key=default_sort_key)
        return Formula(tuple(terms))

    def __eq__(self, other):
        s = np.array(self)
        o = np.array(other)
        if s.shape != o.shape:
            return False
        return np.alltrue(np.equal(np.array(self), np.array(other)))

    def _setup_design(self):
        """ Initialize design

        Create a callable object to evaluate the design matrix at a given set
        of parameter values to be specified by a recarray and observed Term
        values, also specified by a recarray.
        """
        # the design expression is the differentiation of the expression
        # for the mean.  It is a list
        d = self.design_expr
        # Before evaluating, we recreate the formula
        # with numbered terms, and numbered parameters.

        # This renaming has no impact on the
        # final design matrix as the
        # callable, self._f below, is a lambda
        # that does not care about the names of the terms.

        # First, find all terms in the mean expression,
        # and rename them in the form "__t%d__" with a
        # random offset.
        # This may cause a possible problem
        # when there are parameters named something like "__t%d__".
        # Using the random offset will minimize the possibility
        # of this happening.

        # This renaming is here principally because of the intercept.

        random_offset = np.random.random_integers(low=0, high=2**30)

        terms = getterms(self.mean)

        newterms = []
        for i, t in enumerate(terms):
            newt = sympy.Symbol("__t%d__" % (i + random_offset))
            for j, _ in enumerate(d):
                d[j] = d[j].subs(t, newt)
            newterms.append(newt)

        # Next, find all parameters that remain in the design expression.
        # In a standard regression model, there will be no parameters
        # because they will all be differentiated away in computing
        # self.design_expr. In nonlinear models, parameters will remain.

        params = getparams(self.design_expr)
        newparams = []
        for i, p in enumerate(params):
            newp = Dummy("__p%d__" % (i + random_offset))
            for j, _ in enumerate(d):
                d[j] = d[j].subs(p, newp)
            newparams.append(newp)

        # If there are any aliased functions, these need to be added
        # to the name space before sympy lambdifies the expression

        # These "aliased" functions are used for things like
        # the natural splines, etc. You can represent natural splines
        # with sympy but the expression is pretty awful.  Note that
        # ``d`` here is list giving the differentiation of the
        # expression for the mean.  self._f(...) therefore also returns
        # a list
        self._f = lambdify(newparams + newterms, d, ("numpy"))

        # The input to self.design will be a recarray of that must
        # have field names that the Formula will expect to see.
        # However, if any of self.terms are FactorTerms, then the field
        # in the recarray will not actually be in the Term.
        #
        # For example, if there is a Factor 'f' with levels ['a','b'],
        # there will be terms 'f_a' and 'f_b', though the input to
        # design will have a field named 'f'. In this sense,
        # the recarray used in the call to self.design
        # is not really made up of terms, but "preterms".

        # In this case, the callable

        preterm = []
        for t in terms:
            if not is_factor_term(t):
                preterm.append(str(t))
            else:
                preterm.append(t.factor_name)
        preterm = list(set(preterm))

        # There is also an argument for parameters that are not
        # Terms.

        self._dtypes = {'param':np.dtype([(str(p), np.float) for p in params]),
                        'term':np.dtype([(str(t), np.float) for t in terms]),
                        'preterm':np.dtype([(n, np.float) for n in preterm])}

        self.__terms = terms

    def design(self,
               input,
               param=None,
               return_float=False,
               contrasts=None):
        """ Construct the design matrix, and optional contrast matrices.

        Parameters
        ----------
        input : np.recarray
           Recarray including fields needed to compute the Terms in
           getparams(self.design_expr).
        param : None or np.recarray
           Recarray including fields that are not Terms in
           getparams(self.design_expr)
        return_float : bool, optional
           If True, return a np.float array rather than a np.recarray
        contrasts : None or dict, optional
           Contrasts. The items in this dictionary should be (str,
           Formula) pairs where a contrast matrix is constructed for
           each Formula by evaluating its design at the same parameters
           as self.design. If not None, then the return_float is set to True.

        Returns
        -------
        des : 2D array
            design matrix
        cmatrices : dict, optional
            Dictionary with keys from `contrasts` input, and contrast matrices
            corresponding to `des` design matrix.  Returned only if `contrasts`
            input is not None
        """
        self._setup_design()

        preterm_recarray = input
        param_recarray = param

        # The input to design should have field names for all fields in self._dtypes['preterm']
        if not set(preterm_recarray.dtype.names).issuperset(self._dtypes['preterm'].names):
            raise ValueError("for term, expecting a recarray with "
                             "dtype having the following names: %r"
                             % (self._dtypes['preterm'].names,))
        # The parameters should have field names for all fields in self._dtypes['param']
        if param_recarray is not None:
            if not set(param_recarray.dtype.names).issuperset(self._dtypes['param'].names):
                raise ValueError("for param, expecting a recarray with "
                                 "dtype having the following names: %r"
                                 % (self._dtypes['param'].names,))
        # If the only term is an intercept,
        # the return value is a matrix of 1's.
        if list(self.terms) == [sympy.Number(1)]:
            a = np.ones(preterm_recarray.shape[0], np.float)
            if not return_float:
                a = a.view(np.dtype([('intercept', np.float)]))
            return a
        elif not self._dtypes['term']:
            raise ValueError("none of the expresssions are self.terms "
                             "are Term instances; shape of resulting "
                             "undefined")
        # The term_recarray is essentially the same as preterm_recarray,
        # except that all factors in self are expanded
        # into their respective binary columns.
        term_recarray = np.zeros(preterm_recarray.shape[0],
                                 dtype=self._dtypes['term'])
        for t in self.__terms:
            if not is_factor_term(t):
                term_recarray[t.name] = preterm_recarray[t.name]
            else:
                factor_col = preterm_recarray[t.factor_name]
                # Python 3: If column type is bytes, convert to string, to allow
                # level comparison
                if factor_col.dtype.kind == 'S':
                    factor_col = factor_col.astype('U')
                fl_ind =  np.array([x == t.level
                                    for x in factor_col]).reshape(-1)
                term_recarray['%s_%s' % (t.factor_name, t.level)] = fl_ind
        # The lambda created in self._setup_design needs to take a tuple of
        # columns as argument, not an ndarray, so each column
        # is extracted and put into float_tuple.
        float_array = term_recarray.view(np.float)
        float_array.shape = (term_recarray.shape[0], -1)
        float_array = float_array.T
        float_tuple = tuple(float_array)
        # If there are any parameters, they also must be extracted
        # and put into a tuple with the order specified
        # by self._dtypes['param']
        if param_recarray is not None:
            param = tuple(float(param_recarray[n]) for n in self._dtypes['param'].names)
        else:
            param = ()
        # Evaluate the design at the parameters and tuple of arrays
        D = self._f(*(param+float_tuple))
        # TODO: check if this next stepis necessary
        # I think it is because the lambda evaluates sympy.Number(1) to 1
        # and not an array.
        D_tuple = [np.asarray(w) for w in D]

        need_to_modify_shape = []
        OK_row_shapes = []
        for i, row in enumerate(D_tuple):
            if row.shape in [(),(1,)]:
                need_to_modify_shape.append(i)
            else:
                OK_row_shapes.append(row.shape[0])
        # Make sure that each array has the correct shape.
        # The columns in need_to_modify should just be
        # the intercept column, which evaluates to have shape == ().
        # This makes sure that it has the correct number of rows.
        for i in need_to_modify_shape:
            D_tuple[i].shape = ()
            D_tuple[i] = np.multiply.outer(D_tuple[i], np.ones(preterm_recarray.shape[0]))
        # At this point, all the columns have the correct shape and the
        # design matrix is almost ready to output.
        D = np.array(D_tuple).T
        # If we will return a float matrix or any contrasts,
        # we may have some reshaping to do.
        if contrasts is None:
            contrasts = {}
        if return_float or contrasts:
            # If the design matrix is just a column of 1s
            # return a 1-dimensional array.
            D = np.squeeze(D.astype(np.float))
            # If there are contrasts, the pseudo-inverse of D
            # must be computed.
            if contrasts:
                if D.ndim == 1:
                    _D = D.reshape((D.shape[0], 1))
                else:
                    _D = D
                pinvD = np.linalg.pinv(_D)
        else:
            # Correct the dtype.
            # XXX There seems to be a lot of messing around with the dtype.
            # This would be a convenient place to just add
            # labels like a DataArray.
            D = np.array([tuple(r) for r in D], self.dtype)
        # Compute the contrast matrices, if any.
        if contrasts:
            cmatrices = {}
            for key, cf in contrasts.items():
                if not is_formula(cf):
                    cf = Formula([cf])
                L = cf.design(input, param=param_recarray,
                              return_float=True)
                cmatrices[key] = contrast_from_cols_or_rows(L, _D, pseudo=pinvD)
            return D, cmatrices
        else:
            return D

def natural_spline(t, knots=None, order=3, intercept=False):
    """ Return a Formula containing a natural spline

    Spline for a Term with specified `knots` and `order`.

    Parameters
    ----------
    t : ``Term``
    knots : None or sequence, optional
       Sequence of float.  Default None (same as empty list)
    order : int, optional
       Order of the spline. Defaults to a cubic (==3)
    intercept : bool, optional
       If True, include a constant function in the natural
       spline. Default is False

    Returns
    -------
    formula : Formula
         A Formula with (len(knots) + order) Terms (if intercept=False,
         otherwise includes one more Term), made up of the natural spline
         functions.

    Examples
    --------
    >>> x = Term('x')
    >>> n = natural_spline(x, knots=[1,3,4], order=3)
    >>> xval = np.array([3,5,7.]).view(np.dtype([('x', np.float)]))
    >>> n.design(xval, return_float=True)
    array([[   3.,    9.,   27.,    8.,    0.,   -0.],
           [   5.,   25.,  125.,   64.,    8.,    1.],
           [   7.,   49.,  343.,  216.,   64.,   27.]])
    >>> d = n.design(xval)
    >>> print(d.dtype.descr)
    [('ns_1(x)', '<f8'), ('ns_2(x)', '<f8'), ('ns_3(x)', '<f8'), ('ns_4(x)', '<f8'), ('ns_5(x)', '<f8'), ('ns_6(x)', '<f8')]
    """
    if knots is None:
        knots = {}
    fns = []
    for i in range(order+1):
        n = 'ns_%d' % i
        def f(x, i=i):
            return x**i
        s = implemented_function(n, f)
        fns.append(s(t))

    for j, k in enumerate(knots):
        n = 'ns_%d' % (j+i+1,)
        def f(x, k=k, order=order):
            return (x-k)**order * np.greater(x, k)
        s = implemented_function(n, f)
        fns.append(s(t))

    if not intercept:
        fns.pop(0)

    ff = Formula(fns)
    return ff

# The intercept formula

I = Formula([sympy.Number(1)])

class Factor(Formula):
    """ A qualitative variable in a regression model

    A Factor is similar to R's factor. The levels of the Factor can be
    either strings or ints.
    """
    # This flag is defined to avoid using isinstance in getterms
    # and getparams.
    _factor_flag = True

    def __init__(self, name, levels, char='b'):
        """ Initialize Factor

        Parameters
        ----------
        name : str
        levels : [str or int]
            A sequence of strings or ints.
        char : str, optional
            prefix character for regression coefficients
        """
        # Check whether they can all be cast to strings or ints without
        # loss.
        levelsarr = np.asarray(levels)
        if levelsarr.ndim == 0 and levelsarr.dtype.kind in 'SOU':
            levelsarr = np.asarray(list(levels))
        if levelsarr.dtype.kind not in 'SOU': # the levels are not strings
            if not np.alltrue(np.equal(levelsarr, np.round(levelsarr))):
                raise ValueError('levels must be strings or ints')
            levelsarr = levelsarr.astype(np.int)
        elif levelsarr.dtype.kind == 'S': # Byte strings, convert
            levelsarr = levelsarr.astype('U')
        Formula.__init__(self, [FactorTerm(name, l) for l in levelsarr],
                         char=char)
        self.levels = list(levelsarr)
        self.name = name

    # TODO: allow different specifications of the contrasts
    # here.... this is like R's contr.sum

    def get_term(self, level):
        """
        Retrieve a term of the Factor...
        """
        if level not in self.levels:
            raise ValueError('level not found')
        return self["%s_%s" % (self.name, str(level))]

    def _getmaineffect(self, ref=-1):
        v = list(self._terms.copy())
        ref_term = v[ref]
        v.pop(ref)
        return Formula([vv - ref_term for vv in v])
    main_effect = property(_getmaineffect)

    def stratify(self, variable):
        """ Create a new variable, stratified by the levels of a Factor.

        Parameters
        ----------
        variable : str or simple sympy expression
            If sympy expression, then string representation must be all lower
            or upper case letters, i.e. it can be interpreted as a name.

        Returns
        -------
        formula : Formula
            Formula whose mean has one parameter named variable%d, for each
            level in self.levels

        Examples
        --------
        >>> f = Factor('a', ['x','y'])
        >>> sf = f.stratify('theta')
        >>> sf.mean
        _theta0*a_x + _theta1*a_y
        """
        if not set(str(variable)).issubset(ascii_letters + digits):
            raise ValueError('variable should be interpretable as a '
                             'name and not have anything but digits '
                             'and numbers')
        variable = sympy.sympify(variable)
        f = Formula(self._terms, char=variable)
        f.name = self.name
        return f

    @staticmethod
    def fromcol(col, name):
        """ Create a Factor from a column array.

        Parameters
        ----------
        col : ndarray
            an array with ndim==1
        name : str
            name of the Factor

        Returns
        -------
        factor : Factor

        Examples
        --------
        >>> data = np.array([(3,'a'),(4,'a'),(5,'b'),(3,'b')], np.dtype([('x', np.float), ('y', 'S1')]))
        >>> f1 = Factor.fromcol(data['y'], 'y')
        >>> f2 = Factor.fromcol(data['x'], 'x')
        >>> d = f1.design(data)
        >>> print(d.dtype.descr)
        [('y_a', '<f8'), ('y_b', '<f8')]
        >>> d = f2.design(data)
        >>> print(d.dtype.descr)
        [('x_3', '<f8'), ('x_4', '<f8'), ('x_5', '<f8')]
        """
        col = np.asarray(col)
        if col.ndim != 1 or (col.dtype.names and len(col.dtype.names) > 1):
            raise ValueError('expecting an array that can be thought '
                             'of as a column or field of a recarray')
        levels = np.unique(col)
        if not col.dtype.names and not name:
            name = 'factor'
        elif col.dtype.names:
            name = col.dtype.names[0]
        return Factor(name, levels)

def contrast_from_cols_or_rows(L, D, pseudo=None):
    """ Construct a contrast matrix from a design matrix D

    (possibly with its pseudo inverse already computed)
    and a matrix L that either specifies something in
    the column space of D or the row space of D.

    Parameters
    ----------
    L : ndarray
       Matrix used to try and construct a contrast.
    D : ndarray
       Design matrix used to create the contrast.
    pseudo : None or array-like, optional
       If not None, gives pseudo-inverse of `D`.  Allows you to pass
       this if it is already calculated.

    Returns
    -------
    C : ndarray
       Matrix with C.shape[1] == D.shape[1] representing an estimable
       contrast.

    Notes
    -----
    From an n x p design matrix D and a matrix L, tries to determine a p
    x q contrast matrix C which determines a contrast of full rank,
    i.e. the n x q matrix

    dot(transpose(C), pinv(D))

    is full rank.

    L must satisfy either L.shape[0] == n or L.shape[1] == p.

    If L.shape[0] == n, then L is thought of as representing
    columns in the column space of D.

    If L.shape[1] == p, then L is thought of as what is known
    as a contrast matrix. In this case, this function returns an estimable
    contrast corresponding to the dot(D, L.T)

    This always produces a meaningful contrast, not always
    with the intended properties because q is always non-zero unless
    L is identically 0. That is, it produces a contrast that spans
    the column space of L (after projection onto the column space of D).
    """
    L = np.asarray(L)
    D = np.asarray(D)
    n, p = D.shape
    if L.shape[0] != n and L.shape[1] != p:
        raise ValueError('shape of L and D mismatched')
    if pseudo is None:
        pseudo = pinv(D)
    if L.shape[0] == n:
        C = np.dot(pseudo, L).T
    else:
        C = np.dot(pseudo, np.dot(D, L.T)).T
    Lp = np.dot(D, C.T)
    if len(Lp.shape) == 1:
        Lp.shape = (n, 1)
    Lp_rank = matrix_rank(Lp)
    if Lp_rank != Lp.shape[1]:
        Lp = full_rank(Lp, Lp_rank)
        C = np.dot(pseudo, Lp).T
    return np.squeeze(C)

class RandomEffects(Formula):
    """ Covariance matrices for common random effects analyses.

    Examples
    --------
    Two subjects (here named 2 and 3):

    >>> subj = make_recarray([2,2,2,3,3], 's')
    >>> subj_factor = Factor('s', [2,3])

    By default the covariance matrix is symbolic.  The display differs a little
    between sympy versions (hence we don't check it in the doctests):

    >>> c = RandomEffects(subj_factor.terms)
    >>> c.cov(subj) #doctest: +IGNORE_OUTPUT
    array([[_s2_0, _s2_0, _s2_0, 0, 0],
           [_s2_0, _s2_0, _s2_0, 0, 0],
           [_s2_0, _s2_0, _s2_0, 0, 0],
           [0, 0, 0, _s2_1, _s2_1],
           [0, 0, 0, _s2_1, _s2_1]], dtype=object)

    With a numeric `sigma`, you get a numeric array:

    >>> c = RandomEffects(subj_factor.terms, sigma=np.array([[4,1],[1,6]]))
    >>> c.cov(subj)
    array([[ 4.,  4.,  4.,  1.,  1.],
           [ 4.,  4.,  4.,  1.,  1.],
           [ 4.,  4.,  4.,  1.,  1.],
           [ 1.,  1.,  1.,  6.,  6.],
           [ 1.,  1.,  1.,  6.,  6.]])
    """
    def __init__(self, seq, sigma=None, char = 'e'):
        """ Initialize random effects instance

        Parameters
        ----------
        seq : [``sympy.Basic``]
        sigma : ndarray
             Covariance of the random effects. Defaults
             to a diagonal with entries for each random
             effect.
        char : character for regression coefficient
        """

        self._terms = np.asarray(seq)
        q = self._terms.shape[0]

        self._counter = 0
        if sigma is None:
            self.sigma = np.diag([Dummy('s2_%d' % i) for i in range(q)])
        else:
            self.sigma = sigma
        if self.sigma.shape != (q,q):
            raise ValueError('incorrect shape for covariance '
                             'of random effects, '
                             'should have shape %r' % ((q,q)))
        self.char = char

    def cov(self, term, param=None):
        """
        Compute the covariance matrix for some given data.

        Parameters
        ----------
        term : np.recarray
             Recarray including fields corresponding to the Terms in
             getparams(self.design_expr).
        param : np.recarray
             Recarray including fields that are not Terms in
             getparams(self.design_expr)

        Returns
        -------
        C : ndarray
             Covariance matrix implied by design and self.sigma.
        """
        D = self.design(term, param=param, return_float=True)
        return np.dot(D, np.dot(self.sigma, D.T))

def is_term(obj):
    """ Is obj a Term?
    """
    return hasattr(obj, "_term_flag")

def is_factor_term(obj):
    """ Is obj a FactorTerm?
    """
    return hasattr(obj, "_factor_term_flag")

def is_formula(obj):
    """ Is obj a Formula?
    """
    return hasattr(obj, "_formula_flag")

def is_factor(obj):
    """ Is obj a Factor?
    """
    return hasattr(obj, "_factor_flag")


text:
layout: docs
title: Images
description: Documentation and examples for opting images into responsive behavior (so they never become larger than their parent elements) and add lightweight styles to them—all via classes.
group: content
toc: true
---

## Responsive images

Images in Bootstrap are made responsive with `.img-fluid`. `max-width: 100%;` and `height: auto;` are applied to the image so that it scales with the parent element.

{{< example >}}
{{< placeholder width="100%" height="250" class="bd-placeholder-img-lg img-fluid" text="Responsive image" >}}
{{< /example >}}

## Image thumbnails

In addition to our [border-radius utilities]({{< docsref "/utilities/borders" >}}), you can use `.img-thumbnail` to give an image a rounded 1px border appearance.

{{< example >}}
{{< placeholder width="200" height="200" class="img-thumbnail" title="A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera" >}}
{{< /example >}}

## Aligning images

Align images with the [helper float classes]({{< docsref "/utilities/float" >}}) or [text alignment classes]({{< docsref "/utilities/text#text-alignment" >}}). `block`-level images can be centered using [the `.mx-auto` margin utility class]({{< docsref "/utilities/spacing#horizontal-centering" >}}).

{{< example >}}
{{< placeholder width="200" height="200" class="rounded float-left" >}}
{{< placeholder width="200" height="200" class="rounded float-right" >}}
{{< /example >}}

{{< example >}}
{{< placeholder width="200" height="200" class="rounded mx-auto d-block" >}}
{{< /example >}}

{{< example >}}

  {{< placeholder width="200" height="200" class="rounded" >}}

{{< /example >}}

## Picture

If you are using the `<picture>` element to specify multiple `<source>` elements for a specific `<img>`, make sure to add the `.img-*` classes to the `<img>` and not to the `<picture>` tag.

{{< highlight html >}}
<picture>
  <source srcset="..." type="image/svg+xml">

</picture>
{{< /highlight >}}

redpajama_set_name: RedPajamaGithub


text:
French ministers in Moscow to 'ease tensions' with Russia
French Foreign Minister Jean-Yves Le Drian and Defence Minister Florence Parly meet their Russian counterparts in Moscow on 9 September, 2019. REUTERS/Shamil Zhumatov
French Foreign Minister Jean-Yves Le Drian called for easing tensions with Russia as top French ministers met their counterparts in Moscow on Monday.
"The time has come, the time is right, to work towards reducing distrust," Le Drian said at a press conference in the Russian capital.
Le Drian and Defence Minister Florence Parly held the first meeting in the so-called "2+2" format suspended after Russia seized Crimea from Ukraine in 2014.
"We have come to suggest, in the name of the president of the republic, a new agenda of trust and security," Le Drian said.
Parly said "it is important to talk to each other, to avoid misunderstanding and friction."
Russian Foreign Minister Sergei Lavrov said progress on rebuilding ties was "possible and necessary".
Ties between Russia and Europe have been deeply strained since 2014, when the European Union and United States imposed sanctions over the annexation of Crimea and Moscow's support for separatists in eastern Ukraine.
Macron has embarked on a bid to bring Russia in from the cold, hosting President Vladimir Putin for talks in southern France last month and renewing high-level diplomatic contacts.
The two men spoke by phone on Sunday, hailing an exchange of 70 prisoners between Russia and Ukraine as a step forward in peace efforts.
They said work was continuing for a summit of the leaders of France, Germany, Russia and Ukraine in Paris later this month.
'Frank discussion'
As the ministers began the four-way talks, Russia's top diplomat Sergei Lavrov welcomed France's efforts to rebuild relations, in particular remarks made by Macron that the time had come to "rethink our ties".
Le Drian said he and Parly were in Moscow to start a "frank discussion" in order to "move together towards a new architecture of confidence and security in Europe".
Macron's office said in a statement on Sunday that the ministers would be working on a roadmap for improving ties.
Ukraine will be the key issue, with Paris looking for signs that Putin -- and Ukraine's new president Volodymyr Zelensky -- are ready for more compromise after five years of conflict.
Iran is also likely to come up, as France and Russia look to save the unravelling nuclear deal with Tehran.
Ukraine, Russia complete prisoner swap, mixed reaction from West
france - DIPLOMACY
Macron calls on Europe to reach out to Russia

redpajama_set_name: RedPajamaCommonCrawl


text:
Q: querySelector() attachEvent() not working I have a button like bellow
<input type="button" value="check" />

And,I try to alert on this button click as follows
 document.querySelector('input[type="button"]').attachEvent('onclick', function() { alert(1); });

But this is not working,Why?

A: Use this code snippet:-
document.querySelector('input[type="button"]').addEventListener('click', function() { alert(1); });

A: Maybe this ones help:
link:
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_document_addeventlistener_crossbrowser
doc: http://www.w3schools.com/jsref/met_document_addeventlistener.asp

redpajama_set_name: RedPajamaStackExchange


To celebrate, we have a great interview recorded with Chris Evans of Bluegrass Tavern here in Lexington that I'll try and upload it once we hit the fabled 2K! Also, I've [hopefully] fixed our RSS feed so all our casts will show up in iTunes. I'm told this refreshes every 24 hours, so we'll see in a day or so.
Cheers guys, and as always, thanks for listening!
Next Post Cheers to 2K!


text:
Int'l Migrants Day tomorrow
·December 17, 2016
DHAKA, Dec 17, 2016 (BSS) - International Migrants Day 2016 will be observed in the country tomorrow like elsewhere in the globe.
On December 4 in 2000, the UN General Assembly, taking into account the large and increasing number of migrants in the world, proclaimed December 18 as the International Migrants Day.
On that day in 1990, the UN assembly adopted the International Convention on the protection of the rights of all migrant workers and members of their families.
President Md Abdul Hamid and Prime Minister Sheikh Hasina gave separate messages on the eve of the day.
The president, in his message, wished success of observing the day and suggested the authorities concerned to make easier the migration process so more people can get job overseas.
The prime minister in her message said the government had taken several steps to help expand the manpower market in different countries.
She said the Bangladeshi people working abroad are now getting better services due to digitisation of the overseas employment process.
The premier said that the Ministry of Expatriates' Welfare and Overseas Employment would be more active in creating newer job markets for exporting skilled manpower.
She also called the expatriate Bangladeshis to work with sincerity and honesty to earn a good name for their country.
Addressing a press conference in the city today, the Expatriates' Welfare and Overseas Employment Minister Nurul Islam said currently, over 10 million Bangladeshis are working in 161 countries across the world.
Briefing journalists on the day, he said this year the day would be observed under the slogan - 'Migrants First in the Highway of Development'.
The day will began with bringing out a rally in the capital city from the South Plaza of the Jatiya Sangsad at 9:30am. Following the rally, a discussion meeting will be held at the Bangabandhu International Conference Centre (BICC) where ministers, policymakers, experts and other stakeholders will participate.
As part of the day's programme, a shadow parliament debate contest and an easy and a art competition will also be held at the BICC.
Finance Minister Abul Maal Abdul Muhith is expected to present the shadow parliament debate contest as the chief guest, while Prime Minister's economic affairs advisor Dr Mashiur Rahman, expatriate welfare and overseas employment ministry's secretary Begum Shamsun Nahar and United Commercial bank's chairman MA Sabur as special guests.
According to new data presented by the United Nations, the number of international migrants - persons living in a country other than where they were born - reached 244 million in 2015 for the world as a whole, a 41 per cent increase compared to 2000. This figure includes almost 20 million refugees. The share of migrants in the global population reached 3.3 per cent in 2015, up from 2.8 per cent in 2000.
The UN Secretary-General's Message for 2016 said this has been another turbulent year for refugees and migrants. We have witnessed the unacceptable loss of thousands of lives of people in transit in the Mediterranean and elsewhere and witnessed the rise of populist movements that seek to alienate and expel migrants and refugees, and to blame them for various ills of society.
"On this International Migrants Day, I call on the international community to act on the global compact on safe, regular and orderly migration as an important contribution to building a world of peace, prosperity, dignity and opportunity for all." UN Secretary-General, Ban Ki-moon said.
Municipal councils must focus on increasing income or face dissolution: Minister
Covid-19: Educational institution closure extended to Jan 30
4th phase municipal polls: AL announces candidates
O-level student 'rape, murder': Case filed, 1 shown arrested
3 Hobbies to Pick Up During Quarantine
Rajshahi University journalists' body gets new executive committee


This set of "Molecule" holds is a truly spectacular set designed by Psycho Art Holds. It consists of 4 unique X-Large holds that will add a special touch to your wall!
Please carefully check the colour of item before ordering! The images do not necessarily represent the colour of the available item.


text:
Q: Given $a>0$ and continuous function $V$ on $(m,n)$ s.t. $\forall\epsilon \in [-a,a]$, $\log(1+ \epsilon V)$ is concave on $(m,n)$. Prove $V$ is affine Suppose there exists $a>0$ and a continuous function $V$ on $(m,n)$ such that for all $\epsilon \in [-a,a]$, the function $\log(1+ \epsilon V)$ is concave on $(m,n)$. I want to prove that $V$ is necessarily affine.
The argument in the text :  Since this is true for all $\epsilon \in [-a,a]$, we let $\epsilon \to 0^{+}$ and $0^{-}$, we get $V$ is affine.
Intuitively, it is clear why $V$ should be affine but I'm not convinced by the argument above and why that implies $V$ must be affine. Can someone explain this?

A: *

*Write down the concavity condition for the function $g(x) = \log(1+\epsilon V(x))$ and divide it by $\epsilon$.

*Consider the cases $\epsilon > 0$ and $\epsilon < 0$ separately, and note that the sign of the inequality is reversed when dividing by a negative number.

*Now take the limit for $\epsilon \to 0$. Use that $\lim_{\epsilon \to 0} \frac{\log(1+\epsilon V(x))}{\epsilon} = V(x)$.
You'll find that $V$ is both concave and convex, and therefore affine.


text:
ENG FRA DEU ITA
Palazzo Gallenga-Stuart en - Palazzo Gallenga-Stuart en
Palazzo Gallenga-Stuart
Palazzo Gallenga-Stuart is situated in piazza Fortebraccio in the city of Perugia near the impressive Etruscan Arch. The palace is now the headquarters of the Università per Stranieri (University for Foreigners) of Perugia, but it had long been the aristocratic residence of the Antinori family. A visit to the palace is recommended not only to admire its late Baroque style architecture but also to see its richly decorated rooms. For those who enjoy beautiful panoramic vistas, a climb up to the top floors of the building, will be rewarded with stunning views of the thirteenth-century aqueduct.
Piazza Fortebracci, in which the palace stands, is a meeting place for the many foreign students who are studying at the university and taking a course in Italian language and culture.
The palace, in late Baroque style, was built between 1748-58 by the architect Pietro Perugino Carattoli and designed by Francesco Bianchi. During the 1930's the American Count Frederich Thorne Rider financed the construction of the west part of the building which remains unfinished. The façade is punctuated by columns and brick cornices separating the large windows. The interior is decorated with frescoes by Giuli and Carattoli. In the main hall you can admire the painting of The Glorification of Rome by the futurist painter Gerardo Dottori. The small palace theatre saw Carlo Goldoni perform there when he was a child.
Since 1926 the building Gallenga-Stuart is home to the Italian University for Foreigners, whose aim is the learning and dissemination of the Italian language and culture in the world.
Curious fact
Piazza Fortebraccio, where the palace is situated, is also called Grimana in memory of Cardinal Marino Grimani, who promoted its construction in 1536 to fill in the hollow separating the walled city from the Sant'Angelo hamlet.
Palazzo del Capitano del Popolo - Corciano
Church of Sant'Agostino
Strozzacapponi Necropolis - Corciano
MUVIT – Torgiano Wine Museum
Museo della Casa Contadina - Corciano
The "Raphaelesque" style in Deruta
"Ubaldo Grazia Maioliche" Factory Museum - Deruta
Antiquarium - Corciano
Palazzo Municipale - Corciano
Pieve del Vescovo
Palazzo dei Priori - Corciano
Perugia and Spello: the Canticle Wine Route
An itinerary from Perugia to Spello, two of the charming towns of the Canticle Wine Route
A journey through faith: walk the Cammino della Luce – The Path of Light
Discover these spiritual itineraries enshrined in Umbria's pristine nature
From Perugia to Todi, along the Cantico Wine Route
Traavelling through the vineyards of the Colli Perugini hills we find the balance between the austere elegance of Rosso di Torgiano and the fruity verve of Grechetto of Todi wines
Connection Bike Lane of the Tiber –Bike Lane Assisi –Spoleto
A short stretch to be covered in complete peace, which connects Perugia to Assisi. A way to pass through all Umbrian wonders by bike, from North so South, among different bike lanes.
Bike Lane Perugia – Trasimeno
An easy itinerary that starts from an unusual "Perugia Green" by following through the delightful countryside close to the Trasimeno Mountains, up to the Lake that suddenly turns out.
A green island dedicated to the culture, art, tradition, history and beauty.


1. Cut out the course centre stalk from the leaves, then roll them into cigar shapes and finely slice into ribbons.
2. Heat a large saucepan and add the butter. Fry the spring greens for 5 minutes over a low heat, then add the garlic and Ras El Hanout. Add a splash of water, cover with a lid and cook for a further 10 mintes, until tender. Scatter over the pine nuts, taste and season before serving.


text:
GENERAL DEFENSE- MENTAL INCAPACITY
Mental incapacity is a defense which is used in criminal proceedings; it is the situation when a person is of appreciating the nature of the crime and differentiating right from wrong behavior and in this scenario the person is not into his full conscious which make them not legally accountable for the commission of the crime. In this case it must be noted that just by stating a mental disorder cannot act as a complete defense for escaping from the liability of the crime. For using this defense in criminal prosecution the defendant has prove the defense of insanity by a "preponderance of the evidence"
NEED OF THE DEFENSE
If a person is made liable for a crime which he has not even committed than it will result into violation of the basic human rights of any such person, an insane person who is not mentally capable to figure out the fact that whether what he is doing is right or not, when he is not in a condition to differentiate between the right and wrong when he is not able to conclude that what will be the end consequence of his act or omission, any such situation of insanity or mental incapacity as the facts may be the person can use the defense of insanity and escape from such liability.
SECTION 84 OF THE INDIAN PENAL CODE
Section 84 of the Indian penal code explains the any act committed by a person of unsound mind; this section says as follows that nothing will be considered as an offence if it is done by a person who at the time of doing the act was by reason of unsoundness of mind, is incapable of knowing the nature of the act he is doing and does it against the law.
Section 84 has many implicit features in it, this section classify the situation of unsound mind into two broad categories the first one is the major category which includes medical requirement of mental illness and the other one is the minor category, this category includes loss of reasoning requirement. The former category or the major category simply means a situation where the person is suffering from any kind of mental illness during the commission of the act for which he is being tried and the later or the minor category means the situation where the person is in incapable in analyzing the following situations that are
Incapable of knowing the nature of the act or
Incapable of knowing his act is wrong o
Incapable of knowing it is contrary to law.
Both major (mental illness) and minor (loss of reasoning) criteria constitute legal insanity or mental incapacity and can be used as a valid defense in criminal prosecutions.
Section 84 Indian penal code, clearly embodies a fundamental maxim of criminal jurisprudence that is,
(a) The first maxim is "Actus non facit reum nisi mens sit rea" which means an act does not constitute guilt unless done with a guilty intention and
(b) The second maxim is "Furiosi nulla voluntas est." which means the situation in which a person with mental illness has no free will. This means that an act does not constitute a crime unless it is done with a guilty intention called "mens rea" Hence, Section 84 in fastens no culpability on persons with mental illness because they can have no rational thinking or the necessary guilty intent.
LEGAL INSANITY
Legal insanity means a situation where at the time of the commission of any act which is illegal in the eyes of law, the person should be suffering from mental illness and also have a loss of reasoning power. This issue is clearly depicted in Section 84 of the Indian penal code as that person incapable of knowing:
The nature of the act that he has done, or
That he is doing what is either wrong or illegal
The commission of the act is contrary to law.
Mere abnormality of mind or partial delusion, irresistible impulse or compulsive behavior of a psychopath affords no protection under Section 84 Indian penal code.
Surendra Mishra vs. state of Jharkhand
This is a landmark for section 84 of the Indian penal code in this case the Apex Court has stated that an accused who seeks exoneration from liability of an act under Section 84 of the Indian Penal Code is to prove legal insanity and not medical insanity and the court also explained the ambit of this section.
Facts of the case: In this case the deceased Chandrashekhar chaubey was going in a car which was driven by Vidyut Kumar Modi after reaching to a destination Chandrashekhar chaubey asked the driver to stop the car and he called Shasdhar Mukherjee the owner of sulekha auto parts. the deceased (Chandrashekhar chaubey) started talking to him(Shasdhar Mukherjee) from inside the car and all of a sudden the appellant who is the owner of a medical hall came there with a pistol he pushed Shasdhar Mukherjee aside and fired the pistol on Chandrashekhar chaubey after which the driver fled away from the place where this crime happened and he immediately informed the family members of the deceased and left the deceased in the car itself on the basis of the facts a case was filed under section 302 of Indian Penal Code and section 27 of the arms act against the appellant
later on the appellant was put on trial for the Commission of offences under section 302 of Indian Penal Code and section 27 of the arms act the plea of the appellant was that by the virtue of unsoundness of mind the act committed by him comes within the exception under section 84 of the Indian Penal Code and therefore he cannot be held liable for the act done by him the trial court and later the High Court also rejected the plea of the appellant.
In this case the court said that for taking the defense of insanity or the defense of unsound mind under section 84 of the Indian Penal Code it must be established that the act committed are not offence and the person taking the defense is required to prove that at the time of Commission of the act the accused by the reason of unsound mind was incapable of making difference between wrong or right, legal or illegal nature of the act in the present case after the investigation it was made clear that immediately after the appellant had shot dead the deceased he then threatened vidyut Kumar ( the driver of the deceased) and he also ran away from the place of occurrence and he threw the pistol by these acts of the appellant it can be made clear that he was well known that whatever he has done is wrong and illegal. He (the appellant) was running a medical shop and came to the place of occurrence and shot dead the deceased had the appellant been the person of unsound mind it may not have been possible for him to run a medical shop and the court held the appellant libel under the section 302 of Indian penal court and section 27 of the arms act.
Section 84 of the Indian penal code introduction (Mental incapacity) or unsound mind >>> https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4676201/#:~:text=Section%2084%20of%20IPC%20deals,wrong%20or%20contrary%20to%20law.%E2%80%9D
Need of the defense under criminal law >>>https://blog.ipleaders.in/insanity-defence-indian-penal-code/
Ingredients required for constituting the defense of mental incapacity >>> https://www.legalserviceindia.com/legal/article-3140-defense-of-insanity.html
Section 84 of the Indian penal code in the bare act language>>>https://indiankanoon.org/doc/1433889/
Surendra Mishra vs. state of Jharkhand case and its facts >>> https://indiankanoon.org/doc/1259566/
Surendra Mishra vs. state of Jharkhand decree of the trial court, the high court and the supreme court>>> https://www.casemine.com/judgement/in/575fd23d607dba63d7e66f92
Other cases concerned with unsound mind, insanity, and mental incapacity>>>https://www.casemine.com/act/in/5a979d944a93263ca60b70a3#5a97a6d54a93264050a31ac4
Section 302 of the Indian penal code>>> https://indiankanoon.org/doc/1560742/#:~:text=302.,also%20be%20liable%20to%20fine.
Section 27 of the arms act>>>https://www.indiacode.nic.in/show-data?actid=AC_CEN_5_23_00014_195954_1517807322009&sectionId=6853&sectionno=27&orderno=29#:~:text=%5B27.-,Punishment%20for%20using%20arms%2C%20etc.,also%20be%20liable%20to%20fine.
Published by Shreya Khare
My Name is Shreya Khare. I am a law student from Bhopal. I am keen to learn new aspects related to law View all posts by Shreya Khare
Role of State Human Rights Commission
STAMP DUTY AND REGISTRATION CHARGES IN MAHARASHTRA


A bench of Chief Justice Pradeep Nandrajog and Justice NM Jamdar directed the administration of the two Union Territories (UTs) to declare Friday, April 19, a public holiday.
The administrator of Dadra and Nagar Haveli and Daman and Diu had earlier issued a notification marking Good Friday as an optional holiday at government offices.
Their counsel Harish Jagtiani argued that while the Christian population in these Union Territories accounted for just 2 per cent of the total population, the "principles of secularism" mandated that one consider the "sentiments of the minority community and not the numbers".
The petitioners said in the plea that this was the "first instance" in the history of Union Territories that Good Friday had not been notified as a public holiday.
"Ever since these territories came under the Indian Union, it (Good Friday) has always been declared as a public holiday considering that many Christians are living in far flung areas of these Union Territories," the plea read.
"Christmas is celebrated with much bonhomie by all communities. People of all castes, creed and communities observe Good Friday… And chocolate bunnies and Easter eggs are eaten and enjoyed by all," the bench said.
"Considering the importance of Good Friday for the community (Christians), the administrator to declare it as a public holiday," it said while disposing of the petition. Good Friday commemorates the crucifixion of Jesus Christ. It is followed by the celebration of Easter Sunday, commemorating the resurrection of Christ.


text:
Соревнования по боксу среди мужчин в весовой категории до 91 кг на летних Олимпийских играх 2020 года пройдут с 24 июля по 6 августа во дворце спорта Рёгоку Кокугикан. В соревнованиях участвует 17 спортсменов из 17 стран.

История
Соревнование по боксу в мужском тяжелом весе на Олимпийских играх 2020 года будет проводиться в 26 раз. Тяжелая весовая категория впервые появился на Олимпийском турнире по боксу в 1904 году и в ней разыгрывали медали на всех Играх в которых проводился боксерский турнир. До Игр 1980 года тяжелая весовая категория была не ограничена уровнем верхнего веса. С 1984 года при появлении категории сверхтяжелого веса изменен критерий отбора тяжеловесов по весу нижний 81 кг и верхний 91 кг.
Действующим олимпийским чемпионом в данной дисциплине является российский боксёр Евгений Тищенко, который после Игр в Рио-де-Жанейро перешёл в профессионалы и участие в турнире не принимает.
Действующий чемпион мира Муслим Гаджимагомедов из России квалифицировался на Игры.
 Олимпийский чемпион в полутяжелой дисциплине кубинский боксёр  Хулио Сесар Ла Крус перешёл в весовую категорию до 91 кг и принимает участие в турнире в тяжелой весовой категории.

Призёры

Расписание
Время местное (UTC+9)

Соревнование

Примечания

Ссылки
 Турнирная таблица
 Бокс на официальном сайте летних Олимпийских игр 2020 года

Бокс на летних Олимпийских играх 2020

redpajama_set_name: RedPajamaWikipedia


text:
A Couple Collects: Louise and Walter Arensberg
By Shannon Vittoria, Research Assistant On October 29, 2013 · Add Comment · In Blog, Buying and Selling
Walter Arensberg, 1928. Signed passport photograph. From Francis M. Naumann, New York Dada, 1915–23 (New York: Harry N. Abrams, 1994), p. 23
Harvard graduate Walter Arensberg (1878-1954) married Louise Stevens (1879-1953) in 1907. Although the couple was living in Cambridge, Massachusetts when the Armory Show opened in February of 1913, they made their way to New York City to see the exhibition. The Arensbergs were profoundly impacted by the experience: it sparked their interest in modern art, radicalizing their taste and inspiring a lifelong passion for collecting.
Visiting the show in the last days of its New York run – and after many notable works had already sold to eager collectors such as John Quinn and Arthur Jerome Eddy – the Arensbergs purchased only one Édouard Vuillard lithograph from the exhibition. They subsequently returned this print when the Armory Show arrived in Boston, instead acquiring lithographs by Paul Cézanne and Paul Gauguin, as well as a small landscape sketch by Jacques Villon. The latter purchase marked the beginning of their interest in Cubism, a movement they supported through major acquisitions in the wake of the exhibition. In fact, the Arensbergs would later acquire six Cubist paintings that they first saw at the Armory Show, including Marcel Duchamp's Nude Descending a Staircase (No. 2), Albert Gleizes's Man on a Balcony, and Francis Picabia's Dances at the Spring.
In 1914, the couple moved to New York, where they were increasingly active in city's avant-garde art scene. They displayed their growing art collection on the walls of their West 67th Street apartment and hosted nightly salons frequented by writers and artists, as their home became the hub of New York Dada.
Although they eventually settled in Los Angeles, the Arensbergs donated their collection of over one thousand objects to the Philadelphia Museum of Art in 1950. Their interests had expanded significantly since 1913 to include Byzantine and Renaissance painting, American folk art, and Pre-Columbian sculpture. Nevertheless, the Armory Show marked a pivotal moment in their collecting career, as it kindled their spirited and lasting enthusiasm for modern art.
The Armory Show at 100: Modern Art and Revolution is on view October 11, 2013 through February 23, 2013 at the New-York Historical Society.


John Stevenson is MP for Carlisle.
At present, if the current narrative is to be believed, the Parliamentary Conservative Party is split into two distinct groups; the so-called hard Brexiteers against those secretly plotting to ensure we never leave the European Union at all.
No doubt there is a minority in the Conservative Party who are obsessively pro or anti-EU – and they are certainly some of the loudest voices – but there is a sizeable majority of MPs who are generally supportive of the Government's efforts in implementing the result of the referendum. They want the best deal for the UK, but they can hear the clock ticking.
I am one of these MPs. I voted to remain in the referendum, but I accept the result and believe that there are huge opportunities to be had from Brexit if we get it right. Similarly, many of my colleagues who were leavers accept that in order to leave the EU there has to be compromise and an orderly route of departure.
But current difficulties arise because although the referendum decided that we should leave the EU, it didn't decide how. The Government's road map, as far as I can make out, is basically that we are leaving in March 2019 with a transition period until 2021. The planned transition period will be "as you were", other than the fact we will not formally be a member of the EU, and in 2021 we will finally depart with a mutually beneficial bespoke EU/UK trade deal in place.
Of course, a bespoke mutually beneficial UK/EU deal would be ideal, but if we are honest such a deal is not likely to be done by 2021. Just look where we have got in the last 18 months, and the difficulty we face in negotiating with an EU made up if 27 other countries.
The polarised nature of the current debate means that only two options are being presented as possible outcomes. Either we essentially remain in the EU in some kind of limbo until we actually do get a UK/EU deal; or we crash out of the single market, move to WTO rules, and put up hard borders.
But I believe that there is a very real and pragmatic third alternative. I believe that the United Kingdom should leave the EU and re-join the European Free Trade Association (EFTA), with the ultimate aim of agreeing a bespoke bilateral UK-EU trade deal as soon as practicably possible.
EFTA already operates with an agreement in parallel to the EU, which includes participation in the EU Single Market. Despite this, each member nation of EFTA has full rights to enter into bilateral trade agreements with other countries, as well as be part of EFTA-wide agreements. EFTA nations also have complete control over their own agricultural and fisheries policy.
The UK was a founder member of EFTA, and our re-joining would strengthen the organisation hugely. EFTA already has free trade agreements with 38 countries, not including the European Economic Area (EEA) agreement. This could be expanded even further, and UK membership would turbo-charge any future trade deals. With the UK as a member, EFTA could be a genuine free trade counterweight to the increasingly politicised European Union.
Most importantly, joining EFTA would be the easiest, least disruptive, and most productive way for this country to genuinely leave the EU until we have a bespoke UK-EU deal. Once a member of EFTA, the UK would be in a real position to decide its own future, working with strong and sensible member nations like Norway and Switzerland.
There would be compromise, of course. Members of EFTA have to accept EEA arrangements – at least until a new agreement is reached. But, crucially, the European Court of Justice (ECJ) has no jurisdiction over EFTA nations. Opposition to the jurisdiction of the ECJ was a key part of the leave campaign.
More contentiously, free movement of people would be a condition for membership of the EEA. But, whilst EU citizens are free to live and work in EFTA states (and vice-versa), EU citizens do not necessarily have the same rights to welfare and benefits as EFTA citizens do in their own countries. One just has to look at Norway's surprisingly firm but reasonable conditions for EU citizens living in the country.
Again, having this control was a crucial aspect in this country's decision to leave the EU. Many voters resented the fact that being a member of the European Union meant that this country's Government was obliged to confer all the rights and benefits of being a British citizen to 450 million citizens of the EU. They felt it stripped them of their national identity and inheritance. Being a member of EFTA partly addresses this, whilst simultaneously helping to solve immediate issues like disruption at the Irish border and Gibraltar.
It would also mean that this country would continue to have the ability to attract and keep best and brightest from Europe – those who make vital contributions to our industry and business. I don't believe that voters who had justifiable concerns about citizenship and borders would see this as an unacceptable compromise.
Re-joining EFTA would be no betrayal of the vote on June 23rd 2016. It would mean leaving the EU – and, importantly, the institutions that the EU controls. It would do this while giving this country the space and time to re-orientate itself and forge a proper and amicable relationship with the European Union. We would then be in a position to negotiate a new bespoke agreement with the EU while providing a degree of immediate certainty.
And for those who voted to remain, joining EFTA is not the leap in the dark that many feared. It is a well-established and respected organisation, made up of sensible and democratic nations who are happy to work closely with the EU, but who have longstanding reservations about the European Union project as it is.
However, in order for joining EFTA to be a viable option politically the Government has to make the case for it – and with real conviction. Time is running out and the Government has to once more find its own voice whilst ignoring some of the loudest voices of others. Most importantly, the Government has to understand that this is no longer a debate about leave vs remain: it's about Conservative pragmatism working to get the best for the UK.


text:
How Vaginal Fluid Transplants Could Help Cure BV
Story from Body
How Other Women's Vaginal Fluids Could Help Cure Recurring Bacterial Vaginosis
Photographed by Meg O'Donnell.
When it comes to gynaecological symptoms we don't feel comfortable talking about openly, the strong fishy smell associated with bacterial vaginosis is definitely up there. Bacterial vaginosis – or BV – is the most common vaginal infection, with symptoms including a greyish-white, watery discharge and unpleasant fishy odour. It's not sexually transmitted and half of those affected don't have any symptoms, but it can cause complications in pregnancy. And despite the fact that as many as one in three of us will get BV at some point in our lives, it's still badly understood and notoriously difficult to treat.
Research published last week could be a game-changer though. Scientists at Johns Hopkins University in the US have taken the first step towards using vaginal fluid transplants as a potential new treatment option for BV. Inspired by the successful use of faecal microbiota transplants (FMT – or poo transplants, to you and me) to treat gut problems, the idea behind vaginal microbiota transplants (VMT) is effectively to 'reset' the balance of bacteria inside the vagina, using 'good' bacteria from donors' vaginal fluid (or mucus).
Balancing vaginal bacteria
What exactly is the scientific explanation behind this? "The vaginal microbiome is fascinating. Bacteria reside within the mucus that's secreted by the vaginal tract and, in the healthy state, you essentially have a monoculture of [protective] lactobacillus bacteria," explains researcher Dr Laura Ensign, who is also co-author of the paper. "That's completely unique compared to [the microbiomes of] your gut and your skin, where the community of bacteria is very diverse. In the vagina, the dominance of these lactobacillus bacteria keeps the vaginal pH acidic, and that's how you keep other [bad] bacteria out."
I have a very understanding partner, who tries to reassure me, but I'm extremely aware of my symptoms, which can put me off having sex as it really affects my self-esteem. I'm so embarrassed by it.
Vicky*, Support Worker
Bacterial vaginosis, she explains, is a blanket term for that vaginal microbiome being out of whack – instead of being dominated by 'good' lactobacillus bacteria, it's made up of any other combination of bacteria.
Currently BV is treated using antibiotics – either taken orally or applied to the vagina in a gel or cream. The problem, as the Johns Hopkins researchers point out, is that existing BV treatment isn't "curative or restorative" – while antibiotics may treat the harmful bacteria, they don't create a protective environment to prevent them from coming back. As a result, Dr Ensign says, up to 70% of women experience a recurrence of BV. Oh, and the antibiotics used to treat BV can also cause thrush, just in case that recurrent cycle of infection wasn't frustrating enough already.
Vaginal fluid transplants, on the other hand, would work by introducing 'good bacteria' from a healthy woman's vaginal mucus. Those bacteria should then take over and become dominant in the recipient's microbiome, suppressing the other, harmful bacteria.
Healthy vaginal fluid would be self-collected by donors using a flexible plastic disc, similar to a menstrual cup or contraceptive diaphragm, and the recipient could then insert it herself using an applicator, similar to putting in a tampon. What researchers now need is funding and approval to trial the technique.
"I've resigned myself to life with BV"
If clinical trials are successful, vaginal fluid transplants could prove to be an absolute godsend for women like 28-year-old support worker Vicky*, who's lived with recurrent BV for more than two years. "Having BV makes me very self-conscious, not only during sex – especially when my partner performs oral sex – but also during everyday activities. At work I'm required to be on the move quite a lot, or work long hours, which aggravates the condition," Vicky says.
"I'm very aware that my underwear can become quite damp. I have to wear panty liners, which need to be changed regularly, but this doesn't help to tackle the unpleasant odour, which I'm constantly aware of. I'm worried people will think I have poor hygiene, or that I have a sexually transmitted infection," she adds. "I have a very understanding partner, who tries to reassure me, but I'm extremely aware of my symptoms, which can put me off having sex as it really affects my self-esteem. I'm so embarrassed by it."
Like many women, Vicky has struggled with treatments for her BV. "I've tried antibiotics multiple times – including metronidazole, which in turn causes thrush – and usually this works for a couple of days before my symptoms return. I was also given a cream to treat BV internally, and reassured that this would be really effective, but again my symptoms recurred almost immediately," she says.
After two years of treatment trial and error, Vicky says: "I'm at my wit's end. I've given up on going to the doctor for further treatment, and I've resigned myself to life with BV as no treatments have worked, not even in the short term."
But she adds: "It's heartening to hear that progress is being made in the US, and I'm excited to hear about how vaginal fluid transplants could help. It sounds like a very straightforward, pain-free procedure, and at this stage I would be prepared to try anything. I hope that if trials in the US are successful then similar studies will take place in the UK – I'd definitely put myself forward if it means I can be BV-free. This would be a massive boost to my self-esteem and confidence."
BV makes you disconnect from your vagina, and sex, and you become completely obsessed about the smell. I do speak to women who are constantly getting it, going on antibiotics, getting thrush.
Samantha, Sexual Health Nurse
"I whacked probiotic yoghurt up there on a tampon"
Samantha Evans, sexual health expert, former nurse, and founder of online sex toy store Jo Divine, suffered from recurrent bouts of both thrush and BV during her 20s and 30s – in her case triggered by the ingredients in her lubricant.
"I'm 51 now, but in my 20s and 30s I suffered from infections over a 10-year period, before there were over-the-counter treatments. I was a nurse but I didn't have a clue about BV. I'd buy probiotic yoghurt from my local health store and whack that up there on a tampon, because I had this vague idea that it would restore [the bacteria], but that probably didn't do any good either," she says.
Today, Samantha regularly hears from customers affected by vaginal infections, and is passionate about ensuring women understand how the products they're putting in their vagina – like feminine hygiene washes and douches – can affect its delicate pH and bacterial balance, causing or aggravating issues like BV.
"BV makes you disconnect from your vagina, and sex, and you become completely obsessed about the smell. I do speak to women who are constantly getting it, going on antibiotics, getting thrush," she says. "Then they're desperate, and buying any old intimate hygiene product to get rid of the smell, which then exacerbates or masks the problem. This is really exciting research, and the transplants would be utterly amazing to help women break out of that cycle."
Beyond bacterial vaginosis
While trialling vaginal fluid transplants for BV is the next step for researchers, Dr Ensign says there's also scope to use VMT in the treatment of other conditions, like recurrent urinary tract infections and yeast infections.
"There are also indirect implications for vaginal microbiota and preterm birth, and rarer conditions like pelvic inflammatory disease or other types of sexually transmitted infections. Or really, in any case where a woman has to take antibiotics for any reason, if there's a resulting alteration of the vaginal microbiome that you need to reset," she says.
Further down the line, it could also feed into emerging research looking at the links between the vaginal micobiome and gynaecological cancers. "If you could reset someone's [vaginal] microbiome as a young adult, would that end up affecting their cancer risk later?" Dr Ensign asks. "As we start to learn more about the links, there are very interesting questions to look at."
*Name has been changed
What Is A Vaginal Fluid Transplant
Body • Health
written by Sarah Graham
More from Body
'Worst Fatigue Ever': 21 People Share The Pain Of Having COVID & ...
by Maggie Zhou
"I Was Told The Cure Was To Have A Baby": The Sexist ...
"The first time I ever remember having a migraine was when I was 21 and I thought I got food poisoning from a spice bag," says Gillian, 28, who
by Sadhbh O'Sullivan
Voices of Disability
Sometimes I'm Fine, Often I'm Not: My Life With Dynam...
Yesterday I spoke at an event in front of hundreds of people. For hours I wandered around the event space, climbing endless stairs and drinking mulled wine
by Catriona Morton
Wellness Culture Won't Save Us. It's Only Making Us M...
The wellness industry may be a relatively recent mainstream phenomenon but it is far from new. The term 'wellness' was popularised back in the
Pelvic Congestion Syndrome Is Ruining My Life – But Doctors Won&#...
When it comes to chronic pain getting the condition taken seriously, let alone identified, can be as draining as dealing with the pain itself. This is espe
Can Access To Green Spaces Really Combat PMS?
I remember once watching my friend slowly slump to the ground, just like they do in the movies, and audibly wail because the 'good' pizza place
by Pema Bakshi
What I Learned About My Friendships When I Became Disabled
It took an instant for my entire life to change. When I look back, the memory is always black and white; spring flowers poking hopeful heads through the ta
by Louise Jensen
Bathroom Break
"It Was Easier Just To Stay Home": Living With Faecal...
Welcome to Bathroom Break, Refinery29's series all about poo and the complicated relationship we have with our bowels. To see the rest of the articles, c
by Sarah Graham
This Forgotten Affordable Fertility Treatment Is Making A Comeback
Fertility treatment is increasingly expensive and inaccessible for many. NHS treatment in England is dictated by a postcode lottery and cuts to funding (to
A Jargon-Free Guide To Understanding Polycystic Ovary Syndrome
For something that affects around one in ten UK women and AFAB people, Polycystic Ovary Syndrome (PCOS) often goes undiscussed. Even if you are someone tha
TikTokers Are Raising Awareness Of Vomit Phobia
"There's a name for that!" This is a frequent comment under TikTok videos in which the creator is discussing their all-consuming fear of
by Elly Parsons
Eradicating Fatphobia, Embracing Radical Body Love
Award-winning journalist Sofiya Ballin explores how Black women can radically love their bodies in a world incentivised by their ability to hate it.
by Sofiya Ballin


text:
Amend tax return
Tax Prep for International Students and Scholars
J1 Work & Travel
H2B Temporary Workers
Tax Prep for Foreign professionals
Camp Counselors
Sports Scholarships
Tax Determination Software
COVID-19 update: Our team remains available 24/7 to support you. #StayHome #StaySafe
US Tax Preparation for Nonresidents
The only online self-preparation software for nonresident federal and state tax returns
Provides an all-in-one solution covering both IRS and State forms, FICA returns and ITIN applications
Offers automatic generation of completed tax return forms
Guarantees a maximum legal tax refund for federal, state & medicare incl. tax treaty benefits
Assists you through the process via a 24/7 Live Chat, Social Media support, E-mail support, FAQ's and our virtual assistant Stacy
Amend your tax return easily online. Save time and stress
FEDERAL from $37.95
STATE from $29.95
AMENDED RETURNS from $70.95
Tax partner of
If you've already sorted out your Federal Tax Return, you can skip part of the process and easily apply for your state only.
Register for State Return.
How Sprintax Tax Preparation Works
Answer a few simple questions
Sprintax checks deductions and treaty benefits
Sprintax prepares the tax form
Print forms and send to tax authorities
What Does Sprintax Do?
Nonresident 1040NR federal and state tax return preparation
65 international tax treaty agreements and exemptions
Maximum legal tax refund guaranteed
100% US tax compliancy guaranteed
Prepare your US Taxes
Sprintax has helped 100,000 students, scholars, J1 workers, interns, trainees, professionals, au pairs and councillors prepare US tax returns
Help me with my US taxes
100% Compliance Guaranteed.
Fully Guided US TAX Preparation
Sprintax is the only online system for nonresident federal and state tax returns
24 hr live chat with VITA Qualified Chat Agents-we're always available, wherever you are!
Prepare tax returns in minutes in an affordable, guided process
Authorised Nonresident Partner for TurboTax
Facebook Twitter Linkedin Instagram Blog
www.sprintax.com © All rights reserved
Sign In to Sprintax Account
If we have a record of the email address you submitted - you will receive a link to reset your password.
Delivery might take a while.
Please also check your Spam and Trash folders.
Create Sprintax Account
Please Select Afghanistan (+93) Albania (+355) Algeria (+213) American Samoa (+684) Andorra (+376) Angola (+244) Anguilla (+264) Antarctica (+672) Antigua And Barbuda (+268) Argentina (+54) Armenia (+374) Aruba (+297) Australia (+61) Austria (+43) Azerbaijan (+994) Bahamas (+242) Bahrain (+973) Bangladesh (+880) Barbados (+246) Belarus (+375) Belgium (+32) Belize (+501) Benin (+229) Bermuda (+441) Bhutan (+975) Bolivia (+591) Bosnia and Herzegovina (+387) Botswana (+267) Bouvet Island (+47) Brazil (+55) British Indian Ocean Territory (+246) Brunei Darussalam (+673) Bulgaria (+359) Burkina Faso (+226) Burundi (+257) Cambodia (+855) Cameroon (+237) Canada (+1) Cape Verde (+238) Cayman Islands (+345) Central African Republic (+236) Chad (+235) Chile (+56) China (+86) Christmas Island (+672) Cocos (Keeling) Islands (+672) Colombia (+57) Comoros (+269) Congo (+242) Cook Islands (+682) Costa Rica (+506) Cote D'Ivoire (+225) Croatia (+385) Cuba (+53) Cyprus (+357) Czech Republic (+420) Democratic Republic of the Congo (+243) Denmark (+45) Djibouti (+253) Dominica (+767) Dominican Republic (+809) East Timor (+670) Ecuador (+593) Egypt (+20) El Salvador (+503) Equatorial Guinea (+240) Eritrea (+291) Estonia (+372) Ethiopia (+251) Falkland Islands (+500) Faroe Islands (+298) Fiji Islands (+679) Finland (+358) France (+33) French Guiana (+594) French Polynesia (+689) French Southern Territories (+33) Gabon (+241) Gambia (+220) Georgia (+995) Germany (+49) Ghana (+233) Gibraltar (+350) Greece (+30) Greenland (+299) Grenada (+473) Guadeloupe (+590) Guam (+671) Guatemala (+502) Guernsey (+1481) Guinea (+224) Guinea-Bissau (+245) Guyana (+592) Haiti (+509) Heard and Mc Donald Islands (+61) Holland (+31) Honduras (+504) Hong Kong S.A.R. (+852) Hungary (+36) Iceland (+354) India (+91) Indonesia (+62) Iran (+98) Iraq (+964) Ireland (+353) Israel (+972) Italy (+39) Jamaica (+876) Japan (+81) Jordan (+962) Kazakhstan (+7) Kenya (+254) Kiribati (+686) South Korea (+82) Kosovo (+381) Kuwait (+965) Kyrgyzstan (+7) Laos (+856) Latvia (+371) Lebanon (+961) Lesotho (+266) Liberia (+231) Libyan Arab Jamahiriya (+218) Liechtenstein (+423) Lithuania (+370) Luxembourg (+352) Macau S.A.R. (+853) Macedonia (+389) Madagascar (+261) Malawi (+265) Malaysia (+60) Maldives (+960) Mali (+223) Malta (+356) Marshall Islands (+692) Martinique (+596) Mauritania (+222) Mauritius (+230) Mayotte (+269) Mexico (+52) Micronesia (+691) Moldova (+373) Monaco (+377) Mongolia (+976) Montenegro (+385) Montserrat (+664) Morocco (+212) Mozambique (+258) Myanmar (+95) Namibia (+264) Nauru (+674) Nepal (+977) Netherlands (+31) New Zealand (+64) Nicaragua (+505) Niger (+227) Nigeria (+234) Niue (+683) Norfolk Island (+672) Northern Mariana Islands (+670) Norway (+47) Oman (+968) Pakistan (+92) Palau (+680) Palestine (+970) Panama (+507) Papua new Guinea (+675) Paraguay (+595) Peru (+51) Philippines (+63) Pitcairn Island (+872) Democratic Republic of the Congo (+48) Poland (+48) Portugal (+351) Puerto Rico (+939) Qatar (+974) Reunion (+262) Romania (+40) Russia (+7) Rwanda (+250) Saint Helena (+290) Saint Kitts And Nevis (+1869) Saint Lucia (+1758) Saint Pierre and Miquelon (+508) Saint Vincent and The Grenadines (+1784) Samoa (+685) San Marino (+378) Sao Tome and Principe (+239) Saudi Arabia (+966) Senegal (+221) Serbia (+381) Seychelles (+248) S. Georgia and the S. Sandwich Islands (+500) Sierra Leone (+232) Singapore (+65) Slovakia (+421) Slovenia (+386) Solomon Islands (+677) Somalia (+252) South Africa (+27) South Sudan (+211) Spain (+34) Sri Lanka (+94) Sudan (+249) Suriname (+597) Svalbard and Jan Mayen Islands (+79) Swaziland (+268) Sweden (+46) Switzerland (+41) Syrian Arab Republic (+963) Taiwan (+886) Tajikistan (+992) Tanzania (+255) Thailand (+66) Togo (+228) Tokelau (+690) Tonga (+676) Trinidad And Tobago (+868) Tunisia (+216) Turkey (+90) Turkmenistan (+993) Turks And Caicos Islands (+649) Tuvalu (+688) United Arab Emirates (+971) Uganda (+256) United Kingdom (+44) Ukraine (+380) Uruguay (+598) United States (+1) US Minor Outlying Islands (+1808) Uzbekistan (+998) Vanuatu (+678) Vatican City State (+39) Venezuela (+58) Vietnam (+84) Virgin Islands (British) (+284) Virgin Islands (US) (+340) Wallis and Futuna Islands (+681) West Bank (+970) Yemen (+967) Zambia (+260) Zimbabwe (+263)
Choose Password*
I agree to the Sprintax terms and conditions
I agree to information disclosure under IRC Section 7216
Your email address has been confirmed.
Login now to get started.
Something went wrong and we were unable to confirm your email address.
× This website uses cookies, to help provide you with the best experience we can. By continuing to browse this website you are agreeing to our use of cookies in according with our cookie policy.


favorite cocktails. Here are some of our most popular concoctions.
Garnish with celery stick, olive & pickled green bean.
Shake it up and serve it in a cocktail glass.
Shake Vinn Vodka, drinking vinegar, torn basil leaves and ice, add club soda and give it a quick stir.
drops of Fee's Old Fashioned Bitters, arranged interestingly.
From our friends at Boozeniks.


The iNua Collection is delighted to announce the appointment of Frits Potgieter as General Manager of the 5-star Muckross Park Hotel & Spa in Killarney.
With 20 years' experience in a variety of luxury properties across the industry, Frits Potgieter was born in Namibia and then grew up in South Africa, studying at the University of Johannesburg, graduating with a Bachelor's Degree in Commerce and an Honours Degree in Strategic Management. During his holidays from college, Frits spent summers working in his aunt's South African restaurant in Hong Kong, where he fell in love with the hospitality business.
Frits began his career as a hospitality professional in the UK at the 4-star Brands Hatch Thistle Hotel in 1999, from there moving to London, where he worked at the Radisson Edwardian Hotels group for three years, then subsequently joined Red Carnation Hotels as Front of House Manager at The Chesterfield Mayfair Hotel.
Promoted to Deputy General Manager of that hotel in 2005, Frits then moved to The Milestone Hotel & Apartments in 2007, Red Carnation 's London flagship property.
Frits joined The Doyle Collection in 2012 as Hotel Manager at The Marylebone Hotel, and later became General Manager of The Kensington Hotel before moving to Ireland in 2016 to take up the role of General Manager of the Imperial Hotel in Cork city. Frits' wife is originally from the area, and they are happily based in Cork now.
Passionate about hotels and fascinated by people, Frits loves to travel and, unsurprisingly for someone with a South African background, is a keen rugby supporter and loves good red wine.