"""Code from NumFys notebook at https://nbviewer.jupyter.org/urls/www.numfys.net/media/notebooks/introduction_to_numpy.ipynb
Illustrates use of NumPy.
"""

import numpy as np  # 'as np' tells python to name NumPy np

# We will use this for demonstration. Plotting is not part of this notebook,
# if you wish to learn more about plotting see our notebook [here].
import matplotlib.pyplot as plt

my_list = [0, 1, 2, 3, 4]  # Normal Python list
my_array = np.array([0, 1, 2, 3, 4])  # NumPy array

# Let us see what they look like:
print(my_list)
print(my_array)

# Remember how lists behave when we whish to do mathematical operations on them:
print("my_list*2:\t", my_list*2)

print("my_array*2:\t", my_array*2)

# remember that x**y is python syntax for x^y, that is x to the power of y
print("my_array**2:\t\t", my_array**2)
print("my_array**2 - 3/2:\t", my_array**2 - 3/2)

# We can even do this with functions!
def my_function(x):
    y = x + 10*x
    return y**2

print("my_function(my_array):\t", my_function(my_array))

def my_function2(x):
    y = [] # Creating an empty python list
    for i in range(len(x)):
        y_element = x[i] + 10*x[i]
        y.append(y_element**2)
    return y

print("my_function2(my_list):\t", my_function2(my_list))

# Some mathematical functions
x = np.array([-1, -0.5, 0, 0.5, 1])
print("sin(x) =\t", np.sin(x))
print("arccos(x) =\t", np.arccos(x))
print("log(x+10) = \t", np.log(x+10))
print("log10(x+10) =\t", np.log10(x+10))

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.sin(x)  # find sin(x) for each of the elements in x

print("x:\t", x)
print("y:\t", y)

plt.plot(x, y)  # Plotting is not part of this notebook, we use it here only for demonstration purposes
plt.show()

# Get an array of 50 values between 0 and 2
x_lin = np.linspace(0, 2, 50)
print(x_lin)

# Get an array of values between 0 and 2 with spacing 0.1
x_range = np.arange(0, 2, 0.1)
print(x_range)

# Generate two lists, one with zeros and one with ones, both with length 20
zeros = np.zeros(20)
ones = np.ones(20)

# Let us see how they look
print(zeros)
print(ones)

my_list = [1, 2, 3, 4]  # Normal Python list

# We can access different parts of the list by slicing and indexing:
print("my_list[0]:\t", my_list[0])     # First element
print("my_list[:2]:\t", my_list[:2])   # The two first elements
print("my_list[-2:]:\t", my_list[-2:]) # The last two elements
