<jupyter_start><jupyter_text>Plotting ExamplesYourNameHereDateHere Defining Mathematical FunctionsThe following code shows features of numpy for rapidly implementing discrete approximations of mathematical functions.<jupyter_code>def gaussian(x):
    """gaussian(x)
    
    Normalized Gaussian function, also known as a normal distribution, or a bell curve.
    """
    return (1/np.sqrt(2*np.pi))*np.exp(-x**2/2)

def lorentzian(x):
    """lorentzian(x)
    
    Normalized Lorentzian function, also known as a Cauchy distribution, or a resonance linewidth.
    """
    return (1/np.pi)/(1 + x**2)

def sigmoid(x):
    """sigmoid(x)
    
    Sigmoid function, used to simulate neuron activation in neural networks.
    """
    return 1/(1 + np.exp(-x))

def sinc(x):
    """sinc(x)
    
    Sinc function, appears in single-slit diffraction, and is Fourier transform of a tophat function.
    """
    # Avoids division by zero by defaulting to the value 1
    return np.divide(np.sin(x), x, out=np.ones_like(x), where=(x!=0))

def raisedcosine(x):
    """raisedcosine(x)
    
    Raised cosine distribution, has compact support but similar to bell curve.
    """
    # Efficient conditional evaluation across array
    return np.where(np.abs(x) < np.pi, (1 + np.cos(x))/(2*np.pi), 0)<jupyter_output><empty_output><jupyter_text>Note that the python function definitions are type agnostic: the parameter `x` could be any type, and the code will run provided that the expressions inside the function are compatible with that type. This type-agnosticism of python is often called "duck typing", since if it walks like a duck, and quacks like a duck, python will think it is a duck. For the cases above, functions that rely only on array broadcasting and vectorization will have the operations will work correctly when `x` is a float, or when `x` in an array as floats. This is one of the main reasons that broadcasting and vectorization are given no special syntax in numpy.<jupyter_code>[f(1.24) for f in [gaussian, lorentzian, sigmoid]]  # evaluation on a float
[f(np.linspace(-1,1,3)) for f in [gaussian, lorentzian, sigmoid]] # evaluation on an array<jupyter_output><empty_output><jupyter_text>The remaining two functions use features specific to numpy arrays, so will autoconvert a float input to an array output.<jupyter_code>[f(1.24) for f in [sinc, raisedcosine]] # numpy specialized evaluation on a float<jupyter_output><empty_output><jupyter_text>Make sure you understand the concepts of broadcasting and vectorization for arrays. Explain those concepts in your own words below, and use code examples to illustrate your descriptions.<jupyter_code># Broadcasting explanation and example**
# Broadcasting is the process by which numpy computes operations with different sized arrays.
x = np.array([1,2,3])
y = np.ones(shape=[3,3])
y = x+y
print(y)

# Vectorization explanation and example**
# Vectorization is the process by which functions can be evaluated directly upon arrays rather than looping through
np.vectorize(gaussian)
z = gaussian(y)
print(z)<jupyter_output>[[2. 3. 4.]
 [2. 3. 4.]
 [2. 3. 4.]]
[[0.05399097 0.00443185 0.00013383]
 [0.05399097 0.00443185 0.00013383]
 [0.05399097 0.00443185 0.00013383]]<jupyter_text>Plotting Functions  Lazy Plotting with DataframesFor quick plots, it is convenient to neatly package all function range data together with their common domain data. Pandas dataframes are ideally suited for such data organization. Dataframes also provide a simple plot interface to quickly generate plots.<jupyter_code>def make_plots(a=-10,b=10,n=1000):
    # Generate n domain points equally spaced to cover the interval [a,b]
    x = np.linspace(a,b,n)
    
    # Collect function range points corresponding to domain points
    fs = pd.DataFrame({"x":x
                     ,"gaussian":gaussian(x)
                     ,"lorentzian":lorentzian(x)
                     ,"sigmoid":sigmoid(x)
                     ,"sinc":sinc(x)
                     ,"raisedcosine":raisedcosine(x)
                     })
    
    # Plot all range points with respect to same domain points x
    fs.plot(x='x')
