<jupyter_start><jupyter_text><NAME> - 200930437    5990M: Introduction to Programming for Geographical Information Analysis - Core Skills    __**Assignment 2: Investigating the Black Death**__ -------------------------------------------------------------  Project AimThe aim of the project hopes to build a model, based upon initial agent-based framework coding schemes, that generates an analysis into an aspect of 'The Black Death'. This project intends to calculate the fatalities from The Great Plague of London via the known population densities of London parishes in 1665. The generation of this measure from historical data will allow any correlation to be investigated and an overall map of total deaths to be produced. Furthermore, the final code should allow for manipulation in terms of changing parameter weights to investigate possible scenarios that could have ensued.   ContextThe Great Plague of London (1665-1666) was the last occurrence of the fatal ‘Black Death’ Plague that swept across Europe in the 1300s. The bubonic plague caused an epidemic across the 17th century parishes of London, as well as some smaller areas of the UK. The overcrowded city and hot Summer became a breeding ground for the bacterium Yersinia pestis disseminated by rat fleas – the known cause of the plague. Transmission was inevitable due to the high poverty levels, low sanitation rates, and open sewers in closely packed waste-filled streets; especially in poorer areas (Trueman, 2015). Deaths started slowly within the St. Giles’s Parish but rose alarmingly as documented by the weekly ‘Bill of Mortality’ that was legally required from each parish at the time (Defoe, 2005). The numbers of deaths slowed after 18 months due to quarantines, much of the population moving to the country and the onset of Winter, however, the final end emerged due to the Great Fire of London destroying central parts of the city in September 1666.   Data SourceThe calculation of the average death rate from the Great Plague will be generated from two raster maps. The model will be using known rat populations and average population densities of 16 different parishes within London, both from historical records, recorded by rat-catchers and parish figures in 1665, respectively. The original maps have data stored for each 400m x 400m area as text data, but the figures have been averaged to represent either the area covered by the Parish or the area within which the rat-catcher operates.    The relationship to calculate the average death rate from this source data is as follows: Death Rate = (0.8 x Rat Population)(1.3 x Population Density)    Model Expectations The model should first show maps of the original source data: the rat populations and population densities for the 16 investigated parishes. These maps will then be combined using the calculation to generate the average death rate from the Great Plague per week and will be mapped as an image. The final map will then be altered so the user will be able to manipulate the weights of either the rat population or the density population to envision how these alternate factors may change the overall death rate.     The code should run on Windows. ------------------------------------------------------------------------------ Part 1 - Read in Source Data<jupyter_code>'''Step 1 - Set up initial imports for programme'''
import random
%matplotlib inline 
import matplotlib.pyplot 
import matplotlib
import matplotlib.animation
import os
import requests
import tkinter
import pandas as pd #Shortened in standard python documentation format
import numpy as np #Shortened in standard python documentation format
import ipywidgets as widgets #Shortened in standard python documentation format<jupyter_output><empty_output><jupyter_text>Map 1 - Rat Populations (Average Rats caught per week)<jupyter_code>'''Step 2 - Import data for the rat populations and generate environment from the 2D array'''

#Set up a base path for the import of the rats txt file
base_path = "C:\\Users\\Home\\Documents\\MSc GIS\\Programming\\Black_Death\\BlackDeathProject" #Basepath
deathrats = "deathrats.txt" #Saved filename
path_to_file = os.path.join(base_path, deathrats)
f = open(path_to_file , 'r')
#mapA = f.read()
#print(mapA) #Test to show data has imported

#Set up an environment to read the rats txt file into - this is called environmentA
environmentA = []
for line in f:
    parsed_line = str.split(line, ",") #Split values up via commas
    rowlist = []
    for word in parsed_line:
        rowlist.append(float(word))
    environmentA.append(rowlist) #Append all lists individually so can print environment
f.close()
#print(environmentA) #Test environment appears and all lines run 

#Display environment of rat populations
matplotlib.pyplot.xlim(0, 400) #Set up x-axis
matplotlib.pyplot.ylim(0, 400) #Set up y-axis
matplotlib.pyplot.imshow(environmentA) #Shows the environment
matplotlib.pyplot.title('Average Rat Populations', loc='center') #Adds a centred title
hsv() #Altered colourmap to red-yellow-green-cyan-blue-pink-magenta display, from original viridis: aids user interpretation<jupyter_output><empty_output><jupyter_text>This map contains the data for the average rat populations denoted from the amount of rats caught per week. The data is initially placed into a text file which can be seen through print(mapA), but then has been put into an environment which is shown. The different colours show the different amounts of rats, however, this will have more useful when combined with Map 2 in Part 2 when calculating the overall death rates.   Map 2 - Average Population Densities (per Parish)<jupyter_code>'''Step 3 - Import data for the parish population densities and generate environment from the 2D array'''

#Set up a base path for the import of the parish txt file
#base_path = "C:\\Users\\Home\\Documents\\MSc GIS\\Programming\\Black_Death\\BlackDeathProject" #Basepath
deathparishes = "deathparishes.txt" #Saved filename
path_to_file = os.path.join(base_path, deathparishes)
fd = open(path_to_file , 'r')
#mapB = fd.read()
#print(mapB) #Test to show data has imported

#Set up an environment to read the parish txt file into - this is called environmentB
environmentB = []
for line in fd:
    parsed_line = str.split(line, ",") #Split values up via commas
    rowlist = []
    for word in parsed_line:
        rowlist.append(float(word))
    environmentB.append(rowlist) #Append all lists individually so can print environment
f.close()
#print(environmentB) #Test environment appears and all lines run 

#Display environment of parish populations
matplotlib.pyplot.xlim(0, 400) #Set up x-axis
matplotlib.pyplot.ylim(0, 400) #Set up y-axis
matplotlib.pyplot.imshow(environmentB) #Shows the environment
matplotlib.pyplot.title('Average Parish Population Densities', loc='center') #Adds a centred title
hsv() #Altered colourmap to red-yellow-green-cyan-blue-pink-magenta display, from original viridis: aids user interpretation<jupyter_output><empty_output><jupyter_text>This map contains the data for the average population densities per the 16 parishes investigated. The data is initially placed into a text file which can be seen through print(mapB), but then has been put into an environment which is shown. The different colours show the different populations per parish.  ------------------------------------------------------------------------------ Part 2 - Calculate the Average Death Rate<jupyter_code>'''Step 4 - Calculate Map of Average death rates '''

#Sets up a list named results to append all calculated values to
result = []

for r in range(len(environmentA)):#Goes through both environments' (A and B) rows
    row_a = environmentA[r] 
    row_b = environmentB[r]
    rowlist = []
    result.append(rowlist) #Append all lists individually so can merge values from environmentA and environmentB
    for c in range(len(row_a)): #Goes through both environments' (A and B) columns 
        rats = row_a[c]        
        parishes = row_b[c]
        # d = (0.8 x r) x (1.3 x p) Equation used to generate average death rate 
        d = (0.8 * rats) * (1.3 * parishes) #Puts values through death average equation with initial set parameters
        rowlist.append(d)
        #print(d) #Test that results array shows     

'''Step 5 - Plot and show the average death rates'''

#Sets up environment to display the results
matplotlib.pyplot.xlim(0, 400) #Set up x-axis
matplotlib.pyplot.ylim(0, 400) #Set up y-axis
matplotlib.pyplot.imshow(result) #Shows the environment
matplotlib.pyplot.title('Average Weekly Death Rates of the Great Plague', loc='center') #Adds a centred title
hsv() #Altered colourmap to red-yellow-green-cyan-blue-pink-magenta display, from original viridis: aids user interpretation


#To do: 
#Insert legend

'''Step 6 - Save the average death rate results as a seperate txt.file'''

np.savetxt('result.txt', result, fmt='%-6.2f' , newline="\r\n") #Each row should equal a new line on the map
#Results have been padded to a width of 6 and rounded to 2 decimal points within the txt.file<jupyter_output><empty_output><jupyter_text>The output map within Part 2 displays the average death rate calculations within the 400x400 environment of the parishes investigated. The results array has been saved as a  result.txt  file (rounded to two decimal points) that can be manipulated and utilised for further investigation.   ------------------------------------------------------------------------------ Part 3 - Display the Death Rate with Changing Parameters<jupyter_code>'''Step 7 - Set up Rat Population Parameter Slider'''

#Generate a slider for the rats parameter
sR = widgets.FloatSlider(
    value=0.8, #Initial parameter value set by the equation
    min=0, #Minimum of range is 0
    max=5.0, #Maximum of range is 5
    step=0.1, #Values get to 1 decimal place increments
    description='Rats:', #Label for slider
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.1f', 
) 
display(sR) #Dispays the parameter slider for rats that users can alter

'''Step 8 - Set up Parish Population Density Parameter Slider'''

#Generate a slider for the parish parameter
sP = widgets.FloatSlider(
    value=1.3, #Initial parameter value set by the equation
    min=0, #Minimum of range is 0
    max=5.0, #Maximum of range is 5
    step=0.1, #Values get to 1 decimal place increments
    description='Parishes:', #Label for slider
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='.1f',
) 
display(sP) #Displays the parameter slider for parish population that users can alter<jupyter_output><empty_output><jupyter_text>The sliders above are available to alter to investigate the relationship between the rat population values and the average population density amounts. These will then be the next set parameters when the proceeding cell is run.<jupyter_code>'''Step 9 - Display the Changed Parameters '''

#Formatting to display parameter amounts to correlate to the underlying map
print('Changed Parameter Values')
print('Rats:', sR.value) 
print('Parishes:', sP.value)


'''Step 10 - Create a map of the death rate average with new changed parameters'''

#Alter the results list to incorporate the altered parameter values
result = []

for r in range(len(environmentA)): #Goes through both environments' (A and B) rows
    row_a = environmentA[r]
    row_b = environmentB[r]
    rowlist = []
    result.append(rowlist) #Append all lists individually so can merge values from environmentA and environmentB
    for c in range(len(row_a)): #Goes through both environments' (A and B) columns
        rats = row_a[c]        
        parishes = row_b[c]
        # d = (0.8 x r) x (1.3 x p) #Original equation used to generate average death rate 
        d = (sR.value * rats) * (sP.value * parishes) #Updated equation to show the altered parameter values
        rowlist.append(d)
         #print(d) #Test that results array has updated
            
#Set up a larger figure view of the final map
fig = matplotlib.pyplot.figure(figsize=(7,7))
ax = fig.add_axes([0, 0, 1, 1])

matplotlib.pyplot.xlim(0, 400) #Set up x-axis
matplotlib.pyplot.ylim(0, 400) #Set up y-axis
matplotlib.pyplot.imshow(result) #Display the final map
matplotlib.pyplot.xlabel('Rat Populations') #Label the x-axis
matplotlib.pyplot.ylabel('Parish Densities') #Label the y-axis
matplotlib.pyplot.title('Average Weekly Death Rates of the Great Plague at Altered Parameters', loc='center') #Adds a centred title
hsv() #Altered colourmap to red-yellow-green-cyan-blue-pink-magenta display, from original viridis: aids user interpretation

def update(d):
    d = (sR * rats)*(sP * parishes)
    rowlist.append(d) #Updates figure with new parameters
    
print('Average weekly death rate at these parameters =', round(d,2)) #Print the average weekly death rate with altered parameters to 2 decimal places<jupyter_output>Changed Parameter Values
Rats: 2.9
Parishes: 1.0
Average weekly death rate at these parameters = 29754.0
{'fraction_non_alphanumeric': 0.09049290401342897, 'fraction_numerical': 0.01381046848771555, 'mean_word_length': 3.9912414318354914, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '1356', 'license': 'BSL-1.0', 'n_tokens_mistral': 3661, 'n_tokens_neox': 3418, 'n_words': 1654, 'path': '.ipynb', 'repo_name': 'AGreen0/BlackDeathProject', 'size': '13109'}