{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7c124a6c-72b6-4e1c-bf1b-674a776314a5",
   "metadata": {},
   "source": [
    "# MNIST data analyses\n",
    "\n",
    "_Copyright (C) 2023-, Joseph T. Lizier._\n",
    "_Distributed under GNU General Public License v3_\n",
    "\n",
    "This notebook template sets up reading in the data files for the MNIST analysis.\n",
    "\n",
    "First code block is just to start up the JVM. You may need to change your paths below (use the AutoAnalyser to show them for you):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb8b22dc-a5bc-44c9-b879-068a8b9e23e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from jpype import *\n",
    "import numpy\n",
    "import sys\n",
    "# Our python data file readers are a bit of a hack, python users will do better on this:\n",
    "sys.path.append(\"../../../demos/python\")\n",
    "import readIntsFile\n",
    "\n",
    "if (not isJVMStarted()):\n",
    "    # Add JIDT jar library to the path\n",
    "    jarLocation = \"../../../infodynamics.jar\"\n",
    "    # Start the JVM (add the \"-Xmx\" option with say 1024M if you get crashes due to not enough memory space)\n",
    "    startJVM(getDefaultJVMPath(), \"-ea\", \"-Djava.class.path=\" + jarLocation, convertStrings=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f14ff253-b44e-45bf-ba69-d52c8e96a2c8",
   "metadata": {},
   "source": [
    "Next load in the data, and check that we can pull out a sample digit ok.\n",
    "\n",
    "We give code for two options to load the data, either:\n",
    "* Using the `torch` package (may also require `torchvision`) to automatically download the data and load it (_default_), or\n",
    "* via a Matlab pre-processed `.mat` file.\n",
    "\n",
    "Either way, the data is loaded into numpy arrays, being:\n",
    "* `classes` -- a 1D array of the classes 0..9 for each sample;\n",
    "* `pixels1D` -- binarised pixel data for each sample, with dimensions (numTrials, imageDimension * imageDimension) -- i.e. one dimensional data for each sample. (This is the usual JIDT multivariate data format, with each row being a sample, and each column a variable).\n",
    "* `pixels2D` -- binarised pixel data for each sample, with dimensions (numTrials, imageDimension, imageDimension) -- i.e. two dimensional image data for each sample.\n",
    "\n",
    "You can work with whichever of `pixels1D` or `pixels2D` that you prefer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91b18fb5-6f53-4ee8-85d5-0993e264e1c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load/prepare the data:\n",
    "\n",
    "# Choose whether to import via torch or via the distributed Matlab format:\n",
    "downloadViaTorch = True\n",
    "\n",
    "if (downloadViaTorch):\n",
    "    # Option 1: automatically download (into local folder 'data') and import the data using torchvision:\n",
    "    #  (thanks to Isabelle De Backer for pointing this option out)\n",
    "    import torchvision\n",
    "    trainData = torchvision.datasets.MNIST('./data', download=True, train=True)\n",
    "    testData = torchvision.datasets.MNIST('./data', download=True, train=False)\n",
    "    rawPixels2D = numpy.row_stack((trainData.data, testData.data))\n",
    "    imageDimension = rawPixels2D.shape[1];\n",
    "    numPixels = imageDimension * imageDimension;\n",
    "    numTrials = rawPixels2D.shape[0];\n",
    "    rawPixels1D = numpy.reshape(rawPixels2D, (numTrials, imageDimension * imageDimension))\n",
    "    classes = numpy.concatenate((trainData.targets, testData.targets))\n",
    "else:\n",
    "    # Option 2: import the pre-prepared data in Matlab format:\n",
    "    import scipy.io\n",
    "    data = scipy.io.loadmat('./trialAndTest-processedData.mat');\n",
    "    trainAndTestData = numpy.array(data['trialAndTestData'])\n",
    "    classes = trainAndTestData[:,0] - 1; # Need classes to start from 0 for JIDT (and it's sensible to match digits here also)\n",
    "    rawPixels1D = trainAndTestData[:,1:];\n",
    "    numPixels = rawPixels1D.shape[1];\n",
    "    numTrials = rawPixels1D.shape[0];\n",
    "    import math\n",
    "    imageDimension = int(math.sqrt(numPixels)); # Will be 28\n",
    "    rawPixels2D = numpy.reshape(rawPixels1D, (numTrials, imageDimension, imageDimension));\n",
    "\n",
    "numClasses = 10; # We know we only have digits 0-9 here\n",
    "print('Loaded MNIST data with %d samples, classes %d:%d, and %d pixels per sample\\n' %\\\n",
    "    (numTrials, min(classes), max(classes), numPixels));\n",
    "\n",
    "# Binarise the pixel data:\n",
    "threshold = 15; # From viewing histograms of pixel values this seems reasonable.\n",
    "pixels2D = rawPixels2D > threshold; # In dimensions (numTrials, imageDimension, imageDimension) \n",
    "pixels1D = rawPixels1D > threshold; # In dimensions (numTrials, imageDimension * imageDimension)\n",
    "\n",
    "# And check that we can plot of of the images ok from either the 1D or 2D arrangements:\n",
    "import matplotlib.pyplot as plt\n",
    "plt.figure(figsize=(12,6))\n",
    "plt.subplot(1,2,1) # left subplot\n",
    "sampleIndex = 2;\n",
    "plt.imshow( pixels2D[sampleIndex,:,:] ) # Plotting the 3rd digit as a sample\n",
    "plt.title('Sample %d from pixels2D (digit=%d)' % (sampleIndex, classes[sampleIndex]));\n",
    "plt.subplot(1, 2, 2); # right one\n",
    "plt.imshow( numpy.reshape(pixels1D[sampleIndex,:], (imageDimension, imageDimension) )) # Plotting the 3rd digit as a sample\n",
    "plt.title('Sample %d from pixels1D (digit=%d)' % (sampleIndex, classes[sampleIndex]));"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba2c73b5-6b75-4a5f-b0af-f4ebcde41176",
   "metadata": {},
   "source": [
    "# Your analysis goes next ...:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9cb664fb-ed00-4d3c-a923-bf84f406d761",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
