# ---------------------------------------------------------------------------
# weather_analysis.py
#
# One year of daily weather readings for our city, and the questions people
# ask about the weather but usually answer from memory:
#
#   1. How does the temperature move through the year?
#   2. When does the rain actually come, and how much of it?
#   3. Is the rain spread out, or does it arrive in a few heavy days?
#   4. What is a normal summer day, and how often is it extreme?
#   5. Do humid days and rainy days go together?
#
# IMPORTANT: weather data belongs to whoever recorded it. The file used here
# is a LambdaLab sample. If you use real readings — from IMD, data.gov.in or
# your school's own weather station — say so in the report and give the link.
# ---------------------------------------------------------------------------

import pandas as pd
import matplotlib.pyplot as plt

# --- 1. Read -------------------------------------------------------------
df = pd.read_csv("weather.csv", parse_dates=["date"])
print("Rows read        :", len(df))
print("From             :", df["date"].min().date(), "to", df["date"].max().date())
print()

# --- 2. Clean ------------------------------------------------------------
# The two kinds of blank in this file mean different things, and treating
# them the same would be wrong.
#
#   * A blank temperature means the station did not report. There is no
#     reading, so the day is dropped from anything about temperature.
#   * A blank rainfall means nobody wrote anything in the column, which for
#     this station means no rain fell. That is filled with 0.
no_temp = df["max_temp"].isnull().sum()
no_rain = df["rainfall_mm"].isnull().sum()
df["rainfall_mm"] = df["rainfall_mm"].fillna(0)

# The month each reading belongs to, added before anything is split off so
# that both frames below carry it. strftime("%b") gives Jan, Feb, ... which
# reads better on a chart than 1, 2, 3.
df["month"] = df["date"].dt.strftime("%b")
order = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

# The days with no thermometer reading are NOT thrown out of the file. They
# are only kept out of the temperature figures, and `temps` is the frame that
# does that. Dropping them from df altogether would have taken their rainfall
# with them, and rain that fell on a day the thermometer failed still fell.
temps = df.dropna(subset=["max_temp", "min_temp"])

print("Days with no temperature reported :", no_temp,
      "(left out of the temperature figures only)")
print("Days with the rain column blank   :", no_rain, "(taken as 0 mm)")
print("Days in the file                  :", len(df))
print("Days with a usable temperature    :", len(temps))
print()

# --- 3. Question 1: the shape of the year --------------------------------
monthly = temps.groupby("month")[["max_temp", "min_temp"]].mean().reindex(order).round(1)

print("--- Average temperature, month by month ---")
print(monthly)
print()
print("Hottest month  :", monthly["max_temp"].idxmax(),
      "at", monthly["max_temp"].max(), "C")
print("Coldest month  :", monthly["min_temp"].idxmin(),
      "at", monthly["min_temp"].min(), "C")
print("Highest reading:", temps["max_temp"].max(), "C on",
      temps.loc[temps["max_temp"].idxmax(), "date"].date())
print("Lowest reading :", temps["min_temp"].min(), "C on",
      temps.loc[temps["min_temp"].idxmin(), "date"].date())
print()

# Two lines on one pair of axes, so the gap between them can be seen. That
# gap is the day-night swing, and it closes in the monsoon.
plt.figure(figsize=(9, 4.5))
plt.plot(monthly.index, monthly["max_temp"], marker="o",
         color="#e05b3a", label="Average maximum")
plt.plot(monthly.index, monthly["min_temp"], marker="s",
         color="#3b7dd8", label="Average minimum")
plt.title("Average daily temperature through the year")
plt.xlabel("Month")
plt.ylabel("Temperature (C)")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.5)
plt.tight_layout()
plt.savefig("chart1_temperature.png")
plt.close()

# --- 4. Question 2: when does the rain come? -----------------------------
rain_month = df.groupby("month")["rainfall_mm"].sum().reindex(order).round(1)
total_rain = rain_month.sum()

print("--- Rainfall, month by month (mm) ---")
print(rain_month)
print()
print("Rain for the year :", round(total_rain, 1), "mm")
monsoon = rain_month[["Jun", "Jul", "Aug", "Sep"]].sum()
print("June to September :", round(monsoon, 1), "mm, which is",
      round(monsoon / total_rain * 100, 1), "% of the year's rain")
print()

plt.figure(figsize=(9, 4.5))
plt.bar(rain_month.index, rain_month.values, color="#2f8fa8")
plt.title("Rainfall, month by month")
plt.xlabel("Month")
plt.ylabel("Rainfall (mm)")
plt.tight_layout()
plt.savefig("chart2_rainfall.png")
plt.close()

# --- 5. Question 3: spread out, or a few heavy days? ---------------------
rainy = df[df["rainfall_mm"] > 0]
print("--- Rainy days ---")
print("Days on which it rained  :", len(rainy), "out of", len(df))

# Everything below divides by the year's rain or asks for the biggest day, and
# neither means anything if it never rained. A whole year without a drop will
# not happen; a few days of readings with none in them happens all the time,
# and without this guard the program stops with ValueError rather than saying
# so.
if len(rainy) == 0:
    print("It did not rain once in this file, so there is nothing more to say.")
else:
    print("Wettest single day       :", rainy["rainfall_mm"].max(), "mm on",
          rainy.loc[rainy["rainfall_mm"].idxmax(), "date"].date())

    # The point of this line: a handful of days can carry most of the rain.
    heavy = rainy[rainy["rainfall_mm"] >= 25]
    print("Days of 25 mm or more    :", len(heavy), "-- they carried",
          round(heavy["rainfall_mm"].sum() / total_rain * 100, 1), "% of the year's rain")
print()

rainy_days = rainy.groupby("month")["rainfall_mm"].count().reindex(order).fillna(0).astype(int)
print("--- Number of rainy days each month ---")
print(rainy_days)
print()

plt.figure(figsize=(9, 4.5))
plt.bar(rainy_days.index, rainy_days.values, color="#4c9f70")
plt.title("Number of days it rained, month by month")
plt.xlabel("Month")
plt.ylabel("Rainy days")
plt.tight_layout()
plt.savefig("chart3_rainy_days.png")
plt.close()

# --- 6. Question 4: what is a normal day? --------------------------------
print("--- Daily maximum temperature ---")
print(temps["max_temp"].describe().round(1))
print()
above40 = temps[temps["max_temp"] >= 40]
print("Days at 40 C or above:", len(above40))
below10 = temps[temps["min_temp"] <= 10]
print("Nights at 10 C or below:", len(below10))
print()

plt.figure(figsize=(8, 4.5))
plt.hist(temps["max_temp"].values, bins=14, color="#c9772f", edgecolor="white")
plt.title("How often each daytime temperature occurs")
plt.xlabel("Daily maximum temperature (C)")
plt.ylabel("Number of days")
plt.tight_layout()
plt.savefig("chart4_temp_spread.png")
plt.close()

# --- 7. Question 5: humidity against rain --------------------------------
hum_month = df.groupby("month")["humidity"].mean().reindex(order).round(1)
print("--- Average humidity, month by month (%) ---")
print(hum_month)
print()
print("Correlation between humidity and rainfall:",
      round(df["humidity"].corr(df["rainfall_mm"]), 3))
if len(rainy) > 0:
    print("Average humidity on a rainy day :", round(rainy["humidity"].mean(), 1), "%")
print("Average humidity on a dry day   :",
      round(df[df["rainfall_mm"] == 0]["humidity"].mean(), 1), "%")
print()

plt.figure(figsize=(9, 4.5))
plt.plot(hum_month.index, hum_month.values, marker="o", color="#a05fc0")
plt.title("Average humidity through the year")
plt.xlabel("Month")
plt.ylabel("Relative humidity (%)")
plt.grid(True, linestyle="--", alpha=0.5)
plt.tight_layout()
plt.savefig("chart5_humidity.png")
plt.close()

# --- 8. The one-page summary --------------------------------------------
summary = pd.DataFrame({
    "avg_max_temp": monthly["max_temp"],
    "avg_min_temp": monthly["min_temp"],
    "rainfall_mm": rain_month,
    "rainy_days": rainy_days,
    "avg_humidity": hum_month,
})
summary.to_csv("month_summary.csv")

print("Charts saved : chart1_temperature.png .. chart5_humidity.png")
print("Summary saved: month_summary.csv")