make_plots()
make_plots(a=-100,b=100)
make_plots(n=10)<jupyter_output><empty_output><jupyter_text>Plotting with Matplotlib Use `matplotlib.pyplot` to generate a plot comparing the Gaussian function, Lorentzian function, and raised cosine function in more detail. Plot the Gaussian in blue, the Lorentzian in red, and the raised cosine in green. Make the Gaussian solid, the Lorentzian dashed, and the raised cosine dotted. Create a legend that labels each curve. Resize the tickmarks to be double the default size. Label the x axis as "x" and double the default font size. Create a plot title of "Distribution comparison". Annotate the plot with a point on each curve at $x=\pi$, with an arrow pointing to one of the points with a label of $\pi$.After you handle the 1d case, create separate 2d plots of each function by interpreting the "x" value of each function as the radius away from the origin in a 2d plane (so that each 2d function is symmetric under rotations around the origin in the plane).The following resources may be helpful:  - https://www.labri.fr/perso/nrougier/teaching/matplotlib/  - http://matplotlib.org/gallery.html<jupyter_code>def make_plots(a=-10,b=10,n=1000):
    # Generate n domain points equally spaced to cover the interval [a,b]
    x = np.linspace(a,b,n)
    
    # Collect function range points corresponding to domain points
    fs = pd.DataFrame({"x":x
                     ,"gaussian":gaussian(x)
                     ,"lorentzian":lorentzian(x)
                     ,"sigmoid":sigmoid(x)
                     ,"sinc":sinc(x)
                     ,"raisedcosine":raisedcosine(x)
                     })
    
    # Plot all range points with respect to same domain points x
    plt.plot('x','gaussian',color='blue',data=fs,label='gaussian')
    plt.plot('x','lorentzian',color='red',linestyle='dashed',data=fs,label='lorentzian')
    plt.plot('x','raisedcosine',color='green',linestyle='dotted',data=fs,label='raisedcosine')
    plt.legend(loc='upper left')
    plt.tick_params(labelsize='large')
    plt.Axes.
    plt.show()

make_plots()<jupyter_output><empty_output><jupyter_text>Plotting with Seaborn Seaborn is a statistical plotting extension to Matplotlib that uses nicer visual defaults for common data-processing tasks. Consider the following code fragment that generates a set of random points sampled from a normalized Gaussian distribution and generates a histogram of the data. The blue curve is the estimated continuous distribution function that is consistent with the sampled data. The red curve is the Gaussian function defined above. Show by increasing the parameter `n` that collecting more samples improves the estimate to converge to the actual Gaussian being used to generate the data. How many samples are required before the distribution convincingly converges?The following documentation may be helpful:  - https://seaborn.pydata.org/tutorial/distributions.html<jupyter_code>def gaussian_sample(n):
    # Generate n random normally-distributed floats
    data = np.random.randn(n)
    # Create domain of points for plotting
    x = np.linspace(-4,4,100)
    # Plot
    plt.figure(1)
    plt.title("Gaussian sampling")
    plt.xlabel("x")
    plt.plot(x,gaussian(x),label="gaussian",color="red")
    # Use seaborn to generate histogram and estimate distribution
    sb.distplot(data,label="data",color="blue",kde_kws={"label":"estimate"})
    # Label curves
    plt.legend()
gaussian_sample(10)<jupyter_output>/ext/anaconda5/lib/python3.6/site-packages/scipy/stats/stats.py:1713: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
  return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval<jupyter_text>Repeat the above analysis for the Lorentzian distribution (see `numpy.random.standard_cauchy` for sampling Lorentzian-distributed random numbers). How many samples do you need to show convergence to the distribution? Speculate why there is a difference between the Gaussian and Lorentzian cases. (Hint: This problem is tricky, so think about it carefully and describe ways to get around the issues you find.)<jupyter_code># Code goes here<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup