"""
# Exploratory Data Analysis and   Rice Disease Classification using Tensorflow and Keras

In this notebook, I am going to perform exploratory data analysis and build a model to classify rice diseases from the rice-diseases-image-dataset.
"""
"""
## Importing Libraries
"""
import os
import cv2
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn as sns
from PIL import Image
from tensorflow.keras.layers import Dropout, Activation, Input, GlobalAveragePooling2D, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import InceptionResNetV2
from tensorflow.keras.applications.inception_resnet_v2 import preprocess_input
"""
# Exploratory data analysis on the dataset
"""
training_folder = '../input/riceleafs/RiceLeafs/train'
validation_folder = '../input/riceleafs/RiceLeafs/validation'
brownspot = [training_folder + '/BrownSpot/' + img for img in os.listdir(training_folder + '/BrownSpot')[:9]]
healthy = [training_folder + '/Healthy/' + img for img in os.listdir(training_folder + '/Healthy')[:9]]
hispa = [training_folder + '/Hispa/' + img for img in os.listdir(training_folder + '/Hispa')[:9]]
leafblast = [training_folder + '/LeafBlast/' + img for img in os.listdir(training_folder + '/LeafBlast')[:9]]
"""
## Brown Spot: What is brown spot disease and why it occurs? 

Brown spot is a fungal disease that infects the coleoptile, leaves, leaf sheath, panicle branches, glumes, and spikelets. 
The disease can develop in areas with high relative humidity (86−100%) and temperature between 16 and 36°C. It is common in unflooded and nutrient-deficient soil, or in soils that accumulate toxic substances. 

For infection to occur, the leaves must be wet for 8−24 hours.

The fungus can survive in the seed for more than four years and can spread from plant to plant through air. Major sources of brown spot in the field include:

* infected seed, which give rise to infected seedlings
* volunteer rice
* infected rice debris
* weeds
"""
plt.figure(figsize=(16,16))
for i,k  in enumerate(brownspot):
    image = Image.open(k)
    plt.subplot(3,3,i+1)
    plt.imshow(image)
    plt.title("Brown Spot")
"""
## How to Identify Brown Spot 

Check for lesions:
* Infected seedlings have small, circular, yellow brown or brown lesions that may girdle the coleoptile and distort primary and secondary leaves.
* Starting at tillering stage, lesions can be observed on the leaves. They are initially small, circular, and dark brown to purple-brown.
* Fully developed lesions are circular to oval with a light brown to gray center, surrounded by a reddish brown margin caused by the toxin produced by the fungi.
"""
"""
## Hispa: What is Hispa disease and why it occurs?
Rice hispa scrapes the upper surface of leaf blades leaving only the lower epidermis.
The presence of grassy weeds in and near rice fields as alternate hosts harbor and encourage the pest to develop. Heavily fertilized field also encourages the damage.

Heavy rains, especially in premonsoon or earliest monsoon periods, followed by abnormally low precipitation, minimum day-night temperature differential for a number of days, and high RH are favorable for the insect’s abundance.
"""
plt.figure(figsize=(16,16))
for i,k  in enumerate(hispa):
    image = Image.open(k)
    plt.subplot(3,3,i+1)
    plt.imshow(image)
    plt.title("Hispa")
"""
## How to identify Hispa disease?
Check for feeding damage:

* scraping of the upper surface of the leaf blade leaving only the lower epidermis as white streaks parallel to the midrib
* irregular translucent white patches that are parallel to the leaf veins caused by tunneling of larvae through leaf tissue causes
* withering of damaged leaves
* whitish and membranous leaves
"""
"""
## Leaf Blast: What is Leaf Blast and Why it occurs?

Blast is caused by the fungus Magnaporthe oryzae. It can affect all above ground parts of a rice plant.
Blast can occur wherever blast spores are present.

It occurs in areas with low soil moisture, frequent and prolonged periods of rain shower, and cool temperature in the daytime. In upland rice, large day-night temperature differences that cause dew formation on leaves and overall cooler temperatures favor the development of the disease.
"""
plt.figure(figsize=(16,16))
for i,k  in enumerate(leafblast):
    image = Image.open(k)
    plt.subplot(3,3,i+1)
    plt.imshow(image)
    plt.title("Leaf Blast")
