Source code for aitlas.datasets.crops_classification

import logging
import os

import h5py
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

from ..base import BaseDataset
from .schemas import CropsDatasetSchema


logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")


[docs]class CropsDataset(BaseDataset): """CropsDataset - a crop type classification dataset""" schema = CropsDatasetSchema def __init__(self, config): super().__init__(config)
[docs] def preprocess(self): raise NotImplementedError( "Please implement the `preprocess` method for your crop type classification dataset" )
def __len__(self): return len(self.index) def __getitem__(self, index): """ Args: index (int): Index Returns: tuple: (timeseries, target) where target is index of the target class. """ row = self.index.iloc[index] h5path = self.h5path[row.region] if self.X_list is None: # Looks like this is what I need (load directly from file) with h5py.File(h5path, "r") as dataset: X = np.array(dataset[(row.path)]) else: X = self.X_list[index] # translate CODE_CULTU to class id y = self.mapping.loc[row["CODE_CULTU"]].id if self.transform: X, y = self.transform((X, y)) return X, y
[docs] def get_labels(self): return self.index.classid
[docs] def data_distribution_table(self): label_count = ( self.index[["id", "region", "classname"]] .groupby(["classname", "region"]) .count() .reset_index() ) label_count.columns = ["Label", "Region", "Number of parcels"] return label_count
[docs] def parcel_distribution_table(self): # Figure 2 a) in the paper parcel_count = ( self.index[["id", "region"]].groupby("region").count().reset_index() ) parcel_count.columns = ["Region NUTS-3", "# " + self.config.level] total_row = parcel_count.sum(axis=0) total_row["Region NUTS-3"] = "Total" parcel_count = parcel_count.append(total_row, ignore_index=True) return parcel_count
[docs] def data_distribution_barchart(self): # Figure 2 b) in the paper label_count = self.data_distribution_table() fig, ax = plt.subplots(figsize=(12, 10)) g = sns.barplot( x="Label", y="Number of parcels", hue="Region", data=label_count, ax=ax ) g.set_xticklabels(g.get_xticklabels(), rotation=30) g.set_yscale("log") return fig
[docs] def show_samples(self): return self.index.head(20)
[docs] def show_image(self, index): return self.show_timeseries(index)
[docs] def show_timeseries(self, index): # Figure 3 in the paper X, _ = self.__getitem__(index) label = self.index.iloc[index].loc["classname"] fig, ax = plt.subplots(figsize=(8, 6)) ax.set_title( f"Time series with index {index} from the region {self.index.iloc[index].loc['region']}, with label {label}\n", fontsize=14, ) ax.plot(X) ax.legend(self.selected_bands[: X.shape[1]]) ax.set_ylabel("ρ ") # x ${10^4}$ return fig
[docs] def get_codes(self): return self.codes
[docs] def load_classmapping(self, classmapping): if not os.path.exists(classmapping): if self.config.verbose: """ TODO: either add a url for our dataset or remove it for breizhcrops """ else: if self.config.verbose: logging.info(f"Found class mapping at {classmapping}") self.mapping = pd.read_csv(classmapping, index_col=0).sort_values(by="id") self.mapping = self.mapping.set_index("code") self.classes = self.mapping["id"].unique() self.classname = self.mapping.groupby("id").first().classname.values self.klassenname = self.classname self.nclasses = len(self.classes) if self.config.verbose: logging.info(f"read {self.nclasses} classes from {classmapping}")