# AUTOGENERATED! DO NOT EDIT! File to edit: 02_inclinometers.ipynb (unless otherwise specified).

__all__ = ['construct_df_csv', 'drop_columns', 'update_type_date', 'rename_columns', 'add_column_up', 'df_multiindex',
           'compute_average_A_B', 'compute_rotations', '__deformee__', 'column_integration', 'get_zero_measure_date',
           'column_deformee_relative', 'run_computation_inklino', 'extract_df_datetube', 'build_fig_defo']

# Cell
import pandas as pd
import numpy
import io
import csv
from datetime import datetime, date

from google.colab import files

from copy import copy

from datetime import timedelta
from datetime import datetime

import plotly.express as px
import plotly.graph_objects as go

import numpy as np

# Cell
def construct_df_csv(file_name):
  return pd.read_csv(file_name, delimiter=';')

# Cell
def drop_columns(df):

  to_drop = ['format_version',
             'site',
            #  'casing',
             'latitude', 'longitude', 'type',
             'direction', 'mode',
            #  'runs',
              'unit', 'step', 'length', 'azimuth',
              'site_description', 'tube_description', 'os', 'manufacturer', 'model',
              'type2', 'version', 'type3', 'serial', 'firmware', 'T', 'H', 'B', 'V',
              'P', 'serial4', 'firmware5', 'hardware', 'unit6', 'factor',
              'calibration', 'number', 'reference',
            #  'date',
              'delay', 'notes',
            #  'type7',
              'steps', 'number8',
            #  'depth',
              #  'A', 'B9',
              #  'T10',
              'H11', 'V12', 'S']

  df = df.drop(to_drop, 1)

  return df

# Cell
def update_type_date(df):

  str_days = [date.split('T')[0] for date in df['date']] #On conserve uniqument les jours

  dateFormatter = "%Y-%m-%d"

  df['date'] = [datetime.strptime(day, dateFormatter) for day in str_days]

  return df

# Cell
def rename_columns(df):
  df = df.rename(columns={'B9': 'B',
                          'T10': 'temp',
                          'casing': 'tube'})
  return df

# Cell
def add_column_up(df):
  #valeur + <--> A1B1
  df['info value'] = numpy.where(df['type7'] == 'A1B1', '+', '-')
  df = df.drop(['type7','runs'], 1)
  return df

# Cell
def df_multiindex(df):
  df_pivot = df.pivot(index=['date','tube','depth'], columns=['info value'],
                      values=['A', 'B'])
  return df_pivot

# Cell
def compute_average_A_B(df):
  df[('A', 'average')] = (df['A']['+'] - df['A']['-']) / 2.
  df[('B', 'average')] = (df['B']['+'] - df['B']['-']) / 2.

  df = df.sort_index(axis=1)

  return df

# Cell
def compute_rotations(df):

  konstant_inklino = 20000.

  df[('A','rotation')] = df[('A', 'average')] / konstant_inklino
  df[('B','rotation')] = df[('B', 'average')] / konstant_inklino

  df = df.sort_index(axis=1)

  return df

# Cell
def __deformee__(list_incl):
  """
  Retourne la liste du calcul de la déformée dans le sens (depth=0, depth=11.5)
  """
  w = 0
  list_w = []

  for theta in list_incl[::-1]:
    w += .5 * np.sin(theta)
    list_w.append(w)

  list_w.reverse()

  return list_w

# Cell
def column_integration(df):
  df = df.sort_index(axis=0)
  # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées

  idx = pd.IndexSlice

  # Parcourir pour les couple (date, tube)
  elts_index = df.index.levels
  dates, tubes = elts_index[0], elts_index[1]

  for date in dates:
    for tube in tubes:
      df.loc[idx[date, tube], ('A','defo')] = __deformee__(df.loc[idx[date, tube], ('A','rotation')])
      df.loc[idx[date, tube], ('B','defo')] = __deformee__(df.loc[idx[date, tube], ('B','rotation')])

  df = df.sort_index(axis=1)

  return df

# Cell
def get_zero_measure_date(dates, start_date):
  """
  Given a start date returns the date of the measure closest in the past.
  dates: list of sorted datetetime.dates
  start_date: datetime.date
  """

  null_date = min(dates)

  for date in dates:
    if date <= start_date:
      null_date = date

  return null_date

# Cell
def column_deformee_relative(df, start_date):
  """
  Add a column "relative deformations". The reference value is the start_date
  All measures before this date are deleted
  """

  # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées
  # et évite les alertes de performance
  df = df.sort_index(axis=0)

  idx = pd.IndexSlice

  elts_index = df.index.levels
  dates, tubes = elts_index[0], elts_index[1]

  # getting null measure date
  date_0 = get_zero_measure_date(dates, start_date)

  nullmessungen_A = {}
  nullmessungen_B = {}

  # setting relative displacements columns
  # A priori la df sera toujours à deux tubes I1 et I2 mais permet de prevenir les cp
  for tube in tubes:
    nullmessungen_A[tube] = numpy.array(df.loc[idx[date_0, tube], ('A','defo')])
    nullmessungen_B[tube] = numpy.array(df.loc[idx[date_0, tube], ('B','defo')])

  for date in dates:
    for tube in tubes:
      df.loc[idx[date, tube], ('A','defo relat')] = numpy.array(df.loc[idx[date, tube], ('A','defo')]) - nullmessungen_A[tube]
      df.loc[idx[date, tube], ('B','defo relat')] = numpy.array(df.loc[idx[date, tube], ('B','defo')]) - nullmessungen_B[tube]

    # Remove measures before null measure
  df = df.truncate(before=date_0)

  return df

# Cell
def run_computation_inklino(inklino_file_name, start_date):
  """
  Fonction de computation des mesures inclino
  """
  # Importation sous df du fichier
  df_inklino = construct_df_csv(inklino_file_name)

  # Fonctions de traitement
  df_inklino = drop_columns(df_inklino)
  df_inklino = update_type_date(df_inklino)
  df_inklino = rename_columns(df_inklino)

  df_inklino = add_column_up(df_inklino)

  # Fonction pivot
  df_inklino = df_multiindex(df_inklino)

  # compute rotations and deformations
  df_inklino = compute_average_A_B(df_inklino)
  df_inklino = compute_rotations(df_inklino)

  # Add relative deformations
  df_inklino = column_integration(df_inklino)
  df_inklino = column_deformee_relative(df_inklino, start_date)

  return df_inklino

# Cell
def extract_df_datetube(df, date, tube):
  idx = pd.IndexSlice
  return df.loc[idx[date, tube], :]

# Cell
def build_fig_defo(df, lettre='A'):

  fig = go.Figure()

  elts_index = df.index.levels
  dates, _ = elts_index[0], elts_index[1]

  x_min, x_max = 0, 0
  # Add traces, one for each slider step
  for date in dates:
    df_1 = extract_df_datetube(df, date, 'I1')
    df_2 = extract_df_datetube(df, date, 'I2')

    display_date = date.strftime("%d/%m/%Y")

    fig.add_trace(
        go.Scatter(
          visible=False,
          mode='lines+markers',
          line=dict(color="#D32F2F", width=1),
          name="Unverklebt",
          x=df_1[(lettre,'defo relat')],
          y=df_1.index    # depth
        ))
    fig.add_trace(
        go.Scatter(
          visible=False,
          mode='lines+markers',
          line=dict(color="#4DD0E1", width=1),
          name="Vorveklebt",
          x=df_2[(lettre,'defo relat')],
          y=df_2.index    # depth
        ))

    # Paramètres d'affichage
    x_min = min(min(df_1[(lettre,'defo relat')]),
                min(df_2[(lettre,'defo relat')]),
                x_min
                )

    x_max = max(max(df_1[(lettre,'defo relat')]),
                max(df_2[(lettre,'defo relat')]),
                x_max
                )

  x_max = max(x_max, abs(x_min))
  # Make 1st trace visible
  fig.data[0].visible = True
  fig.data[1].visible = True

  # fig data est une liste de plot / on souhaite tracer les graphs 2 à 2

  # Create and add slider
  steps = []
  for i in range(len(fig.data)//2):
      date_essai = dates[i]
      display_date = date_essai.strftime("%d/%m/%Y")
      step = dict(
          method="update",
          args=[{"visible": [False] * len(fig.data)},
                {"title": "Datum: " + display_date}],  # layout attribute
      )
      step["args"][0]["visible"][2*i] = True  # Toggle i'th trace to "visible"
      step["args"][0]["visible"][2*i+1] = True
      steps.append(step)

  # step = {'method': 'update', 'args': [{'visible': [True, False, False, False]},
  #                                       {'title': 'Slider switched to date: 0'}]}

  sliders = [dict(
      active=10,
      currentvalue={"prefix": "Step: "},
      pad={"t": 50}, # Espace slider graph
      steps=steps
  )]

  # Mise en page
  fig.update_layout(
      width=600,
      height=700,
      sliders=sliders,
      margin=dict(l=40, r=30, t=30, b=30),
      template='none',
      title_font=dict(family="Rockwell", size=18),
      legend=dict(
        orientation="h",
        yanchor="top",
        y=0.93,
        xanchor="center",
        x=0.5
      ),
  )

  fig.update_xaxes(
      domain=(0.2, 0.8),
      range=[-x_max*1.1, x_max*1.1],
      title='Bewegung ' + lettre + ' [m]'
  )

  fig.update_yaxes(
      domain=(0, 0.8),
      range=[12, 0],
      title='Tiefe [m]'
      )

  return fig
# AUTOGENERATED! DO NOT EDIT! File to edit: 02_inclinometers.ipynb (unless otherwise specified).

__all__ = ['construct_df_csv', 'drop_columns', 'update_type_date', 'rename_columns', 'add_column_up', 'df_multiindex',
           'compute_average_A_B', 'compute_rotations', '__deformee__', 'column_integration', 'get_zero_measure_date',
           'column_deformee_relative', 'run_computation_inklino', 'extract_df_datetube', 'build_fig_defo']

# Cell
import pandas as pd
import numpy
import io
import csv
from datetime import datetime, date

from google.colab import files

from copy import copy

from datetime import timedelta
from datetime import datetime

import plotly.express as px
import plotly.graph_objects as go

import numpy as np

# Cell
def construct_df_csv(file_name):
  return pd.read_csv(file_name, delimiter=';')

# Cell
def drop_columns(df):

  to_drop = ['format_version',
             'site',
            #  'casing',
             'latitude', 'longitude', 'type',
             'direction', 'mode',
            #  'runs',
              'unit', 'step', 'length', 'azimuth',
              'site_description', 'tube_description', 'os', 'manufacturer', 'model',
              'type2', 'version', 'type3', 'serial', 'firmware', 'T', 'H', 'B', 'V',
              'P', 'serial4', 'firmware5', 'hardware', 'unit6', 'factor',
              'calibration', 'number', 'reference',
            #  'date',
              'delay', 'notes',
            #  'type7',
              'steps', 'number8',
            #  'depth',
              #  'A', 'B9',
              #  'T10',
              'H11', 'V12', 'S']

  df = df.drop(to_drop, 1)

  return df

# Cell
def update_type_date(df):

  str_days = [date.split('T')[0] for date in df['date']] #On conserve uniqument les jours

  dateFormatter = "%Y-%m-%d"

  df['date'] = [datetime.strptime(day, dateFormatter) for day in str_days]

  return df

# Cell
def rename_columns(df):
  df = df.rename(columns={'B9': 'B',
                          'T10': 'temp',
                          'casing': 'tube'})
  return df

# Cell
def add_column_up(df):
  #valeur + <--> A1B1
  df['info value'] = numpy.where(df['type7'] == 'A1B1', '+', '-')
  df = df.drop(['type7','runs'], 1)
  return df

# Cell
def df_multiindex(df):
  df_pivot = df.pivot(index=['date','tube','depth'], columns=['info value'],
                      values=['A', 'B'])
  return df_pivot

# Cell
def compute_average_A_B(df):
  df[('A', 'average')] = (df['A']['+'] - df['A']['-']) / 2.
  df[('B', 'average')] = (df['B']['+'] - df['B']['-']) / 2.

  df = df.sort_index(axis=1)

  return df

# Cell
def compute_rotations(df):

  konstant_inklino = 20000.

  df[('A','rotation')] = df[('A', 'average')] / konstant_inklino
  df[('B','rotation')] = df[('B', 'average')] / konstant_inklino

  df = df.sort_index(axis=1)

  return df

# Cell
def __deformee__(list_incl):
  """
  Retourne la liste du calcul de la déformée dans le sens (depth=0, depth=11.5)
  """
  w = 0
  list_w = []

  for theta in list_incl[::-1]:
    w += .5 * np.sin(theta)
    list_w.append(w)

  list_w.reverse()

  return list_w

# Cell
def column_integration(df):
  df = df.sort_index(axis=0)
  # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées

  idx = pd.IndexSlice

  # Parcourir pour les couple (date, tube)
  elts_index = df.index.levels
  dates, tubes = elts_index[0], elts_index[1]

  for date in dates:
    for tube in tubes:
      df.loc[idx[date, tube], ('A','defo')] = __deformee__(df.loc[idx[date, tube], ('A','rotation')])
      df.loc[idx[date, tube], ('B','defo')] = __deformee__(df.loc[idx[date, tube], ('B','rotation')])

  df = df.sort_index(axis=1)

  return df

# Cell
def get_zero_measure_date(dates, start_date):
  """
  Given a start date returns the date of the measure closest in the past.
  dates: list of sorted datetetime.dates
  start_date: datetime.date
  """

  null_date = min(dates)

  for date in dates:
    if date <= start_date:
      null_date = date

  return null_date

# Cell
def column_deformee_relative(df, start_date):
  """
  Add a column "relative deformations". The reference value is the start_date
  All measures before this date are deleted
  """

  # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées
  # et évite les alertes de performance
  df = df.sort_index(axis=0)

  idx = pd.IndexSlice

  elts_index = df.index.levels
  dates, tubes = elts_index[0], elts_index[1]

  # getting null measure date
  date_0 = get_zero_measure_date(dates, start_date)

  nullmessungen_A = {}
  nullmessungen_B = {}

  # setting relative displacements columns
  # A priori la df sera toujours à deux tubes I1 et I2 mais permet de prevenir les cp
  for tube in tubes:
    nullmessungen_A[tube] = numpy.array(df.loc[idx[date_0, tube], ('A','defo')])
    nullmessungen_B[tube] = numpy.array(df.loc[idx[date_0, tube], ('B','defo')])

  for date in dates:
    for tube in tubes:
      df.loc[idx[date, tube], ('A','defo relat')] = numpy.array(df.loc[idx[date, tube], ('A','defo')]) - nullmessungen_A[tube]
      df.loc[idx[date, tube], ('B','defo relat')] = numpy.array(df.loc[idx[date, tube], ('B','defo')]) - nullmessungen_B[tube]

    # Remove measures before null measure
  df = df.truncate(before=date_0)

  return df

# Cell
def run_computation_inklino(inklino_file_name, start_date):
  """
  Fonction de computation des mesures inclino
  """
  # Importation sous df du fichier
  df_inklino = construct_df_csv(inklino_file_name)

  # Fonctions de traitement
  df_inklino = drop_columns(df_inklino)
  df_inklino = update_type_date(df_inklino)
  df_inklino = rename_columns(df_inklino)

  df_inklino = add_column_up(df_inklino)

  # Fonction pivot
  df_inklino = df_multiindex(df_inklino)

  # compute rotations and deformations
  df_inklino = compute_average_A_B(df_inklino)
  df_inklino = compute_rotations(df_inklino)

  # Add relative deformations
  df_inklino = column_integration(df_inklino)
  df_inklino = column_deformee_relative(df_inklino, start_date)

  return df_inklino

# Cell
def extract_df_datetube(df, date, tube):
  idx = pd.IndexSlice
  return df.loc[idx[date, tube], :]

# Cell
def build_fig_defo(df, lettre='A'):

  fig = go.Figure()

  elts_index = df.index.levels
  dates, _ = elts_index[0], elts_index[1]

  x_min, x_max = 0, 0
  # Add traces, one for each slider step
  for date in dates:
    df_1 = extract_df_datetube(df, date, 'I1')
    df_2 = extract_df_datetube(df, date, 'I2')

    display_date = date.strftime("%d/%m/%Y")

    fig.add_trace(
        go.Scatter(
          visible=False,
          mode='lines+markers',
          line=dict(color="#D32F2F", width=1),
          name="Unverklebt",
          x=df_1[(lettre,'defo relat')],
          y=df_1.index    # depth
        ))
    fig.add_trace(
        go.Scatter(
          visible=False,
          mode='lines+markers',
          line=dict(color="#4DD0E1", width=1),
          name="Vorveklebt",
          x=df_2[(lettre,'defo relat')],
          y=df_2.index    # depth
        ))

    # Paramètres d'affichage
    x_min = min(min(df_1[(lettre,'defo relat')]),
                min(df_2[(lettre,'defo relat')]),
                x_min
                )

    x_max = max(max(df_1[(lettre,'defo relat')]),
                max(df_2[(lettre,'defo relat')]),
                x_max
                )

  x_max = max(x_max, abs(x_min))
  # Make 1st trace visible
  fig.data[0].visible = True
  fig.data[1].visible = True

  # fig data est une liste de plot / on souhaite tracer les graphs 2 à 2

  # Create and add slider
  steps = []
  for i in range(len(fig.data)//2):
      date_essai = dates[i]
      display_date = date_essai.strftime("%d/%m/%Y")
      step = dict(
          method="update",
          args=[{"visible": [False] * len(fig.data)},
                {"title": "Datum: " + display_date}],  # layout attribute
      )
      step["args"][0]["visible"][2*i] = True  # Toggle i'th trace to "visible"
      step["args"][0]["visible"][2*i+1] = True
      steps.append(step)

  # step = {'method': 'update', 'args': [{'visible': [True, False, False, False]},
  #                                       {'title': 'Slider switched to date: 0'}]}

  sliders = [dict(
      active=10,
      currentvalue={"prefix": "Step: "},
      pad={"t": 50}, # Espace slider graph
      steps=steps
  )]

  # Mise en page
  fig.update_layout(
      width=600,
      height=700,
      sliders=sliders,
      margin=dict(l=40, r=30, t=30, b=30),
      template='none',
      title_font=dict(family="Rockwell", size=18),
      legend=dict(
        orientation="h",
        yanchor="top",
        y=0.93,
        xanchor="center",
        x=0.5
      ),
  )

  fig.update_xaxes(
      domain=(0.2, 0.8),
      range=[-x_max*1.1, x_max*1.1],
      title='Bewegung ' + lettre + ' [m]'
  )

  fig.update_yaxes(
      domain=(0, 0.8),
      range=[12, 0],
      title='Tiefe [m]'
      )

  return fig
# AUTOGENERATED! DO NOT EDIT! File to edit: 02_inclinometers.ipynb (unless otherwise specified). # Cell # Cell # Cell #  'casing', #  'runs', #  'date', #  'type7', #  'depth', #  'A', 'B9', #  'T10', # Cell #On conserve uniqument les jours # Cell # Cell #valeur + <--> A1B1 # Cell # Cell # Cell # Cell Retourne la liste du calcul de la déformée dans le sens (depth=0, depth=11.5) # Cell # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées # Parcourir pour les couple (date, tube) # Cell Given a start date returns the date of the measure closest in the past.   dates: list of sorted datetetime.dates   start_date: datetime.date # Cell Add a column "relative deformations". The reference value is the start_date   All measures before this date are deleted # Pour s'assurer que les hauteurs coincident avec les valeurs de defo ajoutées # et évite les alertes de performance # getting null measure date # setting relative displacements columns # A priori la df sera toujours à deux tubes I1 et I2 mais permet de prevenir les cp # Remove measures before null measure # Cell Fonction de computation des mesures inclino # Importation sous df du fichier # Fonctions de traitement # Fonction pivot # compute rotations and deformations # Add relative deformations # Cell # Cell # Add traces, one for each slider step # depth # depth # Paramètres d'affichage # Make 1st trace visible # fig data est une liste de plot / on souhaite tracer les graphs 2 à 2 # Create and add slider # layout attribute # Toggle i'th trace to "visible" # step = {'method': 'update', 'args': [{'visible': [True, False, False, False]}, #                                       {'title': 'Slider switched to date: 0'}]} # Espace slider graph # Mise en page