# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + [markdown] slideshow={"slide_type": "slide"}
# # Aula 3: Python - um pouco mais -  avançado
#

# + [markdown] slideshow={"slide_type": "subslide"}
# Exercício da semana passada, resolvendo usando alguns conceitos (filosóficos) de python:
#
# - DRY: don't repeat yourself (não se repita)
# - Loops para simplificar

# + slideshow={"slide_type": "subslide"}
## carregar arquivo com a lista de especies
lista_especies = open('../dados/lista_de_especies.txt', 'r').read()
lista_especies = lista_especies.split('\n')

# pegamos as ocorrências únicas, ou seja, o nome de cada espécie que aparece na lista
todas_especies = set(lista_especies)

# criamos um dicionario vazio que será preenchido mais pra frente
dicionario_especies = {}

# iteramos pelas especies [DRY+loops]
for especie in todas_especies:
    if especie != '':
        # podemos obter a ocorrência de uma variavel em um lista usando o método count()
        ocorrencias = lista_especies.count(especie)

        # adicionamos um novo registro ao dicionário
        dicionario_especies[especie] = ocorrencias

# vamos exibir na tela a quantidade de organismos de cada especie de forma iterativa, utilizando o método .items():
for especie,ocorrencia in dicionario_especies.items():
    print(f"A espécie {especie} possui {ocorrencia} ocorrencias.")


# + [markdown] slideshow={"slide_type": "subslide"}
# **O que veremos hoje?**
#
# - como declarar funções e importar pacotes em python
# - pacote para manipulação numérica de informações
# - pacote para visualização de dados (1D)
#

# + [markdown] slideshow={"slide_type": "subslide"} endofcell="--"
# **material de apoio**
#
# - numpy guia de usuário: https://numpy.org/doc/stable/numpy-user.pdf
# - numpy: https://ncar-hackathons.github.io/scientific-computing/numpy/intro.html
# - numpy + scipy: https://github.com/gustavo-marques/hands-on-examples/blob/master/scientific-computing/numpy_scipy.ipynb
# - matplotlib documentação: https://matplotlib.org/3.3.2/contents.html
# - 
# --

# + [markdown] slideshow={"slide_type": "slide"}
# # Python - um pouco mais -  avançado
#
# - pequenos problemas, pequenos trechos de códigos
# - funções e métodos

# + [markdown] slideshow={"slide_type": "subslide"}
# ## Funções (functions)
#
# - bloco de código independente
# - uma ou mais ações específicas (funções)
# - retorna ou não alguma informação
#
#
#
#
#
#

# + [markdown] slideshow={"slide_type": "subslide"}
# ## Funções (functions)
#
# - bloco de código independente
# - uma ou mais ações específicas (funções)
# - retorna ou não alguma informação
# - sintaxe:
#
#
# ![image.png](https://www.fireblazeaischool.in/blogs/wp-content/uploads/2020/06/Capture-1.png)
#
# Exemplo prático:

# + slideshow={"slide_type": "subslide"}
def K_para_C(T_em_K):
    # sequencia de bloco de códigos identados
    print('Estamos dentro de uma função!')
    
    # conversão
    T_em_C = T_em_K - 273.15
    
    return T_em_C


# + slideshow={"slide_type": "-"}
temp = 273.15
temperatura = K_para_C(temp)
print(temperatura)


# + [markdown] slideshow={"slide_type": "subslide"}
# Podemos deixar uma função mais completa adicionando informações sobre como ela funciona. Para isso, usamos as ```docstrings```:

# + slideshow={"slide_type": "-"}
def K_para_C(T_em_K):
    """ 
    Este conjunto de texto entre aspas triplas se chamada docstring. É usada para passar informações 
    importantes sobre a função, como: valores que ela recebe e retorna, o que ela faz, se é baseada em algum
    artigo científico, por exemplo, e muito mais. Quando tivermos dúvida sobre alguma função, podemos buscar
    o docstring dela utilizando o comando: K_para_C?
    
    No nosso caso, essa é uma função para converter uma temperatura de Kelvin para Celsius
    
    argumentos
    ----------
    T_em_K: float
        Temperatura em Kelvin para ser convertida.
    
    returns
    -------
    T_em_C: float
        Temperatura em graus Celsius.
    """
    # sequencia de bloco de códigos identados
    print('Estamos dentro de uma função!')
    
    # conversão
    T_em_C = T_em_K - 273.15
    
    return T_em_C

# + slideshow={"slide_type": "-"}
# K_para_C?


# + [markdown] slideshow={"slide_type": "slide"}
# # Pacotes (packages ou libraries)
#
# - coleção de funções
# - objetivo específico
# - podemos criar um
# - podemos (e iremos sempre) importar um pacote

# + [markdown] slideshow={"slide_type": "slide"}
# # NumPy: pacote numérico
#
# - background de qualquer pacote científico hoje em dia
# - utilizado para operações numéricas (matriciais ou escalares)
# - alta performance
# - Importamos da seguinte forma:

# + slideshow={"slide_type": "-"}
import numpy as np

# + [markdown] slideshow={"slide_type": "subslide"}
#
# **Conceitos**
#
# Lembrando alguns conceitos matemáticos:
#
# - Vetores (N,):
#
# $V = \begin{bmatrix}
# 1 & 2 & 3
# \end{bmatrix}$
#
# - Matrizes (NxM, linhasxcolunas):
#
# $M = \begin{bmatrix}
# 1 & 2 & 3\\ 
# 4 & 5 & 6
# \end{bmatrix}$
#
# Vamos ver alguns exemplos e entender na prática a funcionalidade do NumPy.

# + slideshow={"slide_type": "subslide"}
# primeiro importamos e só o precisamos fazer uma vez em cada código
import numpy as np

V = np.array([1, 2, 3]) # vetor: 1D
M = np.array([[1, 2, 3], [4, 5, 6]]) # matriz 2D

M

# + [markdown] slideshow={"slide_type": "subslide"}
# Apesar de falarmos em vetores e matrizes, para o numpy é tudo a mesma coisa. O que diferencia é apenas a dimensão.
#
# Nota: ```ndarray``` significa n-dimensional array (matriz com n-dimensões)
# -

type(M), type(V)

# + [markdown] slideshow={"slide_type": "subslide"}
# Mas como saber quantas dimensões uma matriz tem?

# + slideshow={"slide_type": "-"}
V.ndim, M.ndim

# + [markdown] slideshow={"slide_type": "subslide"}
# Podemo verificar o tamanho de uma matriz utilizando o método .shape. Se quisermos saber o tamanho geral da matriz (número total de itens), usamos o método. size:

# + slideshow={"slide_type": "-"}
# V.shape, V.size
print(V)

# + slideshow={"slide_type": "-"}
# M.shape, M.size
print(M)

# + [markdown] slideshow={"slide_type": "subslide"}
# **Utilidade**
#
# - muito similar a listas
# - numpy nos permite trabalhar com:
#    - operações matriciais
# - performance computacional alta
#
# **Nota**:
#
# - matrizes somente com mesmo tipo de variável (dtype)
# - o tipo de variável mais restritivo comanda o dtype da matriz:
# -

A = np.array([0,'teste'])
A

# + [markdown] slideshow={"slide_type": "subslide"}
# Podemos também indicar o tipo de matriz que queremos, ao cria-la, utilizando o argumento ```dtype``` e inserindo alguma das opções que já nos é conhecida (int, float, bool e complex):
# -

c = np.array([1, 2, 3], dtype=complex)
c

# + [markdown] slideshow={"slide_type": "subslide"}
# **Principais funções disponíveis no Numpy**

# + slideshow={"slide_type": "subslide"}
# criar um vetor ordenado (crescente) de 1 a 1 
x = np.arange(0, 100, 1)
x

