Ho un codice per calcolare i valori mancanti in un'immagine, in base ai valori adiacenti in una finestra circolare 2D. Utilizza anche i valori di una o più immagini adiacenti temporaneamente nelle stesse posizioni (vale a dire la stessa finestra 2D spostata nella terza dimensione).python - combinazione di argsort con mascheramento per ottenere valori più vicini nella finestra mobile
Per ogni posizione mancante, devo calcolare il valore basato non necessariamente su tutti i valori disponibili nell'intera finestra, ma solo sulle n celle spazialmente più vicine che hanno valori (in entrambe le immagini/Z- posizioni degli assi), dove n è un valore inferiore al numero totale di celle nella finestra 2D.
Al minuto, è molto più veloce calcolare per ogni cosa nella finestra, perché il mio mezzo di ordinamento per ottenere le celle n più vicine con i dati è la parte più lenta della funzione in quanto deve essere ripetuta ogni volta anche se il le distanze in termini di coordinate della finestra non cambiano. Non sono sicuro che sia necessario e sento che devo essere in grado di ottenere le distanze ordinate una volta e quindi mascherarle nel processo di selezione delle sole celle disponibili.
Ecco il mio codice per la selezione dei dati da utilizzare all'interno di una finestra della posizione della cella gap:
# radius will in reality be ~100
radius = 2
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
dist = np.sqrt(x**2 + y**2)
circle_template = dist > radius
# this will in reality be a very large 3 dimensional array
# representing daily images with some gaps, indicated by 0s
dataStack = np.zeros((2,5,5))
dataStack[1] = (np.random.random(25) * 100).reshape(dist.shape)
dataStack[0] = (np.random.random(25) * 100).reshape(dist.shape)
testdata = dataStack[1]
alternatedata = dataStack[0]
random_gap_locations = (np.random.random(25) * 30).reshape(dist.shape) > testdata
testdata[random_gap_locations] = 0
testdata[radius, radius] = 0
# in reality we will go through every gap (zero) location in the data
# for each image and for each gap use slicing to get a window of
# size (radius*2+1, radius*2+1) around it from each image, with the
# gap being at the centre i.e.
# testgaplocation = [radius, radius]
# and the variables testdata, alternatedata below will refer to these
# slices
locations_to_exclude = np.logical_or(circle_template, np.logical_or
(testdata==0, alternatedata==0))
# the places that are inside the circular mask and where both images
# have data
locations_to_include = ~locations_to_exclude
number_available = np.count_nonzero(locations_to_include)
# we only want to do the interpolation calculations from the nearest n
# locations that have data available, n will be ~100 in reality
number_required = 3
available_distances = dist[locations_to_include]
available_data = testdata[locations_to_include]
available_alternates = alternatedata[locations_to_include]
if number_available > number_required:
# In this case we need to find the closest number_required of elements, based
# on distances recorded in dist, from available_data and available_alternates
# Having to repeat this argsort for each gap cell calculation is slow and feels
# like it should be avoidable
sortedDistanceIndices = available_distances.argsort(kind = 'mergesort',axis=None)
requiredIndices = sortedDistanceIndices[0:number_required]
selected_data = np.take(available_data, requiredIndices)
selected_alternates = np.take(available_alternates , requiredIndices)
else:
# we just use available_data and available_alternates as they are...
# now do stuff with the selected data to calculate a value for the gap cell
Questo funziona, ma più della metà del tempo totale della funzione è preso nella argsort della mascherato dati sulla distanza spaziale. (~ 900 μS di 1,4 mS totali - e questa funzione verrà eseguita decine di miliardi di volte, quindi questa è una differenza importante!)
Sono sicuro che devo essere in grado di fare questo argsort una volta fuori dal funzione, quando la finestra della distanza spaziale è originariamente impostata e quindi includere gli indici di ordinamento nel mascheramento, per ottenere il primo comeManyToCalcolare gli indici senza dover ripetere l'ordinamento. La risposta potrebbe consistere nel mettere i vari bit da cui stiamo estraendo, in un array di record - ma non riesco a capire come, in caso affermativo. Qualcuno può vedere come posso rendere questa parte del processo più efficiente?
Il codice è davvero difficile da leggere ... Si consiglia di leggere [PEP8] (http://legacy.python.org/dev/peps/pep-0008/) e seguirla: facilita condivisione del codice con altri programmatori Python. – Jaime
Sono d'accordo con Jaime che questo è piuttosto difficile da leggere, specialmente il codice, ma la descrizione lascia spazio anche all'interpretazione. Quindi non mi avventuro a fornire una risposta, ma qui ci sono alcuni strumenti che vorrei verificare se dovessi (se almeno capisco vagamente il tuo problema correttamente). [sklearn.feature_extraction.image.extract_patches] (https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/image.py#L238) ti offre una vista sulle tue patch, che tu può mascherare. Creerà una copia, quindi fai attenzione ai problemi di memoria. – eickenberg
Potresti anche essere interessato a una funzione apparentemente del tutto estranea, che imputa i valori mancanti usando le dilatazioni. Non ti darà il risultato esatto, ma potrebbe essere un buon proxy: [nilearn.masking._extrapolate_out_img] (https://github.com/nilearn/nilearn/blob/fd7e7a7186dca43d0ef5ebd19990b0751d476bda/nilearn/masking.py#L65) – eickenberg