Corrigé TD2

Création d'un histogramme

In [1]:
from pylab import *
%matplotlib inline
In [2]:
# une première version sans filtrage
def Histogram(Liste,(xmin, xmax),N=10):
    Deltax = (xmax-xmin)/float(N)
    H = [0]*N
    for x in Liste:
        ind = min(N-1,int((x-xmin)//Deltax))
        H[ind] += 1
    # abcisses du début des boîtes
    bins = [xmin + n*Deltax for n in range(N+1)]
    # abscisses pour l'histogramme avec dédoublement
    X = sorted(bins + bins[1:-1])
    # ordonnées pour l'histogramme avec normalisation
    norm = Deltax*float(sum(H))
    for i in range(len(H)): H[i] /= norm
    # dédoublement des indices pour les ordonnées
    Y = [ H[i] for i in sorted(range(len(H))*2) ]
    plot(X,Y,'b')
    return (H,bins)
In [3]:
# génération de liste aléatoires
from random import uniform
M = 100000 # nombre d'échantillons
Nbins = 100

xi_uniforme = [ uniform(-0.75,0.75) for i in range(M) ]
H,bin = Histogram(xi_uniforme,(-1.0,1.0),Nbins)
xlabel('x')
ylabel('H(x)')
title('Histogramme des valeurs de $x$')
show()
In [4]:
# une deuxième version avec filtrage
def Histogram(Liste,(xmin, xmax),N=10):
    Deltax = (xmax-xmin)/float(N)
    # on filtre les valeurs dans l'intervalle
    Liste_filtree = filter(lambda x: xmin <= x <= xmax, Liste)
    H = [0]*N
    for x in Liste_filtree:
        ind = min(N-1,int((x-xmin)//Deltax))
        H[ind] += 1
    # abcisses du début des boîtes
    bins = [xmin + n*Deltax for n in range(N+1)]
    # abscisses pour l'histogramme avec dédoublement
    X = sorted(bins + bins[1:-1])
    # ordonnées pour l'histogramme avec normalisation
    # tient compte des données rejetées
    norm = Deltax*float(sum(H)) * len(Liste)/float(len(Liste_filtree))
    for i in range(len(H)): H[i] /= norm
    # dédoublement des indices pour les ordonnées
    Y = [ H[i] for i in sorted(range(len(H))*2) ]
    plot(X,Y,'b')
    return (H,bins)
In [5]:
# génération de liste aléatoires
from random import gauss
M = 10000 # nombre d'échantillons
Nbins = 20
sigma = 0.2

xi_gauss = [ gauss(0.0,sigma) for i in range(M) ]
H,bin = Histogram(xi_gauss,(-1.0,1.0),Nbins)
print H
print bin
# expression analytique
y = [ 1./sqrt(2*pi*sigma**2)*exp(-0.5*(x/sigma)**2) for x in bin ]
plot(bin,y,'r-')
xlabel('x')
ylabel('H(x)')
title('Histogramme des valeurs de $x$')
show()
[0.0, 0.001, 0.003, 0.015, 0.037, 0.142, 0.45, 0.984, 1.498, 1.886, 1.974, 1.467, 0.908, 0.421, 0.155, 0.049, 0.009, 0.001, 0.0, 0.0]
[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.3999999999999999, -0.29999999999999993, -0.19999999999999996, -0.09999999999999998, 0.0, 0.10000000000000009, 0.20000000000000018, 0.30000000000000004, 0.40000000000000013, 0.5, 0.6000000000000001, 0.7000000000000002, 0.8, 0.9000000000000001, 1.0]
In [6]:
help(hist)
Help on function hist in module matplotlib.pyplot:

hist(x, bins=10, range=None, normed=False, weights=None, cumulative=False, bottom=None, histtype=u'bar', align=u'mid', orientation=u'vertical', rwidth=None, log=False, color=None, label=None, stacked=False, hold=None, **kwargs)
    Plot a histogram.
    
    Compute and draw the histogram of *x*. The return value is a
    tuple (*n*, *bins*, *patches*) or ([*n0*, *n1*, ...], *bins*,
    [*patches0*, *patches1*,...]) if the input contains multiple
    data.
    
    Multiple data can be provided via *x* as a list of datasets
    of potentially different length ([*x0*, *x1*, ...]), or as
    a 2-D ndarray in which each column is a dataset.  Note that
    the ndarray form is transposed relative to the list form.
    
    Masked arrays are not supported at present.
    
    Parameters
    ----------
    x : (n,) array or sequence of (n,) arrays
        Input values, this takes either a single array or a sequency of
        arrays which are not required to be of the same length
    
    bins : integer or array_like, optional
        If an integer is given, `bins + 1` bin edges are returned,
        consistently with :func:`numpy.histogram` for numpy version >=
        1.3.
    
        Unequally spaced bins are supported if `bins` is a sequence.
    
        default is 10
    
    range : tuple or None, optional
        The lower and upper range of the bins. Lower and upper outliers
        are ignored. If not provided, `range` is (x.min(), x.max()). Range
        has no effect if `bins` is a sequence.
    
        If `bins` is a sequence or `range` is specified, autoscaling
        is based on the specified bin range instead of the
        range of x.
    
        Default is ``None``
    
    normed : boolean, optional
        If `True`, the first element of the return tuple will
        be the counts normalized to form a probability density, i.e.,
        ``n/(len(x)`dbin)``, i.e., the integral of the histogram will sum
        to 1. If *stacked* is also *True*, the sum of the histograms is
        normalized to 1.
    
        Default is ``False``
    
    weights : (n, ) array_like or None, optional
        An array of weights, of the same shape as `x`.  Each value in `x`
        only contributes its associated weight towards the bin count
        (instead of 1).  If `normed` is True, the weights are normalized,
        so that the integral of the density over the range remains 1.
    
        Default is ``None``
    
    cumulative : boolean, optional
        If `True`, then a histogram is computed where each bin gives the
        counts in that bin plus all bins for smaller values. The last bin
        gives the total number of datapoints.  If `normed` is also `True`
        then the histogram is normalized such that the last bin equals 1.
        If `cumulative` evaluates to less than 0 (e.g., -1), the direction
        of accumulation is reversed.  In this case, if `normed` is also
        `True`, then the histogram is normalized such that the first bin
        equals 1.
    
        Default is ``False``
    
    bottom : array_like, scalar, or None
        Location of the bottom baseline of each bin.  If a scalar,
        the base line for each bin is shifted by the same amount.
        If an array, each bin is shifted independently and the length
        of bottom must match the number of bins.  If None, defaults to 0.
    
        Default is ``None``
    
    histtype : {'bar', 'barstacked', 'step',  'stepfilled'}, optional
        The type of histogram to draw.
    
        - 'bar' is a traditional bar-type histogram.  If multiple data
          are given the bars are aranged side by side.
    
        - 'barstacked' is a bar-type histogram where multiple
          data are stacked on top of each other.
    
        - 'step' generates a lineplot that is by default
          unfilled.
    
        - 'stepfilled' generates a lineplot that is by default
          filled.
    
        Default is 'bar'
    
    align : {'left', 'mid', 'right'}, optional
        Controls how the histogram is plotted.
    
            - 'left': bars are centered on the left bin edges.
    
            - 'mid': bars are centered between the bin edges.
    
            - 'right': bars are centered on the right bin edges.
    
        Default is 'mid'
    
    orientation : {'horizontal', 'vertical'}, optional
        If 'horizontal', `~matplotlib.pyplot.barh` will be used for
        bar-type histograms and the *bottom* kwarg will be the left edges.
    
    rwidth : scalar or None, optional
        The relative width of the bars as a fraction of the bin width.  If
        `None`, automatically compute the width.
    
        Ignored if `histtype` is 'step' or 'stepfilled'.
    
        Default is ``None``
    
    log : boolean, optional
        If `True`, the histogram axis will be set to a log scale. If `log`
        is `True` and `x` is a 1D array, empty bins will be filtered out
        and only the non-empty (`n`, `bins`, `patches`) will be returned.
    
        Default is ``False``
    
    color : color or array_like of colors or None, optional
        Color spec or sequence of color specs, one per dataset.  Default
        (`None`) uses the standard line color sequence.
    
        Default is ``None``
    
    label : string or None, optional
        String, or sequence of strings to match multiple datasets.  Bar
        charts yield multiple patches per dataset, but only the first gets
        the label, so that the legend command will work as expected.
    
        default is ``None``
    
    stacked : boolean, optional
        If `True`, multiple data are stacked on top of each other If
        `False` multiple data are aranged side by side if histtype is
        'bar' or on top of each other if histtype is 'step'
    
        Default is ``False``
    
    Returns
    -------
    n : array or list of arrays
        The values of the histogram bins. See **normed** and **weights**
        for a description of the possible semantics. If input **x** is an
        array, then this is an array of length **nbins**. If input is a
        sequence arrays ``[data1, data2,..]``, then this is a list of
        arrays with the values of the histograms for each of the arrays
        in the same order.
    
    bins : array
        The edges of the bins. Length nbins + 1 (nbins left edges and right
        edge of last bin).  Always a single array even when multiple data
        sets are passed in.
    
    patches : list or list of lists
        Silent list of individual patches used to create the histogram
        or list of such list if multiple input datasets.
    
    Other Parameters
    ----------------
    kwargs : `~matplotlib.patches.Patch` properties
    
    See also
    --------
    hist2d : 2D histograms
    
    Notes
    -----
    Until numpy release 1.5, the underlying numpy histogram function was
    incorrect with `normed`=`True` if bin sizes were unequal.  MPL
    inherited that error.  It is now corrected within MPL when using
    earlier numpy versions.
    
    Examples
    --------
    .. plot:: mpl_examples/statistics/histogram_demo_features.py
    
    
    
    Additional kwargs: hold = [True|False] overrides default hold state

In [7]:
# avec la fonction hist de pylab, attention à bien donner range=() et normed=1
n2, bin2, patches = hist(xi_gauss, Nbins, range=(-1.0,1.0), normed=1, facecolor='white')
print n2
print bin2
xlabel('x')
ylabel('H(x)')
title('Histogramme des valeurs de $x$')
y = [ 1./sqrt(2*pi*sigma**2)*exp(-0.5*(x/sigma)**2) for x in bin ]
plot(bin,y,'r-')
show()
[  0.00000000e+00   1.00000000e-03   3.00000000e-03   1.50000000e-02
   3.70000000e-02   1.42000000e-01   4.50000000e-01   9.84000000e-01
   1.49800000e+00   1.88600000e+00   1.97400000e+00   1.46700000e+00
   9.08000000e-01   4.21000000e-01   1.55000000e-01   4.90000000e-02
   9.00000000e-03   1.00000000e-03   0.00000000e+00   0.00000000e+00]
[-1.  -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1  0.   0.1  0.2  0.3  0.4
  0.5  0.6  0.7  0.8  0.9  1. ]

La pommme d'arrosage

In [8]:
# Algorithme de Verlet
def Verlet(r0,v0,tf,F,N=100):
    Fx, Fz = F
    dt = tf/float(N)
    x, z = [0.0]*N, [0.0]*N
    x[0], z[0] = r0[0], r0[1]

    x[1] = x[0] + v0[0]*dt + 0.5*Fx(x[0],z[0])*dt**2
    z[1] = z[0] + v0[1]*dt + 0.5*Fz(x[0],z[0])*dt**2
    
    for i in range(2,N):
        x[i] = 2*x[i-1]-x[i-2] + Fx(x[i-1],z[i-1])*dt**2
        z[i] = 2*z[i-1]-z[i-2] + Fz(x[i-1],z[i-1])*dt**2

    return (x,z)
In [9]:
from math import cos, sin, tan, pi

g, v0, h = 9.81, 0.2, 1.0
def Fx(x,z): return 0.0
def Fz(x,z): return -g

N, tf = 100, 0.5

for theta in [pi/5,pi/4,pi/3]:
    (x,z) = Verlet((0.0,h),(v0*sin(theta),v0*cos(theta)),tf,(Fx,Fz),N)
    plot(x, z)
    def Exact(x): return h + x/tan(theta) -0.5*g*(x/(v0*sin(theta)))**2
    plot(x, [ Exact(pos) for pos in x ],'+')

show()
In [10]:
theta = pi/4
(x,z) = Verlet((0.0,h),(v0*sin(theta),v0*cos(theta)),tf,(Fx,Fz),N)
def Exact(x): return h + x/tan(theta) -0.5*g*(x/(v0*sin(theta)))**2
diff = [ abs(Exact(x[i])-z[i])**0.5 for i in range(len(x)) ]
plot(diff)
show()
In [12]:
# une fonction qui détermine la position au sol à partir de (x,z)
def Position(x,z):
    for i in range(len(z)):
        if z[i] < 0.0:
            break
#    return x[i] # version sans interpolation assez sommaire
    return x[i] - z[i]*(x[i]-x[i-1])/(z[i]-z[i-1]) # avec interpolation linéaire

Npoints, thetamin, thetamax = 1000, pi/5, pi/3
dtheta = (thetamax-thetamin)/float(Npoints-1)
Thetas = [thetamin + i*dtheta for i in range(Npoints) ]
pos = []
for theta in Thetas:
    (x,z) = Verlet((0.0,h),(v0*sin(theta),v0*cos(theta)),tf,(Fx,Fz),N)
    pos.append(Position(x,z))
In [13]:
n, bin, patches = hist(pos, bins=100, range=(0.05,0.085), normed=1, facecolor='white')
xlabel('x')
ylabel('H(x)')
title('Histogramme des valeurs de $x$')
show()
In [ ]: