diff --git a/01_DATAVIZ_TOOL.ipynb b/01_DATAVIZ_TOOL.ipynb index c114475..2cbfc7c 100644 --- a/01_DATAVIZ_TOOL.ipynb +++ b/01_DATAVIZ_TOOL.ipynb @@ -1,1247 +1,1242 @@ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Wall structural behaviour\n", "\n", "This script reproduces the results of the shear-compression tests, focusing on the structural behaviour of the walls. Part of the results that are reproduced by the script are contained in the journal article: \n", "\n", "Godio M., Vanin F., Zhang S. & Beyer K. (2019) \"Quasi-static shear-compression tests on stone masonry walls with plaster: Influence of load history and axial load ratio\". Engineering Structures. https://doi.org/10.1016/j.engstruct.2019.04.041" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Created by: M. Godio (EESD @ EPFL) on: August 3 2019 - \n", "Last modification by: M.Godio on: August 14 2019`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Import libraries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section imports the Python libraries needed to run this script" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Libraries have been imported\n" ] } ], "source": [ "# libraries to import\n", "import os\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import scipy.io as sio\n", "\n", "from matplotlib import rc\n", "from scipy.signal import find_peaks\n", "from tabulate import tabulate\n", "from scipy.interpolate import interp1d\n", "\n", "# to install a library from the anaconda prompt, run a command of the kind:\n", "# pip install numpy\n", "\n", "print(\" Libraries have been imported\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Define classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section defines the classes used in this script" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Classes have been defined\n" ] } ], "source": [ "\"\"\" \n", "These classe contain the test data from shear-compression tests:\n", "F = horizontal force (kN)\n", "u = horizontal displacement (mm)\n", "N = vertical force (kN)\n", "v = vertical displacement (mm)\n", "ss = sampling step \n", "\"\"\"\n", "class Dataset_sc():\n", " \"\"\"Import the dataset contained in the -mat file.\"\"\"\n", " \n", " def __init__(self):\n", " \"\"\"Initialize variables.\"\"\" \n", " self.dataset = {}\n", " \n", " def get_mat_sc(self, pwd, nameset, test_num):\n", " \"\"\"import mat file and create dictionary out of it.\"\"\"\n", " dataset={}\n", " sio.loadmat(pwd + os.sep + nameset + '.mat',mdict=dataset);\n", " for test in range(test_num):\n", " self.dataset['Test' + str(test)] = {}\n", " F = []\n", " u = []\n", " N = []\n", " v = []\n", " ss = []\n", " for dataId in range(len(dataset['TESTS'][0][test][0])):\n", " F.append(dataset['TESTS'][0][test][0][dataId][0])\n", " u.append(dataset['TESTS'][0][test][2][dataId][0])\n", " N.append(dataset['TESTS'][0][test][1][dataId][0])\n", " v.append(dataset['TESTS'][0][test][3][dataId][0])\n", " ss.append(dataId+1)\n", " self.dataset['Test' + str(test)]['F'] = F\n", " self.dataset['Test' + str(test)]['u'] = u\n", " self.dataset['Test' + str(test)]['N'] = N\n", " self.dataset['Test' + str(test)]['v'] = v\n", " self.dataset['Test' + str(test)]['ss'] = ss\n", " print(\"The dataset \" + nameset + \" has been imported.\")\n", " \n", "print(\" Classes have been defined\")\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Define functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section defines the functions used in this script" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Functions have been defined\n" ] } ], "source": [ "\"\"\"\n", "This function gives an xy line plot on a defined domain\n", "\"\"\"\n", "def plot_one(setname,x,y,col,lab_x,lab_y,leg_lab,leg_pos,x_lim_lw,x_lim_up,y_lim_lw,y_lim_up,if_grid,f_size,x_size,y_size,if_show):\n", " \n", " rc('text', usetex=True) \n", " # change font gloabally\n", " plt.rcParams[\"font.family\"] = \"Times New Roman\"\n", " \n", " # plot function\n", " plt.figure(figsize=(x_size,y_size))\n", " plt.plot(x, y, color = col)\n", "\n", " # config the graph\n", " plt.xlabel(lab_x, fontsize=f_size-1)\n", " plt.ylabel(lab_y, fontsize=f_size-1)\n", " plt.tick_params(axis='both', labelsize=f_size)\n", " plt.ylim([y_lim_lw, y_lim_up])\n", " plt.xlim([x_lim_lw, x_lim_up])\n", " plt.grid(if_grid)\n", " plt.legend([leg_lab], loc=leg_pos, fontsize = f_size-1, frameon = False)\n", " \n", " # save\n", " plt.savefig(setname + '.pdf',bbox_inches='tight')\n", " \n", " # show the graph\n", " if if_show == True:\n", " plt.show()\n", " else:\n", " plt.close()\n", " \n", "\"\"\"\n", "This function gives multiple xy line plots on the defined domain\n", "\"\"\"\n", "def plot_multi(setname,x,y,col,lab_x,lab_y,leg_lab,leg_pos,x_lim_lw,x_lim_up,y_lim_lw,y_lim_up,if_grid,f_size,x_size,y_size,if_show):\n", " \n", " rc('text', usetex=True) \n", " # change font gloabally\n", " plt.rcParams[\"font.family\"] = \"Times New Roman\"\n", " \n", " # plot function\n", " plt.figure(figsize=(x_size,y_size))\n", " for plot_index in range(len(x)):\n", " plt.plot(x[plot_index], y[plot_index], color = col[plot_index])\n", "\n", " # config the graph\n", " plt.xlabel(lab_x, fontsize=f_size-1)\n", " plt.ylabel(lab_y, fontsize=f_size-1)\n", " plt.tick_params(axis='both', labelsize=f_size)\n", " plt.ylim([y_lim_lw, y_lim_up])\n", " plt.xlim([x_lim_lw, x_lim_up])\n", " plt.grid(if_grid)\n", " plt.legend(leg_lab, loc=leg_pos, fontsize = f_size-1, frameon = False)\n", " \n", " # save\n", " plt.savefig(setname + '.pdf',bbox_inches='tight')\n", " \n", " # show the graph\n", " if if_show == True:\n", " plt.show()\n", " else:\n", " plt.close()\n", " \n", "\"\"\"\n", "This function gives the test label\n", "\"\"\"\n", "def test_unit(i):\n", " switcher={\n", " 0:'SC1',\n", " 1:'SC2',\n", " 2:'SC4',\n", " 3:'SC5',\n", " 4:'SC6',\n", " 5:'SC7'\n", " }\n", " return switcher.get(i)\n", "\n", "\"\"\"\n", "This function calcultes the envelope force-displacement curve starting from a cyclic one\n", "input: u = displacement array\n", " V = force array \n", " oddindex = 1 for positive envelope\n", " = 2 for negative envelope\n", "Note: the first peak in the negative envelope will be skipped \n", "not to obtain me too high values of initial stiffness\n", "\n", "Created by B. Wilding (EESD @ EPFL) in Matlab format\n", "Modified, and implemented in Python, by M. Godio (EESD @ EPFL)\n", "\"\"\"\n", "def fEnvelope(u,V,oddindex):\n", " \n", " # find peak position and value\n", " nPE, _ = find_peaks(u) #,distance=2) #,height=0.05,distance=2)\n", " uPE = u[nPE]\n", " nPE = np.append(nPE,len(u))\n", " uPE = np.append(uPE,u[len(u)-1])\n", " \n", " # decide from where to start in calculating the envelope\n", " if oddindex == 1:\n", " startfrom = 2 - 1\n", " else:\n", " startfrom = 3 - 1\n", "\n", " # calculate envelope only if input is cyclic response\n", " if len(nPE) == 0 or len(nPE) == 1:\n", " uE = u\n", " VE = V\n", " else:\n", " uE = 0\n", " VE = 0\n", " # take the origin plus the first valid point - only for positive envelope\n", " if oddindex == 1:\n", " uE = np.append(uE,u[0:nPE[0]])\n", " VE = np.append(VE,V[0:nPE[0]])\n", " for C in range(startfrom,len(nPE)):\n", " # if current peak > previous peak\n", " if uPE[C] > uPE[C-1]:\n", " ulap = u[nPE[C-1]+1:len(u)]\n", " if C == 1:\n", " max_prev = uPE[0]\n", " else:\n", " max_prev = max(uPE[0:C]) # this was C-1 and has changed to match matlab\n", " for ulap_index in range(len(ulap)):\n", " # look for first time value greater than peak ever seen\n", " if ulap[ulap_index] > max_prev:\n", " n_first = ulap_index\n", " break\n", " else:\n", " n_first = 1000\n", " init_pos_tmp = n_first + nPE[C-1] + 1 # nPE[C-1] in matlab\n", " end_pos_tmp = nPE[C] + 1 # nPE[C] in matlab\n", " if init_pos_tmp == end_pos_tmp: # new part in Python\n", " addu = u[init_pos_tmp:end_pos_tmp+1]\n", " addV = V[init_pos_tmp:end_pos_tmp+1]\n", " else:\n", " addu = u[init_pos_tmp:end_pos_tmp]\n", " addV = V[init_pos_tmp:end_pos_tmp]\n", " uE = np.append(uE, addu)\n", " VE = np.append(VE, addV)\n", " \n", " return uE, VE\n", "\n", "print(\" Functions have been defined\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Define working directories" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section defines the working directories used in the script:\n", "\n", "" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'os' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# get current working directory\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mcwd\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetcwd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;31m# define other working directories\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mwhere_to_import\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcwd\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msep\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m\"01_WALL_STRUCTURAL_BEHAVIOUR\"\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msep\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m\"INPUT_DATASET\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# get current working directory\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mcwd\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgetcwd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;31m# define other working directories\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mwhere_to_import\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcwd\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msep\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m\"01_WALL_STRUCTURAL_BEHAVIOUR\"\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msep\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m\"INPUT_DATASET\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mNameError\u001b[0m: name 'os' is not defined" ] } ], "source": [ "# get current working directory\n", "cwd = os.getcwd()\n", "\n", "# define other working directories\n", "where_to_import = cwd + os.sep + \"01_WALL_STRUCTURAL_BEHAVIOUR\" + os.sep + \"INPUT_DATASET\"\n", "\n", "print(\" Working directories have been defined\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.1 Define wall properties" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section defines the geometry and material properties of the test wall units tested in shear-compression: SC1, SC2, SC4, SC5, SC6, SC7. The variable test_number gives the number of tests performed. The dictionary wall containing the following variables is created:\n", "\n", "
    \n", "
  • height = wall height [mm]
  • \n", "
  • length = wall length [mm]
  • \n", "
  • thickness = wall thickness [mm]
  • \n", "
  • b = wall aspect ratio
  • \n", "
  • H0 = wall shear span [mm]
  • \n", "
  • N = axial load [kN]
  • \n", "
  • alr = axial load ratio
  • \n", "
  • LH = load history - for labels
  • \n", "
  • LHn = load history - for plots
  • \n", "
  • density = stone density [kg/m3]
  • \n", "
  • porosity = stone porosity [%]
  • \n", "
  • W = wall body weight [kN]
  • \n", "
  • fcm = masonry compressive strength [Mpa]
  • \n", "
  • fb = stone compressive strength [Mpa]
  • \n", "
  • fbt = stone tensile strength [MPa]
  • \n", " \n", "
" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Wall properties have been imported for all test units\n" ] } ], "source": [ "test_number = 6\n", "\n", "wall = {\n", " 'height': [900, 900, 900, 900, 900, 900],\n", " 'length': [900, 900, 900, 900, 900, 900],\n", " 'thickness': [200, 200, 200, 200, 200, 200],\n", " 'b': {},\n", " 'H0': [450, 450, 450, 450, 450, 450],\n", " 'N': {},\n", " 'alr': [7.5, 10., 15., 11.5, 11.5, 11.5],\n", " 'LH': ['$LH1$', '$LH1$', '$LH1$', '$LH1$', '$LH2$', 'monotonic'],\n", " 'LHn':[1, 1, 1, 1, 2, 0],\n", " 'density': 2688,\n", " 'porosity': 7,\n", " 'W': {},\n", " 'fcm': 10, \n", " 'fb': 65.60, \n", " 'fbt': 8\n", "}\n", "\n", "for test in range(test_number):\n", " wall['N'][test] = wall['alr'][test]/100*wall['fcm']*wall['thickness'][test]*wall['length'][test]/1000\n", " wall['b'][test] = wall['height'][test]/wall['length'][test]\n", " wall['W'][test] = wall['height'][test]/1000*wall['length'][test]/1000*wall['thickness'][test]/1000*wall['density']*9.81/1000\n", "\n", "print(\" Wall properties have been imported for all test units\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.2 Import test data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section imports the dataset related to the structural behaviour of the walls. Tha data is contained in the corresponding TESTS MAT-file and is imported in the dictionary test which includes the following variables:\n", "
    \n", "
  • F = horizontal - shear - force
  • \n", "
  • u = horizontal displacement
  • \n", "
  • N = vertical - axial - force
  • \n", "
  • v = vertical displacement
  • \n", "
" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The dataset TESTS has been imported.\n" ] } ], "source": [ "sc_tests = Dataset_sc()\n", "sc_tests.get_mat_sc(where_to_import,'TESTS',6)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.8 Calculate envelope curves" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section computes the F-u envelope curves starting from the experimental curves. The envelopes are save in the dictionary envelope having the following structure:\n", "
    \n", "
  • envelope.positive = including the positive envelope
  • \n", "
  • envelope.negative = including the negative envelope
  • \n", "
\n", "Inside the dictionaries positive and negative the following variables are contained:\n", "
    \n", "
  • F = horizontal force
  • \n", "
  • u = horizontal displacement
  • \n", "
" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Envelope curves have been calculated for all test units\n" ] } ], "source": [ "# loop over the test units\n", "envelope = {}\n", "for test in range(test_number):\n", " \n", " # initialize\n", " envelope['Test' + str(test)] = {\n", " 'positive': {},\n", " 'negative': {} \n", " }\n", " u = []; V = []\n", " uPos = []; VPos = []; indPos = []\n", " uNeg = []; VNeg = []; indNeg = []\n", " uEPos = []; VEPos = [] \n", " uENeg = []; VENeg = []\n", " \n", " # tmp arrays used for brevity in the notation\n", " u = np.array(sc_tests.dataset['Test' + str(test)]['u'])\n", " V = np.array(sc_tests.dataset['Test' + str(test)]['F'])\n", "\n", " # define type of loading\n", " if test == 5:\n", " # monotonic\n", " type = 1 \n", " else:\n", " # cyclic\n", " type = 0 \n", " \n", " # calculate envelope response\n", " if type == 1:\n", " uEPos, VEPos = fEnvelope(u,V,1)\n", " uENeg = uEPos \n", " VENeg = VEPos\n", " else:\n", " #positive response\n", " uPos = np.array([val for val in u if val >= 0])\n", " indPos = [ind for ind in range(len(u)) if u[ind] >= 0]\n", " VPos = np.array([V[ind] for ind in indPos])\n", " # negative response\n", " uNeg = np.array([val for val in u if val <= 0])\n", " indNeg = [ind for ind in range(len(u)) if u[ind] <= 0]\n", " VNeg = np.array([V[ind] for ind in indNeg])\n", " # envelopes\n", " uEPos, VEPos = fEnvelope(uPos,VPos,1)\n", " uENeg, VENeg = fEnvelope(-uNeg,-VNeg,2)\n", " \n", " # apply corrections\n", " if test == 0:\n", " uEPosTmp = []\n", " VEPosTmp = []\n", " oo = 0;\n", " jobdone = 0;\n", " for kk in range(len(uEPos)):\n", " if kk > 44 and kk < 56:\n", " if jobdone == 0:\n", " oo += 1\n", " uEPosTmp = np.append(uEPosTmp,1.05)\n", " VEPosTmp = np.append(VEPosTmp,66.03)\n", " jobdone = 1\n", " else:\n", " oo += 1\n", " uEPosTmp = np.append(uEPosTmp,uEPos[kk]);\n", " VEPosTmp = np.append(VEPosTmp,VEPos[kk]);\n", " uEPos = []\n", " VEPos = []\n", " uEPos = uEPosTmp\n", " VEPos = VEPosTmp\n", "\n", " # save in dictionary\n", " envelope['Test' + str(test)]['positive']['F'] = VEPos\n", " envelope['Test' + str(test)]['positive']['u'] = uEPos\n", " envelope['Test' + str(test)]['negative']['F'] = VENeg\n", " envelope['Test' + str(test)]['negative']['u'] = uENeg\n", " \n", "print(\" Envelope curves have been calculated for all test units\")\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.10 Calculate key parameters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section computes the key parameters of the wall structural behaviour. The results contained in Table 3 and Table 4 of Godio et al. (2019) are reproduced. The parameters are appended to the key dictionary. Inside the dictionary the following variables are added:\n", "
    \n", "
  • peak_force = peak shear force, $V_\\text{max}$
  • \n", "
  • initial_stiffness = initial stiffness calculated as secant stiffness at 15% the peak force, $K_\\text{init}$
  • \n", "
  • delta_cracking = drift corresponding at the onset of cracking in the masonry, $\\delta_\\text{cr}$
  • \n", "
  • delta_yielding = drift at the yielding point of the bi-linear curve, $\\delta_\\text{y}$
  • \n", "
  • delta_max = drift measured when the peak force is reached, $\\delta_\\text{max}$
  • \n", "
  • delta_SD = drift at the Severe Damage (SD) limit state, $\\delta_\\text{SD}$
  • \n", "
  • delta_ultimate = ultimate drift, $\\delta_\\text{u}$
  • \n", "
  • delta_collapse = drift at collapse, $\\delta_\\text{c}$
  • \n", "
\n", "Each variable contains values for both the positive and the negative envelopes, e.g. peak_force.positive and peak_force.pegative, plus the average value peak_force.average\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# initialize the key dictionary\n", "key = {}\n", "for test in range(test_number):\n", " \n", " key['Test' + str(test)] = {\n", " 'peak_force':{},\n", " 'initial_stiffness':{},\n", " 'delta_cracking':{},\n", " 'delta_yielding':{},\n", " 'delta_max':{},\n", " 'delta_SD':{},\n", " 'delta_ultimate':{},\n", " 'delta_collapse':{},\n", " }\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Peak force" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # save in dictionary\n", " key['Test' + str(test)]['peak_force']['positive'] = max(envelope['Test' + str(test)]['positive']['F'])\n", " key['Test' + str(test)]['peak_force']['negative'] = max(envelope['Test' + str(test)]['negative']['F'])\n", " key['Test' + str(test)]['peak_force']['average'] = (key['Test' + str(test)]['peak_force']['positive'] + key['Test' + str(test)]['peak_force']['negative'])/2\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Initial stiffness" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "beta = 0.15\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive value\n", " u = []; F = []; f = []; u_pre = []; F_pre = []; ind_15_pos = []\n", " u = envelope['Test' + str(test)]['positive']['u']\n", " F = envelope['Test' + str(test)]['positive']['F']\n", " F_15_pos = beta*key['Test' + str(test)]['peak_force']['positive']\n", " ind_15_pos = [ind for ind in range(len(F)) if F[ind] >= F_15_pos]\n", " F_pre = F[0:ind_15_pos[0]+1]\n", " u_pre = u[0:ind_15_pos[0]+1]\n", " f = interp1d(F_pre, u_pre)\n", " u_15_pos = f(F_15_pos)\n", " key['Test' + str(test)]['initial_stiffness']['positive'] = F_15_pos/u_15_pos\n", "\n", " # negative value\n", " u = []; F = []; f = []; u_pre = []; F_pre = []; ind_15_neg = []\n", " u = envelope['Test' + str(test)]['negative']['u']\n", " F = envelope['Test' + str(test)]['negative']['F']\n", " F_15_neg = beta*key['Test' + str(test)]['peak_force']['negative']\n", " ind_15_neg = [ind for ind in range(len(F)) if F[ind] >= F_15_neg]\n", " F_pre = F[0:ind_15_neg[0]+1]\n", " u_pre = u[0:ind_15_neg[0]+1]\n", " f = interp1d(F_pre, u_pre)\n", " u_15_neg = f(F_15_neg)\n", " key['Test' + str(test)]['initial_stiffness']['negative'] = F_15_neg/u_15_neg\n", " \n", " # average value\n", " key['Test' + str(test)]['initial_stiffness']['average'] = (key['Test' + str(test)]['initial_stiffness']['positive'] + key['Test' + str(test)]['initial_stiffness']['negative'])/2\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Drift at masonry craking" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "\n", "# displacement values measured after visual inspection + DIC check\n", "def disp_cracking_positive(i):\n", " switcher={\n", " 0:1.0145,\n", " 1:0.8284,\n", " 2:0.6674,\n", " 3:1.0204,\n", " 4:0.9239,\n", " 5:1.48\n", " }\n", " return switcher.get(i)\n", "def disp_cracking_negative(i):\n", " switcher={\n", " 0:0.8821,\n", " 1:0.6767,\n", " 2:0.514,\n", " 3:1.29,\n", " 4:1.0567,\n", " 5:1.48\n", " }\n", " return switcher.get(i)\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive negative and average values\n", " key['Test' + str(test)]['delta_cracking']['positive'] = disp_cracking_positive(test)/wall['height'][test]*100\n", " key['Test' + str(test)]['delta_cracking']['negative'] = disp_cracking_negative(test)/wall['height'][test]*100\n", " key['Test' + str(test)]['delta_cracking']['average'] = (key['Test' + str(test)]['delta_cracking']['positive'] + key['Test' + str(test)]['delta_cracking']['negative'])/2\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Drift at yielding" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# note: I use here the interp function which is the closest to matlab interp1 function\n", "# initialize \n", "tmp_table = []\n", "beta = 0.70\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive value\n", " u = []; F = []; u_pre = []; F_pre = []; ind_70_pos = []\n", " u = envelope['Test' + str(test)]['positive']['u']\n", " F = envelope['Test' + str(test)]['positive']['F']\n", " F_70_pos = beta*key['Test' + str(test)]['peak_force']['positive']\n", " ind_70_pos = [ind for ind in range(len(F)) if F[ind] >= F_70_pos]\n", " F_pre = F[0:ind_70_pos[0]+1]\n", " u_pre = u[0:ind_70_pos[0]+1]\n", " key['Test' + str(test)]['delta_yielding']['positive'] = np.interp(F_70_pos, F_pre, u_pre)/wall['height'][test]*100\n", "\n", " # negative value\n", " u = []; F = []; u_pre = []; F_pre = []; ind_70_neg = []\n", " u = envelope['Test' + str(test)]['negative']['u']\n", " F = envelope['Test' + str(test)]['negative']['F']\n", " F_70_neg = beta*key['Test' + str(test)]['peak_force']['negative']\n", " ind_70_neg = [ind for ind in range(len(F)) if F[ind] >= F_70_neg]\n", " F_pre = F[0:ind_70_neg[0]+1]\n", " u_pre = u[0:ind_70_neg[0]+1]\n", " key['Test' + str(test)]['delta_yielding']['negative'] = np.interp(F_70_neg, F_pre, u_pre)/wall['height'][test]*100\n", "\n", " # average value\n", " key['Test' + str(test)]['delta_yielding']['average'] = (key['Test' + str(test)]['delta_yielding']['positive'] + key['Test' + str(test)]['delta_yielding']['negative'])/2\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Drift at peak" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive value\n", " u = []; F = []\n", " u = envelope['Test' + str(test)]['positive']['u']\n", " F = envelope['Test' + str(test)]['positive']['F']\n", " ind_peak = [ind for ind in range(len(F)) if F[ind] >= key['Test' + str(test)]['peak_force']['positive']]\n", " key['Test' + str(test)]['delta_max']['positive'] = u[ind_peak[0]]/wall['height'][test]*100\n", " \n", " # negative value\n", " u = []; F = []\n", " u = envelope['Test' + str(test)]['negative']['u']\n", " F = envelope['Test' + str(test)]['negative']['F']\n", " ind_peak = [ind for ind in range(len(F)) if F[ind] >= key['Test' + str(test)]['peak_force']['negative']]\n", " key['Test' + str(test)]['delta_max']['negative'] = u[ind_peak[0]]/wall['height'][test]*100\n", "\n", " # average value\n", " key['Test' + str(test)]['delta_max']['average'] = (key['Test' + str(test)]['delta_max']['positive'] + key['Test' + str(test)]['delta_max']['negative'])/2\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Drift at SD limit state" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive value\n", " key['Test' + str(test)]['delta_SD']['positive'] = min(3*key['Test' + str(test)]['delta_cracking']['positive'],key['Test' + str(test)]['delta_max']['positive'])\n", " \n", " # negative value\n", " key['Test' + str(test)]['delta_SD']['negative'] = min(3*key['Test' + str(test)]['delta_cracking']['negative'],key['Test' + str(test)]['delta_max']['negative'])\n", "\n", " # average value\n", " key['Test' + str(test)]['delta_SD']['average'] = min(3*key['Test' + str(test)]['delta_cracking']['average'],key['Test' + str(test)]['delta_max']['average'])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ultimate drift" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# note: I use here the interp function which is the closest to matlab interp1 function\n", "# initialize \n", "tmp_table = []\n", "beta = 0.80\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive value\n", " u = []; F = []; u_post = []; F_post = [];\n", " u = envelope['Test' + str(test)]['positive']['u']\n", " F = envelope['Test' + str(test)]['positive']['F']\n", " ind_peak = [ind for ind in range(len(F)) if F[ind] >= key['Test' + str(test)]['peak_force']['positive']][0]\n", " F_post = F[ind_peak:len(F)]\n", " u_post = u[ind_peak:len(u)]\n", " F_80 = beta*key['Test' + str(test)]['peak_force']['positive']\n", " if F[-1] < F_80:\n", " ind_80 = ind_peak + [ind for ind in range(len(F_post)) if F_post[ind] <= F_80][0] \n", " key['Test' + str(test)]['delta_ultimate']['positive'] = u[ind_80]/wall['height'][test]*100\n", " else:\n", " ind_80 = len(F)\n", " key['Test' + str(test)]['delta_ultimate']['positive'] = u[-1]/wall['height'][test]*100\n", " \n", " # negative value\n", " u = []; F = []; u_post = []; F_post = [];\n", " u = envelope['Test' + str(test)]['negative']['u']\n", " F = envelope['Test' + str(test)]['negative']['F']\n", " ind_peak = [ind for ind in range(len(F)) if F[ind] >= key['Test' + str(test)]['peak_force']['negative']][0]\n", " F_post = F[ind_peak:len(F)]\n", " u_post = u[ind_peak:len(u)]\n", " F_80 = beta*key['Test' + str(test)]['peak_force']['negative']\n", " if F[-1] < F_80:\n", " ind_80 = ind_peak + [ind for ind in range(len(F_post)) if F_post[ind] <= F_80][0] \n", " key['Test' + str(test)]['delta_ultimate']['negative'] = u[ind_80]/wall['height'][test]*100\n", " else:\n", " ind_80 = len(F)\n", " key['Test' + str(test)]['delta_ultimate']['negative'] = u[-1]/wall['height'][test]*100\n", "\n", " # minimum value\n", " if test == 4:\n", " key['Test' + str(test)]['delta_ultimate']['minimum'] = max(key['Test' + str(test)]['delta_ultimate']['positive'],key['Test' + str(test)]['delta_ultimate']['negative'])\n", " else:\n", " key['Test' + str(test)]['delta_ultimate']['minimum'] = min(key['Test' + str(test)]['delta_ultimate']['positive'],key['Test' + str(test)]['delta_ultimate']['negative'])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Drift at collapse" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "# initialize\n", "tmp_table = []\n", "\n", "# displacement values measured after visual inspection + DIC check\n", "def disp_collapse_positive(i):\n", " switcher={\n", " 0:40.63,\n", " 1:10.06,\n", " 2:11.51,\n", " 3:15.93,\n", " 4:2.1,\n", " 5:111.8860\n", " }\n", " return switcher.get(i)\n", "def disp_collapse_negative(i):\n", " switcher={\n", " 0:22.19,\n", " 1:21.93,\n", " 2:13.71,\n", " 3:21.84,\n", " 4:10.44,\n", " 5:111.8860\n", " }\n", " return switcher.get(i)\n", "\n", "# loop over the test units\n", "for test in range(test_number):\n", " \n", " # positive negative and average values\n", " key['Test' + str(test)]['delta_collapse']['positive'] = disp_collapse_positive(test)/wall['height'][test]*100\n", " key['Test' + str(test)]['delta_collapse']['negative'] = disp_collapse_negative(test)/wall['height'][test]*100\n", " if test == 4:\n", " key['Test' + str(test)]['delta_collapse']['minimum'] = max(key['Test' + str(test)]['delta_collapse']['positive'],key['Test' + str(test)]['delta_collapse']['negative'])\n", " else:\n", " key['Test' + str(test)]['delta_collapse']['minimum'] = min(key['Test' + str(test)]['delta_collapse']['positive'],key['Test' + str(test)]['delta_collapse']['negative'])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.11 Data Visualization Tool for Wall Structural Behaviour" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Import libraries" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ - "# Import libraries\n", + "# Import additional libraries for the dataviz tool\n", "import ipywidgets as widgets\n", - "\n", "from ipywidgets import FloatSlider\n", "from ipywidgets import interact, interactive, fixed, interact_manual, interactive_output, Text\n", - "\n", "from IPython.display import display\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", "import pandas as pd\n", "\n", "%matplotlib nbagg\n", "%matplotlib inline\n", "\n", "# to be able to use widgets I need to install this through the anaconda prompt\n", "# conda install -c conda-forge nodejs\n", "# conda install -c conda-forge ipywidgets\n", "# jupyter labextension install @jupyter-widgets/jupyterlab-manager\n", "# jupyter nbextension enable --py widgetsnbextension\n", "# useful youtube video: https://www.youtube.com/watch?v=rkBPgTL-D3Y" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e78e4835eaec41fabd4fad5fd434eeb7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(VBox(children=(ToggleButtons(button_style='success', description='Test unit', index=2, options=…" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7797c14c689c4f91864e5c06f7f63dcb", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def select_units(i):\n", " switcher={\n", " 'F':'Horizontal Force (kN)',\n", " 'N':'Vertical Force (kN)',\n", " 'u':'Horizontal Displacement (mm)',\n", " 'v':'Vertical Displacement (mm)',\n", " }\n", " return switcher.get(i)\n", "\n", "def select_add(i):\n", " switcher={\n", " 'None':None,\n", " 'Positive Envelope':print('ciao'),\n", " 'Negative Envelope':None,\n", " }\n", " return switcher.get(i)\n", "\n", "def update_plot(test, xaxis, yaxis, add_PosEnv, add_NegEnv, colour, f_size, if_grid, what_to_save, where_to_save):\n", " \"\"\"\n", " this function gets called to update the plot\n", " \"\"\"\n", " if not where_to_save.strip():\n", " where_to_save = 'C:\\Temp'\n", " \n", " test_ind = [ind for ind in range(len(w_test.options)) if w_test.options[ind] == w_test.value][0]\n", "\n", " x = sc_tests.dataset['Test' + str(test_ind)][xaxis]\n", " y = sc_tests.dataset['Test' + str(test_ind)][yaxis]\n", " \n", " plt.figure(figsize=(8,6))\n", " plt.plot(x,y, color = colour)\n", " \n", " if add_PosEnv == True:\n", " plt.plot(envelope['Test' + str(test_ind)]['positive']['u'], envelope['Test' + str(test_ind)]['positive']['F'], color = \"blue\" )\n", " if add_NegEnv == True:\n", " plt.plot(-envelope['Test' + str(test_ind)]['negative']['u'], -envelope['Test' + str(test_ind)]['negative']['F'], color = \"red\" )\n", " \n", " x_lim_lw = 1.2*min(sc_tests.dataset['Test' + str(test_ind)][xaxis])\n", " x_lim_up = 1.2*max(sc_tests.dataset['Test' + str(test_ind)][xaxis])\n", " y_lim_lw = 1.2*min(sc_tests.dataset['Test' + str(test_ind)][yaxis])\n", " y_lim_up = 1.2*max(sc_tests.dataset['Test' + str(test_ind)][yaxis])\n", " plt.xlim([x_lim_lw, x_lim_up])\n", " plt.ylim([y_lim_lw, y_lim_up])\n", " plt.xlabel(select_units(xaxis), fontsize = f_size-1)\n", " plt.ylabel(select_units(yaxis), fontsize = f_size-1)\n", " \n", " plt.tick_params(axis='both', labelsize = f_size)\n", " if if_grid == True:\n", " plt.grid(if_grid)\n", " \n", " if what_to_save == \"Figure\":\n", " plt.savefig(where_to_save + '\\Test_' + test + '_' + xaxis + '-' + yaxis + '.pdf', bbox_inches = 'tight')\n", " print('Plots have been saved in ' + where_to_save)\n", " \n", " if what_to_save == \"Data\":\n", " data_x1 = pd.DataFrame({xaxis: sc_tests.dataset['Test' + str(test_ind)][xaxis]})\n", " data_y1 = pd.DataFrame({yaxis: sc_tests.dataset['Test' + str(test_ind)][yaxis]})\n", " data_t = data_x1.join(data_y1)\n", " if add_PosEnv == True:\n", " data_x2 = pd.DataFrame({'u, Pos. Env': envelope['Test' + str(test_ind)]['positive']['u']})\n", " data_y2 = pd.DataFrame({'F, Pos. Env.': envelope['Test' + str(test_ind)]['positive']['F']})\n", " data_t = data_t.join(data_x2)\n", " data_t = data_t.join(data_y2)\n", " if add_NegEnv == True:\n", " data_x3 = pd.DataFrame({'u, Neg. Env': - envelope['Test' + str(test_ind)]['negative']['u']})\n", " data_y3 = pd.DataFrame({'F, Neg. Env.': - envelope['Test' + str(test_ind)]['negative']['F']})\n", " data_t = data_t.join(data_x3)\n", " data_t = data_t.join(data_y3)\n", " data_t.to_csv(where_to_save + '\\Test_' + test + '_' + xaxis + '-' + yaxis + '.csv', index = False)\n", " print('Data have been saved in ' + where_to_save)\n", "\n", "w_test = widgets.ToggleButtons(\n", " options = ['SC1', 'SC2', 'SC4', 'SC5', 'SC6', 'SC7'],\n", " value = 'SC4',\n", " description = 'Test unit',\n", " disabled = False,\n", " button_style = 'success',\n", ")\n", "\n", "w_xaxis = widgets.ToggleButtons(\n", " options = ['F', 'N', 'u', 'v'],\n", " value = 'u',\n", " description = 'X axis',\n", " disabled = False,\n", ")\n", "\n", "w_yaxis = widgets.ToggleButtons(\n", " options = ['F', 'N', 'u', 'v'],\n", " value = 'F',\n", " description = 'Y axis',\n", " disabled = False,\n", ")\n", "\n", "w_colour = widgets.ColorPicker(\n", " concise = False,\n", " description = 'Plot options',\n", " value = 'black',\n", " disabled = False\n", ")\n", "\n", "w_add_PosEnvelope = widgets.Checkbox(\n", " value = False,\n", " description = 'Add positive envelope (for F-u)',\n", " disabled = False\n", ")\n", "\n", "w_add_NegEnvelope = widgets.Checkbox(\n", " value = False,\n", " description = 'Add negative envelope (for F-u)',\n", " disabled = False\n", ")\n", "\n", "w_f_size = widgets.IntSlider(\n", " value = 28,\n", " min = 2,\n", " max = 50,\n", " step = 1,\n", " description = 'Font size',\n", " disabled = False,\n", " continuous_update = False,\n", " orientation = 'horizontal',\n", " readout = True,\n", " readout_format = '.1f',\n", ")\n", "\n", "w_if_grid = widgets.Checkbox(\n", " value = True,\n", " description = 'Grid',\n", " disabled = False\n", ")\n", "\n", "w_save = widgets.ToggleButtons(\n", " options = ['Figure', 'Data'],\n", " value = None,\n", " description = 'Save',\n", " disabled = False,\n", " tooltips = ['Save plot in PDF-format','Save data in CSV-format'],\n", " button_style = 'warning',\n", ")\n", "\n", "w_path = widgets.Textarea(\n", " value='',\n", " placeholder='Folder where to save plots and tables',\n", " description='',\n", " disabled=False\n", ")\n", "\n", "out = interactive_output(update_plot, {\"test\":w_test, \"xaxis\":w_xaxis, \"yaxis\":w_yaxis, \"add_PosEnv\":w_add_PosEnvelope, \"add_NegEnv\":w_add_NegEnvelope, \n", " \"colour\":w_colour, \"f_size\":w_f_size, \"if_grid\":w_if_grid, \"what_to_save\":w_save, \"where_to_save\": w_path})\n", "\n", "hbox1 = widgets.VBox([w_test, w_yaxis, w_xaxis])\n", "hbox2 = widgets.HBox([w_add_PosEnvelope, w_add_NegEnvelope])\n", "hbox21 = widgets.HBox([widgets.HTML(value=\"​\",description='',)])\n", "hbox3 = widgets.HBox([w_colour, w_f_size, w_if_grid])\n", "hbox4 = widgets.HBox([w_save, w_path])\n", "ui = widgets.VBox([hbox1, hbox2, hbox3, hbox4])\n", "\n", "display(ui, out)\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.3" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }