Skip to content
Snippets Groups Projects
Commit 01225e30 authored by Adriaens, Ines's avatar Adriaens, Ines :v_tone2:
Browse files

adjust ethograms to show zones

parent b448cc49
No related branches found
No related tags found
No related merge requests found
No preview for this file type
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 8 16:47:19 2023
@author: adria036
"""
import os
os.chdir(r"C:\Users\adria036\OneDrive - Wageningen University & Research\iAdriaens_doc\Projects\cKamphuis\nlas\scripts\uwb")
#%% import modules
from datetime import date, datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import seaborn as sns
#%matplotlib qt
#%% import data, seth paths and constants
# path_out
svpath = r"C:\Users\adria036\OneDrive - Wageningen University & Research\iAdriaens_doc\Projects\cKamphuis\nlas\results\exploration"
# path to per barn areas
path = os.path.join("W:","\ASG","WLR_Dataopslag","DairyCampus","3406_Nlas","uwb_processed")
path_zones = os.path.join("W:","\ASG","WLR_Dataopslag","DairyCampus","3406_Nlas","raw","dc_sewio")
fna = "\\Barn_areas.xlsx"
area_zones = pd.read_excel(path_zones+fna, sheet_name = "areas")
# barn_edges = pd.read_excel(path_zones+fna, sheet_name = "edges")
del fna, path_zones
# settings
settings = {'barn' : [60,61], # [60,61,62,70,71,72,73],
'startdate' : date(2022,10,1),
'enddate' : date(2022,10,10),
'cows' : [2658,2155], # or specific cow number
}
# files that comply with settings
fn = []
for b in range(0,len(settings["barn"])):
print("barn = " + str(settings["barn"][b]))
if settings["cows"] == 0:
fbarn = [f for f in os.listdir(path + "/barn" + str(settings["barn"][b])) \
if os.path.isfile(os.path.join(path,"barn"+str(settings["barn"][b]),f)) \
and (datetime.strptime(f[5:13], '%Y%m%d').date() >= settings["startdate"]) \
and (datetime.strptime(f[5:13], '%Y%m%d').date() <= settings["enddate"])]
fbarn.sort()
else:
fbarn = [f for f in os.listdir(path + "/barn" + str(settings["barn"][b])) \
if os.path.isfile(os.path.join(path,"barn"+str(settings["barn"][b]),f)) \
and (int(f[26:-4]) in settings["cows"]) \
and (datetime.strptime(f[5:13], '%Y%m%d').date() >= settings["startdate"]) \
and (datetime.strptime(f[5:13], '%Y%m%d').date() <= settings["enddate"])]
fbarn.sort()
fn.extend(fbarn)
fn.sort()
# find unique cows
cows = list(set([int(f[26:-4]) for f in fn]))
# read data
data = pd.DataFrame([])
for f in fn:
barn = f[19:21]
sub = pd.read_csv(path + "/barn" + barn + "/" + f,
usecols = ["cowid","barn","date","t","xnew","ynew","area","zone","X","y"],
dtype = {"cowid" : "int64","barn" : "int64","date" : "object",
"t" : "int64", "xnew":"float64","ynew":"float64",
"area":"object","zone":"float64","X":"float64","y" : "float64"})
sub["date"] = pd.to_datetime(sub["date"], format = "%Y-%m-%d")
data = pd.concat([data,sub])
data = data.sort_values(by = ["cowid","date","t"])
data = data.reset_index(drop=1)
# correct the areas
cows = data["cowid"].drop_duplicates().reset_index(drop=1)
for cow in cows:
print(cow)
days = data.loc[(data["cowid"]==cow),["date"]].drop_duplicates()
days = days.sort_values(by = ["date"]).reset_index(drop=1)
for dd in days["date"]:
print(dd)
barnnr = int(data.loc[(data["cowid"] == cow) &
(data["date"] == dd),"barn"].mean())
myarea = area_zones.loc[(area_zones["barn"] == barnnr) | \
(area_zones["barn"].isna() == True) \
,:].reset_index(drop=1)
for j in range(0,len(myarea)):
x1,y1,x2,y2,x3,y3,x4,y4 = myarea[["x1","y1","x2","y2","x3","y3","x4","y4"]].values[j]
data.loc[((data["cowid"] == cow) & (data["date"] == dd) & \
(data["xnew"] >= x1) & (data["xnew"] <= x2) & \
(data["xnew"] >= x3) & (data["xnew"] <= x4) & \
(data["ynew"] >= y1) & (data["ynew"] >= y2) & \
(data["ynew"] <= y3) & (data["ynew"] <= y4)),"area"] = myarea["area"][j]
data.loc[((data["cowid"] == cow) & (data["date"] == dd) & \
(data["xnew"] >= x1) & (data["xnew"] <= x2) & \
(data["xnew"] >= x3) & (data["xnew"] <= x4) & \
(data["ynew"] >= y1) & (data["ynew"] >= y2) & \
(data["ynew"] <= y3) & (data["ynew"] <= y4)),"zone"] = myarea["zone"][j]
del x1,y1,x2,y2,x3,y3,x4,y4
del cows, dd, days
data.loc[data["zone"].isna(),"zone"] = 8
data.loc[data["zone"] == 8 ,"area"] = "unknown"
data["date"] = data["date"].dt.date
# check correctly read ids
print(data[["cowid","barn"]].drop_duplicates())
#%% RESTING BEHAVIOUR
cows = data["cowid"].drop_duplicates().reset_index(drop=1)
for cow in cows:
subset =
......@@ -16,8 +16,9 @@ import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib.patches import Rectangle
import seaborn as sns
from heatmap_visualisation import heatmap_barn
from heatmap_visualisation import heatmap_barn,heatmap_barn2
#%matplotlib qt
#%% set paths and constants and load data
......@@ -39,7 +40,7 @@ del fna, path_zones
# settings
settings = {'barn' : [60,61,62,70,71,72,73], # [60,61,62,70,71,72,73],
'startdate' : date(2022,10,1),
'enddate' : date(2022,10,15),
'enddate' : date(2022,10,2),
'cows' : [907,89,98,517,1748,495,3107], # or specific cow number
}
......@@ -260,8 +261,6 @@ for cow in cows:
# ------------------------- individual cow heatmaps ---------------------------
cows = data["cowid"].drop_duplicates().reset_index(drop=1)
#barn limits
barn = {"60":[64.8,75.6],
"61":[54,64.8],
......@@ -339,6 +338,11 @@ for cow in cows:
print(dd)
subset = data.loc[(data["cowid"]==cow) & \
(data["date"]==dd),:].copy()
# set limits (based on information barn)
barnnr = int(data.loc[(data["cowid"] == cow) &
(data["date"] == dd),"barn"].mean())
x_lim = barn[str(barnnr)]
y_lim = [-18,0]
fig, ax = plt.subplots(1, 2, gridspec_kw={'width_ratios': [3, 1.5]}, figsize = (22,7))
# plot scatter + line
......@@ -358,15 +362,10 @@ for cow in cows:
ax[0].set_xticks([0,14400,28800,43200,57600,72000,86400])
ax[0].set_xticklabels(['00:00','04:00','08:00','12:00','16:00','20:00','24:00'])
ax[0].set_xlabel("time [h]")
ax[0].set_title("cow = " + str(cow) + ', date = ' + str(dd))
ax[0].set_title("barn = " +str(barnnr) + ', cow = ' + str(cow) + \
", date = " + str(dd))
ax[0].set_xlim([-1000,87400])
# set limits (based on information barn)
barnnr = int(data.loc[(data["cowid"] == cow) &
(data["date"] == dd),"barn"].mean())
x_lim = barn[str(barnnr)]
y_lim = [-18,0]
# plot heatmap
ax[1] = heatmap_barn(subset["xnew"], subset["ynew"], 0.1, 0.1, x_lim, y_lim)
ax[1].set_xlabel('y coordinate')
......@@ -376,6 +375,37 @@ for cow in cows:
ax[1].xaxis.tick_top()
ax[1].yaxis.tick_right()
ax[1].yaxis.set_label_position("right")
# ax[1].invert_xaxis()
# plot rectangles ~ barn areas
myarea = area_zones.loc[(area_zones["barn"] == barnnr) | \
(area_zones["barn"].isna() == True) \
,:].reset_index(drop=1)
myarea = myarea.drop((myarea.loc[myarea["zone"]==7]).index)
myarea = myarea.drop((myarea.loc[myarea["zone"]==0]).index)
myarea = myarea.reset_index(drop=1)
yax = ax[1].get_ylim()
ycor = barn[str(barnnr)]
colors = []
for j in range(0,len(myarea)):
x1,y1,x2,y2,x3,y3,x4,y4 = myarea[["x1","y1","x2","y2","x3","y3","x4","y4"]].values[j]
color = myarea["area"][j]
X = y3*(-10)
W = (y2*(-10)) - X
Y = round((x1-ycor[0]),2)*10
H = round((x4-x3),2)*10
ax[1].add_patch(Rectangle((X,Y),W,H, color = palette[color],
fc = palette[color],
alpha = 0.15,
linestyle = 'dotted',
linewidth= 2
))
ax[1].add_patch(Rectangle((X,Y),W,H, color = palette[color],
fc = 'none',
linestyle = 'dotted',
linewidth= 2
))
del x2,y2,x3,y3,x4,y4,X,Y,H,W
plt.savefig(svpath+"\\spatial_cow_" + str(cow) + "_" + str(dd).replace("-","") + ".png")
plt.close()
\ No newline at end of file
......@@ -115,7 +115,9 @@ def heatmap_barn(data_x,data_y,xstep,ystep,x_lim,y_lim):
yticklabels = round(1/xstep),
xticklabels = round(1/ystep*2),
robust = True,
cbar = False
cbar = False,
cmap = "Greys_r"
# alpha = 0.5
)
return ax
......@@ -179,3 +181,142 @@ for cow in cows["cowid"]:
plt.close()
"""
def heatmap_barn2(
data_x, data_y, xstep, ystep, x_lim, y_lim, image_data=False, **kwargs
):
"""
Plot the frequency of positions registered, given data_x and data_y
xstep and ystep determine how fine these positions are taken
x_lim and y_lim set boundaries (e.g. incl feeding lane)
Parameters
----------
data_x : TYPE = Pandas series
Data of the x-coordinate as registered by the sewio system
data_y : TYPE = Pandas series
Data of the y-coordinate as registered by the sewio system
xstep : TYPE = float
How fine you want to determine location in x-direction (e.g. 1 is one
meter, 0.1 = 10 centimeters)
ystep : TYPE = float
How fine you want to determine location in x-direction (e.g. 1 is one
meter, 0.1 = 10 centimeters)
x_lim : TYPE = list of floats
Physical boundaries of plot you want to make (e.g. cut off feeding lane
then indicate lower boundary in y direction = -4)
y_lim : TYPE = list of floats
Physical boundaries of plot you want to make (e.g. cut off feeding lane
then indicate lower boundary in y direction = -4)
image_data : TYPE = bool
Do X,Y data originate from an image?
Returns
-------
ax : TYPE = sns heatmap
figure axes with heatmap
"""
# transform data_x and data_y for count
x_transf = (data_x * (1 / xstep)).round() * xstep
y_transf = (data_y * (1 / ystep)).round() * ystep
# put x_transf and y_transf in DataFrame
frame = {"xT": x_transf.round(decimals=4), "yT": y_transf.round(decimals=4)}
df = pd.DataFrame(frame)
# count and groupby
heatdata = df.groupby(["xT", "yT"]).size()
heatdata = heatdata.to_frame(name="counts")
heatdata = heatdata.reset_index()
# set limits to agree with steps
x_low = round(round(x_lim[0] * (1 / xstep)) * xstep, ndigits=4)
x_high = round(round(x_lim[1] * (1 / xstep)) * xstep, ndigits=4)
y_low = round(round(y_lim[0] * (1 / ystep)) * ystep, ndigits=4)
y_high = round(round(y_lim[1] * (1 / ystep)) * ystep, ndigits=4)
# delete the rows for which values are outside x_lim or y_lim
heatdata = heatdata.loc[
(heatdata["xT"] >= x_lim[0])
& (heatdata["xT"] <= x_lim[1])
& (heatdata["yT"] >= y_lim[0])
& (heatdata["yT"] <= y_lim[1])
]
heatdata.reset_index(drop=True, inplace=True)
# expected axes limits based on lim and step
x = np.arange(x_low, x_high + xstep, xstep, dtype=float)
y = np.arange(y_low, y_high + ystep, ystep, dtype=float)
# Create rectangular dataframe (x_high, y_high)
if image_data:
temp_holder = pd.DataFrame(
data={
"xT": pd.Series(
[
int(i)
for i in np.arange(x_low, x_high + 1, xstep, dtype=float)
for _ in np.arange(y_low, y_high + 1, ystep, dtype=int)
]
),
"yT": np.tile(
np.arange(y_low, y_high + 1, ystep, dtype=int),
len(np.arange(x_low, x_high + 1, xstep, dtype=float)),
),
}
)
else:
temp_holder = pd.DataFrame(
data={
"xT": pd.Series(
[
i
for i in np.arange(x_low, x_high, xstep, dtype=float)
for _ in np.arange(y_low, y_high, ystep, dtype=float)
]
),
"yT": np.tile(
np.arange(y_low, y_high, ystep, dtype=float),
len(np.arange(x_low, x_high, xstep, dtype=float)),
),
}
)
#
temp_holder["yT"] = round(temp_holder["yT"],1)
temp_holder["xT"] = round(temp_holder["xT"],1)
heatdata["yT"] = round(heatdata["yT"],1)
heatdata["xT"] = round(heatdata["xT"],1)
# merge into frame
tdf = pd.merge(temp_holder, heatdata, how="left", on=["xT", "yT"])
tdf["counts"] = tdf["counts"].fillna(0)
tdf = tdf.pivot(index="yT", columns="xT", values="counts").T
# convert to df with right colnames and indices
xcols = np.array(x.round(decimals=3),dtype = str)
ycols = np.flip(np.array(y.round(decimals=3),dtype = str))
# df = pd.DataFrame(tdf, columns = ycols, index = xcols)
defaultkwargs = {'yticklabels' : round(1 / ystep),
'xticklabels' : round(1 / xstep * 2),
'cmap' : plt.cm.YlOrRd_r,}
kwargs = {**defaultkwargs, **kwargs}
# make heatmap
ax = sns.heatmap(
tdf,
yticklabels = round(1/xstep),
xticklabels = round(1/ystep*2),
robust = True,
cbar = False,
cmap = "Greys"
)
return ax
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment