# Activity measurement of the movement data
# Developer: Mohsen Ahmadkhani
# Date: May 2019
# Commenting date: Nov 2020
# Note: This code was programmed more than a year ago! I was a beginner in Python at that time.
# That being said, this code is not pythionic and efficient at all. But, the output is tested and correct.

import pandas as pd
import numpy as np
import statistics as stat
import math
import time

start_time = time.time()

# Reading the preprocessed Moose GPS data
df = pd.read_csv("aa00_f_75.csv")

# Everywhere in the script "C" as a suffix denotes Calf and "D" stands for Dam

k = 0
c = 0
i = 0
Total_DC = 0
Total_Du = 0
Total_AC = 0
Total_DD = 0
Total_AD = 0
x = []
y = []
x_D = []
y_D = []
Numb = []
TD_C = []
TD_D = []
TA = []
TA_D = []
TDU = []
iCalfID = []
i_values = []
iCalfID = []
CollarID = []
PK = []
Dists_C = []
Dists_D = []
means = []
varis = []
means_D = []
varis_D = []
R_Squared_D = []
R_Squared2_D = []
R_Squared = []
R_Squared2 = []
Azimuths_C = []
Azimuths_D = []
Az_mean = []
Az_var = []
Az_mean_D = []
Az_var_D = []
Di_D = []
DI_Global = []
Di_Theta = []
Az_mean_D = []
Az_var_D = []
Az_mean_D = []
Az_var_D = []
C_Aban = []
C_Year = []
C_Twin = []
C_CID = []
C_COID = []
count = 1
did = 0
kk = 0
di_g = 0
diTheta = 0
join = 0
Joining = []
Percent = []
Sch = 0
Schism = []

# Do this for all 74 calves (an inefficient loop!)
while c < 75:
    for index, row in df.iterrows():  # looping over the rows of the dataframe

        if i < 5940:  # watching for the last line segment

            # df.iloc[i,3]--> trajectory unique id
            if (
                df.iloc[i, 3] == df.iloc[i + 1, 3] and count < 25
            ):  # selecting only the first 24 trajectory segments

                Total_DC = Total_DC + float(
                    df.iloc[i, 10]
                )  # Measuring total distance for calves' trajectories
                Total_AC = Total_AC + float(
                    df.iloc[i, 15]
                )  # Measuring total Azimuth for calves' trajectories
                Total_DD = Total_DD + float(df.iloc[i, 11])  # total traj length for dam
                Total_AD = Total_AD + float(df.iloc[i, 16])  # total Azimuth for Dam
                Total_Du = Total_Du + int(df.iloc[i, 14])  # total duration (~ 24 hours)

                if (
                    df.iloc[i, 19] < 21
                ):  # counting the number of reunions (if the calf-dam distance is smaller than or equal to 20 meters)
                    join += 1

                Sch = Sch + float(
                    df.iloc[i, 19]
                )  # Measuring the total schism between dam-calfs
                d_i_d = 1 - (
                    abs(df.iloc[i, 11] - df.iloc[i, 10])
                    / (df.iloc[i, 11] + df.iloc[i, 10])
                )  # local Di_D calculation
                did = did + d_i_d
                d_i_Th = math.cos(
                    (df.iloc[i, 16] - df.iloc[i, 15]) * math.pi / 180
                )  # local Di_Theta calculation
                diTheta = diTheta + d_i_Th
                di_g = di_g + d_i_d * d_i_Th  # local Di calculation

                # Copying the other columns in the new outputting file
                Dists_C.append(df.iloc[i, 10])
                Dists_D.append(df.iloc[i, 11])
                Azimuths_C.append(df.iloc[i, 15])
                Azimuths_D.append(df.iloc[i, 16])
                x.append(df.iloc[i, 5])
                y.append(df.iloc[i, 6])
                x_D.append(df.iloc[i, 17])
                y_D.append(df.iloc[i, 18])
                i += 1
                k += 1
                count += 1

            if (
                df.iloc[i, 3] == df.iloc[i + 1, 3] and count > 24
            ):  # If the length goes beyond 24 hours just ignore them.
                i += 1
                count += 1
            if (
                df.iloc[i, 3] != df.iloc[i + 1, 3]
            ):  # if one trajectory finishes, update the variables for that trajectory.

                iCalfID.append(df.iloc[i, 1])
                CollarID.append(df.iloc[i, 2])
                PK.append(df.iloc[i, 20])
                C_Aban.append(df.iloc[i, 22])
                C_Year.append(df.iloc[i, 21])
                C_Twin.append(df.iloc[i, 23])
                C_CID.append(df.iloc[i, 24])
                C_COID.append(df.iloc[i, 25])
                Joining.append(join)
                Schism.append(Sch)

                i_values.append(c)
                TD_C.append(Total_DC)
                TD_D.append(Total_DD)

                TA.append(
                    Total_AC / k
                )  # storing total (calf) Azimuth divided by the number of segments (24)
                TA_D.append(
                    Total_AD / k
                )  # storing total (dam) Azimuth divided by the number of segments (24)
                Percent.append(join / k)  # the percentage of reunions
                TDU.append(Total_Du)  # total duration (~24 hours)
                Numb.append(k)  # number of segments (24)
                means.append(stat.mean(Dists_C))  # average segment size for calves
                varis.append(
                    stat.variance(Dists_C)
                )  # variance of segment sizes for calves
                means_D.append(stat.mean(Dists_D))  # average segment size for dams
                varis_D.append(
                    stat.variance(Dists_D)
                )  # variance of segment sizes for dams

                Di_D.append(
                    did / k
                )  # calculating Global Di_d (distance) for the first 24 hours
                Di_Theta.append(
                    diTheta / k
                )  # calculating Global Di_theta (azimuth) for the first 24 hours
                DI_Global.append(
                    di_g / k
                )  # calculating Global Di for the first 24 hours

                Az_mean.append(
                    stat.mean(Azimuths_C)
                )  # average segment direction for calves
                Az_var.append(
                    stat.variance(Azimuths_C)
                )  # variance of segment directions for calves
                Az_mean_D.append(
                    stat.mean(Azimuths_D)
                )  # average segment direction for dams
                Az_var_D.append(
                    stat.variance(Azimuths_D)
                )  # variance of segment directions for dams

                x = []
                y = []
                x_D = []
                y_D = []
                c += 1
                k = 0
                Total_DC = 0
                Total_AC = 0
                Total_Du = 0
                did = 0
                di_g = 0
                diTheta = 0
                Sch = 0
                join = 0
                count = 1
                i += 1
        if (
            i == 5940
        ):  # if this is the last segment, break out (again, an inefficient code piece!)
            c += 1
            break