# + slideshow={"slide_type": "subslide"}
# podemos criar o mesmo vetor, mas na ordem descrescente
x_inverso  = np.arange(100, 0, -1)
x_inverso

# + slideshow={"slide_type": "subslide"}
# criar um vetor de 0 a 100, com de 10 intervalos
y = np.linspace(0, 100, 10)
y

# + slideshow={"slide_type": "subslide"}
# criar uma grade

x,y  = np.mgrid[0:5, 0:5]
x

# + slideshow={"slide_type": "subslide"}
# utilizando números aleatórios
np.random.rand(5,3)

# + [markdown] slideshow={"slide_type": "subslide"}
# Outros métodos:
#
# cumsum, dot, det, sort, max, min, argmax, argmin, sqrt, e outros.
#
# Testem o que estes métodos fazem.
#
# Lembre que parar usar você deve:
#
# ```python
# x = np.arange(0,10,1)
# soma = x.sum()
# ```

# + [markdown] slideshow={"slide_type": "-"}
# Para quem vem do matlab:
#
# http://wiki.scipy.org/NumPy_for_Matlab_Users
# -



# + [markdown] slideshow={"slide_type": "slide"}
# # Pacote de visualização: Matplotlib
#
# - base para qualquer visualização de dados
# - é um saco importar, porém com o tempo fica menor pior
# - muito poderoso em termos de controle dos elementos do gráfico e da estrutura em si, isto é:
#  - estruturas complexas de eixos de visualização podem ser manipuladas por este pacote
#
# **Importar**
#
# ```python
# import matplotlib.pyplot as plt
# ```
#
# Quando utilizando um notebook, como no caso da aula, precisamos ativar o modo de exibir as figuras dentro do próprio notebook. Usamos então:
#
# ```python
# # # %matplotlib inline
# ```

# + [markdown] slideshow={"slide_type": "subslide"}
# **Elementos de uma figura**
#
# ![image1](https://raw.githubusercontent.com/storopoli/ciencia-de-dados/e350e1c686cd00b91c0f316f33644dfd2322b2e3/notebooks/images/matplotlib-anatomy.png)
#
# Fonte: Prof Storopoli [https://github.com/storopoli/ciencia-de-dados]

# + slideshow={"slide_type": "subslide"}
import matplotlib.pyplot as plt

# quando usando notebook, use o comando mágico abaixo para exibir as figuras no proprio arquivo:
# %matplotlib inline 

# + [markdown] slideshow={"slide_type": "subslide"}
# Gráfico único na figura:

# + slideshow={"slide_type": "-"}
fig = plt.figure()

# porém, como não existe informação plotada, nada é exibido abaixo.

# + [markdown] slideshow={"slide_type": "subslide"}
# Refazendo o comando, mas inserindo um plot 1D simples:

# + slideshow={"slide_type": "-"}
fig = plt.figure()

plt.plot([1,2,3])

# + [markdown] slideshow={"slide_type": "subslide"}
# Múltiplos gráficos em uma mesma figura:

# + slideshow={"slide_type": "-"}
fig,axes = plt.subplots(nrows=1, ncols=2)

axes[1]
# -

# Note: 
#
# - subplots já estruturados
# - a variável ```axes```é uma matriz 1D contendo os subplots

# + slideshow={"slide_type": "subslide"}
fig,axes = plt.subplots(nrows=1, ncols=2)

# exibindo o tipo de axes
print(type(axes))

# plotando no gráfico da esquerda (1o gráfico)
ax = axes[0]
ax.plot([1,2,3])

# plotando no gráfico da direita (2o gráfico)
axes[1].plot([3,2,1])

# + [markdown] slideshow={"slide_type": "subslide"}
# Como o eixo y (ordenada) compartilham o mesmo intervalo, podemos usar:

# + slideshow={"slide_type": "-"}
fig,axes = plt.subplots(nrows=2, ncols=1, sharex=True)

# plotando no gráfico da esquerda (1o gráfico)
ax = axes[0]
ax.plot([1,2,3])

# plotando no gráfico da direita (2o gráfico)
axes[1].plot([3,2,1])

# + [markdown] slideshow={"slide_type": "subslide"}
# E ainda podemos especificar o tamanho da nossa figura com o argumento ```figsize```. Este argumento também funciona em ```plt.figure()```.

# + slideshow={"slide_type": "-"}
fig,axes = plt.subplots(nrows=1, ncols=3, sharey=True, figsize=(20,5))

# plotando no gráfico da esquerda (1o gráfico)
ax = axes[0]
ax.plot([1,2,3])

# plotando no gráfico da direita (2o gráfico)
axes[1].plot([3,2,1])

axes[2].plot([3,2,1])

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Customizando nossos gráficos

# + slideshow={"slide_type": "-"}
fig,axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(15,5))

# plotando no gráfico da esquerda (1o gráfico)
ax = axes[0]
ax.plot([1,2,3], 'r')

# plotando no gráfico da direita (2o gráfico)
axes[1].plot([3,2,1], 'g-o')


# + [markdown] slideshow={"slide_type": "subslide"}
# Para exemplificar uma função de visualização, vamos transformar o código acima em uma função:

# + slideshow={"slide_type": "-"}
def plot_simples():
    fig,axes = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(15,5))

    # plotando no gráfico da esquerda (1o gráfico)
    ax = axes[0]
    ax.plot([1,2,3], 'r-')

    # plotando no gráfico da direita (2o gráfico)
    axes[1].plot([3,2,1], 'g-o')
    
    # retornamos fig e axes pq precisaremos no futuro
    return fig,axes


# + slideshow={"slide_type": "subslide"}
# usando a função. Note que atribuimos o retorno da função a duas variáveis
fig,axes = plot_simples()

# inserindo rótulos ao eixo das abscissas (x) e ordenada (y):
axes[0].set_xlabel('Abscissa', fontsize=20)
axes[0].set_ylabel('Ordenada', fontsize=20)
axes[1].set_xlabel('Abscissa', fontsize=20)

# adicionando um título para cada subplot
axes[0].set_title('Figura da esquerda', fontsize=25)
axes[1].set_title('Figura da direita', fontsize=25)

# podemos configurar o intervalo discreto das abscissas e ordenadas
axes[0].set_xticks(np.arange(0,3,1))

# podemos ainda trocar os rótulos de cada tick
axes[0].set_xticklabels(['primeiro', 'segundo', 'terceiro'])

# configurar os limites
axes[1].set_xlim([0,10])

# inserindo outros elementos:
axes[0].grid('--', alpha=.3)
axes[1].grid('--', alpha=.3)

# axes[0].fill_between([0,1,2], 0, 2)
# -



# + [markdown] slideshow={"slide_type": "subslide"}
# **Tipos de gráficos para 1D**
#
# - linha: ```plt.plot()```
# - barra: ```plt.barh()```
# - histograma: ```plt.hist()```
#
# Podemos plotar, de forma semelhante, histogramas ou gráficos de barra ou histograma:

# + slideshow={"slide_type": "-"}
fig,axes = plt.subplots(1,2,figsize=(15,5))

# grafico de barras horizontal
axes[0].barh(x,y)

# histograma para x
_,_,_ = axes[1].hist(x,5)

# bonus: personalizacao dos subplots usando apenas uma linha com compreensão de listas (list comprehension)
_ = [ax.grid('--', alpha=.3) for ax in axes]

# + slideshow={"slide_type": "subslide"}
# precisando de ajuda? 
help(plt.plot)
# # plt.plot?

# + [markdown] slideshow={"slide_type": "subslide"}
# Enfim, para **salvar** uma figura, utilizamos o método ```plt.savefig()```:
#
# - formatos disponíveis: pdf, png, jpg, tif, svg
# - dpi: qualidade da figura salva
# - bbox_to_inches: use ```tight``` para remover espaços em branco ao redor

