def saveJacobian(save_filename, n_el=20, n_per_el=3): # number electrodes el_pos = np.arange(n_el * n_per_el) # create an object with the meshing characteristics to initialise a Forward object mesh_obj = mesh(n_el) fwd = Forward(mesh_obj, el_pos, n_el) ex_mat = train.generateExMat(ne=n_el) f, meas, new_ind = fwd.solve_eit(ex_mat=ex_mat, perm=fwd.tri_perm) #print(f) ind = np.arange(len(meas)) np.random.shuffle(ind) pde_result = train.namedtuple("pde_result", ['jac', 'v', 'b_matrix']) f = pde_result(jac=f.jac[ind], v=f.v[ind], b_matrix=f.b_matrix[ind]) meas = meas[ind] new_ind = new_ind[ind] h = h5.File(save_filename, 'w') try: h.create_dataset('jac', data=f.jac) h.create_dataset('v', data=f.v) h.create_dataset('b', data=f.b_matrix) h.create_dataset('meas', data=meas) h.create_dataset('new_ind', data=new_ind) h.create_dataset('p', data=mesh_obj['node']) h.create_dataset('t', data=mesh_obj['element']) except: TypeError('Error with saving files!') h.close()
def getNextPrediction(fileJac: str, measuring_electrodes: np.ndarray, voltages: np.ndarray, num_returned: int=10, n_el: int=20, n_per_el: int=3, n_pix: int=64, pert: float=0.5, p_influence: float=-10., p_rec: float=10., p: float=0.2, lamb:float=0.1) -> np.ndarray: # extract const permittivity jacobian and voltage (& other) file = h5.File(fileJac, 'r') meas = file['meas'][()] new_ind = file['new_ind'][()] p = file['p'][()] t = file['t'][()] file.close() # initialise const permitivity and el_pos variables perm = np.ones(t.shape[0], dtype=np.float32) el_pos = np.arange(n_el * n_per_el).astype(np.int16) mesh_obj = {'element': t, 'node': p, 'perm': perm} # list all possible active/measuring electrode permutations of this measurement meas = cp.array(meas) # find their indices in the already calculated const. permitivity Jacobian (CPJ) measuring_electrodes = cp.array(measuring_electrodes) measurements_0 = cp.amin(measuring_electrodes[:, :2], axis=1) measurements_1 = cp.amax(measuring_electrodes[:, :2], axis=1) measurements_2 = cp.amin(measuring_electrodes[:, 2:], axis=1) measurements_3 = cp.amax(measuring_electrodes[:, 2:], axis=1) measuring_electrodes = cp.empty((len(measuring_electrodes), 4)) measuring_electrodes[:, 0] = measurements_0 measuring_electrodes[:, 1] = measurements_1 measuring_electrodes[:, 2] = measurements_2 measuring_electrodes[:, 3] = measurements_3 index = (cp.sum(cp.equal(measuring_electrodes[:, None, :], meas[None, :, :]), axis=2) == 4) index = cp.where(index) #print(index) ind = cp.unique(index[1]) #print(ind) i = cp.asnumpy(ind) j = index[0] mask = np.zeros(len(meas), dtype=int) mask[i] = 1 mask = mask.astype(bool) # take a slice of Jacobian, voltage readings and B matrix (the one corresponding to the performed measurements) file = h5.File(fileJac, 'r') jac = file['jac'][mask, :][()] v = file['v'][mask][()] b = file['b'][mask, :][()] file.close() # put them in the form desired by the GREIT function pde_result = train.namedtuple("pde_result", ['jac', 'v', 'b_matrix']) f = pde_result(jac=jac, v=v, b_matrix=b) # now we can use the real voltage readings and the GREIT algorithm to reconstruct greit = train.greit.GREIT(mesh_obj, el_pos, f=f, ex_mat=(meas[index[1], :2]), step=None) greit.setup(p=p, lamb=lamb, n=n_pix) h_mat = greit.H reconstruction = greit.solve(voltages, f.v).reshape(n_pix, n_pix) # fix_electrodes_multiple is in meshing.py _, el_coords = train.fix_electrodes_multiple(centre=None, edgeX=0.1, edgeY=0.1, a=2, b=2, ppl=n_el, el_width=0.02, num_per_el=3) # find the distances between each existing electrode pair and the pixels lying on the liine that connects them pixel_indices, voltage_all_possible = measopt.find_all_distances(reconstruction, h_mat, el_coords, n_el, cutoff=0.8) # call function get_total_map that generates the influence map, the gradient map and the log-reconstruction total_map, grad_mat, rec_log = np.abs(measopt.get_total_map(reconstruction, voltages, h_mat, pert=pert, p_influence=p_influence, p_rec=p_rec)) # get the indices of the total map along the lines connecting each possible electrode pair total_maps_along_lines = total_map[None] * pixel_indices # find how close each connecting line passes to the boundary of an anomaly (where gradient supposed to be higher) proximity_to_boundary = np.sum(total_maps_along_lines, axis=(1, 2)) / np.sum(pixel_indices, axis=(1, 2)) # rate the possible src-sink pairs by their proximity to existing anomalies proposed_ex_line = voltage_all_possible[np.argsort(proximity_to_boundary)[::-1]][:num_returned] number_of_voltages = 10 # generate the voltage measuring electrodes for this current driver pair proposed_voltage_pairs = measopt.findNextVoltagePair(proposed_ex_line[0], fileJac, total_map, number_of_voltages, 0, npix=n_pix, cutoff=0.97) return proposed_ex_line, proposed_voltage_pairs, reconstruction, total_map
def simulateMeasurements(fileJac, anomaly=0, measurements=None, v_meas=None, n_el=20, n_per_el=3, n_pix=64, a=2.): # extract const permittivity jacobian and voltage (& other) file = h5.File(fileJac, 'r') meas = file['meas'][()] new_ind = file['new_ind'][()] p = file['p'][()] t = file['t'][()] file.close() # initialise const permitivity and el_pos variables perm = np.ones(t.shape[0], dtype=np.float32) el_pos = np.arange(n_el * n_per_el).astype(np.int16) mesh_obj = {'element': t, 'node': p, 'perm': perm} #for testing if measurements is None: el_dist = np.random.randint(1, 20) ex_mat = (cp.concatenate((cp.arange(20)[None], (cp.arange(20) + el_dist)[None])) % 20).T #print(ex_mat.shape) fem_all = Forward(mesh_obj, el_pos) measurements = fem_all.voltMeter(ex_mat) #ex_mat = mesurements[1] measurements = cp.concatenate((measurements[1], measurements[0]), axis=1) #print(measurements.shape) # list all possible active/measuring electrode permutations of this measurement meas = cp.array(meas) # find their indices in the already calculated const. permitivity Jacobian (CPJ) measurements = cp.array(measurements) measurements_0 = cp.amin(measurements[:, :2], axis=1) measurements_1 = cp.amax(measurements[:, :2], axis=1) measurements_2 = cp.amin(measurements[:, 2:], axis=1) measurements_3 = cp.amax(measurements[:, 2:], axis=1) measurements = cp.empty((len(measurements), 4)) measurements[:, 0] = measurements_0 measurements[:, 1] = measurements_1 measurements[:, 2] = measurements_2 measurements[:, 3] = measurements_3 index = (cp.sum(cp.equal(measurements[:, None, :], meas[None, :, :]), axis=2) == 4) index = cp.where(index) ind = cp.unique(index[1]) i = cp.asnumpy(ind) j = index[0] mask = np.zeros(len(meas), dtype=int) mask[i] = 1 mask = mask.astype(bool) # take a slice of Jacobian, voltage readings and B matrix file = h5.File(fileJac, 'r') jac = file['jac'][mask, :][()] v = file['v'][mask][()] b = file['b'][mask, :][()] file.close() pde_result = train.namedtuple("pde_result", ['jac', 'v', 'b_matrix']) f = pde_result(jac=jac, v=v, b_matrix=b) # simulate voltage readings if not given if v_meas is None: if np.isscalar(anomaly): print("generating new anomaly") anomaly = train.generate_anoms(a, a) true = train.generate_examplary_output(a, int(n_pix), anomaly) mesh_new = train.set_perm(mesh_obj, anomaly=anomaly, background=1) fem = FEM(mesh_obj, el_pos, n_el) new_ind = cp.array(new_ind) f2, raw = fem.solve_eit(volt_mat_all=meas[ind, 2:], new_ind=new_ind[ind], ex_mat=meas[ind, :2], parser=None, perm=mesh_new['perm'].astype('f8')) v_meas = f2.v ''' #plot fig = plt.figure(3) x, y = p[:, 0], p[:, 1] ax1 = fig.add_subplot(111) # draw equi-potential lines print(raw.shape) raw = cp.asnumpy(raw[5]).ravel() vf = np.linspace(min(raw), max(raw), 32) ax1.tricontour(x, y, t, raw, vf, cmap=plt.cm.viridis) # draw mesh structure ax1.tripcolor(x, y, t, np.real(perm), edgecolors='k', shading='flat', alpha=0.5, cmap=plt.cm.Greys) ax1.plot(x[el_pos], y[el_pos], 'ro') for i, e in enumerate(el_pos): ax1.text(x[e], y[e], str(i+1), size=12) ax1.set_title('Equipotential Lines of Uniform Permittivity') # clean up ax1.set_aspect('equal') ax1.set_ylim([-1.2, 1.2]) ax1.set_xlim([-1.2, 1.2]) fig.set_size_inches(6, 6) #plt.show()''' elif len(measurements) == len(v_meas): measurements = np.array(measurements) v_meas = np.array(v_meas[j[:len(ind)]]) else: raise ValueError('Sizes of arrays do not match (have to have voltage reading for each measurement). If you don\'t have readings, leave empty for simulation.') print('Number of measurements:', len(v_meas), len(f.v)) # now we can use the real voltage readings and the GREIT algorithm to reconstruct greit = train.greit.GREIT(mesh_obj, el_pos, f=f, ex_mat=(meas[index[1], :2]), step=None) greit.setup(p=0.2, lamb=0.01, n=n_pix) h_mat = greit.H reconstruction = greit.solve(v_meas, f.v).reshape(n_pix, n_pix) # optional: see reconstruction ''' plt.figure(1) im1 = plt.imshow(reconstruction, cmap=plt.cm.viridis, origin='lower', extent=[-1, 1, -1, 1]) plt.title("Reconstruction") plt.colorbar(im1) plt.figure(2) im2 = plt.imshow(true, cmap=plt.cm.viridis, origin='lower', extent=[-1, 1, -1, 1]) plt.colorbar(im2) plt.title("True Image") plt.show() ''' return reconstruction, h_mat, v_meas, f.v, true, len(v_meas)