# Doing the same variable updating for the last (74th) trajectory
Total_DC = Total_DC + float(df.iloc[i + 1, 10])
Total_AC = Total_AC + float(df.iloc[i + 1, 15])
Total_DD = Total_DD + float(df.iloc[i + 1, 11])
Total_AD = Total_AD + float(df.iloc[i + 1, 16])
Total_Du = Total_Du + int(df.iloc[i + 1, 14])

d_i_d = 1 - (abs(df.iloc[i, 11] - df.iloc[i, 10]) / (df.iloc[i, 11] + df.iloc[i, 10]))
did = did + d_i_d
d_i_Th = math.cos((df.iloc[i, 16] - df.iloc[i, 15]) * math.pi / 180)
diTheta = diTheta + d_i_Th
di_g = di_g + d_i_d * d_i_Th
Dists_C.append(df.iloc[i + 1, 10])
Dists_D.append(df.iloc[i + 1, 11])
Azimuths_C.append(df.iloc[i + 1, 15])
Azimuths_D.append(df.iloc[i + 1, 16])
x.append(df.iloc[i + 1, 5])
y.append(df.iloc[i + 1, 6])
x_D.append(df.iloc[i + 1, 17])
y_D.append(df.iloc[i + 1, 18])
k += 1
iCalfID.append(df.iloc[i, 1])
CollarID.append(df.iloc[i, 2])
PK.append(df.iloc[i, 20])
C_Aban.append(df.iloc[i, 22])
C_Year.append(df.iloc[i, 21])
C_Twin.append(df.iloc[i, 23])
C_CID.append(df.iloc[i, 24])
C_COID.append(df.iloc[i, 25])
Joining.append(join)
Schism.append(Sch)

i_values.append(c)
TD_C.append(Total_DC)
TD_D.append(Total_DD)

TA.append(Total_AC / k)
TA_D.append(Total_AD / k)
Percent.append(join / k)
TDU.append(Total_Du)
Numb.append(k)
means.append(stat.mean(Dists_C))
varis.append(stat.variance(Dists_C))
means_D.append(stat.mean(Dists_D))
varis_D.append(stat.variance(Dists_D))

Di_D.append(did / k)
Di_Theta.append(diTheta / k)
DI_Global.append(di_g / k)

Az_mean.append(stat.mean(Azimuths_C))
Az_var.append(stat.variance(Azimuths_C))
Az_mean_D.append(stat.mean(Azimuths_D))
Az_var_D.append(stat.variance(Azimuths_D))


# exporting the output as a CSV file
np.savetxt(
    "24_DI.csv",
    np.column_stack(
        (
            i_values,
            PK,
            iCalfID,
            CollarID,
            TD_C,
            TD_D,
            TA,
            TA_D,
            TDU,
            means,
            means_D,
            varis,
            varis_D,
            Az_mean,
            Az_mean_D,
            Az_var,
            Az_var_D,
            Numb,
            Schism,
            Joining,
            Percent,
            Di_D,
            Di_Theta,
            DI_Global,
            C_Year,
            C_Aban,
            C_Twin,
            C_CID,
            C_COID,
        )
    ),
    header="0_i_values,PK,1_iCalfID,CollarID,T_Dist_C,T_Dist_D, Mean_Azimuth_C, Mean_Azimuth_D, Total_Duration, Step_Mean, Step_Mean_D, Step_variance,Step_variance_D, Az_mean,Az_mean_D,Az_variance_C, Az_variance_D, Number,Schism (Total D&C Dist), Joining (<26), Percent(join/num), Di_D, Di_Theta, DI_Global,C_Year,C_Aban,C_Twin,C_CID,C_COID",
    delimiter=",",
    fmt="%s",
)

print("--- %s seconds ---" % (time.time() - start_time))