# + slideshow={"slide_type": "-"}
# usando a nossa função
fig,ax = plot_simples()

# salvando a figura
plt.savefig('nome_da_figure.png', dpi=150, bbox_to_inches='tight')


# + [markdown] slideshow={"slide_type": "subslide"}
# Exercício:
#
# Utilizando o dicionário criado com a lista de espécies, plote um gráfico de barras horizontais, utilizando ```plt.barh()```.
#
# **dica**: use ```list()``` para converter as chaves e valores do dicionário para uma lista.

# +
# solução
especies = list(dicionario_especies.keys())
ocorrencias = list(dicionario_especies.values())

fig = plt.figure(figsize=(15,5))
ax = plt.barh(especies, ocorrencias)
plt.xlabel('Ocorrências')
plt.title('Titulo para o gráfico')

# + [markdown] slideshow={"slide_type": "subslide"}
#
# É claro que existem diversas formas de visualização de gráficos de uma dimensão no python. Apresentamos dois tipos bem básicos, porém muito utilizados no dia a dia de um cientista. 
#
# Para mais exemplo, navegue pela documentação do matplotlib. Ao longo do curso iremos explorar diversos formatos de visualização e explicaremos cada caso conforme uso.

# + [markdown] slideshow={"slide_type": "subslide"}
# Exercícios de casa: perfis verticais
#
# Arquivos com temperatura e salinidade climatológica do World Ocean Atlas (WOA) serão fornecidos para uma região específica do litoral Norte de São Paulo: Ubatuba. 
#
# 1. carregue os dados com numpy usando genfromtxt ou loadtxt(sep=','), sendo uma variável para cada propriedade
#
# ```python
# temperatura = np.loadtxt('../dados/salinidade_woa2018_ubatuba_60m.csv', delimiter=',')
# ```
#
# 2. explore a estrutura da matriz que virá. Por exemplo, identifique:
#    - o que é cada coluna? E cada linha?
#    - como acessá-los pelo indexamento de matrizes?
#
# Esteja familiarizado com a matriz fornecida antes de prosseguir para a visualização, assim erros que poderão assustar serão evitados.
# -

# codigo para baixar o arquivo, caso você esteja rodando este notebook no Google Colab
# !wget --directory-prefix=../dados/ https://raw.githubusercontent.com/nilodna/python-basico/feature_iojr-shortcourse/dados/temperatura_woa2018_ubatuba_60m.csv
# !wget --directory-prefix=../dados/ https://raw.githubusercontent.com/nilodna/python-basico/feature_iojr-shortcourse/dados/salinidade_woa2018_ubatuba_60m.csv

# + slideshow={"slide_type": "subslide"}
# explorando matrizes de temperatura e salinidade
temperatura = np.loadtxt('../dados/temperatura_woa2018_ubatuba_60m.csv', delimiter=',')
temperatura[:, 12]

# + [markdown] slideshow={"slide_type": "subslide"}
# Nível 1:
# - faça subplots de perfis verticais para o mês de janeiro. Cada subplot será uma propriedade (temperatura e salinidade)
#
# Nível 2:
# - Faça uma média dos meses de verão e meses de inverno
# - plot as médias em dois subplots, para cada propriedade
#
# Nível 3:
# - plote todos os meses da climatologia em cada figura (uma para cada propriedade como feito nos anteriores).
# - mantenha consistência em cores ou marcadores para cada mês
#
# Bônus:
# - plote em um só gráfico a temperatura e salinidade para um mês a sua escolha. 
# - sabendo que os limites serão diferentes, adicione um segundo eixo (eixo gêmeo) à figura usando ```ax.twinx()```.
#
# **dicas**
# - use ```:``` para acessar todos os valores de uma dimensão da matriz
# - estilize seu perfil vertical com gradeamento (grid), rotulos (labels) nos eixos. legenda (legend), etc...

StarcoderdataJupyterScriptsDedupFiltered