def update_global_opts(self): """checks if bayesian optimisation registration is better than simply taking the previous best transformation found and applying that without any new registration. Updates global optimal to be whichever of current transformation or previous is best """ current_traj_globalT = transform_points(self.global_opt_variables['opt_transform'], self.traj) current_traj_globalT_list = current_traj_globalT.tolist() current_traj_globalT_matlab = matlab.double(current_traj_globalT_list) current_error = self.eng.closestPoint_error(self.aorta, current_traj_globalT_matlab, nargout=1) / self.traj.shape[0] #unnormalise previous error to calc new error using best found transformation so far updated_global_error = (((self.global_opt_variables['opt_error'] * (len(self.traj_list) - 1) ) + current_error))/ len(self.traj_list) if updated_global_error < self.bo_opt_variables['opt_error']: print('previous BO better than new BO') self.set_global_opt_vars(updated_global_error, self.global_opt_variables['opt_center'], self.global_opt_variables['opt_transform'], False) self.global_opt_variables['opt_from_prev_noReg'] = True else: print('new BO better than previous') self.set_global_opt_vars(self.bo_opt_variables['opt_error'], self.bo_opt_variables['opt_center'], self.bo_opt_variables['opt_transform'], self.bo_opt_variables['opt_from_prev_wreg']) self.global_opt_variables['opt_from_prev_noReg'] = False
def get_reg_error(self, center_positions): """registers trajectory with center_positions as init location. Contains options to alter how the registration is performed. See class attributes. """ print(self.iteration) self.iteration += 1 num_trajs = len(self.traj_list) errors = np.zeros((1,center_positions.shape[0])) if self.reg_prev_best_transform: #saved transformation already moves points to CP but need to recalc CP for new larger trajectory #as CP input is CP for the previous trajectory prev_opt_traj = transform_points(self.global_opt_variables['opt_transform'], self.traj) trajs_matlab, differences = self.get_traj_matlabarray(center_positions, prev_opt_traj, np.mean(prev_opt_traj, axis=0)) else: trajs_matlab, differences = self.get_traj_matlabarray(center_positions, self.traj, self.traj_center) diff = np.ones((1,4)) idx = 0 for tm in trajs_matlab: errors_added = 0 registered_points, transformation, reg_error = self.perform_reg(self.aorta, tm, nargout=3) errors[0,idx] += reg_error errors_added += 1 transformation = np.array(transformation) if self.reg_prev_best_transform: transformation = np.dot(transformation, self.global_opt_variables['opt_transform']) diff[0,:3] = differences[idx] translate_t = np.eye(4) translate_t[:,3] = diff transformation = np.dot(transformation, translate_t) if self.all_past_checks: for traj_idx in range(num_trajs - 1): errors[0, idx] += self.get_past_traj_error(transformation, traj_idx) errors_added += 1 if self.limited_past_checks and num_trajs >= 3: if num_trajs % 2 == 0: traj_idx = int(num_trajs / 2) else: traj_idx = int((num_trajs + 1) / 2) errors[0, idx] += self.get_past_traj_error(transformation, traj_idx) errors_added += 1 errors[0,idx] = errors[0,idx]/ errors_added if errors[0,idx] < self.bo_opt_variables['opt_error']: print('NEW OPTIMAL') if self.reg_prev_best_transform: self.set_bo_opt_vars(errors[0,idx], center_positions[idx], transformation, True) else: self.set_bo_opt_vars(errors[0,idx], center_positions[idx], transformation, False) if not self.sparse: self.sparse_error = self.get_sparse_error(transformation, self.traj) if self.reg_prev_best_transform: self.reg_prev_best_transform = False #only use previous T once idx += 1 return errors
def get_init_samples(BO_reg, selected_error, traintest_data=None, num_samples=5, GP=None): two_samples = False if GP is not None: print('to implement') else: if BO_reg.reg_prev_best_transform: prev_best = transform_points(BO_reg.global_opt_variables['opt_transform'], BO_reg.traj) prev_best_center = np.mean(np.array(prev_best), axis=0) y_BO_prev_best = selected_error(prev_best_center.reshape(1,3)) two_samples = True X_BO = traintest_data['y_train'][np.random.choice(traintest_data['y_train'].shape[0], num_samples, replace=False), :] y_BO = selected_error(X_BO) if two_samples: X_BO = np.vstack((prev_best_center, X_BO)) y_BO = np.concatenate((y_BO_prev_best, y_BO), axis=1) return X_BO, y_BO.reshape(-1,1)
def bo_optimisation_errors(BO_reg, selected_error_function, traintest_data, all_trajs,sparse_idxs = None, sparse=False, num_subsections=8, reg_prev_best_transform=False, plot_trajs=False, max_iter=5, aq_weight=40, rand_rotation = False, max_rotation=False): """Performs bayesian optimisation registration between the aorta and catheter points for n = num_subsections subsets of the catheter points to the full trajectory. Returns the results of the registration. Attributes: BO_reg: Instance of the registration class containing the vars needed to perform different versions of the registration selected_error_function: The method belonging to BO_reg chosen to perform the registration traintest_data: Dictionary containing X_train, X_test, y_train, y_test data all_trajs: Dictionary containing traj_indices (list indices in trajs & GT_trajs where each trajectory subset can be found), trajs (rotated trajectory and subsets), GT_trajs (ground truth trajectory and subsets) sparse: bool showing whether the trajectory is sparse or full sparse_idxs: bool array the same length as traj idicating which points are part of the sparse array num_subsections: how many subsets of the trajectory to register and store the results of max_iter: Number of iterations to run the BO for aq_weight: Value to determine how much exploration is done by the BO rand_rotation: Bool indicating if trajectory has been randomly rotated max_rotation: Bool indicating if trajectory was rotated by the maximum value (i.e. max of rand_rotation) all_past_checks: boolean deciding if error measure is calculated for only the transformation and current trajectory or all past trajectories as well limited_past_checks: boolean deciding if error measure is for the transformation, current trajectory and one previous trajectory reg_prev_best_transform: boolean deciding if when initialising the Bayesian optimisation the previous best transformation is used as one if the initialisation points bo_opt_variables: dictionary storing the variables for the most recent Bayesian optimisation round. opt_from_prev_wreg describes if the best found came from the previous registration or a new one. opt_from_prev_noReg describes if best found came from the previous registration but without any registration applied global_opt_variables: same as above but for the entire BO registration process not just the most recent Output: bo_stats: Dictionary containing keys of the subset index 0-num_subsections and the registration results for that subset and a key of creation_params detailing the settings of the registration and the nature of the data used """ num_trajs = int(all_trajs['trajs'].shape[1] / 3) steps = ceil(num_trajs/num_subsections) BO_reg.sparse = sparse bo_stats = {} traj_idx = -1 for test_value in range(0, num_trajs, steps): traj_idx += 1 traj, GT_traj = get_test_trajs(test_value, all_trajs) BO_reg.add_traj(traj) BO_reg.set_bo_opt_vars(inf, np.zeros((1,3)), np.eye(4), False) if reg_prev_best_transform: BO_reg.reg_prev_best_transform = True if not sparse: BO_reg.sparse_idxs = sparse_idxs[:traj.shape[0]] X_BO, y_BO = get_init_samples(BO_reg, selected_error_function, traintest_data) t1 = time() bounds = [{'name':'cathReg', 'type':'bandit', 'domain':traintest_data['y_train']}] Bopt = GPyOpt.methods.BayesianOptimization(f=selected_error_function, domain=bounds, X=X_BO, Y=y_BO, acquisition_type='LCB', acquisition_weight=aq_weight) Bopt.run_optimization(max_iter) t2 = time() if sparse: bo_opt_error = GPyOpt.util.general.best_value(Bopt.Y)[-1] bo_opt_full_error = 0 else: bo_opt_error = BO_reg.sparse_error bo_opt_full_error = GPyOpt.util.general.best_value(Bopt.Y)[-1] print('Optimal X:' + str(Bopt.x_opt)) BO_trans = transform_points(BO_reg.bo_opt_variables['opt_transform'], traj) diff_to_GT = register_pointclouds(GT_traj, BO_trans, BO_reg.eng, noreg_error=True) / BO_trans.shape[0] GT_error = register_pointclouds(BO_reg.aorta, GT_traj, BO_reg.eng, noreg_error=True) / GT_traj.shape[0] if plot_trajs: reg_error, BO_registered = BO_reg.get_simple_reg_error_and_points(np.array([Bopt.x_opt])) BO_registered = np.array(BO_registered) global_traj = transform_points(BO_reg.global_opt_variables['opt_transform'], traj) plot_registration(np.array(BO_reg.aorta), GT_traj, BO_registered, BO_trans, global_traj, point=Bopt.x_opt) BO_reg.update_global_opts() bo_stats[str(traj_idx)] = {'global_opt_error':BO_reg.global_opt_variables['opt_error'], 'bo_opt_error':bo_opt_error, 'bo_opt_full_error': bo_opt_full_error, 'diff_to_GT_error':diff_to_GT, 'GT_error':GT_error, 'comp_time':t2-t1, 'opt_from_prev_wreg':BO_reg.global_opt_variables['opt_from_prev_wreg'], 'opt_from_prev_noReg':BO_reg.global_opt_variables['opt_from_prev_noReg'], 'opt_CP':np.ndarray.tolist(Bopt.x_opt)} bo_stats['creation_params'] = {'max_iters':max_iter, 'reg_prev_best_transform':reg_prev_best_transform, 'all_past_checks':BO_reg.all_past_checks, 'limited_past_checks':BO_reg.limited_past_checks, 'aquisition_weight':aq_weight, 'sparse':sparse, 'max_rotation':max_rotation, 'rand_rotation':rand_rotation, 'num_subsections':num_subsections} return bo_stats
def get_sparse_error(self, transformation, full_traj): sparse_traj = [points for points,select in zip(full_traj, self.sparse_idxs) if select] transformed_traj = transform_points(transformation, np.array(sparse_traj)) transformed_traj_matlab = matlab.double(transformed_traj.tolist()) return self.eng.closestPoint_error(self.aorta, transformed_traj_matlab, nargout=1) / transformed_traj.shape[0]
def get_past_traj_error(self, transformation, traj_idx): transformed_traj = transform_points(transformation, self.traj_list[traj_idx]) transformed_traj_matlab = matlab.double(transformed_traj.tolist()) return self.eng.closestPoint_error(self.aorta, transformed_traj_matlab, nargout=1) / transformed_traj.shape[0]