def loadFaultDict(file_path, reverse=False): #Load data raw_data = gix.loadCSV(file_path, row_ignore=0, col_ignore=0, isInput=False, isCategorical=False) #Create dict fault_dict = {} for i in range(len(raw_data)): fault_dict.update({raw_data[i][0] : [int(x) for x in raw_data[i][1:]]}) if reverse: fault_dict = {v: k for k, v in fault_dict.items()} return fault_dict
def loadPlaneGeometry(fault_name): plane_geometry = [] for i in range(len(fault_name)): #Load the data data = [] data_path = './faultPlanes/' + fault_name[i].split('_')[0] + '.cnrs' with open(data_path) as csvfile: readCSV = csv.reader(csvfile, delimiter=' ') for row in readCSV: single_line = [] for i in range(len(row)): if gix.isNumber(row[i]): single_line.append(float(row[i])) if len(single_line) > 1: data.append( gix.convertWGS2NZTM2000(single_line[0], single_line[1])) plane_geometry.append(np.array(data)) return plane_geometry
def loadRuptureDict(file_path, reverse=False): #Load data raw_data = gix.loadCSV(file_path) #Create dict rupt_dict = {} for i in range(len(raw_data)): rupt_dict.update({raw_data[i][0]: int(raw_data[i][1])}) if reverse: rupt_dict = {v: k for k, v in rupt_dict.items()} return rupt_dict
def loadRealStationID(file_path, reverse=False): #Load data raw_data = gix.loadCSV(file_path) #Create dict label_dict = {} for i in range(len(raw_data)): label_dict.update({raw_data[i][0]: raw_data[i][1]}) if reverse: label_dict = {v: k for k, v in label_dict.items()} return label_dict
def loadGM_clust(str_GM): #Get file names file_path_str = './data/' + str_GM + '*.csv' file_str = glob.glob(file_path_str) #Load every GM corresponding to this label GM = [] GM_lbl = [] for i in range(len(file_str)): GM_lbl.append(file_str[i][7:-4]) GM.append(gix.loadCSV(file_str[i])) return GM, GM_lbl
def loadCS_stationList(data_path): dic_CS = {} with open(data_path) as csvfile: readCSV = csv.reader(csvfile, delimiter=' ') for row in readCSV: if not len(row) == 1: #Input vector single_line = [] for i in range(len(row)): if gix.isNumber(row[i]): single_line.append(float(row[i])) else: if not row[i] == '': single_line.append(row[i]) dic_CS[single_line[2]] = gix.convertWGS2NZTM2000( single_line[0], single_line[1]) else: el = row[0].split('\t') dic_CS[el[2]] = gix.convertWGS2NZTM2000( float(el[0]), float(el[1])) return dic_CS
def loadGM_CS(data_path): M = [] with open(data_path) as csvfile: readCSV = csv.reader(csvfile) for row in readCSV: #Input vector single_line = [] for i in range(len(row)): if i == 0: single_line.append(row[i]) else: if gix.isNumber(row[i]): single_line.append(float(row[i])) else: single_line.append(row[i]) M.append(single_line) return M
import matplotlib.pyplot as plt import discr_utils as du import os ########################################### # User-defined parameters ########################################### #Selected IMs IM_considered = ['PGA', 'PGV', 'pSA_0.1', 'pSA_1.0', 'pSA_3.0', 'Ds595', 'AI'] #Test split test_split = 0.2 ########################################### #Import IM, station and label dict station_dict = gix.loadStationDict('station_dict.csv') label_dict = gcl.loadLabelDict('label_dict.csv') IM_dict = gix.loadIMDict('IM_dict.csv') lbl_GM = list(label_dict.values()) lbl_GM_orig = list(label_dict.keys()) IM_ID = [IM_dict[IM_considered[i]] for i in range(len(IM_considered))] #Import GM print('Load data...') data, GM_name = gcl.loadGM_clust('*') n_rupture = len(data) #Create result folder folder_path = './gen' try:
#Generator model name gen_model_name = 'Generator_RFEncod' #Discriminator model name discr_model_name = 'RF_discriminator' ########################################### #Create result folder dir_path = './gen/' if not os.path.exists(dir_path): os.mkdir(dir_path) #Load dictionaries print('Load ' + data_name + '...') realID = gml.loadRealStationID('./realStationID.csv') IM_name = gix.loadCSV('./selectedIM.csv') #Load rupture fault dictionary fault_dict = du.loadFaultDict('./fault_dict.csv') rupture_dict = du.loadRuptureDict('./rupture_dict.csv') #Load discriminator print('Load discriminator...') rf_load = open('./Discriminator/' + discr_model_name + '.mdl', 'rb') discriminator_GM = pickle.load(rf_load) #Load generator print('Load generator...') json_file = open('./Generator/' + gen_model_name + '/generator.json', 'r') loaded_model_json = json_file.read() json_file.close()
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load list of selected faults fault_select = gix.loadCSV('./selectedFault_list.csv') #Find the appropriate fault geometry file_path = glob.glob1('./NZ_Faults_NZTM2000/', '*.csv') fault_geometry = [] color_f = [] for i in range(len(file_path)): #Check if fault is selected isSelected = False for j in range(len(fault_select)): if fault_select[j][0] + '.' in file_path[i]: isSelected = True break if isSelected: fault_geometry_i = gix.loadCSV('./NZ_Faults_NZTM2000/' + file_path[i]) f_geo = [[x[0].split(';')[0], x[0].split(';')[1]]
from matplotlib import rc from sklearn.metrics import silhouette_score def cm2inch(value): return value / 2.54 ########################################### # User-defined parameters ########################################### ########################################### #Import faultList fault = gix.loadCSV('selectedFault_list.csv') #Load station dict lbl_dict = gcl.loadLabelDict('label_dict.csv') lbl = list(set(lbl_dict.values())) n_rupt = len(lbl) n_fault = len(fault) count = np.zeros(n_fault) Mw = [] for i in range(n_fault): fault[i][0] = fault[i][0] + '_' for i in range(n_rupt): lbl[i] = lbl[i][:-1]
import glob def cm2inch(value): return value/2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load PGA GM_raster = gix.loadCSV('./data/shakemapv2.csv') GM_raster = np.asarray(GM_raster) PGV = gix.loadCSV('./data/PGV_obs.csv') PGV = np.asarray(PGV) base = gix.loadCSV('./data/base.csv') base = np.asarray(base) orig = np.copy(GM_raster) #ind = np.where(PGV[:, 2] > 5) #orig = orig[ind, :] res_h = [] for i in range(len(orig[:, 0])): for j in range(len(base[:, 0])):
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load list of selected faults fault_select = gix.loadCSV('./selectedFault_list.csv') #Find the appropriate fault geometry file_path = glob.glob1('./NZ_Faults_NZTM2000/', '*.csv') fault_geometry = [] color_f = [] for i in range(len(file_path)): fault_geometry_i = gix.loadCSV('./NZ_Faults_NZTM2000/' + file_path[i]) f_geo = [[x[0].split(';')[0], x[0].split(';')[1]] for x in fault_geometry_i] fault_geometry.append(np.array(f_geo).astype(float)) #Check if fault is selected isSelected = False for j in range(len(fault_select)): if fault_select[j][0] + '.' in file_path[i]: isSelected = True
import glob def cm2inch(value): return value/2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load PGA GM_raster = gix.loadCSV('./data/shakemap_PGV.csv') GM_raster = np.asarray(GM_raster) IM_name = 'PGV' b_dict = {} str_lbl = {} b_dict['PGA'] = [0.025, 1.25] str_lbl['PGA'] = 'PGA [$g$]' str_lbl['PGV'] = 'PGV [$cm/s$]' b_dict['PGV'] = [2.5, 80.] str_file = 'shakemap_PGV.pdf' vmin = 0.0 #Load DEM NZI = './NZI/NZI.tif' raster = rio.open(NZI)
import numpy as np import matplotlib.pyplot as plt import GMdataImportFx as gmx from matplotlib import rc def cm2inch(value): return value / 2.54 #Import final training data_f = gmx.loadCSV('./Generator/Generator_RFEncod/trainingHistory.csv') data_t = gmx.loadCSV('./Generator/Generator_BTEncod/trainingHistory.csv') #Range for final training epoch_f = np.arange(1, len(data_f[0]) + 1) #Plot rc('text', usetex=True) rc('font', family='serif') fig, ax = plt.subplots() fig.set_size_inches(cm2inch(14), cm2inch(8)) #s1, = plt.plot(epoch_f, data_f[2], label='Training loss', linestyle='--', color='dimgrey') s2, = plt.plot(data_f[0], data_f[2], label='RF encoded - Validation loss', linestyle='-', color='black') p1, = plt.plot(data_f[0][np.argmin(data_f[2])], min(data_f[2]),
########################################### #Model name model_name = 'BT_discriminator.mdl' #IM used by the discriminator IM_name = 'AI' ########################################### #Load generator data name GM_name = np.load('./data/generator/X_name_test.npy') #Load dictionary of real stations realID = gml.loadRealStationID('./realStationID.csv') #Load dictionary of IM - position in file IM_dict = gix.loadIMDict('./IM_dict.csv') IM_ID = IM_dict[IM_name] + 3 #Load discriminator rf_load = open('./Discriminator/' + model_name, 'rb') discr = pickle.load(rf_load) #For each data name P = [] for i in range(len(GM_name)): #Load GM str_rupt = './data/discriminator/' + GM_name[i] + '.csv' GM = du.loadGM_1D(str_rupt, realID, IM_ID) #Get vector of P P.append(discr.predict_proba([GM]))
import numpy as np import GMdataImportFx as gmx import matplotlib.pyplot as plt import csv ########################################### # User-defined parameters ########################################### #Min moment magnitude considered Mw_min = 6.8 ########################################### faultList = gmx.loadCSV('./faultList.csv') Mw = [x[1] for x in faultList] for i in range(len(Mw)): if Mw[i] % 0.01 > 0.0: Mw[i] = Mw[i] - 0.2 #Empirical CDF CDF = [] step = 0.05 Mw_range = np.arange(5.0, 8.0, step) for i in range(len(Mw_range)): accu = 0 for j in range(len(Mw)): if Mw[j] < Mw_range[i]: accu = accu + 1 CDF.append(accu)
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load list of stations station = gix.loadStationDict('./station_dict.csv') station = np.array(list(station.values())) #Load DEM NZI = './NZI/NZI.tif' raster = rio.open(NZI) trf = raster.transform NZI = raster.read() ext = [ trf[0] - 50, trf[0] + 50 + NZI.shape[2] * 100, trf[3] - 50 - NZI.shape[1] * 100, trf[3] + 50 ] NZI = NZI[0] #Plot cmap = plt.cm.get_cmap('bwr')
import prepDx as pdx import matplotlib.pyplot as plt import glob #Name of IM to save IM_name = ['PGA', 'PGV', 'AI', 'pSA_0.5', 'pSA_1.0', 'pSA_3.0'] #Set grid cell size cell_size = 20000. #meters #Load station list station = pdx.loadVirtStationDict('virt_station_dict.csv') data = np.asarray(list(station.values())) #Load GM list for testing GM_test_lbl = gix.loadCSV('./GM_test.csv') #Rotate locations #Christchurch cathedral translation = [-1200000., -4570000.] loc_chch = gix.convertWGS2NZTM2000(172.6376, -43.5309) for i in range(len(data)): data[i] = gix.rotateCoordinate(loc_chch, data[i], 25.0) data[i] = gix.translateCoordinate(translation, data[i]) #Load label dict lbl_dict = gmc.loadLabelDict('./label_dict.csv') #Map station to grid loc station_rot_dict = {} station_name = list(station.keys())
import GMdataImportFx as gix import numpy as np import os import matplotlib.pyplot as plt import csv ########################################### # User-defined parameters ########################################### #Path to the main data file data_path = './data/DB_IM.csv' ########################################### #Import data print('Load data...') data = gix.loadCSV(data_path, isInput=False, row_ignore=1, col_ignore=0) #Convert station location print('Convert station coordinate system...') for i in range(len(data)): data[i][1:3] = gix.convertWGS2NZTM2000(data[i][1], data[i][2]) del data[i][3] #Collect stations and rupture labels data_ar = np.asarray(data).T station_str = data_ar[0].tolist() label_str = data_ar[25].tolist() station_loc_x = data_ar[1].tolist() station_loc_y = data_ar[2].tolist() station_loc_x = [float(x) for x in station_loc_x] station_loc_y = [float(x) for x in station_loc_y]
def saveGeneratorResultsComparison(GM_map, GM_obs, data_name, IM_name, saveSHP, savePlot): s = GM_map.shape translation = [1200000., 4570000.] rotation_angle = -25.0 rotation_pivot = gix.convertWGS2NZTM2000(172.6376, -43.5309) if saveSHP: #Create result folder dir_path = './gen/' + data_name + '/shp/' if not os.path.exists(dir_path): os.mkdir(dir_path) ext = [] NZI = [] if savePlot: #Create result folder dir_path = './gen/' + data_name + '/plot/' if not os.path.exists(dir_path): os.mkdir(dir_path) #Load the raster and rescale it NZI = './NZI/NZI.tif' raster = rio.open(NZI) trf = raster.transform print(trf) NZI = raster.read() ext = [ trf[2] - 50, trf[2] + 50 + NZI.shape[2] * 100, trf[5] - 50 - NZI.shape[1] * 100, trf[5] + 50 ] NZI = NZI[0] else: ext = None NZI = None grid_loc = [] for i in range(s[0]): for j in range(s[1]): x = i * 20000. y = j * 20000. loc = gix.translateCoordinate(translation, [y, x]) loc = gix.rotateCoordinate(rotation_pivot, loc, rotation_angle) grid_loc.append(loc) for i in range(s[2]): GM_raster = [] for j in range(s[0]): for k in range(s[1]): GM_raster.append([ grid_loc[j * s[1] + k][0], grid_loc[j * s[1] + k][1], np.exp(GM_map[j, k, i]) ]) with open('./gen/' + data_name + '/' + IM_name[i][0] + '_pred.csv', "w") as f: writer = csv.writer(f) writer.writerows(GM_raster) f.close() if saveSHP: str_file = './gen/' + data_name + '/shp/' + IM_name[i][ 0] + '_pred.shp' saveResultSHP(np.array(GM_raster), str_file) if savePlot: str_file = './gen/' + data_name + '/plot/' + IM_name[i][ 0] + '_pred.pdf' saveResultPlot(np.array(GM_raster), str_file, IM_name[i][0], NZI, ext) for i in range(s[2]): GM_raster = [] for j in range(s[0]): for k in range(s[1]): GM_raster.append([ grid_loc[j * s[1] + k][0], grid_loc[j * s[1] + k][1], np.exp(GM_obs[j, k, i]) ]) with open('./gen/' + data_name + '/' + IM_name[i][0] + '_obs.csv', "w") as f: writer = csv.writer(f) writer.writerows(GM_raster) f.close() if saveSHP: str_file = './gen/' + data_name + '/shp/' + IM_name[i][ 0] + '_obs.shp' saveResultSHP(np.array(GM_raster), str_file) if savePlot: str_file = './gen/' + data_name + '/plot/' + IM_name[i][ 0] + '_obs.pdf' saveResultPlot(np.array(GM_raster), str_file, IM_name[i][0], NZI, ext) for i in range(s[2]): GM_raster = [] for j in range(s[0]): for k in range(s[1]): GM_raster.append([ grid_loc[j * s[1] + k][0], grid_loc[j * s[1] + k][1], GM_map[j, k, i] - GM_obs[j, k, i] ]) with open('./gen/' + data_name + '/' + IM_name[i][0] + '_res.csv', "w") as f: writer = csv.writer(f) writer.writerows(GM_raster) f.close() if saveSHP: str_file = './gen/' + data_name + '/shp/' + IM_name[i][ 0] + '_res.shp' saveResultSHP(np.array(GM_raster), str_file) if savePlot: str_file = './gen/' + data_name + '/plot/' + IM_name[i][ 0] + '_res.pdf' saveResultPlot(np.array(GM_raster), str_file, IM_name[i][0], NZI, ext)
def saveFaultMap(P_fault, fault_name, str_file): #Load the raster and rescale it NZI = './NZI/NZI.tif' raster = rio.open(NZI) trf = raster.transform NZI = raster.read() ext = [ trf[2] - 50, trf[2] + 50 + NZI.shape[2] * 100, trf[5] - 50 - NZI.shape[1] * 100, trf[5] + 50 ] NZI = NZI[0] #Get the name of fault with P>0.01 ind = np.argwhere(P_fault > 0.0122) ind_fault = [] for i in range(len(ind)): ind_fault.append(ind[i][0]) fault_select = [] P_select = [] x1 = 10000000000.0 x2 = 0.0 y1 = 10000000000.0 y2 = 0.0 for i in range(len(ind_fault)): fault_select.append(fault_name[ind_fault[i]].split('_')[0]) P_select.append(P_fault[ind_fault[i]] * 100.) P_max = np.max(P_select) #Load fault geometries fault_geometry = [] for i in range(len(fault_select)): fault_geometry_i = gix.loadCSV('./NZ_Faults_NZTM2000/' + fault_select[i] + '.csv') f_geo = [[x[0].split(';')[0], x[0].split(';')[1]] for x in fault_geometry_i] fault_geometry.append(np.array(f_geo).astype(float)) for j in range(len(f_geo)): if float(f_geo[j][0]) > x2: x2 = float(f_geo[j][0]) if float(f_geo[j][0]) < x1: x1 = float(f_geo[j][0]) if float(f_geo[j][1]) > y2: y2 = float(f_geo[j][1]) if float(f_geo[j][1]) < y1: y1 = float(f_geo[j][1]) dx = 0.05 * (x2 - x1) dy = 0.05 * (y2 - y1) x1 = x1 - dx x2 = x2 + dx y1 = y1 - dy y2 = y2 + dy #Load planes plane_geometry = loadPlaneGeometry(fault_select) #Plot cmap = cmap = plt.cm.get_cmap('Reds') cmap_NZI = plt.cm.get_cmap('Greys_r') rc('text', usetex=True) rc('font', family='serif') im = plt.scatter(P_select, P_select, c=P_select, cmap=cmap, vmin=1., vmax=2.01) #P_max+0.01) cNorm = colors.Normalize(vmin=1.0, vmax=2.01) #P_max+0.01) scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cmap) fig, ax = plt.subplots() fig.set_size_inches(cm2inch(10), cm2inch(14)) ax.imshow(NZI, extent=ext, zorder=1, cmap=cmap_NZI) for i in range(len(fault_select)): col = scalarMap.to_rgba(P_select[i]) ax.plot(fault_geometry[i][:, 0], fault_geometry[i][:, 1], color=col, linewidth=1.25, zorder=5) for j in range(int(len(plane_geometry[i]) / 4)): ax.fill(plane_geometry[i][j * 4:j * 4 + 4, 0], plane_geometry[i][j * 4:j * 4 + 4, 1], zorder=3, alpha=0.6, c=col, linewidth=0.0) axins = zoomed_inset_axes(ax, 3., loc=2) axins.set_xlim(x1, x2) axins.set_ylim(y1, y2) axins.grid() axins.set_xticklabels([]) axins.set_yticklabels([]) axins.set_yticks([]) axins.set_xticks([]) axins.imshow(NZI, extent=ext, zorder=1, cmap=cmap_NZI) for i in range(len(fault_select)): col = scalarMap.to_rgba(P_select[i]) axins.plot(fault_geometry[i][:, 0], fault_geometry[i][:, 1], color=col, linewidth=1.25, zorder=5) for j in range(int(len(plane_geometry[i]) / 4)): axins.fill(plane_geometry[i][j * 4:j * 4 + 4, 0], plane_geometry[i][j * 4:j * 4 + 4, 1], zorder=3, alpha=0.6, c=col, linewidth=0.0) mark_inset(ax, axins, loc1=4, loc2=3, fc="none", ec="0.25", zorder=4) ax.set_xlim([ext[0], ext[1]]) ax.set_ylim([ext[2], ext[3]]) ax.set_xticks([1205923., 1600000., 1994077.]) ax.set_xticklabels(['168.0$^\circ$E', '173.0$^\circ$E', '178.0$^\circ$E']) ax.set_yticks([5004874., 5560252., 6115515.]) ax.set_yticklabels(['45.0$^\circ$S', '40.0$^\circ$S', '35.0$^\circ$S']) divider = make_axes_locatable(ax) cax = divider.append_axes('bottom', size='3%', pad=0.35) cb = plt.colorbar(im, orientation='horizontal', cax=cax, ticks=np.arange(1., 2. + 0.01, (2. - 1.) / 5.)) #P_max+0.01, (P_max-1.)/5.)) cb.ax.set_xlabel('Probability of rupture, [\%]') plt.tight_layout() plt.savefig(str_file, dpi=600) plt.close('all')
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load list of selected faults kaikoura = gix.loadCSV('./data/shakemapv2.csv') GM_raster = np.array(kaikoura) GM_raster = GM_raster[np.where(GM_raster[:, 2] > 2.5)] IM_name = 'PGV' b_dict = {} str_lbl = {} b_dict['PGA'] = [0.025, 1.25] str_lbl['PGA'] = 'PGA [$g$]' str_lbl['PGV'] = 'PGV [$cm/s$]' b_dict['PGV'] = [2.5, 80.] str_file = 'shakemap_PGV.pdf' vmin = 0.0 #Load DEM NZI = './NZI/NZI.tif'
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load PGA GM_raster = gix.loadCSV('./data/PGA_res_init.csv') GM_raster = np.asarray(GM_raster) PGV = gix.loadCSV('./data/PGV_obs.csv') PGV = np.asarray(PGV) base = gix.loadCSV('./data/base.csv') base = np.asarray(base) res_h_0 = np.copy(GM_raster) ind = np.where(PGV[:, 2] > 2.5) res_h_0 = res_h_0[ind, :] res_h = [] for i in range(len(ind[0])): for j in range(len(base[:, 0])):
import glob def cm2inch(value): return value/2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### ######################################################################### ######################################################################### #Load list of stations station = gix.loadStationDict('./station_dict.csv') station = np.array(list(station.values())) #Load waveforms s = 800000. wf0 = gix.loadCSV('./data/wf1.txt') wf0 = np.array(wf0) wf0 = wf0[:, 3:].astype(float)*s wf1 = gix.loadCSV('./data/wf2.txt') wf1 = np.array(wf1) wf1 = wf1[:, 3:].astype(float)*s wf2 = gix.loadCSV('./data/wf3.txt') wf2 = np.array(wf2) wf2 = wf2[:, 3:].astype(float)*s
########################################### # User-defined parameters ########################################### #Selected IM IM_name = 'Ds595' #Min number of exaple per label N_min = 8 #Save map and silhouette score plots (True = yes) savePlots = True ########################################### #Import faultList fault = gix.loadCSV('selectedFault_list.csv') #fault = fault[0] #Load station dict station_dict = gix.loadStationDict('station_dict.csv') #Load IM dict IM_dict = gix.loadIMDict('./IM_dict.csv') IM_ID = IM_dict[IM_name] #Initialize dict label dict_GM = {} if savePlots: #Create results folder folder_path = './gen'
def cm2inch(value): return value / 2.54 ######################################################################### ######################################################################### # User-defined paramters ######################################################################### #Fault name fault_name = 'ConwayOS' ######################################################################### ######################################################################### #Load hypocentre locations data = gix.loadCSV('./rupture_info.csv', row_ignore=1) data = np.array(data) lbl = data[:, 0] data = data[:, [1, 2]].astype(float) #Convert locations loc = gix.convertWGS2NZTM2000(data[:, 1], data[:, 0]) loc = np.array(loc) #Load label dict lbl_dict = gml.loadLabelDict('./label_dict.csv') #Select hypocentres from fault name i_rupt = [] for i in range(len(lbl)): if fault_name + '_' in lbl[i]: