diff --git a/Notas/08_Clases_y_Objetos/05_Teledeteccion.md b/Notas/08_Clases_y_Objetos/05_Teledeteccion.md index 88fbd04..1d393d8 100644 --- a/Notas/08_Clases_y_Objetos/05_Teledeteccion.md +++ b/Notas/08_Clases_y_Objetos/05_Teledeteccion.md @@ -7,7 +7,7 @@ En este ejercicio vamos a trabajar con una imagen satelital obtenida por sensore ### Ejercicio 8.14: Optativo de teledetección **Autora: [Mariela Rajngewerc](https://github.com/marielaraj/)** -La imagen original fue bajada de la página del [earthexplorer](https://earthexplorer.usgs.gov/). En esa página se pueden bajar imágenes con distinto nivel de pre-procesamiento. Para este ejercicio bajamos una imagen de nivel de procesamiento 2, esto quiere decir que los valores de los pixeles representan la reflectancia en superficie en distintas longitudes de onda. [Acá](https://www.usgs.gov/media/files/landsat-8-collection-1-land-surface-reflectance-code-product-guide) pueden encontrar el manual de estas imagenes donde les detallan la descripción tanto de los nombres de lor archivos como de los preprocesamiento que tienen realizados. +La imagen original fue bajada de la página del [earthexplorer](https://earthexplorer.usgs.gov/). En esa página se pueden bajar imágenes con distinto nivel de pre-procesamiento. Para este ejercicio bajamos una imagen de nivel de procesamiento 2, esto quiere decir que los valores de los pixeles representan la reflectancia en superficie en distintas longitudes de onda. [Acá](https://www.usgs.gov/media/files/landsat-8-collection-1-land-surface-reflectance-code-product-guide) pueden encontrar el manual de estas imagenes donde les detallan la descripción tanto de los nombres de lor archivos como de los preprocesamiento que tienen realizados. Para este ejercicio hemos realizado un clip de cada una de las bandas originales de la imagen y ya multiplicamos a cada una de las bandas por el factor de escala indicado en el manual (0,0001). @@ -32,11 +32,11 @@ En la carpeta [clip](https://drive.google.com/file/d/1uoigo5s2xgWfbBQdUcJfOdhfYM ### Ejercicio 8.15: Ver una banda a) Usá [numpy](https://numpy.org/doc/stable/reference/generated/numpy.load.html) para levantar cada una de las bandas y `plt.imshow(banda)` para verla. -¿Se ve correctamente? Podés ajustar el rango de visualización de colores usando los parámetros `vmin` y `vmax`. +¿Se ve correctamente? Podés ajustar el rango de visualización de colores usando los parámetros `vmin` y `vmax`. -_Sugerencia_: Con `plt.hist(banda.flatten(),bins=100)` vas a ver un histograma de los valores en la matriz `banda`. Podés usarlo para guiarte en la búsqueda del rango que tiene sentido usar como vmin y vmax. +_Sugerencia_: Con `plt.hist(banda.flatten(),bins = 100)` vas a ver un histograma de los valores en la matriz `banda`. Podés usarlo para guiarte en la búsqueda del rango que tiene sentido usar como vmin y vmax. -b) Probá usando percentiles para fijar el rango. Algo como +b) Probá usando percentiles para fijar el rango. Algo como ```python vmin = np.percentile(data.flatten(), q) @@ -84,9 +84,9 @@ Creá un `np.array` que le asigne a cada píxel el número dado por el *identifi c) Generá un gráfico con `matplotlib` mostrando las clases obtenidas. -d) Crear un colorMap para lograr asignarle a cada clase el color sugerido en la tabla. Para esto podés usar la función ListedColormap incluída en `matplotlib.colors` y crear un colorMap (cmap). +d) Crear un colorMap para lograr asignarle a cada clase el color sugerido en la tabla. Para esto podés usar la función ListedColormap incluída en `matplotlib.colors` y crear un colorMap (cmap). -e) Ponele una leyenda que indique el nombre de cada clase con el color asignado, para eso te sugerimos usar la función `mpatches` que se encuentra en `matplotlib.patches`. Para que puedas orientarte, te mostramos a continuación un ejemplo de resultado esperado: +e) Ponele una leyenda que indique el nombre de cada clase con el color asignado, para eso te sugerimos usar la función `Patch` que se encuentra en `matplotlib.patches`. Para que puedas orientarte, te mostramos a continuación un ejemplo de resultado esperado: ![](./img.png) @@ -96,14 +96,14 @@ Si llegaste hasta acá, no te olvides de guardar tu trabajo en el archivo `NDVI. En el ejercicio anterior definimos a mano los umbrales que distinguen las clases. Es posible hacer esto de forma automática. Para eso se usan técnicas de clustering. El siguiente código muestra un ejemplo con un clasificador muy sencillo: `kmeans`. Este clasificador está ya implementado en la biblioteca [sklearn](https://scikit-learn.org/stable/) que es una biblioteca dedicada al aprendizaje automático en python (probablemente la más usada para esto). ```python -# filtro datos ruidosos o que puedan traer problemas. +# filtro datos ruidosos o que puedan traer problemas. # el NDVI debe estar entre -1 y 1. -ndvi[ndvi>1]=1 -ndvi[ndvi<-1]=-1 +ndvi[ndvi > 1] = 1 +ndvi[ndvi < -1] = -1 #importo el clasificador y defino una instancia para clasificar con dos etiquetas from sklearn.cluster import KMeans -kmeans = KMeans(n_clusters=2) +kmeans = KMeans(n_clusters = 2) #le saco la estructura bidimensional a la matriz NDVI y la llamo datos datos = ndvi.reshape(-1,1) #datos es un vector con un dato de NDVI por pixel. @@ -111,13 +111,13 @@ datos = ndvi.reshape(-1,1) #datos es un vector con un dato de NDVI por pixel. #entreno o ajusto el el clasificador con los datos (demora!) kmeans.fit(datos) #ajusta el modelo #usa el modelo ajustado para poner etiquetas -etiquetas = kmeans.predict(ndvi.reshape(-1,1)) +etiquetas = kmeans.predict(ndvi.reshape(-1,1)) #visualizo los resultados recuperando la estructura bidimensional de la matriz plt.imshow(etiquetas.reshape(ndvi.shape)) ``` -Probá ajustando el número de clusters (`n_clusters=5`, por ejemplo) y corriendo nuevamente el modelo. Ponele colores diferentes a las diferentes clases obtenidas. +Probá ajustando el número de clusters (`n_clusters = 5`, por ejemplo) y corriendo nuevamente el modelo. Ponele colores diferentes a las diferentes clases obtenidas. Si tarda mucho podés trabajar con un pedazo de la imágen. Por ejemplo si hacés `ndvi_clip = ndvi[1000:2000,2000:3000]` te quedás con un cuadradito que es un octavo de la imagen original y podés usarlo para probar cosas rápido. Si te convencen los resultados podés correr tu algoritmo sobre la imágen completa. @@ -138,7 +138,7 @@ plt.imshow(clases_ndvi, cmap=cmap, norm=norm) ``` -Y este para las leyendas: +Y éste para las leyendas: ```python import matplotlib.patches as mpatches # Genero leyenda y grafico con leyenda @@ -147,8 +147,8 @@ texts = ['Sin vegetacion', 'Area desnuda', 'Vegetacion baja', patches = [mpatches.Patch(color=cmap(i), label="{:s}".format(texts[i]) ) for i in range(len(texts))] plt.legend(handles=patches, bbox_to_anchor=(0.2,1.3), loc='center', ncol=1 ) plt.imshow(clases_ndvi, cmap=cmap, norm=norm) -plt.show()``` - +plt.show() +``` [Contenidos](../Contenidos.md) \| [Anterior (4 Objetos, pilas y colas)](04_Pilas_Colas.md) \| [Próximo (6 Cierre de la octava clase)](06_Cierre.md) diff --git a/Notas/09_Generadores_e_Iteradores/00_Resumen.md b/Notas/09_Generadores_e_Iteradores/00_Resumen.md index bbeb41d..29eb594 100644 --- a/Notas/09_Generadores_e_Iteradores/00_Resumen.md +++ b/Notas/09_Generadores_e_Iteradores/00_Resumen.md @@ -3,9 +3,9 @@ # 9. Generadores e iteradores Programar es básicamente escribir condicionales, ciclos y asignaciones de variables. Aunque no de cualquier forma. -Los ciclos, ya sean ciclos `while` o iteraciones `for` son una de las estructuras más ubicuas en cualquier lenguaje. Los programas hacen muchas iteraciones para procesar listas, leer archivos, buscar en bases de datos y demás. +Los ciclos, ya sean ciclos `while` o iteraciones `for` son una de las estructuras más ubicuas en cualquier lenguaje. Los programas hacen muchas iteraciones para procesar listas, leer archivos, buscar en bases de datos y demás. -Una de las características más poderosas de Python es la capacidad de redefinir la iteración mediante las llamadas "funciones generadoras". En esta sección veremos de que se trata ésto. Hacia el final vas a escribir programas que procesan datos en tiempo real, a medida que son generados. +Una de las características más poderosas de Python es la capacidad de redefinir la iteración mediante las llamadas "funciones generadoras". En esta sección veremos de qué se trata esto. Hacia el final vas a escribir programas que procesan datos en tiempo real, a medida que son generados. Terminamos la clase con un ejercicio optativo que combina dos temas importantes: objetos y simulaciones. El ejercicio optativo propone simular en el espacio y tiempo la dinámica predador-presa utilizando para esto programación orientada a objetos. diff --git a/Notas/09_Generadores_e_Iteradores/01_protocolo_Iteracion.md b/Notas/09_Generadores_e_Iteradores/01_protocolo_Iteracion.md index 26fefc8..9eb4538 100644 --- a/Notas/09_Generadores_e_Iteradores/01_protocolo_Iteracion.md +++ b/Notas/09_Generadores_e_Iteradores/01_protocolo_Iteracion.md @@ -10,15 +10,15 @@ Podemos iterar sobre una gran diversidad de objetos. ```python a = 'hola a todes' -for c in a: # Iterar las letras en a +for c in a: # Iterar sobre las letras en a ... -b = { 'nombre': 'Elsa', 'password':'foo'} -for k in b: # Iterar para cada clave de diccionario +b = {'nombre': 'Elsa', 'password':'foo'} +for k in b: # Iterar sobre las claves de diccionario ... -c = [1,2,3,4] -for i in c: # Iterar sobre los items en una lista ó tupla +c = [1, 2, 3, 4] +for i in c: # Iterar sobre los items en una lista o tupla ... f = open('foo.txt') @@ -26,7 +26,7 @@ for x in f: # Iterar sobre las líneas de un archivo ASCII ... ``` -Podemos iterar sobre todos estos objetos porque cumplen con un *protocolo* que permite, justamente, iterar. Veamos algo sobre este protocolo: +Podemos iterar sobre todos estos objetos porque cumplen con un *protocolo* que permite, justamente, iterar. Veamos algo sobre este protocolo: ### El protocolo de iteración @@ -95,10 +95,10 @@ for c in camion: Construí la siguiente lista: ```python -a = [1,9,4,25,16] +a = [1, 9, 4, 25, 16] ``` -Y ahora iterá sobre esa lista *a mano*: Llamá al método `__iter__()` para obtener un objeto iterador y llama al método `__next__()` para obtener sucesivamente cada uno de los elementos. +Y ahora iterá sobre esa lista *a mano*: Llamá al método `__iter__()` para obtener un objeto iterador y llama al método `__next__()` para obtener sucesivamente cada uno de los elementos. ```python >>> i = a.__iter__() @@ -127,7 +127,7 @@ La función nativa de Python `next()` es un "atajo" al método `__next__()` de u >>> f = open('Data/camion.csv') >>> f.__iter__() # Notar que esto apunta al método... # ...que accede al archivo mismo. -<_io.TextIOWrapper name='Data/portfolio.csv' mode='r' encoding='UTF-8'> +<_io.TextIOWrapper name='Data/camion.csv' mode='r' encoding='UTF-8'> >>> next(f) 'nombre,cajones,precio\n' >>> next(f) @@ -174,7 +174,7 @@ from camion import Camion def leer_camion(filename): ''' - Lee un archivo con el contenido de un camión + Lee un archivo con el contenido de un camión y lo devuelve como un objeto Camion. ''' with open(filename) as file: @@ -182,7 +182,7 @@ def leer_camion(filename): select=['nombre','cajones','precio'], types=[str,int,float]) - camion = [ Lote(d['nombre'], d['cajones'], d['precio']) for d in camiondicts ] + camion = [Lote(d['nombre'], d['cajones'], d['precio']) for d in camiondicts] return Camion(camion) ... ``` @@ -245,7 +245,7 @@ Testealo, testealo, y testealo para asegurarte que funciona: ``` ### Ejercicio 9.3: Un iterador adecuado -Cuando hagas clases que sean recipientes ó contenedores de estructuras de datos vas a necesitar que hagan algo más que simplemente iterar. Probá modificar la clase `Camion` de modo que tenga algunos de los "métodos mágicos" que mencionamos en la [Sección 8.3](../08_Clases_y_Objetos/03_Métodos_Especiales.md#métodos-especiales-para-convertir-a-strings). Aquí hay algunos: +Cuando hagas clases que sean recipientes o contenedores de estructuras de datos vas a necesitar que hagan algo más que simplemente iterar. Probá modificar la clase `Camion` de modo que tenga algunos de los "métodos mágicos" que mencionamos en la [Sección 8.3](../08_Clases_y_Objetos/03_Métodos_Especiales.md#métodos-especiales-para-convertir-a-strings). Aquí hay algunos: ```python class Camion: @@ -287,7 +287,9 @@ Lote('Lima', 100, 32.2) >>> camion[1] Lote('Naranja', 50, 91.1) >>> camion[0:3] -[Lote('Lima', 100, 32.2), Lote('Naranja', 50, 91.1), Lote('Caqui', 150, 83.44)] +[Lote('Lima', 100, 32.2), + Lote('Naranja', 50, 91.1), + Lote('Caqui', 150, 103.44)] >>> 'Naranja' in camion True >>> 'Manzana' in camion @@ -297,8 +299,8 @@ False Guardá tu versión de `camion.py` con estos cambios para entregar y para la revisión de pares. -**Un comentario importante sobre todo esto:** -Se considera *de buen estilo Python* al código que comparte ciertas normas de interacción con el resto del mundo Python. Este concepto aplicado a objetos contenedores significa que estos cumplen con las buenas costumbres de ser iterables, indexables y que admiten otras operaciones que naturalmente se esperan *a priori* que vayan a cumplir, justamente por el simple hecho de ser objetos contenedores. +**Un comentario importante sobre todo esto:** +Se considera *de buen estilo Python* al código que comparte ciertas normas de interacción con el resto del mundo Python. Este concepto aplicado a objetos contenedores significa que éstos cumplen con las buenas costumbres de ser iterables, indexables y que admiten otras operaciones que naturalmente se espera *a priori* que vayan a cumplir, justamente por el simple hecho de ser objetos contenedores. [Contenidos](../Contenidos.md) \| [Próximo (2 Iteración a medida)](02_iteracion_a_medida.md) diff --git a/Notas/09_Generadores_e_Iteradores/02_iteracion_a_medida.md b/Notas/09_Generadores_e_Iteradores/02_iteracion_a_medida.md index fdd573c..4b6da11 100644 --- a/Notas/09_Generadores_e_Iteradores/02_iteracion_a_medida.md +++ b/Notas/09_Generadores_e_Iteradores/02_iteracion_a_medida.md @@ -4,7 +4,7 @@ En esta sección introducimos el concepto de función generadora. Estas funciones te permiten obtener el iterador que necesites. -### Un problema de iteración +### Un problema de iteración Suponé que querés crear una secuencia particular de iteración: una cuenta regresiva, por decir algo. @@ -27,7 +27,7 @@ def regresiva(n): yield n n -= 1 ``` -*Nota: "yield" se traduce como "rendir" ó "entregar"* +*Nota: "yield" se traduce como "rendir" ó "entregar".* Por ejemplo: @@ -43,7 +43,7 @@ Un generador es *cualquier* función que usa el commando `yield`. El comportamiento de los generadores es algo diferente al del resto de las funciones. -Al llamar a un generador creás un objeto generador, pero su función no se ejecuta de inmediato. +Al llamar a un generador creás un objeto generador, pero su función no se ejecuta de inmediato. ```python def regresiva(n): @@ -82,7 +82,7 @@ Lo que hace `yield` es notable: produce un valor, y luego suspende la ejecución >>> x.__next__() 8 ``` -Cuando finalmente se llega al final de la función, la iteración da un error. +Cuando finalmente se llega al final de la función, la iteración da un error. ```python >>> x.__next__() @@ -112,19 +112,19 @@ Por ejemplo, probá este generador que busca un archivo y entrega las líneas qu >>> for line in open('Data/camion.csv'): print(line, end='') -nombre,cantidad,precio -"Lima",100,32.20 -"Naranja",50,91.10 -"Limon",150,83.44 -"Mandarina",200,51.23 -"Durazno",95,40.37 -"Mandarina",50,65.10 -"Naranja",100,70.44 +nombre,cajones,precio +Lima,100,32.2 +Naranja,50,91.1 +Caqui,150,103.44 +Mandarina,200,51.23 +Durazno,95,40.37 +Mandarina,50,65.1 +Naranja,100,70.44 >>> for line in filematch('Data/camion.csv', 'Naranja'): print(line, end='') -"Naranja",50,91.10 -"Naranja",100,70.44 +Naranja,50,91.1 +Naranja,100,70.44 >>> ``` @@ -143,9 +143,9 @@ bash % python3 sim_mercado.py Después, olvidate de él. Dejálo ahí, corriendo. -Usando otra consola, mirá el contenido de `Data/mercadolog.csv`. Vas a ver que cada tanto se agrega una nueva línea al archivo. +Usando otra consola, mirá el contenido de `Data/mercadolog.csv`. Vas a ver que cada tanto se agrega una nueva línea al archivo. -Ahora que el programa generador de datos está en ejecución, escribamos un programa que abra el archivo, vaya al final, y espere nuevos datos. Para esto creá un programa llamado `vigilante.py` (es uno de los ejercicios a entregar) que contenga el siguiente código. +Ahora que el programa generador de datos está en ejecución, escribamos un programa que abra el archivo, vaya al final, y espere nuevos datos. Para esto creá un programa llamado `vigilante.py` (es uno de los ejercicios a entregar) que contenga el siguiente código. ```python # vigilante.py @@ -170,13 +170,13 @@ while True: *Nota: EOF = End Of File (fin de archivo)* -Cuando ejecutes el programa vas a ver un indicador de precios en el mercado en tiempo real, con indicación de qué producto se trata, cuál es su precio, y cuál es el volumen de la operación (en cantidad de cajones). +Cuando ejecutes el programa vas a ver un indicador de precios en el mercado en tiempo real, con indicación de qué producto se trata, cuál es su precio, y cuál es el volumen de la operación (en cantidad de cajones). *Observación:* La forma en que usamos el método `readline()` en este ejemplo es un poco rara, no es la forma en que se suele usar (dentro de un ciclo `for` para recorrer el contenido de un archivo). En este caso la estamos usando para mirar constantemente el fin de archivo para obtener los últimos datos que se hayan agregado (`readline()` devuelve ó bien el último dato o bien una cadena vacía). ### Ejercicio 9.6: Uso de un generador para producir datos Si analizás un poco el código del [Ejercicio 9.5](../09_Generadores_e_Iteradores/02_iteracion_a_medida.md#ejercicio-95-monitoreo-de-datos-en-tiempo-real) vas a notar que la primera parte del programa "produce" datos (los obtiene del archivo) y la segunda los procesa y los imprime, es decir "consume" datos. Una característica importante de las funciones generadoras es que podés mover todo el código a una función reutilizable. Probalo vos. - + Modificá el código del [Ejercicio 9.5](../09_Generadores_e_Iteradores/02_iteracion_a_medida.md#ejercicio-95-monitoreo-de-datos-en-tiempo-real) de modo que la lectura del archivo esté resuelta por una única función generadora `vigilar()` a la que se le pasa un nombre de archivo como parámetro. Hacelo de modo que el siguiente código funcione: ```python @@ -202,20 +202,20 @@ if __name__ == '__main__': Guradá esta versión de `vigilante.py` para entregar al final de la clase. ### Ejercicio 9.7: Cambios de precio de un camión -Modificá el programa `vigilante.py` para que sólo informe las líneas que tienen precios de lotes incluídos en un camión, e ignore el resto de los productos. Por ejemplo: +Modificá el programa `vigilante.py` para que sólo informe las líneas que tienen precios de lotes incluídos en un camión, e ignore el resto de los productos. Por ejemplo: ```python if __name__ == '__main__': import informe - + camion = informe.leer_camion ('Data/camion.csv') - + for line in vigilar('Data/mercadolog.csv'): fields = line.split(',') nombre = fields[0].strip('"') precio = float(fields[1]) volumen = int(fields[2]) - + if nombre in camion: print(f'{nombre:>10s} {precio:>10.2f} {volumen:>10d}') ``` diff --git a/Notas/Ejercicios.zip b/Notas/Ejercicios.zip index d9b03f5..ea0c9ff 100644 Binary files a/Notas/Ejercicios.zip and b/Notas/Ejercicios.zip differ