diff --git a/main.py b/main.py index 23c3427..0f57563 100755 --- a/main.py +++ b/main.py @@ -20,27 +20,42 @@ logger.add( ) BASE_PATH = Path(__file__).parent -WIND_GUSTS_PATH = BASE_PATH.joinpath("data", "vejaAtrumsBrazmas.xlsx") -WIND_SPEED_PATH = BASE_PATH.joinpath("data", "vejaAtrumsFaktiskais.xlsx") -AIR_TEMP_PATH = BASE_PATH.joinpath("data", "gaisaTemperatura2022.xlsx") -PDF_PATH = BASE_PATH.joinpath("plots.pdf") +WIND_GUSTS_FILENAME = "vejaAtrumsBrazmas.xlsx" +WIND_SPEED_FILENAME = "vejaAtrumsFaktiskais.xlsx" +AIR_TEMP_FILENAME = "gaisaTemperatura2022.xlsx" +PDF_FILENAME = "plots.pdf" BLUE = "#1f77b4" ORANGE = "#ff7f0e" BLACK = "#000000" -@logger.catch -def read_data(path: Path) -> pd.DataFrame: - dataframe = pd.read_excel(path, parse_dates=["Datums"], index_col="Datums", date_format="%d.%m.%Y") - logger.info(f"Read data from {path}") - return dataframe +def read_data(filename: str) -> pd.DataFrame: + """ + Read data from Excel file and return a pandas DataFrame. + + Raises: + FileNotFoundError: if the specified file is not found. + """ + possible_paths = [ + BASE_PATH.joinpath(filename), + BASE_PATH.joinpath("data", filename), + ] + + for path in possible_paths: + if path.exists(): + dataframe = pd.read_excel(path, parse_dates=["Datums"], index_col="Datums", date_format="%d.%m.%Y") + logger.info(f"Read data from {path}") + return dataframe + + raise FileNotFoundError(f"Could not find {filename}") -@logger.catch def create_bar_chart() -> plt.Figure: - df_avg: pd.Series = read_data(WIND_SPEED_PATH).mean(axis=1) - df_max: pd.Series = read_data(WIND_GUSTS_PATH).max(axis=1) - df_avg + """Create a bar chart with average and maximum wind speed.""" + + df_avg: pd.Series = read_data(WIND_SPEED_FILENAME).mean(axis=1) + df_max: pd.Series = read_data(WIND_GUSTS_FILENAME).max(axis=1) - df_avg df_combined: pd.DataFrame = pd.concat( [df_avg, df_max], @@ -49,7 +64,8 @@ def create_bar_chart() -> plt.Figure: fig, ax = plt.subplots(figsize=(12, 8)) - df_combined.columns = ["Vidējais", "Maksimālais"] + df_combined.columns = ["Vidējais", "Maksimālais"] # Rename columns + df_combined.plot.bar( stacked=True, figsize=(12, 8), @@ -58,14 +74,17 @@ def create_bar_chart() -> plt.Figure: ax=ax, ) + # Format x-axis date_format = df_combined.index.strftime("%d.%m.%Y") ax.set_xticks(np.arange(len(date_format))) ax.set_xticklabels(date_format, rotation=45) + ax.set_xlabel("Mērījumu Datums") + + # Format y-axis ax.set_yticks(np.arange(0, df_combined.max().max() + 2.5, 2.5)) + ax.set_ylabel("Vēja ātrums (m/s)") ax.set_title("Vidējais un maksimālais vēja ātrums 2023. gada augustā") - ax.set_xlabel("Mērījumu Datums") - ax.set_ylabel("Vēja ātrums (m/s)") logger.info("Created bar chart") @@ -80,10 +99,12 @@ SEASONS: dict[int, str] = { } -@logger.catch def create_box_plot() -> plt.Figure: - df: pd.DataFrame = read_data(AIR_TEMP_PATH) + """Create a box plot showing the distribution of air temperature across seasons.""" + df: pd.DataFrame = read_data(AIR_TEMP_FILENAME) + + # Assign season to each row df["Season"] = df.index.month % 12 // 3 + 1 df["Season"] = df["Season"].map(SEASONS) @@ -104,23 +125,36 @@ def create_box_plot() -> plt.Figure: widths=0.4, ) + # Format x-axis + ax.set_xlabel("") + + # Format y-axis min_value: float = np.floor(df["Average"].min() / 5) * 5 max_value: float = np.ceil(df["Average"].max() / 5) * 5 tick_step: int = 5 - ax.set_yticks(np.arange(min_value, max_value, tick_step)) - ax.set_title("Gaisa temperatūra Rīgā četros gadalaikos") ax.set_ylabel("Gaisa temperatūra (Celsija grādos)") - ax.set_xlabel("") + + ax.set_title("Gaisa temperatūra Rīgā četros gadalaikos") logger.info("Created box plot") return fig -@logger.catch -def open_pdf(pdf_path: Path) -> None: - logger.info(f"Opening {pdf_path}") +def open_pdf(filename: str) -> None: + """ + Open a PDF file using the default system viewer. + + Raises: + FileNotFoundError: if the specified file is not found. + """ + + pdf_path = BASE_PATH.joinpath(filename) + if not pdf_path.exists(): + raise FileNotFoundError(f"Could not find {pdf_path}") + + logger.info(f"Opening {filename}") system = platform.system().lower() if system == "linux": @@ -135,7 +169,10 @@ def open_pdf(pdf_path: Path) -> None: @logger.catch def main() -> None: - with PdfPages(PDF_PATH) as pdf: + """Main function to generate and save plots to a PDF file, then open the PDF.""" + + # Generate and save plots to a PDF file + with PdfPages(PDF_FILENAME) as pdf: fig1 = create_bar_chart() pdf.savefig(fig1) plt.close(fig1) @@ -145,7 +182,7 @@ def main() -> None: plt.close(fig2) try: - open_pdf(PDF_PATH) + open_pdf(PDF_FILENAME) except Exception as e: logger.error(e) logger.warning("Something went wrong while opening the PDF. Please open it manually.") diff --git a/plots.pdf b/plots.pdf index bb51c9c..7af32c9 100644 Binary files a/plots.pdf and b/plots.pdf differ diff --git a/pyproject.toml b/pyproject.toml index 37691d7..b8dfbc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,6 @@ requires-python = ">=3.11" license = { text = "MIT" } dependencies = [ "openpyxl==3.1.2", - "attrs==23.1.0", "loguru==0.7.2", "matplotlib==3.8.2", "pandas==2.1.4", @@ -18,9 +17,9 @@ dependencies = [ check_untyped_defs = true disallow_any_generics = true ignore_missing_imports = true -# no_implicit_optional = true -# no_implicit_reexport = true -# show_error_codes = true +no_implicit_optional = true +no_implicit_reexport = true +show_error_codes = true strict_equality = true warn_redundant_casts = true warn_return_any = true diff --git a/requirements_dev.txt b/requirements_dev.txt index 67e96b7..3c096e2 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,3 +1,2 @@ mypy>=1.6.1 -pytest>=7.4.3 ruff>=0.1.4