"""
## How to Identify?
Check the leaf and collar for lesions:

* Initial symptoms appear as white to gray-green lesions or spots, with dark green borders.
* Older lesions on the leaves are elliptical or spindle-shaped and whitish to gray centers with red to brownish or necrotic border.
"""
"""
## Healthy:
"""
plt.figure(figsize=(16,16))
for i,k  in enumerate(healthy):
    image = Image.open(k)
    plt.subplot(3,3,i+1)
    plt.imshow(image)
    plt.title("Healthy")
"""
# Preparing Data and Building Classification Model  
"""
batch_size = 10
image_size = 300
input_shape = (image_size, image_size, 3)
dropout_rate = 0.3
"""
## Prepare the training and validation data generators
"""
train_datagen = ImageDataGenerator(
        rescale=1./255,
        horizontal_flip=True,
        vertical_flip=True,
        fill_mode = 'nearest',
        channel_shift_range=0.5,
        brightness_range=[0.5,1.2],
        rotation_range=25,
        zoom_range=[0.5, 1],
        )
validation_datagen = ImageDataGenerator(rescale=1./255, 
                                        horizontal_flip = True,
                                        vertical_flip = True,
                                        fill_mode = "nearest")
train_datagenerator = train_datagen.flow_from_directory(
        training_folder,
        target_size=(image_size, image_size),
        shuffle=True,
        batch_size=batch_size,
        class_mode='categorical')
validation_datagenerator = validation_datagen.flow_from_directory(
        validation_folder,
        target_size=(image_size, image_size),
        shuffle=True,
        batch_size=batch_size,
        class_mode='categorical') 
# This function will plot images in the form of a grid with 3 row and 3 columns where images are placed in each column.
def plotImages(images_arr):
    fig, axes = plt.subplots(3, 3, figsize=(16,16))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
    plt.tight_layout()
    plt.show()
    
augmented_images = [train_datagenerator[0][0][0] for i in range(9)]
plotImages(augmented_images)
"""
## Building Model

I am using an InceptionResNet on rice disease classes.
"""
def create_model():
    resnet= InceptionResNetV2(weights="imagenet", 
                                   include_top=False, 
                                   input_shape=input_shape, 
                                   )


    input_layer = Input(shape = input_shape)
    preprocess = preprocess_input(input_layer)
    efficientnet = resnet(preprocess)
    pooling = GlobalAveragePooling2D()(efficientnet)
    dropout = Dropout(dropout_rate)(pooling)
    outputs = Dense(4, activation="softmax")(dropout)
    model = Model(inputs=input_layer, outputs=outputs)

    return model
model = create_model()
model.summary()
epochs = 10
decay_steps = int(np.ceil(train_datagenerator.n / float(batch_size)))*epochs
cosine_decay = tf.keras.experimental.LinearCosineDecay(initial_learning_rate=1e-4, decay_steps=decay_steps, alpha=0.3)
callbacks = [tf.keras.callbacks.ModelCheckpoint(filepath='best_rice_disease_model.h5', monitor='val_loss', save_best_only=True)]
model.compile(loss=tf.keras.losses.CategoricalCrossentropy(), optimizer=tf.keras.optimizers.Adam(cosine_decay), metrics=["accuracy"])
# Fitting models to the generators
history = model.fit(
    train_datagenerator,
    steps_per_epoch=int(np.ceil(train_datagenerator.n / float(batch_size))),
    epochs=epochs,
    validation_data=validation_datagenerator,
    validation_steps=int(np.ceil(validation_datagenerator.n / float(batch_size)))
)
"""
Now, I will check, how my model performed on similar level on both the training and validation. The training curve will also tel, if I stopped training too early or may have overfitted in comparison to the validation data.
"""
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Accuracy over epochs')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Validation'], loc='best')
plt.show()