# -*- coding: utf-8 -*- """ Spyder Editor This is a temporary script file. TODO: allow general deselection. does it it need a rerun of "prepare"? TODO: allow deselection in derived features (gradients, hessian) """ import numpy as np from scipy import ndimage import dask_image.ndfilters import dask import dask.array from itertools import combinations_with_replacement, combinations import xarray as xr def ball_4d(sig): bnd = np.zeros((sig*2+1,sig*2+1,sig*2+1,sig*2+1), dtype = bool) bnd[sig,sig,sig,sig] = True ecd = ndimage.distance_transform_edt(~bnd) bnd = (ecd not so good for many time steps self.time_stats() #does something similar like the dynamic rank filter, however only one pixel in space self.diff_to_first_and_last(self.take_means, self.num_means) if self.loc_features: self.pixel_coordinates() # #this feature is a double-edged sword, use with care!! self.prepared = True def stack_features(self): if not self.prepared: print('prepare first') else: self.feature_names = np.array(self.feature_names) self.feature_names_time_independent = np.array(self.feature_names_time_independent) self.stack_has_been_reduced = False self.feature_stack = dask.array.stack(self.calculated_features, axis = 4) self.feature_stack_time_independent = dask.array.stack(self.calculated_features_time_independent, axis=3) shp = self.feature_stack_time_independent.shape self.feature_stack_time_independent = self.feature_stack_time_independent.reshape(shp[0],shp[1],shp[2],1,shp[3]) if self.ignored_features is not None: ids_time = np.ones(len(self.feature_names), dtype=bool) ids_independent = np.ones(len(self.feature_names_time_independent), dtype=bool) for i in range(len(ids_time)): if self.feature_names[i] in self.ignored_features: ids_time[i] = False for i in range(len(ids_independent)): if self.feature_names_time_independent[i] in self.ignored_features: ids_independent[i] = False self.reduce_feature_stack(ids_time, ids_independent, verbose=self.verbose) def create_feature_ids(self, feature_names_to_use): # time dependent features ids_time = np.zeros(len(self.feature_names), dtype=bool) for i in range(len(ids_time)): if self.feature_names[i] in feature_names_to_use: ids_time[i] = True self.ids_time = ids_time # time in-dependent features ids_independent = np.zeros(len(self.feature_names_time_independent), dtype=bool) for i in range(len(ids_independent)): if self.feature_names_time_independent[i] in feature_names_to_use: ids_independent[i] = True self.ids_independent = ids_independent def reduce_feature_stack(self, feature_names_to_use): # what about adding features? --> not implemented, better idea to start from the start and use saved label images # in jupyter notebook to add a step to reduce feature stack # TODO: option selection in GUI would be nice, maybe jupyter widget is a straightforward option """ Parameters ---------- ids_time : boolean array same length as self.calculated_features True for features to use ids_independent : boolean array same length as self.calculated_features True for features to use verbose : boolean, optional Print overview of used features. The default is False. Returns ------- 2 lazy dask arrays only using selected features 2 lists of feature names """ self.create_feature_ids(feature_names_to_use) ids_time = self.ids_time ids_independent = self.ids_independent self.reduced_stack = self.feature_stack[...,ids_time] self.reduced_stack_time_independent = self.feature_stack_time_independent[...,ids_independent] self.feature_names_reduced = self.feature_names[ids_time] self.feature_names_reduced_time_independent = self.feature_names_time_independent[ids_independent] self.feature_selection = ids_time self.feature_selection_time_idependent = ids_independent self.stack_has_been_reduced = True if self.verbose: print('Considered dynamic features') for name in self.feature_names_reduced: print(name) print('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%') print('Considered static features') for name in self.feature_names_reduced_time_independent: print(name) def make_xarray(self, use_reduced=True): if use_reduced and self.stack_has_been_reduced: shp = self.reduced_stack.shape feature_names = self.feature_names_reduced feature_names_time_independent = self.feature_names_reduced_time_independent feature_stack = self.reduced_stack feature_stack_time_independent = self.reduced_stack_time_independent print('using reduced feature stack') else: shp = self.feature_stack.shape feature_names = self.feature_names feature_names_time_independent = self.feature_names_time_independent feature_stack = self.feature_stack feature_stack_time_independent = self.feature_stack_time_independent print('using full feature stack because') if not use_reduced: print('- reduced stack not selected') if use_reduced and not self.stack_has_been_reduced: print('- reduced stack not calculated') coords = {'x': np.arange(shp[0]), 'y': np.arange(shp[1]), 'z': np.arange(shp[2]), 'time': np.arange(shp[3]), 'time_0': [0], 'feature': feature_names, 'feature_time_independent': feature_names_time_independent} self.feature_xarray = xr.Dataset({'feature_stack': (['x','y','z','time', 'feature'], feature_stack), 'feature_stack_time_independent': (['x','y','z','time_0', 'feature_time_independent'], feature_stack_time_independent)}, coords = coords )