Este exámen se enfoca en dos temas, gráficos y ajustes, los puntos a desarrollar son los siguientes. En una carpeta con su nombre encontrará:
3 gráficos en orden de dificultad, su tarea es escribir el código requerido para generar dicho gráfico, incluyendo títulos en los ejes, leyenda y grilla, la función a la que obedecen los datos con los que se genera el gráfico se puede encontrar en la leyenda.
3 conjuntos de datos también en orden de dificultad (data00.txt
el más fácil) debe cargar estos datos usando la función x, y = np.loadtxt('data##.txt', unpack=True)
para despues ajustarlos usando una de las técnicas vistas en clase. Si abre el archivo .txt
encontrará en el encabezado una pista sobre la función de la que provienen los datos. Para este punto debe:
2 compuestos para los cuales deberá proveer un análisis TGA, incluyendo, identificación de componentes, cuantificación de los componentes en masa, porcentaje de error con respecto a la temperatura ideal y gráficos asociados.
Cada uno de los 3 puntos tendrá el mismo valor sobre la nota final.
A continuación se presenta el código usado para generar los parciales (sin embargo, se oculta la semilla utilizada).
In [1]:
%matplotlib inline
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
import numpy as np
import os
import json
In [2]:
np.random.seed(12)
GUYS = [
'Federico',
'Sebastian Alejandro',
'Fernando',
'Ivan Dario',
'Sebastian',
'Christian David',
'Sergio Alejandro',
'Juan Camilo',
'Angel Santiago',
'Anngie Carolina',
'Cristian Elias',
'Juan Sebastian',
'Daniela',
'Maria Victoria',
'Laura Victoria',
'Maria Camila',
'Oscar (Bolaños)',
]
In [3]:
PARTIAL_DIR = 'exam2'
SOLUTIONS_DIR = 'exam2_solutions'
In [4]:
def create_missing_dirs(*dirs):
for folder in dirs:
if not os.path.exists(folder):
os.makedirs(folder)
create_missing_dirs(PARTIAL_DIR, SOLUTIONS_DIR)
In [5]:
def random_params(number, min_val=1, max_val=5):
return tuple(
np.round(
np.random.uniform(min_val, max_val, size=number),
decimals=1
)
)
In [6]:
def random_style():
style = np.random.choice(['-', '-.', '--'], p=[.50, .30, .20])
color = np.random.choice(['blue', 'green', 'red'])
return style, color
In [7]:
def plot(x, y, label, plot_command=None):
if plot_command is None:
plot_command=plt.plot
style, color = random_style()
plot_command(x, y, style, label=label, color=color)
plt.xlabel(r'$x$')
plt.ylabel(r'$y$')
plt.grid()
plt.legend(loc='best')
In [8]:
def cos_plot():
a, omega, phi = random_params(3)
x = np.linspace(-10, 10, 200)
y = a * np.cos(omega * x + phi)
plot(x, y,
r'$y = {:.1f} \, \cos({:.1f} x + {:.1f})$'.format(a, omega, phi))
def line_plot():
a, b = random_params(2)
x = np.linspace(-10, 10)
y = a * x + b
plot(x, y, label=r'$y = {:.1f} x + {:.1f}$'.format(a, b))
def parable_plot():
a, b, c = random_params(3)
x = np.linspace(-10, 10)
y = a * x ** 2 + b * x + c
plot(x, y,
label=r'$y = {:.1f} x ^ 2 + {:.1f} x + {:.1f}$'.format(a, b, c))
def sqrt_plot():
a, = random_params(1)
x = np.linspace(0, 10)
y = a * np.sqrt(x)
plot(x, y, label=r'$y = {:.1f} \sqrt{{x}}$'.format(a))
def exponential_plot():
a, n, = random_params(2, min_val=0.5, max_val=2)
x = np.linspace(0, 10)
y = a * x ** n
plot(x, y, label=r'$y = {:.1f} x ^ {{{:.1f}}}$'.format(a, n))
def exponential_loglog_plot():
a, n, = random_params(2)
x = np.linspace(0, 10)
y = a * x ** n
plot(x, y,
label=r'$y = {:.1f} x ^ {{{:.1f}}}$'.format(a, n),
plot_command=plt.loglog)
EASY_PLOTS = [
cos_plot,
line_plot,
parable_plot,
sqrt_plot,
exponential_plot,
exponential_loglog_plot,
]
In [9]:
def hard_plot():
components = np.random.choice(EASY_PLOTS, 2, replace=False)
for i, p in enumerate(components):
plt.subplot(1, 2, i + 1)
p()
plt.tight_layout()
HARD_PLOTS = [
hard_plot
for _ in range(10)
]
In [10]:
def harder_plot():
p1, p2, p3 = np.random.choice(EASY_PLOTS, 3, replace=False)
plt.subplot(2, 1, 1)
p1()
plt.subplot(2, 2, 3)
p2()
plt.subplot(2, 2, 4)
p3()
plt.tight_layout()
HARDER_PLOTS = [
harder_plot
for _ in range(10)
]
In [11]:
def get_x():
return np.linspace(0, 20, 1000)
In [12]:
def line_data():
a, b = random_params(2)
x = get_x()
y = a * x + b
return x, y, '$y = a x + b$', ('line', a, b)
def parable_data():
a, b, c = random_params(3)
x = get_x()
y = a * x ** 2 + b * x + c
return x, y, r'$y = a x^2 + bx + c$', ('parable', a, b, c)
def sqrt_data():
a, = random_params(1)
x = get_x()
y = a * np.sqrt(x)
return x, y, r'$y = a \sqrt{x}$', ('sqrt', a)
def exponential_data():
a, n, = random_params(2, min_val=0.5, max_val=2)
x = get_x()
y = a * x ** n
return x, y, r'$y = a x ^ n$', ('exponential', a, n)
def exponential_data():
a, n, = random_params(2, min_val=0.5, max_val=2)
x = get_x()
y = a * x ** n
return x, y, r'$y = a x ^ n$', ('exponential', a, n)
def logarithmic_data():
a, b, = random_params(2, min_val=0.5, max_val=2)
x = get_x()
y = a * np.log(x + b)
return x, y, r'$y = a \log(x + b)$', ('logarithm', a, b)
SUPER_EASY_DATA = [
line_data,
# parable_data,
sqrt_data,
# exponential_data,
logarithmic_data,
]
In [13]:
from collections import namedtuple
Peak = namedtuple('Peak', ['pos', 'amp', 'width'])
def gausian(x, pos, amp, width):
return amp * np.exp(- (x - pos) ** 2 / (2 * width ** 2))
def multi_peak(x, *peaks):
return np.sum(gausian(x, *peak) for peak in peaks)
def multi_peak_data():
n_gausian = np.random.choice([1, 2, 3, 4])
centers = random_params(n_gausian, min_val=2, max_val=18)
amplitudes = random_params(n_gausian, min_val=5, max_val=20)
widths = random_params(n_gausian, min_val=0.1, max_val=0.8)
peaks = [
Peak(c, a, w)
for c, a, w in zip(centers, amplitudes, widths)
]
x = get_x()
y = multi_peak(x, *peaks)
return x, y, '{} gausians'.format(n_gausian), ('multi peak', *[p._asdict() for p in peaks])
In [14]:
def easy_data():
d1, d2 = np.random.choice(SUPER_EASY_DATA, 2, replace=False)
x1, y1, label1, params1 = d1()
x2, y2, label2, params2 = d2()
return (
x1,
y1 + y2,
'\n'.join([label1, label2]),
(params1, params2)
)
EASY_DATA = [
easy_data
for _ in range(20)
]
In [15]:
def hard_data():
d1 = np.random.choice(SUPER_EASY_DATA)
x1, y1, label1, params1 = d1()
x2, y2, label2, params2 = multi_peak_data()
return (
x1,
y1 + y2,
'Gotta figure this one out', # '\n'.join([label1, label2]),
(params1, params2)
)
HARD_DATA = [
hard_data
for _ in range(20)
]
In [16]:
import random
import numpy
import os
Substance = namedtuple('Substance', ['name', 'bp'])
WATER = Substance('Agua', 273.15 + 100)
SUBSTANCES = [
Substance('Metanol', 273.15 + 65),
Substance('Ciclopentanol', 273.15 + 140),
Substance('Ciclohexanol', 273.15 + 161),
Substance('Alcohol cinamílico', 273.15 + 257),
Substance('Glicerol', 273.15 + 290),
]
ROOM_TEMP = 273.15 + 20
def transition(temp, center, mass, width=5):
return mass * (numpy.tanh(- (temp - center) / width) + 1) / 2
def artificial_tga(temp, components):
tga = numpy.zeros_like(temp)
for subs, mass in components:
tga += transition(temp, subs.bp, mass)
return tga
def get_rand_solution(num_components, include_water=True):
components = list(zip(
random.sample(SUBSTANCES, num_components),
numpy.round(
numpy.random.uniform(0, 5, size=num_components),
2
),
))
if include_water:
components.append((
WATER,
numpy.round(numpy.random.uniform(0, 2), 2)
))
return list(components)
def generate_tga_data(path, components, points=100000, noise=0.01):
solution = get_rand_solution(components)
temp = numpy.linspace(ROOM_TEMP, 600, points)
tga = artificial_tga(temp, solution)
tga_exp = tga + numpy.random.normal(0, noise, size=points)
numpy.savetxt(
path + '.txt.gz',
numpy.array([temp, tga_exp]).T,
header='T[K] m[g]'
)
return [{'component': c._asdict(), 'mass': w} for c, w in solution]
In [17]:
for guy in GUYS:
guy_dir = os.path.join(PARTIAL_DIR, guy)
create_missing_dirs(guy_dir)
all_plots = (
[np.random.choice(EASY_PLOTS)] +
[np.random.choice(HARD_PLOTS)] +
[np.random.choice(HARDER_PLOTS)]
)
pp = PdfPages(os.path.join(guy_dir, 'gráficos.pdf'))
for p in all_plots:
plt.figure()
p()
pp.savefig()
plt.close()
pp.close()
solutions = []
all_data = (
[np.random.choice(EASY_DATA)] +
[np.random.choice(HARD_DATA)] +
[np.random.choice(HARD_DATA)]
)
for i, d in enumerate(all_data):
x, y, label, conditions = d()
np.savetxt(
os.path.join(guy_dir, 'data{:02}.txt'.format(i)),
np.array([x, y]).T,
header=label,
)
solutions.append(conditions)
solutions.extend([
generate_tga_data(os.path.join(guy_dir, 'TGA{:2}'.format(0)), 2),
generate_tga_data(os.path.join(guy_dir, 'TGA{:2}'.format(1)), 4)
])
guy_solutions = os.path.join(SOLUTIONS_DIR, '{}.json'.format(guy))
with open(guy_solutions, 'w') as sol:
json.dump(solutions, sol, indent=4)
print('done with', guy)
In [ ]: