diff --git a/earthquakes.py b/earthquakes.py index 7c18069..4acf493 100644 --- a/earthquakes.py +++ b/earthquakes.py @@ -7,32 +7,15 @@ import sys from datetime import datetime import pandas as pd -from utils import crud, parser, stats, utils + +from utils import parser, crud, stats, utils, visuals, filters HEADER = """=== Terramotos ===""" -EVENT_COLS = [ - "Data", - "Latitude", - "Longitude", - "Profundidade", - "Tipo Evento", - "Gap", - "Magnitudes", - "Regiao", - "Sentido", -] -STATION_COLS = [ - "Estacao", - "Hora", - "Min", - "Seg", - "Componente", - "Distancia Epicentro", - "Tipo Onda", -] +EVENT_COLS = ["Data", "Latitude", "Longitude", "Profundidade", "Tipo Evento", "Gap", "Magnitudes", "Regiao", "Sentido", "Pub", "SZ", "VZ"] +STATION_COLS = ["Estacao", "Hora", "Min", "Seg", "Componente", "Distancia Epicentro", "Tipo Onda"] -MENU = """[1] Criar a base de dados +MENU ="""[1] Criar a base de dados [3] Apagar um evento [4] Apagar uma entrada de um evento [5] Visualizar um evento @@ -40,6 +23,8 @@ MENU = """[1] Criar a base de dados [7] Guardar como CSV [8] Estatísticas [9] Criar uma entrada +[10] Gráficos +[11] Filtros (T7) [Q] Sair """ @@ -48,7 +33,7 @@ MENU = """[1] Criar a base de dados def guardar_json(df: pd.DataFrame, fname: str) -> bool: _retValues = utils.create_dict_struct(df, EVENT_COLS, None) - with open(fname, "w") as fp: + with open(fname , "w") as fp: try: json.dump(_retValues, fp) except: @@ -68,7 +53,8 @@ def guardar_csv(df: pd.DataFrame, fname: str): def main(): isRunning = True db = None - + original_db = None + retInfo = None while isRunning: @@ -84,9 +70,11 @@ def main(): if _file_exists(fname) and fname.endswith(".json"): db = pd.read_json(fname) + original_db = db.copy() print("Base de dados populada.") elif _file_exists(fname): db = parser.parse(fname) + original_db = db.copy() input("Base de dados populada. Enter para voltar ao menu inicial") else: input("Base de dados não encontrada. Por favor tenta de novo.") @@ -106,6 +94,7 @@ def main(): else: retInfo = "Base de dados não encontrada!" + case "4": if db is not None: crud.read_ids(db) @@ -153,7 +142,7 @@ def main(): fname = _get_usr_input("Nome do ficheiro a guardar? ") if fname is None: fname = "valores.json" - guardar_json(db, fname) + utils.save_as_json(db, fname, EVENT_COLS, STATION_COLS) else: retInfo = "Base de dados não encontrada!" @@ -168,10 +157,10 @@ def main(): case "8": if db is not None: - stats.stats(db) + stats.stat_menu(db) else: retInfo = "Base de dados não encontrada!" - + case "9": if db is not None: crud.read_ids(db) @@ -196,6 +185,21 @@ def main(): input() else: retInfo = "Base de dados não encontrada!" + + case "10": + if db is not None: + visuals.visual_menu(db) + else: + retInfo = "Base de dados não encontrada!" + + case "11": + if db is not None: + # Passa db e original_db para o menu de filtros + # Retorna a nova db ativa (filtrada ou redefinida) + db = filters.filter_menu(db, original_db) + else: + retInfo = "Base de dados não encontrada!" + case "q": isRunning = False continue @@ -214,30 +218,25 @@ def _file_exists(name: str) -> bool: return True return False - def _event_exists(df, eid) -> bool: allEvents = set(df["ID"]) return eid in allEvents -def _get_usr_input(msg: str, asType=str): +def _get_usr_input(msg:str, asType=str): usrIn = input(msg) if usrIn == "": return None return asType(usrIn) - def _prettify_event(df): preambleInfo = df.drop_duplicates(subset="ID", keep="first") stations = df[["Estacao", "Componente", "Tipo Onda", "Amplitude"]] info = df.drop_duplicates(subset="Data", keep="first") data = datetime.fromisoformat(info.Data.values[0]).strftime("%c") - print( - f"Região: {info['Regiao'].values[0]}\nData: {data}\nLatitude: {info.Lat.values[0]}\nLongitude: {info.Long.values[0]}" - + f"\nProfundidade: {info.Prof.values[0]}\nTipo de evento: {info['Tipo Ev'].values[0]}\n" - ) + print(f"Região: {info["Regiao"].values[0]}\nData: {data}\nLatitude: {info['Latitude'].values[0]}\nLongitude: {info['Longitude'].values[0]}" + + f"\nProfundidade: {info['Profundidade'].values[0]}\nTipo de evento: {info['Tipo Evento'].values[0]}\n") - -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..e58eb5d --- /dev/null +++ b/shell.nix @@ -0,0 +1,14 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = with pkgs; [ + python3 + python3Packages.pandas + python3Packages.numpy + python3Packages.matplotlib + ]; + + shellHook = '' + echo "Funcionou" + ''; +} diff --git a/utils/crud.py b/utils/crud.py index 338c053..e8b0ffb 100644 --- a/utils/crud.py +++ b/utils/crud.py @@ -8,7 +8,7 @@ pd.set_option('display.width', 150) # -- globals -HEADER_COLS = ["Data", "Distancia", "Tipo Ev", "Lat", "Long", "Prof", "Magnitudes"] +HEADER_COLS = ["Data", "Distancia", "Tipo Evento", "Latitude", "Longitude", "Profundidade", "Magnitudes"] TABLE_READ_RET = ["Estacao", "Hora", "Min", "Seg", "Componente", "Amplitude"] # -- helper funcs @@ -33,14 +33,13 @@ def get_unique_events_table(df): def read_header(df, event_id): - # Informações do header do evento + # Obtém a informação da primeira linha do evento (cabeçalho) row = df[df["ID"] == event_id].iloc[0] cols = list(df.columns) - # end = cols.index("ID") - 1 - # header_cols = cols[:end] - # Para selecionar todas as colunas em vez de só algumas + info = [] for (i, col) in enumerate(HEADER_COLS): + # Constrói a string formatada "Índice Nome: Valor" info.append(f"{i+1} {col}: {row[col]}") infoString = f"Header do evento {event_id}:\n" + "\n".join(info) return infoString @@ -56,15 +55,23 @@ def get_table(df, event_id): def read_table_row(df, event_id, row_number_1): - # retorna uma linha específica da tabela + # Retorna uma linha específica da tabela de estações + # row_number_1 é o índice dado pelo utilizador (começa em 1) + # row_number_0 é o índice real da lista (começa em 0) row_number_0 = row_number_1 - 1 table = get_table(df, event_id) + + # Verifica se a linha pedida existe dentro das linhas deste evento if row_number_0 < 0 or row_number_0 >= len(table): return f"Linha {row_number_1} não pertence ao evento {event_id}." + row = table.iloc[row_number_0] cols = list(df.columns) + + # Encontra onde começam as colunas da estação para mostrar apenas os dados relevantes start = cols.index("Estacao") tableCols = cols[start:] + info = [] for (i, col) in enumerate(tableCols): info.append(f"{i+1} {col}: {row[col]}") @@ -79,9 +86,10 @@ def update_table_row(df, row_line, new_data): def update_header(df, event_id, new_data): - # atualiza o header de um evento + # Atualiza o cabeçalho de um evento com os novos dados for key, value in new_data.items(): if key in df.columns: + # Atualiza todas as linhas deste evento (ID == event_id) com o novo valor df.loc[(df["ID"] == event_id) | df.iloc[0], key] = value return f"Header do evento {event_id} atualizado com sucesso." @@ -94,48 +102,60 @@ def delete_event(df, event_id): def delete_table_row(df, event_id, row_number): - # Apaga uma linha específica da tabela do evento - # Cria uma nova linha vazia no dataframe na posição insertion_point + # Apaga uma linha específica da tabela de estações de um evento + + # Encontra todos os índices (números de linha no DataFrame que pertencem a este evento matching_indices = df.index[df['ID'] == event_id].tolist() first_event_row = matching_indices[0] last_event_row = matching_indices[-1] + # Garante que não estamos a apagar uma linha que pertence a outro evento if row_number < first_event_row or row_number > last_event_row: return df, f"Erro: A posição a apagar, {row_number} está fora do intervalo permitido para o evento {event_id}." + new_df = df.drop([row_number]).reset_index(drop=True) - return new_df, f"Linha {row_choice} apagada com sucesso!" + return new_df, f"Linha {row_number} apagada com sucesso!" def create_blank_event(df, event_id): - # Criar um evento vazio com linha de header e 1 linha de coluna + # Cria um novo evento vazio + # Primeiro, avança os IDs de todos os eventos seguintes para arranjar espaço df.loc[df["ID"] >= event_id, "ID"] += 1 + # Cria 2 linhas novas: uma para o cabeçalho e outra vazia para dados blank_row_df = pd.DataFrame(columns=df.columns, index=[0, 1]) blank_row_df["ID"] = event_id blank_row_df = blank_row_df.astype(df.dtypes) + # Junta as novas linhas ao dataframe principal new_df = pd.concat([df, blank_row_df], ignore_index=True) + # Ordena por ID para garantir que fica tudo na ordem certa (mergesort é estável) new_df = new_df.sort_values(by="ID", kind="mergesort").reset_index(drop=True) return new_df def create_table_row(df, event_id, insertion_point): - # Cria uma nova linha vazia no dataframe na posição insertion_point + # Insere uma nova linha vazia numa posição específica dentro do evento + + # Encontra os limites (início e fim) do evento atual matching_indices = df.index[df['ID'] == event_id].tolist() first_event_row = matching_indices[0] last_event_row = matching_indices[-1] + # Valida se o ponto de inserção é válido para este evento if insertion_point < first_event_row or insertion_point > last_event_row + 1: return df, f"Erro: A posição de inserção {insertion_point} está fora do intervalo permitido para o evento {event_id}" + # Cria a nova linha new_row_df = pd.DataFrame(columns=df.columns, index=[0]) new_row_df['ID'] = event_id new_row_df = new_row_df.fillna(0) new_row_df = new_row_df.astype(df.dtypes) + # Parte o dataframe em dois (antes e depois do ponto de inserção) e mete a nova linha no meio df_before = df.iloc[:insertion_point] df_after = df.iloc[insertion_point:] diff --git a/utils/dados.txt b/utils/dados.txt new file mode 100644 index 0000000..8c6391f --- /dev/null +++ b/utils/dados.txt @@ -0,0 +1,839 @@ + 2014 1 5 0332 36.3 LQ 38.433 -28.403 0.0 *AZO 11 0.5 2.8LAZO 1 + GAP=208 1.45 9.4 4.7 8.3 -0.1953E+02 0.2063E+02 -0.5068E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140105033236 I + OP: CVUA-RM/RC 3 + STATUS: OK SENTIDO 3 + SENTIDO: II/III -Pico: S. Caetano 3 + PUB: NAO 3 + WEB: SIM 3 + OBS: Por ordem do CT nao foi emitido novo comunicado 3 + OBS: Sismo sobreposto 3 + REGIAO: Pico,VZ14,SZ06,FE95 405 3 + S. Caetano F 2 +MM AZO 2 + 2014-01-05-0331-37S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PBOI EZ EP 332 36.87 102 0.1210 2.48 82 + PBOI EZ E 332 37.72 2.48 82 + PBOI EN E 332 37.73 101 2.48 82 + PCND EZ EP 332 37.04 96 -0.4310 6.51 308 + PCND EN E 332 38.28 97 6.51 308 + PCND EZ IAML 332 38.42 15553.4 0.30 6.51 308 + PTEI EZ EP 332 37.21 96 -0.5410 7.99 31 + PTEI EN E 332 38.82 96 7.99 31 + PTEI EZ IAML 332 40.06 16089.8 0.48 7.99 31 + PLGR EZ EP 332 40.80 59 -0.1310 26.4 311 + PLGR EN ES 332 43.64 59 -0.7710 26.4 311 + PCTB EZ EP 332 41.70 59 0.0410 31.3 290 + PCTB EN ES 332 46.87 59 1.1810 31.3 290 + PCTB EZ IAML 332 48.56 793.4 0.48 31.3 290 + PAMA EZ EP 332 42.17 59 0.1410 33.6 35 + PAMA EN ES 332 46.74 59 0.3910 33.6 35 + PAMA EZ IAML 332 48.13 1860.1 0.42 33.6 35 + PCUT EE E 332 48.90 34.3 309 + ROSA BZ EP 9 332 41.30 59 -0.91 0 34.8 24 + ROSA BN ES 332 46.33 59 0.5810 34.8 24 + PTCA EN E 332 48.36 38.2 296 + PLUZ EN E 332 55.18 74.6 30 + STGR EZ E 332 48.34 79.8 26 + + 2014 1 5 0333 4.5 LQ 38.431 -28.405 0.0 *AZO 10 0.4 2.6LAZO 2.6CAZO 1 + GAP=214 1.01 5.2 3.4 5.0 -0.8103E+01 0.1158E+02 -0.9278E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140105033304 I + OP: CVUA-RM/RC 3 + STATUS: OK SENTIDO 3 + SENTIDO: II/III -Pico: S. Caetano 3 + PUB: NAO 3 + WEB: SIM 3 + OBS: Por ordem do CT nao foi emitido novo comunicado 3 + REGIAO: Pico,VZ14,SZ06,FE95 405 3 + S. Caetano F 2 +MM AZO 2 + 2014-01-05-0331-37S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PBOI EZ EP 333 5.10 48 101 0.1110 2.70 76 + PBOI EN E 333 5.94 2.70 76 + PCND EZ EP 333 5.32 51 96 -0.3710 6.56 311 + PCND EN E 333 6.53 6.56 311 + PTEI EZ EP 333 5.42 52 96 -0.5910 8.32 31 + PTEI EN ES 333 6.96 96 -0.1910 8.32 31 + PTEI EZ IAML 333 8.23 13778.4 0.34 8.32 31 + PLGR EZ EP 333 8.99 59 -0.1510 26.5 312 + PLGR EN ES 333 12.45 59 -0.1810 26.5 312 + PLGR EZ IAML 333 13.67 617.9 0.30 26.5 312 + PCTB EZ EP 333 9.95 59 0.1010 31.3 291 + PCTB EN ES 333 13.85 59 -0.0310 31.3 291 + PAMA EN ES 333 15.36 59 0.7210 33.9 35 + PCUT EN ES 333 14.68 59 -0.0710 34.4 309 + PCUT EZ IAML 333 16.71 530.5 0.47 34.4 309 + ROSA BN ES 4 333 16.65 59 1.70 0 35.1 24 + PTCA EN ES 333 16.43 59 0.6610 38.1 297 + PTCA EZ IAML 333 16.98 652.6 0.37 38.1 297 + PLUZ EN E 333 25.77 74.9 30 + STGR EN E 333 24.54 80.2 26 + + 2014 1 6 0839 22.5 LQ 38.082 -26.498 0.0 *AZO 19 0.3 2.8LAZO 2.7CAZO 1 + GAP=199 0.92 16.1 14.1 5.6 0.2263E+03 -0.6104E+02 -0.7019E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140106083922 I + OP: CVUA-AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa Hirondelle,SZ18,FE95 405 3 + 2014-01-06-0839-02S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + SET4 EZ EP 839 32.92 44 50 -0.1310 65.6 110 + SET4 EZ ES 839 40.72 50 -0.2310 65.6 110 + SET2 EZ EP 839 33.33 41 50 0.1710 66.2 113 + SET2 EZ ES 839 41.05 50 -0.0910 66.2 113 + PFET EZ EP 839 33.07 45 50 -0.4310 68.9 115 + PSAN EZ EP 839 34.49 38 50 0.4810 72.5 110 + PSAN EZ ES 839 42.69 50 0.0610 72.5 110 + FAC EZ ES 839 44.88 43 0.1510 82.0 114 + PFAV EZ EP 839 35.60 47 43 -0.1810 86.6 324 + PFAV EN IS 839 45.57 43 -0.1610 86.6 324 + PFAV EZ IAML 839 45.61 78.0 0.28 86.6 324 + PRIB EZ EP 839 35.52 42 43 -0.4810 88.1 318 + PRIB EN ES 839 46.30 43 0.1910 88.1 318 + PRIB EZ IAML 839 46.91 173.0 0.28 88.1 318 + CML EZ EP 839 36.79 52 43 0.5010 90.5 112 + CMLA B2 ES 4 839 50.79 43 3.70 0 92.6 112 + PVNV EZ EP 839 36.34 46 43 -0.4710 94.8 323 + PVNV EN ES 839 47.55 43 0.0210 94.8 323 + PVNV EZ IAML 839 47.85 148.4 0.29 94.8 323 + PMAT EN ES 839 47.10 43 -0.4810 94.9 108 + PMAT EZ IAML 839 47.62 420.5 0.58 94.9 108 + LFA EZ EP 839 36.53 52 43 -0.4510 95.6 111 + PPAD EZ EP 839 37.15 49 43 0.0110 97.3 315 + PPAD EN IS 839 48.59 43 0.4910 97.3 315 + PPAD EZ IAML 839 49.04 149.7 0.25 97.3 315 + PRCH EZ EP 839 37.21 41 43 0.0210 97.8 113 + PRCH EN ES 839 48.28 43 0.0910 97.8 113 + MESC EZ EP 839 37.08 46 43 -0.2010 97.9 109 + MESC EN ES 839 48.14 43 -0.2110 97.9 109 + MESC EZ IAML 839 48.28 160.4 0.36 97.9 109 + VIF EN ES 839 48.93 43 0.0910 100 112 + PBIS EN E 839 50.26 100 319 + ASBA EN ES 839 49.44 43 0.3210 102 314 + PCNG EZ EP 839 37.94 39 43 0.0510 103 109 + PCNG EN ES 839 50.30 43 0.8810 103 109 + MIRA EZ E 839 51.05 112 107 + + 2014 1 8 2246 5.4 LQ 38.460 -29.065 8.7 *AZO 7 0.1 2.1LAZO 2.0CAZO 1 + GAP=327 0.40 3.5 3.3 4.2 -0.2535E+01 -0.1768E+01 0.9548E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140108224605 I + OP: CVUA-SA/AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: WSW Faial,SZ31,FE95 405 3 + 2014-01-08-2245-41S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PTCA EZ EP 2246 10.07 19 96 0.1710 27.2 59 + PTCA EN ES 2246 13.49 96 0.2210 27.2 59 + PTCA EZ IAML 2246 14.04 389.6 0.16 27.2 59 + PCTB EZ EP 2246 10.14 20 95 -0.0510 29.3 74 + PCTB EN ES 2246 13.80 95 0.0310 29.3 74 + PCTB EZ IAML 2246 14.63 353.7 0.28 29.3 74 + PCUT EZ EP 2246 11.05 21 94 -0.0910 36.0 59 + PCUT EN ES 2246 15.34 94 -0.0910 36.0 59 + PCUT EZ IAML 2246 15.76 459.8 0.09 36.0 59 + PLGR EN ES 2246 16.34 93 -0.2310 40.5 69 + PLGR EZ IAML 2246 16.51 114.5 0.30 40.5 69 + PCND EZ EP 2246 13.44 29 92 -0.0410 52.6 89 + PCND EN ES 2246 19.47 92 -0.0610 52.6 89 + PCND EZ IAML 2246 19.88 36.3 0.19 52.6 89 + PBOI EZ EP 2246 14.51 29 64 -0.0210 60.2 92 + PBOI EN ES 2246 21.54 64 0.1710 60.2 92 + PBOI EZ IAML 2246 21.57 43.4 0.16 60.2 92 + PTEI EN E 2246 22.41 61.9 86 + + 2014 1 9 0607 7.2 LQ 37.714 -26.259 0.0 *AZO 17 0.3 2.1LAZO 2.4CAZO 1 + GAP=235 0.87 4.9 2.7 3.6 0.9360E+01 -0.1490E+01 -0.5738E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140109060707 I + OP: CVUA-IA/AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: S Fossa Hirondelle,SZ18,FE95 405 3 + 2014-01-09-0606-43S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + SET2 EZ EP 6 7 14.10 34 59 -0.2510 42.4 70 + SET2 EZ ES 6 7 20.26 59 0.5510 42.4 70 + PFET EZ EP 6 7 14.10 33 59 -0.3510 43.1 74 + PFET EZ ES 6 7 19.81 59 -0.0610 43.1 74 + SET4 EZ EP 6 7 14.08 36 59 -0.5710 44.3 66 + SET4 EZ ES 6 7 20.58 59 0.3610 44.3 66 + PSAN EZ EP 6 7 14.96 36 59 -0.4810 49.4 72 + PSAN EZ ES 6 7 20.98 59 -0.6310 49.4 72 + FAC EZ EP 6 7 16.25 30 50 0.1210 54.1 83 + FAC EZ ES 6 7 22.63 50 -0.1910 54.1 83 + CML EZ EP 6 7 17.38 39 50 -0.0310 63.2 84 + CML EZ ES 6 7 25.28 50 0.2210 63.2 84 + CMLA B2 ES 4 6 7 24.33 50 -1.17 0 65.0 85 + PVER EN ES 6 7 25.52 50 -0.2610 66.4 82 + PRCH EZ EP 6 7 18.23 34 50 0.0710 68.7 88 + PRCH EN ES 6 7 26.56 50 0.1910 68.7 88 + PRCH EZ IAML 6 7 27.56 149.5 0.19 68.7 88 + LFA EZ EP 6 7 18.54 33 50 0.3110 68.8 84 + PMAT EZ EP 6 7 18.33 24 50 -0.0610 70.4 80 + PMAT EN ES 6 7 26.55 50 -0.2310 70.4 80 + PMAT EZ IAML 6 7 26.62 84.8 0.16 70.4 80 + MESC EN ES 6 7 27.35 50 0.0010 72.3 83 + MESC EZ IAML 6 7 28.22 30.4 0.19 72.3 83 + VIF EN ES 6 7 27.75 50 0.4010 72.4 87 + VIF EZ IAML 6 7 28.20 43.6 0.25 72.4 87 + PCNG EN ES 6 7 28.88 43 0.5910 76.4 85 + FRA1 EN ES 6 7 29.08 43 0.0010 80.0 87 + FRA1 EZ IAML 6 7 30.04 47.2 0.24 80.0 87 + PFAV EN ES 6 7 40.40 43 0.0010 132 327 + PFAV EZ IAML 6 7 41.27 17.2 0.27 132 327 + PRIB EN ES 6 7 40.76 43 0.1110 133 323 + PRIB EZ IAML 6 7 41.85 25.3 0.28 133 323 + PVNV EN ES 6 7 42.35 43 0.1610 140 326 + + 2014 1 9 1503 59.5 LQ 38.063 -26.236 0.0 *AZO 20 0.3 2.3LAZO 2.7CAZO 1 + GAP=183 0.83 11.8 9.6 3.7 0.1125E+03 -0.2100E+02 -0.2738E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140109150359 I + OP: CVUA-BC/RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa Hirondelle,SZ18,FE95 405 3 + 2014-01-09-1503-33S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + SET4 EZ EP 15 4 6.75 53 59 -0.0610 43.7 118 + SET4 EZ ES 15 4 12.56 59 0.2510 43.7 118 + SET2 EZ EP 15 4 7.11 59 0.1110 44.9 123 + PFET EZ EP 15 4 7.36 36 59 -0.0810 47.8 125 + PFET EZ ES 15 4 13.61 59 0.2010 47.8 125 + PSAN EZ EP 15 4 7.63 43 59 -0.2510 50.6 118 + PSAN EZ ES 15 4 14.44 59 0.2510 50.6 118 + CML EZ EP 15 4 10.11 50 -0.3210 68.8 118 + PVER EN ES 15 4 18.74 50 -0.1710 70.0 115 + CMLA BZ EP 9 15 4 9.53 54 50 -1.19 0 70.8 118 + CMLA B1 ES 15 4 18.27 0.3010 70.8 118 + PMAT EZ EP 15 4 10.60 44 50 -0.3610 72.6 112 + PMAT EN ES 15 4 19.36 50 -0.2110 72.6 112 + PMAT EZ IAML 15 4 20.21 258.3 0.17 72.6 112 + LFA EZ IP 15 4 10.76 54 50 -0.3910 73.6 116 + MESC EZ EP 15 4 10.99 54 50 -0.4610 75.6 113 + MESC EN ES 15 4 20.08 50 -0.3510 75.6 113 + MESC EZ IAML 15 4 20.34 71.7 0.19 75.6 113 + PRCH EN ES 15 4 20.71 43 0.2910 76.2 119 + VIF EZ EP 15 4 12.18 44 43 0.4010 78.4 116 + VIF EN ES 15 4 21.37 43 0.3610 78.4 116 + VIF EZ IAML 15 4 22.08 64.5 0.20 78.4 116 + PCNG EN ES 15 4 21.78 43 0.2610 80.8 114 + FRA1 EN ES 15 4 22.94 43 0.4210 85.4 114 + FRA1 EZ IAML 15 4 23.65 69.7 0.16 85.4 114 + MIRA EZ EP 15 4 12.78 35 43 -0.4110 89.6 110 + MIRA EZ ES 15 4 23.52 43 0.0410 89.6 110 + PFAV EN ES 15 4 26.99 43 0.6510 103 314 + PRIB EE ES 15 4 26.99 43 -0.0310 106 310 + PRIB EZ IAML 15 4 27.46 63.8 0.14 106 310 + PVNV EN ES 15 4 27.95 43 -0.2210 112 314 + PVNV EZ IAML 15 4 28.81 33.2 0.19 112 314 + PPAD EN ES 15 4 29.18 43 0.0410 116 308 + PPAD EZ IAML 15 4 29.49 18.7 0.12 116 308 + ASBA EN ES 15 4 30.19 43 0.0110 120 308 + + 2014 1 9 2224 43.4 LQ 37.442 -24.806 0.7 *AZO 18 0.3 2.9LAZO 3.2CAZO 1 + GAP=247 0.72 3.5 14.6 9.2 0.4637E+02 0.1281E+03 0.2725E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140109222443 I + OP: CVUA-RM 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa da Povoacao,SZ13,FE95 404 3 + 2014-01-09-2224-00S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + MIRA EZ EP 2224 52.17 65 50 -0.4610 56.5 313 + FRA1 EZ EP 2224 53.37 85 50 0.4710 58.7 305 + FRA1 EN ES 2224 59.43 50 -0.6110 58.7 305 + FRA1 EZ IAML 2225 1.59 391.7 0.23 58.7 305 + PSPR EZ EP 2224 52.91 82 50 -0.0210 59.1 200 + PSPR EN ES 2225 0.33 50 0.2510 59.1 200 + PSPR EZ IAML 2225 2.73 296.7 0.33 59.1 200 + PVPO EZ EP 2224 53.14 93 50 -0.2410 62.5 210 + PVPO EN ES 2225 0.70 50 -0.1710 62.5 210 + PVPO EZ IAML 2225 1.00 201.2 0.19 62.5 210 + PCNG EZ EP 2224 53.90 63 50 0.3410 63.3 305 + PCNG EN ES 2225 0.94 50 -0.2410 63.3 305 + PCNG EZ IAML 2225 3.22 125.7 0.48 63.3 305 + VIF EZ EP 2224 53.87 82 50 0.0410 65.3 301 + VIF EN ES 2225 1.85 50 0.1910 65.3 301 + VIF EZ IAML 2225 2.96 778.3 0.20 65.3 301 + PRCH EZ EP 2224 53.97 74 50 -0.1110 67.4 298 + PRCH EN ES 2225 2.25 50 0.1510 67.4 298 + PRCH EZ IAML 2225 3.45 898.9 0.19 67.4 298 + MESC EZ EP 2224 54.12 96 50 -0.1910 68.6 305 + MESC EN ES 2225 2.42 50 -0.0810 68.6 305 + MESC EZ IAML 2225 4.09 420.2 0.23 68.6 305 + LFA EZ EP 2224 54.48 86 50 -0.0310 70.1 302 + PMAT EZ EP 2224 54.42 76 50 -0.2810 71.9 305 + PMAT EN ES 2225 3.60 50 0.4210 71.9 305 + PMAT EZ IAML 2225 4.03 381.7 0.20 71.9 305 + CMLA BZ EP 9 2224 53.80 79 50 -1.04 0 72.8 300 + CMLA B2 ES 2225 2.56 0.1810 72.8 300 + PVER EZ EP 2224 55.25 76 50 0.2810 73.9 303 + PVER EN ES 2225 3.53 50 -0.1210 73.9 303 + PVER EZ IAML 2225 4.69 259.7 0.38 73.9 303 + CML EZ EP 2224 54.98 77 50 -0.1410 74.8 300 + CML EZ ES 2225 4.11 50 0.2010 74.8 300 + FAC EZ EP 4 2224 56.89 71 43 0.75 0 83.1 297 + FAC EZ ES 2225 5.55 43 -0.1510 83.1 297 + PSAN EZ EP 2224 57.50 68 43 0.1010 93.0 300 + PSAN EZ ES 2225 8.31 43 0.4010 93.0 300 + PFET EZ EP 2224 57.99 66 43 0.1910 96.2 296 + PFET EZ ES 2225 8.56 43 -0.0410 96.2 296 + SET2 EZ EP 2224 58.55 70 43 0.3910 98.9 297 + SET2 EZ ES 2225 9.05 43 -0.1810 98.9 297 + SET4 EZ EP 2224 58.16 69 43 -0.1010 99.9 299 + SET4 EZ ES 2225 9.18 43 -0.2410 99.9 299 + + 2014 111 1337 24.9 LQ 37.605 -25.179 6.6 *AZO 14 0.2 2.0LAZO 2.3CAZO 1 + GAP=317 0.69 4.0 4.5 2.7 0.8869E+01 0.7143E+01 0.6380E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140111133724 I + OP: CVUA-IA/RC 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa da Povoacao,SZ13,FE95 405 3 + 2014-01-11-1336-29S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + FRA1 EZ EP 1337 28.15 104 -0.4910 21.6 315 + FRA1 EN ES 1337 31.78 104 0.3310 21.6 315 + FRA1 EZ IAML 1337 32.57 310.2 0.27 21.6 315 + MIRA EZ IP C 1337 28.96 30 104 0.2510 22.0 337 + MIRA EZ ES 1337 31.36 104 -0.2110 22.0 337 + PCNG EZ EP 1337 28.85 24 101 -0.5010 26.3 314 + PCNG EN ES 1337 32.76 101 0.0710 26.3 314 + PCNG EZ IAML 1337 33.38 37.6 0.14 26.3 314 + VIF EZ EP 1337 29.51 45 100 -0.0710 27.7 304 + VIF EN ES 1337 33.36 100 0.2610 27.7 304 + VIF EZ IAML 1337 34.08 245.8 0.17 27.7 304 + PRCH EZ EP 1337 30.08 29 63 0.2310 29.8 297 + PRCH EN ES 1337 33.42 63 -0.1510 29.8 297 + PRCH EZ IAML 1337 34.57 1059.5 0.33 29.8 297 + MESC EZ EP 1337 30.30 63 0.1510 31.4 312 + MESC EN ES 1337 34.14 63 0.0610 31.4 312 + MESC EZ IAML 1337 34.50 194.6 0.14 31.4 312 + LFA EZ EP 1337 30.59 31 63 0.2910 32.6 305 + PMAT EZ EP 1337 30.62 24 63 0.0810 34.8 312 + PMAT EN ES 1337 34.62 63 -0.1610 34.8 312 + PMAT EZ IAML 1337 35.76 173.7 0.20 34.8 312 + CMLA B1 ES 4 1337 33.99 63 -0.90 0 35.1 300 + CML EZ EP 1337 31.16 46 63 0.2710 37.2 300 + CML EZ ES 1337 35.29 63 -0.0910 37.2 300 + FAC EZ EP 1337 31.83 39 63 -0.2010 45.5 295 + FAC EZ ES 1337 36.98 63 -0.4110 45.5 295 + PSAN EZ EP 1337 33.25 30 63 -0.1710 55.4 300 + PSAN EZ ES 1337 40.11 63 0.2910 55.4 300 + PFET EZ E 1337 34.11 58.7 294 + PFET EZ ES 1337 40.74 63 0.1310 58.7 294 + SET2 EZ EP 1337 34.48 44 63 0.2210 61.3 296 + SET2 EZ ES 1337 41.03 63 -0.2610 61.3 296 + SET4 EZ E 1337 34.58 62.3 299 + SET4 EZ ES 1337 41.57 63 0.0810 62.3 299 + + 2014 114 0756 0.2 LQ 38.530 -29.435 0.0 *AZO 7 0.1 2.4LAZO 2.3CAZO 1 + GAP=344 0.36 6.4 8.4 6.1 -0.3015E+02 -0.4733E+02 0.1987E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140114075600 I + OP: CVUA-RC 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: W Faial,SZ31,FE95 405 3 + 2014-01-14-0755-37S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PTCA EZ EP 756 9.49 26 50 0.1610 55.9 84 + PTCA EN ES 756 16.27 50 0.0610 55.9 84 + PTCA EZ IAML 756 17.45 222.3 0.28 55.9 84 + PCTB EZ EP 756 9.85 31 50 -0.1010 60.5 90 + PCTB EN ES 756 17.15 50 -0.1410 60.5 90 + PCTB EZ IAML 756 18.81 194.3 0.14 60.5 90 + PCUT EN ES 756 18.19 50 0.0110 64.0 80 + PCUT EZ IAML 756 18.94 183.6 0.25 64.0 80 + PCND EN ES 756 23.06 43 -0.0910 85.1 94 + PCND EZ IAML 756 27.57 53.7 0.60 85.1 94 + PBOI EZ EP 756 14.21 33 43 -0.0710 93.0 96 + PBOI EN ES 756 25.00 43 0.1410 93.0 96 + PBOI EZ IAML 756 26.39 60.8 0.41 93.0 96 + PTEI EN ES 756 25.28 43 0.1110 94.1 92 + ROSA BE ES 4 756 26.52 43 -1.13 0 106 78 + PAMA EE ES 756 28.58 43 -0.0810 111 81 + + 2014 115 0550 8.7 LQ 37.476 -24.668 5.1 *AZO 14 0.3 2.3LAZO 2.1CAZO 1 + GAP=266 0.71 3.5 17.7 15.4 0.5281E+02 0.2528E+03 0.3904E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140115055008 I + OP: CVUA-RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa da Povoacao,SZ13,FE95 404 3 + 2014-01-15-0550-00S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + MIRA EZ ES 550 25.51 63 -0.4510 63.9 303 + FRA1 EN E 550 30.95 67.3 296 + PSPR EZ EP 550 19.20 21 63 0.1710 67.6 209 + PSPR EN ES 550 26.97 63 0.2010 67.6 209 + PSPR EZ IAML 550 27.68 66.4 0.22 67.6 209 + PCNG EN ES 550 27.49 53 -0.3110 71.9 297 + PVPO EZ EP 550 19.46 22 53 -0.1610 72.5 217 + PVPO EN ES 550 27.44 53 -0.3710 72.5 217 + PVPO EZ IAML 550 28.05 49.1 0.27 72.5 217 + VIF EN ES 550 28.87 53 0.5210 74.4 294 + PRCH EN ES 550 28.89 53 0.0710 77.0 292 + PRCH EZ IAML 550 30.14 115.1 0.37 77.0 292 + MESC EN ES 550 29.09 53 0.1010 77.1 297 + LFA EZ EP 550 20.58 22 53 0.0510 79.1 295 + PMAT EZ EP 550 20.51 53 -0.1010 80.3 298 + PMAT EZ IAML 550 29.39 65.1 0.16 80.3 298 + PMAT EN ES 550 29.47 53 -0.0810 80.3 298 + CMLA B2 ES 4 550 30.27 53 0.31 0 82.1 293 + CML EZ EP 550 21.22 27 53 0.1210 84.1 293 + FAC EZ ES 550 32.51 53 0.2410 92.8 291 + PSAN EZ E 550 35.07 102 294 + PFET EZ E 550 36.42 106 291 + + 2014 115 1021 18.1 LQ 38.714 -29.090 0.1 *AZO 8 0.2 2.0LAZO 2.2CAZO 1 + GAP=329 0.46 3.9 6.1 4.6 0.1389E+02 -0.2205E+02 -0.7152E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140115102118 I + OP: CVUA-AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: W Faial,SZ31,FE95 405 3 + 2014-01-15-1020-46S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PTCA EZ IP D 1021 23.13 40 59 -0.0310 29.3 119 + PTCA EN IS 1021 27.00 59 0.0410 29.3 119 + PTCA EZ IAML 1021 27.21 150.9 0.13 29.3 119 + PCUT EZ EP 1021 23.88 27 59 -0.0810 34.4 106 + PCUT EN IS 1021 28.25 59 -0.1110 34.4 106 + PCUT EZ IAML 1021 28.70 388.3 0.11 34.4 106 + PCTB EZ EP 1021 24.00 23 59 -0.2910 36.6 124 + PCTB EN ES 1021 29.13 59 0.1910 36.6 124 + PLGR EZ EP 1021 25.31 36 59 0.1110 42.2 109 + PLGR EN ES 1021 30.62 59 0.0910 42.2 109 + PLGR EZ IAML 1021 30.98 60.7 0.10 42.2 109 + PCND EN E 1021 36.15 61.1 116 + PTEI EZ IAML 1021 37.04 28.2 0.18 68.4 111 + PTEI EN ES 1021 37.09 50 -0.1910 68.4 111 + PBOI EN ES 1021 37.55 50 0.0610 69.5 116 + PBOI EZ IAML 1021 37.87 26.2 0.11 69.5 116 + ROSA BN ES 4 1021 36.96 50 -1.53 0 73.8 89 + PAMA EZ EP 1021 30.74 43 0.2710 79.3 92 + PAMA EN ES 1021 39.68 43 -0.0710 79.3 92 + PAMA EZ IAML 1021 40.35 86.0 0.24 79.3 92 + + 2014 115 1037 53.7 LQ 39.126 -28.466 10.6 *AZO 12 0.3 2.6LAZO 2.6CAZO 1 + GAP=251 0.90 13.1 4.6 21.8 0.3363E+02 0.7146E+02 0.2738E+03E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140115103753 I + OP: CVUA-AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: W Graciosa,SZ27,FE95 405 3 + 2014-01-15-1036-47S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PVIA EZ EP 1037 59.24 30 97 -0.1610 36.1 100 + PVIA EN IS 1038 3.84 97 0.1410 36.1 100 + PVIA EZ IAML 1038 4.13 97.3 0.23 36.1 100 + STGR EZ EP 1037 59.80 36 96 -0.2110 40.5 97 + STGR EN ES 1038 4.28 96 -0.4910 40.5 97 + STGR EZ IAML 1038 4.91 426.1 0.28 40.5 97 + PLUZ EZ EP 1038 1.00 35 95 0.5010 44.0 106 + PLUZ EN ES 1038 5.71 95 0.0910 44.0 106 + PLUZ EZ IAML 1038 6.67 342.2 0.31 44.0 106 + ROSA BN ES 4 1038 5.17 94 -1.73 0 49.1 157 + PAMA EZ EP 1038 2.27 57 64 0.2110 55.4 153 + PAMA EN ES 1038 8.20 64 -0.1510 55.4 153 + PAMA EZ IAML 1038 8.31 89.6 0.08 55.4 153 + PCUT EZ IP D 1038 2.39 33 64 -0.1410 59.3 201 + PCUT EN IS 1038 9.41 64 0.2310 59.3 201 + PCUT EZ IAML 1038 9.57 309.6 0.24 59.3 201 + PLGR EZ IP C 1038 2.56 43 64 -0.2210 61.0 194 + PLGR EN IS 1038 9.65 64 0.0310 61.0 194 + PLGR EZ IAML 1038 10.58 1597.1 0.22 61.0 194 + PTCA EZ EP 1038 3.38 45 64 -0.0610 66.5 206 + PTCA EN ES 1038 10.18 64 -0.5810 66.5 206 + PTCA EZ IAML 1038 10.43 196.8 0.26 66.5 206 + PCTB EZ EP 1038 3.70 30 64 -0.1910 70.3 200 + PCTB EN ES 1038 12.09 64 0.5410 70.3 200 + PCTB EZ IAML 1038 12.53 202.5 0.46 70.3 200 + PTEI EZ EP 1038 4.43 43 64 0.4110 70.6 172 + PTEI EN ES 1038 12.19 64 0.4010 70.6 172 + PTEI EZ IAML 1038 12.56 81.7 0.43 70.6 172 + PCND EZ EP 1038 4.29 55 64 0.0110 72.9 180 + PCND EZ IAML 1038 11.39 255.3 0.40 72.9 180 + PCND EN ES 1038 11.69 64 -0.5510 72.9 180 + PBOI EZ EP 1038 5.17 58 64 0.4010 76.9 174 + PBOI EN ES 1038 12.70 64 -0.4010 76.9 174 + PBOI EZ IAML 1038 13.27 56.8 0.11 76.9 174 + PIED EZ ES 1038 15.25 64 0.1810 86.2 155 + + 2014 121 0321 25.9 LQ 38.637 -29.115 7.2 *AZO 7 0.1 2.1LAZO 2.3CAZO 1 + GAP=338 0.37 4.4 5.2 4.9 0.5891E-02 -0.1925E+02 0.1545E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140121032125 I + OP: CVUA-IA/AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: W Faial,SZ31,FE95 405 3 + 2014-01-21-0321-03S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PTCA EZ IP D 321 30.77 33 63 0.1110 28.3 102 + PTCA EN ES 321 34.29 63 0.1010 28.3 102 + PTCA EZ IAML 321 34.99 143.3 0.23 28.3 102 + PCUT EN ES 321 35.95 63 0.0810 35.2 92 + PCUT EZ IAML 321 36.47 467.4 0.39 35.2 92 + PLGR EZ EP 321 32.57 34 63 -0.0810 42.4 97 + PLGR EN ES 321 37.45 63 -0.2210 42.4 97 + PLGR EZ IAML 321 38.11 68.7 0.25 42.4 97 + PCND EZ EP 321 35.04 32 63 -0.0410 59.8 108 + PCND EN ES 321 41.98 63 0.0510 59.8 108 + PCND EZ IAML 321 42.46 63.1 0.39 59.8 108 + PTEI EZ E 321 37.76 67.9 103 + PTEI EN ES 321 43.75 53 -0.1310 67.9 103 + PBOI EN ES 321 43.94 53 0.0610 68.2 109 + ROSA BN ES 4 321 44.37 53 -1.28 0 76.5 83 + PAMA EN ES 321 46.82 53 0.0710 81.5 86 + PAMA EZ IAML 321 47.72 103.4 0.25 81.5 86 + + 2014 122 0737 8.6 LQ 36.996 -24.214 17.4 *AZO 15 0.2 2.8LAZO 3.0CAZO 1 + GAP=312 0.64 5.2 11.8159.4 0.5013E+02 -0.1735E+04 -0.7225E+03E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140122073708 I + OP: CVUA-SA/RC 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Falha Gloria,SZ11,FE95 404 3 + 2014-01-22-0737-01S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PSPR EZ IP C 737 19.34 60 94 0.2610 73.4 266 + PSPR EN ES 737 26.83 94 -0.0810 73.4 266 + PSPR EZ IAML 737 28.09 233.0 0.27 73.4 266 + PVPO EZ IP C 737 20.43 64 93 0.0010 84.4 267 + PVPO EN ES 737 29.21 93 -0.0610 84.4 267 + PVPO EZ IAML 737 29.84 73.6 0.23 84.4 267 + MIRA EZ EP 737 25.79 49 92 -0.2710 129 313 + MIRA EZ ES 737 38.84 92 -0.2810 129 313 + FRA1 EN E 737 39.88 131 310 + PCNG EN E 737 41.52 135 310 + VIF EZ EP 737 26.85 49 92 -0.1910 137 308 + VIF EN ES 737 40.80 92 -0.0410 137 308 + VIF EZ IAML 737 40.89 40.7 0.28 137 308 + PRCH EN ES 737 40.90 92 -0.2210 139 306 + PRCH EZ IAML 737 41.93 248.5 0.34 139 306 + MESC EZ EP 737 27.56 50 92 0.0410 140 309 + MESC EN ES 737 42.01 92 0.3310 140 309 + MESC EZ IAML 737 43.14 45.2 0.66 140 309 + LFA EZ EP 737 27.61 54 92 -0.0510 142 308 + PMAT EN ES 737 42.78 92 0.5010 144 310 + PVER EN ES 737 42.62 92 -0.0110 146 308 + CML EZ EP 737 28.14 49 92 -0.0110 146 307 + CML EZ ES 737 42.92 92 0.1410 146 307 + FAC EZ ES 737 44.63 91 0.1810 154 305 + PSAN EZ EP 737 30.65 50 91 0.2310 164 306 + PFET EZ ES 737 46.85 91 -0.4510 167 304 + + 2014 122 1156 3.1 LQ 38.028 -25.812 0.0 *AZO 22 0.3 2.4LAZO 2.4CAZO 1 + GAP=174 0.84 2.0 2.3 3.1 0.2948E+01 -0.1306E+00 -0.2479E+01E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140122115603 I + OP: CVUA-RC/RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa Hirondelle,SZ18,FE95 405 3 + 2014-01-22-1155-18S_SWARM.SEI 6 + 2014-01-22-1156-01S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + SET4 EZ EP 1156 6.43 36 91 0.2310 17.0 176 + SET4 EZ ES 1156 8.83 91 0.3010 17.0 176 + SET2 EZ ES 1156 8.96 59 -0.6410 20.5 179 + PSAN EZ EP 1156 6.93 32 59 0.0410 21.0 159 + PSAN EZ ES 1156 10.19 59 0.4610 21.0 159 + PFET EZ IP C 1156 7.07 34 59 -0.1810 23.4 175 + PFET EZ ES 1156 10.19 59 -0.1810 23.4 175 + FAC EZ EP 1156 8.64 40 59 0.1210 31.6 153 + FAC EZ ES 1156 12.82 59 0.2410 31.6 153 + PVER EN ES 1156 14.26 59 0.3110 36.6 134 + PVER EZ IAML 1156 15.61 353.0 0.42 36.6 134 + CML EZ EP 1156 9.11 51 59 -0.2410 36.8 140 + CML EZ ES 1156 14.06 59 0.0210 36.8 140 + PMAT EZ IP C 1156 9.46 47 59 -0.0810 38.1 128 + PMAT EN ES 1156 14.72 59 0.3510 38.1 128 + PMAT EZ IAML 1156 15.90 599.4 0.39 38.1 128 + LFA EZ IP C 1156 9.70 59 -0.2510 40.4 134 + MESC EZ IP C 1156 9.90 40 59 -0.2110 41.4 129 + MESC EN ES 1156 15.66 59 0.2910 41.4 129 + MESC EZ IAML 1156 16.40 215.4 0.44 41.4 129 + PRCH EZ EP 1156 10.19 38 59 -0.3110 44.3 139 + PRCH EN ES 1156 15.63 59 -0.4310 44.3 139 + PRCH EZ IAML 1156 16.98 800.4 0.27 44.3 139 + VIF EZ EP 1156 10.69 37 59 -0.0210 45.3 134 + VIF EN ES 1156 16.33 59 -0.0910 45.3 134 + VIF EZ IAML 1156 17.18 160.3 0.20 45.3 134 + PCNG EN ES 1156 17.03 59 0.2610 46.6 128 + MIRA EZ EP 1156 11.66 50 -0.4110 54.0 120 + MIRA EZ E 1156 17.57 54.0 120 + PVPO EE E 1156 35.01 132 154 + PFAV EZ E 1156 40.37 135 305 + PRIB EN ES 1156 37.29 43 -0.4910 139 301 + PSPR EE E 1156 37.06 139 150 + PVNV EN ES 1156 38.91 43 0.2810 143 305 + PPAD EN ES 1156 40.12 43 0.1310 149 301 + PBIS EN E 1156 40.31 150 303 + ASBA EN ES 1156 41.53 43 0.4910 153 301 + + 2014 123 0244 55.0 LQ 38.098 -26.435 0.0 *AZO 16 0.2 2.2LAZO 2.5CAZO 1 + GAP=193 0.67 12.7 11.0 3.5 0.1387E+03 -0.2793E+02 -0.3228E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140123024455 I + OP: CVUA-AP/RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: Fossa Hirondelle,SZ18,FE95 405 3 + 2014-01-23-0244-46S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + SET4 EZ EP 245 4.66 35 50 -0.2110 61.1 114 + SET4 EZ ES 245 12.24 50 -0.0610 61.1 114 + SET2 EZ EP 245 4.95 33 50 -0.0610 62.0 117 + SET2 EZ ES 245 12.89 50 0.3510 62.0 117 + PFET EZ EP 245 5.12 36 50 -0.2510 64.7 119 + PFET EZ ES 245 13.66 50 0.4910 64.7 119 + PSAN EZ EP 245 5.74 34 50 -0.0910 68.0 114 + PSAN EZ ES 245 13.87 50 -0.1210 68.0 114 + FAC EZ EP 245 7.43 33 43 0.3010 77.8 117 + FAC EZ ES 245 16.00 43 -0.2510 77.8 117 + CML EZ EP 245 8.04 30 43 -0.1510 86.1 115 + CML EZ ES 245 17.88 43 -0.2210 86.1 115 + PVER EZ EP 245 8.21 33 43 -0.1310 87.5 112 + PVER EN ES 245 18.50 43 0.1310 87.5 112 + PVER EZ IAML 245 19.46 36.1 0.33 87.5 112 + CMLA BZ EP 9 245 7.46 34 43 -0.99 0 88.2 115 + CMLA B2 ES 245 17.72 0.1410 88.2 115 + PMAT EZ EP 245 8.54 37 43 -0.1610 90.3 110 + PMAT EN ES 245 19.16 43 0.1610 90.3 110 + PRIB EZ EP 245 8.67 31 43 -0.0910 90.6 315 + PRIB EN ES 245 19.03 43 -0.0810 90.6 315 + PRIB EZ IAML 245 19.52 107.9 0.11 90.6 315 + LFA EZ EP 245 8.47 32 43 -0.3910 91.1 113 + LFA EZ ES 245 19.58 43 0.3010 91.1 113 + MESC EZ EP 245 8.90 34 43 -0.2510 93.3 111 + MESC EN ES 245 19.81 43 0.0310 93.3 111 + MESC EZ IAML 245 20.14 22.7 0.56 93.3 111 + PRCH EN ES 245 19.89 43 0.2010 93.4 116 + PVNV EZ EP 245 9.30 34 43 -0.2210 96.9 320 + PVNV EN ES 245 20.23 43 -0.2110 96.9 320 + PVNV EZ IAML 245 21.15 56.3 0.09 96.9 320 + PPAD EZ EP 245 10.42 30 43 0.4810 100 312 + PPAD EN ES 245 21.42 43 0.2610 100 312 + PPAD EZ IAML 245 22.29 22.1 0.25 100 312 + ASBA EN ES 245 22.43 43 0.2410 104 312 + ASBA EZ IAML 245 24.22 31.4 0.09 104 312 + + 2014 123 0949 25.0 LQ 37.229 -24.555 33.9 *AZO 14 0.3 2.6LAZO 2.8CAZO 1 + GAP=279 0.93 5.9 18.7 31.3 0.9577E+02 -0.5305E+03 -0.1659E+03E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140123094925 I + OP: CVUA-IA/RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: E Ilheus das Formigas,SZ13,FE95 404 3 + 2014-01-23-0949-09S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PSPR EZ IP C 949 33.50 53 118 -0.0810 53.3 233 + PSPR EN ES 949 40.44 118 0.4310 53.3 233 + PSPR EZ IAML 949 41.13 181.0 0.17 53.3 233 + PVPO EZ IP C 949 34.21 48 114 -0.3010 61.8 241 + PVPO EN ES 949 41.36 114 -0.2810 61.8 241 + PVPO EZ IAML 949 42.41 53.2 0.36 61.8 241 + MIRA EZ EP 949 37.27 40 106 -0.5310 88.9 314 + MIRA EZ ES 949 46.77 106 -0.6210 88.9 314 + FRA1 EN ES 949 47.83 106 0.1210 90.7 309 + PCNG EN ES 949 49.10 105 0.4010 95.3 309 + VIF EZ EP 949 39.08 48 105 0.3310 96.9 307 + VIF EN ES 949 49.36 105 0.3010 96.9 307 + VIF EZ IAML 949 49.60 65.6 0.38 96.9 307 + PRCH EZ EP 949 39.15 58 104 0.2310 98.8 304 + PRCH EN ES 949 49.15 104 -0.1910 98.8 304 + PRCH EZ IAML 949 49.98 171.3 0.23 98.8 304 + MESC EZ EP 949 39.31 46 104 0.1010 101 309 + MESC EN ES 949 50.24 104 0.3810 101 309 + MESC EZ IAML 949 50.79 71.9 0.45 101 309 + LFA EZ EP 949 39.59 53 104 0.2410 102 307 + LFA EZ ES 949 49.83 104 -0.2810 102 307 + PMAT EN ES 949 50.73 103 0.2910 104 309 + PMAT EZ IAML 949 51.41 87.4 0.25 104 309 + CMLA B2 ES 4 949 48.90 103 -1.62 0 104 305 + CML EZ EP 949 39.87 47 103 0.0310 106 305 + CML EZ ES 949 50.38 103 -0.5710 106 305 + FAC EZ E 949 52.85 114 302 + PSAN EZ ES 4 949 55.79 101 0.94 0 124 304 + PFET EZ E 949 53.55 127 301 + SET2 EZ E 949 47.07 130 302 + + 2014 126 0117 25.6 LQ 38.334 -26.843 8.1 *AZO 19 0.4 2.2LAZO 2.0CAZO 1 + GAP=195 1.17 10.7 12.6 10.1 0.1311E+03 -0.6700E+02 -0.4421E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140126011725 I + OP: CVUA-RC 3 + STATUS: OK 3 + PUB: NAO 3 + WEB: SIM 3 + REGIAO: SE Terceira,SZ20,FE95 405 3 + 2014-01-26-0116-58S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PFAV EZ EP 117 32.38 22 63 -0.4010 46.9 333 + PFAV EN ES 117 38.64 63 0.4410 46.9 333 + PFAV EZ IAML 117 40.88 74.8 0.09 46.9 333 + PRIB EZ EP 117 32.74 23 63 -0.1310 47.3 323 + PRIB EN ES 117 38.73 63 0.3910 47.3 323 + PRIB EZ IAML 117 39.35 173.9 0.16 47.3 323 + PVNV EZ EP 117 33.38 23 63 -0.5110 54.8 330 + PVNV EN ES 117 39.93 63 -0.2010 54.8 330 + PVNV EZ IAML 117 42.88 77.9 0.14 54.8 330 + PPAD EZ EP 117 33.54 22 63 -0.5610 56.2 317 + PPAD EN ES 117 40.81 63 0.3210 56.2 317 + PPAD EZ IAML 117 42.64 260.5 0.19 56.2 317 + PBIS EN ES 117 41.19 63 -0.1110 59.4 323 + PBIS EZ IAML 117 42.34 107.8 0.17 59.4 323 + ASBA EZ EP 117 34.45 63 -0.2810 60.5 315 + ASBA EN ES 117 41.79 63 0.1910 60.5 315 + ASBA EZ IAML 117 43.42 125.9 0.31 60.5 315 + SET4 EZ ES 117 51.18 53 -0.1410 105 119 + PIED EZ E 117 44.70 106 275 + SET2 EZ ES 117 51.74 53 0.1410 106 121 + PFET EZ E 117 42.09 109 121 + PSAN EZ ES 117 52.50 53 -0.3310 112 118 + FAC EZ ES 117 54.86 53 -0.1210 122 120 + PVER EE E 117 57.41 131 117 + PMAT EN ES 117 57.31 53 -0.2310 133 115 + LFA EZ EP 117 44.80 53 0.7510 135 117 + MESC EN ES 117 57.87 53 -0.4810 136 116 + PRCH EN E 117 59.16 137 119 + VIF EE E 118 1.08 139 117 + MIRA EZ EP 117 47.14 53 1.1410 150 113 + MIRA EZ ES 118 1.43 53 0.1110 150 113 + + 2014 126 0117 49.3 LQ 38.314 -26.853 1.0 *AZO 21 0.3 2.5LAZO 2.6CAZO 1 + GAP=197 0.86 6.8 8.2 3.9 0.5466E+02 -0.1542E+02 -0.1079E+02E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140126011749 I + OP: CVUA-RC 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: SE Terceira,SZ20,FE95 405 3 + 2014-01-26-0116-58S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PFAV EZ EP 117 57.55 41 59 0.2610 48.5 335 + PFAV EE ES 118 3.60 59 0.3310 48.5 335 + PFAV EZ IAML 118 4.31 172.0 0.16 48.5 335 + PRIB EZ EP 117 57.69 50 59 0.3710 48.6 325 + PRIB EN ES 118 3.41 59 0.0910 48.6 325 + PRIB EZ IAML 118 4.20 304.6 0.16 48.6 325 + PVNV EZ EP 117 58.03 48 50 -0.4010 56.4 332 + PVNV EN ES 118 4.75 50 -0.5110 56.4 332 + PVNV EZ IAML 118 7.34 137.1 0.17 56.4 332 + PPAD EZ IP C 117 58.45 40 50 -0.1210 57.3 319 + PPAD EN ES 118 5.56 50 0.0510 57.3 319 + PPAD EZ IAML 118 8.34 373.2 0.16 57.3 319 + PBIS EN ES 118 6.23 50 -0.1510 60.7 325 + PBIS EZ IAML 118 8.64 155.8 0.19 60.7 325 + ASBA EN ES 118 6.77 50 0.1710 61.5 317 + ASBA EZ IAML 118 8.69 272.3 0.19 61.5 317 + SET4 EZ EP 118 4.62 36 43 -0.1110 104 117 + SET4 EZ ES 118 16.40 43 0.1210 104 117 + PIED EZ E 118 9.73 106 277 + SET2 EZ EP 118 4.98 42 43 0.1110 106 119 + SET2 EZ ES 118 16.43 43 -0.1110 106 119 + PFET EZ EP 118 5.39 29 43 0.1910 108 120 + PFET EZ ES 118 17.38 43 0.2610 108 120 + PSAN EZ EP 118 5.48 30 43 -0.1110 111 117 + PSAN EZ ES 118 17.05 43 -0.7410 111 117 + FAC EZ ES 118 20.42 43 0.5010 121 119 + CML EZ ES 118 22.33 43 0.6010 130 117 + PVER EN ES 118 21.72 43 -0.2310 131 116 + PVER EZ IAML 118 23.02 59.4 0.42 131 116 + PMAT EN ES 118 22.94 43 0.4210 133 114 + PMAT EZ IAML 118 24.45 47.4 0.16 133 114 + LFA EZ EP 118 8.50 41 43 0.0010 134 116 + MESC EZ EP 118 8.55 36 43 -0.2110 136 115 + MESC EN ES 118 23.11 43 -0.2210 136 115 + PRCH EE ES 118 22.97 43 -0.3610 137 118 + VIF EN ES 118 24.06 43 0.1410 139 116 + PCNG EN E 118 25.51 142 115 + MIRA EZ EP 118 10.16 39 43 -0.3110 150 112 + + 2014 127 1050 49.6 RQ 39.424 -29.951 10.6 *AZO 16 0.3 3.3LAZO 3.4CAZO 1 + GAP=330 0.86 69.5 171.5302.4 -0.1183E+05 -0.5180E+05 0.2093E+05E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140127105049 I + OP: CVUA-BC/RS 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + OBS: Sismo sem qualidade para calculo MW 3 + REGIAO: Crista Media Atlantica,SZ32,FE95 405 3 + 2014-01-27-1050-32S_SWARM.SEI 6 + 2014-01-27-1050-33S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PTCA EZ EP 1051 8.05 48 64 -0.1210 137 133 + PCUT EN E 1051 22.08 139 129 + PCTB EN ES 1051 24.04 64 0.3210 144 133 + PLGR EZ EP 1051 9.18 51 64 -0.3210 147 129 + PLGR EN ES 1051 23.50 64 -0.8910 147 129 + PLGR EZ IAML 1051 25.05 310.0 0.28 147 129 + PCND EZ EP 1051 12.06 82 64 0.0510 167 129 + PCND EN ES 1051 28.72 64 -0.0710 167 129 + ROSA BZ EP 9 1051 10.64 71 64 -1.37 0 167 117 + ROSA BN ES 1051 27.64 0.2210 167 117 + PCND EZ IAML 1051 30.10 115.6 0.26 167 129 + PVIA EE ES 1051 28.76 64 -0.1810 168 103 + PTEI EZ EP 1051 12.68 66 64 -0.0310 172 126 + PTEI EZ IAML 1051 32.57 227.7 0.59 172 126 + STGR EN E 1051 28.60 172 102 + PTEI EN ES 1051 30.20 64 0.1810 172 126 + PAMA EZ E 1051 17.05 174 118 + PBOI EZ EP 1051 13.25 72 64 0.2310 175 128 + PBOI EN ES 1051 31.06 64 0.5010 175 128 + PBOI EZ IAML 1051 32.34 79.8 0.28 175 128 + PLUZ EE E 1051 29.98 176 104 + PPAD EZ EP 1051 21.80 64 0.1910 244 108 + PVNV EZ EP 1051 22.72 49 64 0.0610 253 106 + PRIB EZ EP 1051 22.77 50 64 -0.1510 255 108 + PFAV EZ EP 1051 23.86 57 64 0.2410 260 107 + + 2014 129 1950 45.0 LQ 37.276 -24.604 0.0 *AZO 12 0.3 2.2LAZO 2.6CAZO 1 + GAP=272 0.94 4.5 42.0 27.5 -0.1606E+03 0.1136E+04 -0.1079E+03E + ACTION:UPD 24-11-22 11:01 OP:RS STATUS: ID:20140129195045 I + OP: CVUA-BC/AR 3 + STATUS: OK 3 + PUB: EPI 3 + WEB: SIM 3 + REGIAO: E Ilheus das Formigas,SZ10,FE95 404 3 + 2014-01-29-1950-17S_SWARM.SEI 6 + STAT SP IPHASW D HRMM SECON CODA AMPLIT PERI AZIMU VELO AIN AR TRES W DIS CAZ7 + PSPR EZ IP C 1950 53.77 48 50 -0.0210 53.3 226 + PSPR EE ES 1951 0.94 50 0.5410 53.3 226 + PSPR EZ IAML 1951 1.45 70.6 0.14 53.3 226 + PVPO EZ EP 1950 54.42 44 50 -0.4010 60.9 234 + PVPO EN ES 1951 1.85 50 -0.3610 60.9 234 + PVPO EZ IAML 1951 2.72 36.4 0.12 60.9 234 + MIRA EZ ES 1951 6.99 43 -0.3810 82.2 314 + FRA1 EZ EP 1950 57.55 30 43 -0.4210 84.1 308 + FRA1 EN ES 1951 7.73 43 0.0110 84.1 308 + PCNG EN E 1951 9.55 88.7 308 + VIF EN ES 1951 9.55 43 0.4210 90.4 305 + PRCH EZ EP 1950 59.47 34 43 0.5110 92.3 303 + PRCH EN ES 1951 9.38 43 -0.0710 92.3 303 + PRCH EZ IAML 1951 10.33 143.0 0.31 92.3 303 + MESC EZ EP 1950 59.46 45 43 0.2110 94.0 308 + MESC EN ES 1951 10.38 43 0.4310 94.0 308 + LFA EZ EP 1950 59.65 43 43 0.2510 95.3 306 + LFA EZ E 1951 9.51 95.3 306 + PMAT EN ES 1951 10.46 43 -0.0810 97.3 308 + CMLA B2 ES 4 1951 9.71 43 -0.95 0 97.7 304 + CML EZ EP 1950 59.67 45 43 -0.2310 99.8 304 + CML EZ ES 1951 10.69 43 -0.4110 99.8 304 + FAC EZ E 1951 13.79 108 301 + diff --git a/utils/filters.py b/utils/filters.py new file mode 100644 index 0000000..b29fc88 --- /dev/null +++ b/utils/filters.py @@ -0,0 +1,108 @@ +import pandas as pd +from datetime import datetime +import os +import sys + + +def filter_by_date(df: pd.DataFrame, start_date: str, end_date: str) -> pd.DataFrame: + # filtra o dataframe por intervalo de datas (strings em formato ISO) + mask = (df['Data'] >= start_date) & (df['Data'] <= end_date) + return df.loc[mask] + +def filter_by_depth(df: pd.DataFrame, min_depth: float, max_depth: float) -> pd.DataFrame: + mask = (df['Profundidade'] >= min_depth) & (df['Profundidade'] <= max_depth) + return df.loc[mask] + +def filter_by_magnitude(df: pd.DataFrame, min_mag: float, max_mag: float, mag_type: str = 'L') -> pd.DataFrame: + def filter_mag(mags): + # Filtrar por tipo de magnitude específico + vals = [float(m['Magnitude']) for m in mags if m.get('Tipo') == mag_type] + if not vals: + return False + # Se houver múltiplas magnitudes do mesmo tipo, usa o máximo para filtragem + mx = max(vals) + return min_mag <= mx <= max_mag + + mask = df['Magnitudes'].apply(filter_mag) + return df.loc[mask] + +# -- t7 filters + +def filter_by_gap(df: pd.DataFrame, max_gap: float) -> pd.DataFrame: + # Filtra onde Gap <= max_gap + return df[df['Gap'] <= max_gap] + +def filter_by_quality(df: pd.DataFrame, quality: str) -> pd.DataFrame: + return df[df['Pub'] == quality] + +def filter_by_zone(df: pd.DataFrame, zone_type: str, zone_val: str) -> pd.DataFrame: + return df[df[zone_type] == zone_val] + +FILTER_MENU = """[1] Filtrar por Data (Inicio:Fim) +[2] Filtrar por Gap (< Valor) +[3] Filtrar por Qualidade (EPI) +[4] Filtrar por Zona SZ +[5] Filtrar por Zona VZ +[6] Filtrar por Magnitude (Min:Max) +[7] Filtrar por Profundidade (Min:Max) +[R] Reset Filtros + +[Q] Voltar +""" + +def filter_menu(db: pd.DataFrame, original_db: pd.DataFrame): + currDb = db + + while True: + os.system("cls" if sys.platform == "windows" else "clear") + print("=== T7: Filtros ===") + print(f"Linhas actuais: {len(currDb)}") + print(FILTER_MENU) + usrIn = input("Opção: ").lower() + + + match usrIn: + case "1": + start = input("Data Inicio (YYYY-MM-DD): ") + end = input("Data Fim (YYYY-MM-DD): ") + currDb = filter_by_date(currDb, start, end) + + case "2": + val = float(input("Gap Máximo: ")) + currDb = filter_by_gap(currDb, val) + + + case "3": + confirm = input("Filtrar apenas eventos com Qualidade EPI? (s/n): ").lower() + if confirm == 's': + currDb = filter_by_quality(currDb, "EPI") + else: + print("Filtro não aplicado.") + + case "4": + val = input("Zona SZ (ex: SZ31): ") + currDb = filter_by_zone(currDb, "SZ", val) + + case "5": + val = input("Zona VZ (ex: VZ14): ") + currDb = filter_by_zone(currDb, "VZ", val) + + case "6": + print("Filtrar por Magnitude Tipo 'L'") + min_m = float(input("Min Mag L: ")) + max_m = float(input("Max Mag L: ")) + + currDb = filter_by_magnitude(currDb, min_m, max_m, "L") + + case "7": + min_d = float(input("Min Profundidade: ")) + max_d = float(input("Max Profundidade: ")) + currDb = filter_by_depth(currDb, min_d, max_d) + + case "r": + currDb = original_db.copy() + + case "q": + return currDb + case _: + pass \ No newline at end of file diff --git a/utils/parser.py b/utils/parser.py index ecaba9b..1d1c4e7 100644 --- a/utils/parser.py +++ b/utils/parser.py @@ -1,54 +1,49 @@ -# pyright: basic import io + from collections import defaultdict from datetime import datetime import pandas as pd -# --- globals --- +# --- variáveis globais --- DIST_IND = {"L": "Local", "R": "Regional", "D": "Distante"} TYPE = {"Q": "Quake", "V": "Volcanic", "U": "Unknown", "E": "Explosion"} -# --- helper funcs --- +# --- funções auxiliares --- def is_blank(l: str) -> bool: return len(l.strip(" ")) == 0 - -def parse_flt(v: str) -> float | None: +def parse_flt(v:str) -> float | None: try: t = float(v) return t except ValueError: return None - -def parse_int(v: str) -> int | None: +def parse_int(v:str) -> int | None: try: t = int(v) return t except ValueError: return None - def into_dataframe(data) -> pd.DataFrame: if len(data) == 0: return pd.DataFrame() aux = {k: [] for k in data.keys()} - for k, v in data.items(): + for (k,v) in data.items(): aux[k].append(v) return pd.DataFrame(data=aux) - def _concat(preamble, df: pd.DataFrame): - for k, v in preamble.items(): - df.insert(len(df.columns) - 1, k, [v for _ in range(len(df))]) + for (k,v) in preamble.items(): + df.insert(len(df.columns)-1, k, [v for _ in range(len(df))]) return df - -def validate_no_stations(expected: int, stationsDF: pd.DataFrame) -> bool: +def validate_no_stations(expected:int , stationsDF:pd.DataFrame) -> bool: uniqueStations = stationsDF["Estacao"].nunique() return expected == uniqueStations @@ -59,31 +54,29 @@ def parse(fname): data = [l for l in fp.read().split("\n")] chunks = boundaries(data) df = pd.DataFrame() - for idx, c in enumerate(chunks): - a = parse_chunk(data[c[0] : c[1]]) + for (idx,c) in enumerate(chunks): + a = parse_chunk(data[c[0]:c[1]]) aux = pd.concat([df, a], axis=0, ignore_index=True) df = aux fp.close() return df - def boundaries(data: list[str]): boundaries = [] start = None - for idx, l in enumerate(data): + for (idx,l) in enumerate(data): if start is None: if not is_blank(l): start = idx else: if is_blank(l): - boundaries.append((start, idx)) + boundaries.append((start,idx)) start = None return boundaries - def parse_chunk(chunk_lines: list[str]): hIdx = None - for idx, l in enumerate(chunk_lines): + for (idx, l) in enumerate(chunk_lines): if l[-1] == "7": hIdx = idx break @@ -95,7 +88,6 @@ def parse_chunk(chunk_lines: list[str]): return _concat(preambleRet, phaseRet) - def _parse_preamble(hLines: list[str]): aux = defaultdict(list) @@ -118,7 +110,7 @@ def _parse_preamble(hLines: list[str]): pass headerDict = dict() - for k, v in aux.items(): + for (k,v) in aux.items(): if len(v) != 0: headerDict.update(FUNCS[k](v)) return headerDict @@ -133,7 +125,7 @@ def _parse_type_1(data: list[str]): m = int(aux[13:15]) s = int(aux[16:18]) mil = int(aux[19]) * 10**5 - dt = datetime(y, mo, d, h, m, s, mil) + dt = datetime(y,mo,d,h,m,s,mil) dist_ind = DIST_IND[aux[21]] ev_type = TYPE[aux[22]] @@ -142,28 +134,18 @@ def _parse_type_1(data: list[str]): depth = float(aux[38:43]) no_stat = int(aux[48:51]) - hypo = { - "Data": dt.isoformat(), - "Distancia": dist_ind, - "Tipo Evento": ev_type, - "Latitude": lat, - "Longitude": long, - "Profundidade": depth, - "Estacoes": no_stat, - "Magnitudes": list(), - } + hypo = {"Data": dt.isoformat(), "Distancia": dist_ind, "Tipo Evento": ev_type, "Latitude": lat, "Longitude": long, "Profundidade": depth, "Estacoes": no_stat, "Magnitudes": list()} for l in data: hypo["Magnitudes"] = hypo["Magnitudes"] + _parse_mag(l) return hypo - def _parse_mag(line: str): magnitudes = [] base = 55 while base < 79: - m = line[base : base + 4] - mt = line[base + 4] + m = line[base:base+4] + mt = line[base+4] if not is_blank(m): magnitudes.append({"Magnitude": m, "Tipo": mt}) base += 8 @@ -173,23 +155,22 @@ def _parse_mag(line: str): def _parse_type_3(data: list[str]): comments = {} for line in data: - if line.startswith(" SENTIDO"): + if line.startswith(" SENTIDO") or line.startswith(" REGIAO") or line.startswith(" PUB"): c, v = line[:-2].strip().split(": ", maxsplit=1) - v = v.split(",")[0] - comments[c.capitalize()] = v - - elif line.startswith(" REGIAO"): - c, vals = line[:-2].strip().split(": ", maxsplit=1) - _d = {} - for v in vals.split(","): - if v.startswith("SZ"): - comments["SZ"] = int(v[2:]) - elif v.startswith("VZ"): - comments["VZ"] = int(v[2:]) - elif v.startswith("FE"): - comments["FZ"] = v[2:] - else: - comments["Regiao"] = v + + if c == "REGIAO": + parts = v.split(",") + comments["Regiao"] = parts[0].strip() + for p in parts[1:]: + p = p.strip() + if "SZ" in p: + comments["SZ"] = p + elif "VZ" in p: + comments["VZ"] = p + elif c == "PUB": + comments["Pub"] = v.strip() + else: + comments[c.capitalize()] = v.split(",")[0] return comments @@ -203,59 +184,21 @@ def _parse_type_6(data: list[str]): def _parse_type_7(data: list[str]): aux = io.StringIO("\n".join(data)) - dados = pd.read_fwf( - aux, - colspecs=[ - (1, 5), - (6, 8), - (10, 15), - (18, 20), - (20, 22), - (23, 28), - (34, 38), - (71, 75), - ], - ) - dados.rename( - columns={ - "STAT": "Estacao", - "SP": "Componente", - "PHASW": "Tipo Onda", - "HR": "Hora", - "MM": "Min", - "SECON": "Seg", - "AMPL": "Amplitude", - " DIST": "Distancia Epicentro", - }, - inplace=True, - ) + dados = pd.read_fwf(aux, colspecs=[(1,5), (6,8),(10,15), (18,20), (20,22), (23,28), (34,38), (71,75)]) + dados.rename(columns={'STAT': "Estacao", 'SP': "Componente" , 'PHASW': "Tipo Onda", 'HR': "Hora", 'MM': "Min", 'SECON': "Seg", 'AMPL': "Amplitude", " DIST": "Distancia Epicentro"}, inplace=True) return dados def _parse_type_e(data: list[str]): aux = data[0] - error = { - "Gap": int(aux[5:8]), - "Origin": float(aux[14:20]), - "Error_lat": float(aux[24:30]), - "Error_long": float(aux[32:38]), - "Error_depth": float(aux[38:43]), - "Cov_xy": float(aux[43:55]), - "Cov_xz": float(aux[55:67]), - "Cov_yz": float(aux[67:79]), - } + error = {"Gap": int(aux[5:8]), "Origin": float(aux[14:20]), "Error_lat": float(aux[24:30]), "Error_long": float(aux[32:38]), "Error_depth": float(aux[38:43]), "Cov_xy": float(aux[43:55]), "Cov_xz": float(aux[55:67]), "Cov_yz": float(aux[67:79])} return error def _parse_type_i(data: list[str]): aux = data[0] - return {"ID": int(aux[60:74])} + return {"ID":int(aux[60:74])} -FUNCS = { - 1: _parse_type_1, - 3: _parse_type_3, - 6: _parse_type_6, - "E": _parse_type_e, - "I": _parse_type_i, -} +FUNCS = {1: _parse_type_1, 3: _parse_type_3, 6: _parse_type_6, "E": _parse_type_e, "I": _parse_type_i} + diff --git a/utils/stats.py b/utils/stats.py index bc32450..904bd1c 100644 --- a/utils/stats.py +++ b/utils/stats.py @@ -1,176 +1,321 @@ -# pyright: basic +import os +import sys -import datetime - -import numpy as np import pandas as pd -import utils +import numpy as np + +STAT_HEADER ="""=== Terramotos === + == Estatísticas == +""" + +STAT_MENU = """[1] Média +[2] Variância +[3] Desvio padrão +[4] Máximo +[5] Mínimo +[6] Moda +[T] Estatísticas Temporais (T5) + +[Q] Voltar ao menu principal +""" + +FILTER_CHOICES = """[1] Magnitudes +[2] Distância +[3] Profundidade + +""" + +CHOICE = {"1": "Magnitudes", "2": "Distancia","3": "Profundidade"} -def stats(df: pd.DataFrame) -> None: - """Estatisticas para a DataFrame - :param df: DataFrame em questão""" +def filter_submenu(type: str): + os.system("cls" if sys.platform == "windows" else "clear") + print(f"{STAT_HEADER}\n = {type} = ") + print(FILTER_CHOICES) - mags = mags_avg_std(df) - depth = depth_avg_std(df) + choice = input("Qual dos valores: ") - median_mags = median_mags(df) + try: + usrChoice = CHOICE[choice] + return usrChoice + except KeyError: + return None -def mags_avg_std(data: pd.DataFrame) -> tuple[np.floating, np.floating]: - """Media e desvio-padrao das magnitudes - :param data: Dataframe com dados a filtrar - :returns: Tuple com a media e desvio-padrao - """ - filtered_data: pd.DataFrame = filter_mags(data) - vals = filtered_data["MagL"].to_numpy() - return (np.average(vals), np.std(vals)) + +# -- t5 funcs + +def _get_unique_events(df: pd.DataFrame) -> pd.DataFrame: + return df.drop_duplicates(subset="ID", keep='first') + +def convert_to_datetime(df: pd.DataFrame) -> pd.DataFrame: + # Converte coluna Data para objetos datetime + df = df.copy() + df['Data'] = pd.to_datetime(df['Data'], format='mixed') + return df + +def events_per_period(df: pd.DataFrame, period: str): + # Calcula o número de eventos por dia ('D') ou mês ('M') + df = convert_to_datetime(df) + events = _get_unique_events(df) + + if period == 'M': + period = 'ME' + + res = events.set_index('Data').resample(period).size() + return res.index, res.values + +def stats_depth_month(df: pd.DataFrame): + # Calcula estatísticas de Profundidade por Mês + df = convert_to_datetime(df) + events = _get_unique_events(df) + + grouped = events.set_index('Data').resample('ME')['Profundidade'] + + stats_df = pd.DataFrame({ + 'Mean': grouped.mean(), + 'Std': grouped.std(), + 'Median': grouped.median(), + 'Q1': grouped.quantile(0.25), + 'Q3': grouped.quantile(0.75), + 'Min': grouped.min(), + 'Max': grouped.max() + }) + return stats_df + +def stats_mag_month(df: pd.DataFrame): + # Calcula estatísticas de Magnitude por Mês + df = convert_to_datetime(df) + events = _get_unique_events(df) + + def get_max_mag(mags): + vals = [float(m['Magnitude']) for m in mags if 'Magnitude' in m] + return max(vals) if vals else np.nan + + events = events.copy() + events['MaxMag'] = events['Magnitudes'].apply(get_max_mag) + + grouped = events.set_index('Data').resample('ME')['MaxMag'] + + stats_df = pd.DataFrame({ + 'Mean': grouped.mean(), + 'Std': grouped.std(), + 'Median': grouped.median(), + 'Q1': grouped.quantile(0.25), + 'Q3': grouped.quantile(0.75), + 'Min': grouped.min(), + 'Max': grouped.max() + }) + return stats_df -def depth_avg_std(data: pd.DataFrame) -> tuple[np.floating, np.floating]: - """Media e desvio-padrao das profundidades - :param data: Dataframe com dados a filtrar - :returns: Tuple com a media e desvio-padrao - """ - filtered_data: pd.DataFrame = filter_depth(data) - vals = np.average(filtered_data["Profundidade"].to_numpy()) - return (np.average(vals), np.std(vals)) +# -- t5 menu + +T5_MENU = """[1] Número de eventos por dia +[2] Número de eventos por mês +[3] Estatísticas Profundidade por mês +[4] Estatísticas Magnitude por mês + +[Q] Voltar +""" + +def t5_menu(df: pd.DataFrame): + while True: + os.system("cls" if sys.platform == "windows" else "clear") + print(STAT_HEADER + "\n" + " == T5: Estatísticas Temporais ==\n" + T5_MENU) + usrIn = input("Opção: ").lower() + + match usrIn: + case "1": + dates, counts = events_per_period(df, 'D') + print("\nEventos por Dia:") + print(pd.DataFrame({'Data': dates, 'Contagem': counts}).to_string(index=False)) + + case "2": + dates, counts = events_per_period(df, 'M') + print("\nEventos por Mês:") + print(pd.DataFrame({'Data': dates, 'Contagem': counts}).to_string(index=False)) + + case "3": + st = stats_depth_month(df) + print("\nEstatísticas Profundidade por Mês:") + print(st.to_string()) + + case "4": + st = stats_mag_month(df) + print("\nEstatísticas Magnitude por Mês:") + print(st.to_string()) + + case "q": + return + case _: + pass + + input("\n[Enter] para continuar...") -def median_mags(data: pd.DataFrame): - filtered_data: pd.DataFrame = filter_mags(data) - vals = sorted(filtered_data["MagL"].to_numpy()) +# -- stat menu - quartil = len(vals) // 4 +def stat_menu(df: pd.DataFrame): + inStats = True + while inStats: + os.system("cls" if sys.platform == "windows" else "clear") + print(STAT_HEADER + "\n" + STAT_MENU) + usrIn = input("Opção: ").lower() - return ( - filtered_data[quartil, :]["MagL"], - filtered_data[quartil * 2, :]["MagL"], - filtered_data[quartil * 3, :]["MagL"], - ) + match usrIn: + case "t": + t5_menu(df) + continue + + case "1": + c = filter_submenu("Média") + + if c is not None: + retValue = average(df, c) + if retValue: + print(f"A média de {c} é {retValue}") + else: + print("Um erro aconteceu. Nada a apresentar de momento.") + else: + continue + + case "2": + c = filter_submenu("Variância") + + if c is not None: + retValue = variance(df, c) + if retValue: + print(f"A variância dos dados de {c} é {retValue}") + else: + print("Um erro aconteceu. Nada a apresentar de momento.") + else: + continue + + case "3": + c = filter_submenu("Desvio Padrão") + + if c is not None: + retValue = std_dev(df, c) + if retValue: + print(f"O desvio padrão de {c} é {retValue}") + else: + print("Um erro aconteceu. Nada a apresentar de momento.") + else: + continue + + case "4": + c = filter_submenu("Máximo") + + if c is not None: + retValue = max_v(df, c) + print(f"O valor máximo em {c} é {retValue}") + else: + continue + + case "5": + c = filter_submenu("Mínimo") + + if c is not None: + retValue = min_v(df, c) + print(f"O valor mínimo em {c} é {retValue}") + else: + continue + + case "6": + c = filter_submenu("Moda") + + if c is not None: + retValue = moda(df, c) + print(f"O valor moda em {c} é {retValue}") + else: + continue + + case "q": + inStats = False + continue + + case _: + pass + + input("Clica `Enter` para continuar") -def filter_mags(data, more_than=None, less_than=None) -> pd.DataFrame: - """Filters by magnitudes a DataFrame into a new Dataframe +def average(df: pd.DataFrame, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :param more_than(optional): Filter for magnitudes above threshold - :param after(optional): Filters for dates after set date - :returns: Returns a filtered pandas DataFrame - """ - v = data.drop_duplicates(subset="ID", keep="first") - _dict = {"Data": [], "MagL": []} - for idx, c in v.iterrows(): - _dict["Data"].append(str(c.Data)) - _dict["MagL"].append(utils.extract_mag_l(c.Magnitudes)) - - _df = pd.DataFrame.from_dict(_dict) - if more_than: - _df = _df[_df["MagL"] >= more_than] - - if less_than: - _df = _df[_df["MagL"] <= less_than] - return _df + if filter_by == "Magnitudes": + values = _unpack_mags(values) + try: + return np.average(values) + except: + return None -def filter_date( - data: pd.DataFrame, - before: datetime.datetime | None = None, - after: datetime.datetime | None = None, -) -> pd.DataFrame: - """Filters by date a DataFrame into a new Dataframe +def variance(df, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :param before(optional): Filter for dates before set date - :param after(optional): Filters for dates after set date - :returns: Returns a filtered pandas DataFrame - """ - v = data - for idx, c in v.iterrows(): - v.at[idx, "Data"] = datetime.datetime.fromisoformat(c.Data) + if filter_by == "Magnitudes": + values = _unpack_mags(values) - if after: - v = v[v["Data"] >= after] - - if before: - v = v[v["Data"] >= before] - return v + try: + return np.var(values) + except: + return None -def filter_depth( - data: pd.DataFrame, - less_than: float | None = None, - more_than: float | None = None, -) -> pd.DataFrame: - """Filters by the depth a DataFrame into a new Dataframe +def std_dev(df, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :param less_than(optional): Filter for depths below the threshold - :param after(optional): Filters for depths deeper than threshold - :returns: Returns a filtered pandas DataFrame - """ - v = data.drop_duplicates(subset="ID", keep="first") - - if more_than: - v = v[v["Profundidade"] >= more_than] - - if less_than: - v = v[v["Profundidade"] >= less_than] - return v + if filter_by == "Magnitudes": + values = _unpack_mags(values) + + try: + return np.std(values) + except: + return None -def filter_gap( - data: pd.DataFrame, - threshold: int, -) -> pd.DataFrame: - """Filters by the depth a DataFrame into a new Dataframe +def max_v(df, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :param threshold: Filter for GAPS below the threshold - :returns: Returns a filtered pandas DataFrame - """ - v = data.drop_duplicates(subset="ID", keep="first") - v = v[v["Gap"] <= threshold] - return v + if filter_by == "Magnitudes": + values = _unpack_mags(values) + + return np.max(values) -def filter_sz( - data: pd.DataFrame, -) -> pd.DataFrame: - """Filters by SZ plane a DataFrame into a new Dataframe +def min_v(df, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :returns: Returns a filtered pandas DataFrame - """ - v = data[data["SZ"].notna()] - return v + if filter_by == "Magnitudes": + values = _unpack_mags(values) + + return np.min(values) -def filter_vz( - data: pd.DataFrame, -) -> pd.DataFrame: - """Filters by VZ plane a DataFrame into a new Dataframe +def moda(df, filter_by): + events = _get_unique_events(df) + values = events[filter_by].to_numpy() - :param data: Raw pandas DataFrame - :returns: Returns a filtered pandas DataFrame - """ - v = data[data["VZ"].notna()] - return v + if filter_by == "Magnitudes": + values = _unpack_mags(values) + + uniques, count = np.unique(values, return_counts=True) + uniques_list = list(zip(uniques, count)) + + return sorted(uniques_list, reverse=True ,key=lambda x: x[1])[0][0] -def _preprare_days(data): - c = data.Data.to_list() - for idx, d in enumerate(c): - aux = datetime.datetime.fromisoformat(d) - c[idx] = datetime.datetime.strftime(aux, "%Y-%m-%d") +def _unpack_mags(arr: np.ndarray): + newVals = np.empty(0) + for v in arr: + for m in v: + newVals = np.append(newVals, float(m["Magnitude"])) + return newVals - return c - - -def _preprare_months(data): - c = data.Data.to_list() - for idx, d in enumerate(c): - aux = datetime.datetime.fromisoformat(d) - c[idx] = datetime.datetime.strftime(aux, "%Y-%m") - - return c diff --git a/utils/utils.py b/utils/utils.py index dcfb9ef..1e04fd7 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -1,30 +1,21 @@ #! /usr/bin/env python # pyright: basic -import json from datetime import time +import json from math import modf from typing import Any -import numpy as np import pandas as pd -def extract_mag_l(data) -> np.float64: - for v in data: - if v["Tipo"] == "L": - return np.float64(v["Magnitude"]) - - return np.float64(0.0) - - -def save_as_json(info: dict[str, Any]) -> bool: - with open("test.json", "w") as fp: - json.dump(info, fp) - +def save_as_json(df: pd.DataFrame, fname, event_cols, station_cols) -> bool: + info = create_dict_struct(df, event_cols, station_cols) + with open(fname, "w") as fp: + json.dump(info, fp, indent=4) + return True - # TODO: passar os nomes das colunas, para não haver problemas no futuro, caso se altere os nomes da dataframe def create_dict_struct(df: pd.DataFrame, event_cols, station_cols) -> dict[str, Any]: # get all events by their id @@ -61,20 +52,15 @@ def create_stations_info_1(info: pd.DataFrame) -> dict[str, Any]: aux = info.iloc[idx] micro, sec = tuple(map(int, modf(aux["Seg"]))) - hms = time( - hour=aux["Hora"], minute=aux["Min"], second=sec, microsecond=micro - ).strftime("%H:%M:%S.%f") - station = { - "Componente": aux["Componente"], - "Hora": hms, - "Distancia": float(aux["DIS"]), - } + hms = time(hour=aux["Hora"],minute=aux["Min"], second=sec, microsecond=micro).strftime("%H:%M:%S.%f") + station = {"Componente": aux["Componente"], "Hora": hms, "Distancia": float(aux["DIS"])} if type(aux["Tipo Onda"]) != float: station.update({"Tipo Onda": aux["Tipo Onda"]}) if aux["Tipo Onda"] == "IAML": station.update({"Amplitude": float(aux["Amplitude"])}) + if aux["Estacao"] not in stationsDict.keys(): stationsDict[aux["Estacao"]] = [station] else: @@ -89,7 +75,7 @@ def create_mag_info(magnitudes): return mags -if __name__ == "__main__": +if __name__ == '__main__': import parser df = parser.parse("dados.txt") diff --git a/utils/vis.py b/utils/vis.py new file mode 100644 index 0000000..844b89e --- /dev/null +++ b/utils/vis.py @@ -0,0 +1,38 @@ +import json +import plotly.express as px +import pandas as pd +from dash import Dash, html, Input, Output, dcc, callback +import parser as parser + + +@callback( + Output('dump-json', 'children'), + Input('map3D-view', 'clickData') +) +def display_clicked_content(clickData): + return json.dumps(clickData, indent=2) + +def update_map(clickData): + return + +df = parser.parse("dados.txt") + +map2D = px.scatter_map(df, lat="Latitude", lon="Longitude", map_style="satellite") +map3D = px.scatter_3d(df, x="Longitude", y="Latitude", z="Profundidade") +map3D.update_scenes(zaxis_autorange="reversed") + +app = Dash() +app.layout = html.Div(children=[ + dcc.Graph( + id="map3D-view", + figure=map3D + ), + dcc.Graph( + id="map2D-view", + figure=map2D + ), + html.Div(children=[html.Pre(id='dump-json', style={'overflowX': 'scroll'}, children="1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15") +])]) + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/utils/visuals.py b/utils/visuals.py new file mode 100644 index 0000000..b88f644 --- /dev/null +++ b/utils/visuals.py @@ -0,0 +1,133 @@ +import matplotlib.pyplot as plt +import pandas as pd +import sys +import os +import numpy as np + +from utils import stats + +# -- helpers + +def plot_bar(x, y, xLabel, yLabel, title): + plt.figure(figsize=(10, 6)) + plt.bar(x, y) + plt.xlabel(xLabel) + plt.ylabel(yLabel) + plt.title(title) + plt.xticks(rotation=45) + plt.tight_layout() + plt.show() + +def plot_linear_with_std(x, mean, std, xLabel, yLabel, title): + plt.figure(figsize=(10, 6)) + plt.errorbar(x, mean, yerr=std, fmt='-o', capsize=5, ecolor='red') + plt.xlabel(xLabel) + plt.ylabel(yLabel) + plt.title(title) + plt.xticks(rotation=45) + plt.grid(True) + plt.tight_layout() + plt.show() + +def plot_boxplot(dataList, labels, xLabel, yLabel, title): + # dataList: lista de arrays/series, um para cada etiqueta + # labels: lista de etiquetas correspondentes a dataList + plt.figure(figsize=(10, 6)) + plt.boxplot(dataList, labels=labels) + plt.xlabel(xLabel) + plt.ylabel(yLabel) + plt.title(title) + plt.xticks(rotation=90) + plt.tight_layout() + plt.show() + +# -- t6 logic + +def viz_events_per_period(df: pd.DataFrame, period: str, title_suffix: str): + dates, counts = stats.events_per_period(df, period) + # Formatar datas para melhor leitura no gráfico + if period == 'D': + # dates é um DatetimeIndex + labels = [d.strftime('%Y-%m-%d') for d in dates] + else: + labels = [d.strftime('%Y-%m') for d in dates] + + plot_bar(labels, counts, "Data", "Número de Eventos", f"Eventos por {title_suffix}") + +def viz_linear_stats(df: pd.DataFrame, target: str): + # Média +/- Desvio Padrão + if target == 'Profundidade': + st = stats.stats_depth_month(df) + unit = "km" + else: # Magnitude + st = stats.stats_mag_month(df) + unit = "Magn" + + labels = [d.strftime('%Y-%m') for d in st.index] + + plot_linear_with_std(labels, st['Mean'], st['Std'], "Mês", f"{target} ({unit})", f"Média e Desvio Padrão de {target} por Mês") + +def viz_boxplot(df: pd.DataFrame, target: str): + df = stats.convert_to_datetime(df) + events = stats._get_unique_events(df) + + # Agrupar por mês + grouped = events.set_index('Data').resample('ME') + + data_to_plot = [] + labels = [] + + for name, group in grouped: + if target == 'Profundidade': + vals = group['Profundidade'].dropna().values + else: + # Extrair magnitudes máximas + def get_max_mag(mags): + vals = [float(m['Magnitude']) for m in mags if 'Magnitude' in m] + return max(vals) if vals else np.nan + vals = group['Magnitudes'].apply(get_max_mag).dropna().values + + if len(vals) > 0: + data_to_plot.append(vals) + labels.append(name.strftime('%Y-%m')) + + plot_boxplot(data_to_plot, labels, "Mês", target, f"Boxplot de {target} por Mês") + + +# --- Menu --- + +VISUALS_MENU = """[1] Gráfico Barras: Eventos por Dia +[2] Gráfico Barras: Eventos por Mês +[3] Gráfico Linear: Profundidade (Média +/- DP) por Mês +[4] Gráfico Linear: Magnitude (Média +/- DP) por Mês +[5] Boxplot: Profundidade por Mês +[6] Boxplot: Magnitude por Mês + +[Q] Voltar +""" + +HEADER = "=== T6: Representação Gráfica ===" + +def visual_menu(df: pd.DataFrame): + while True: + os.system("cls" if sys.platform == "windows" else "clear") + print(HEADER + "\n" + VISUALS_MENU) + usrIn = input("Opção: ").lower() + + match usrIn: + case "1": + viz_events_per_period(df, 'D', "Dia") + case "2": + viz_events_per_period(df, 'M', "Mês") + case "3": + viz_linear_stats(df, "Profundidade") + case "4": + viz_linear_stats(df, "Magnitude") + case "5": + viz_boxplot(df, "Profundidade") + case "6": + viz_boxplot(df, "Magnitude") + case "q": + return + case _: + pass