Suppose I have a list of (greyscale) pixels, e.g.
x = np.array([13, 14, 14, 14, 15])
y = np.array([ 2, 7, 5, 7, 8])
V = np.array([.3, .7, .4, .2, .1])
So, e.g. the second pixel is at location (14, 7) with intensity 0.7
NOTE: x is always non-decreasing in this list. So p > q => x[p] >= x[q].
However the same pixel may be revisited. In my example, pixels #1 and #3 have coordinates (14, 7).
How to efficiently amalgamate the duplicates? So that in my example, I get:
x2 = np.array([ 13, 14 , 14, 15 ])
y2 = np.array([ 2, 7 , 5, 8 ])
V2 = np.array([ .3, .7+.2 , .4, .1 ])
NOTE: Order isn't important, so it may help to sort by increasing y for pixels with a given x.
NOTE: x, y, V came from cols of a matrix M. What I am to do could be considered as a 2-D histogram or cumulative sum.
IDEA: I could map x, y -> x + y*nPixelsX, so now I'm dealing with pairs, e.g. (1073, 0.4), (1071, 1.8), (1073, 0.7) which I could sort.
EDIT: This is the problem I am actually trying to solve (code is Python despite variable glyphs):
# split columns of tradematrix into 1D numpy arrays
time_ms, price, vol, buyer_is_maker = ᬑ.ᘐA.T
# TODO: https://stackoverflow.com/questions/67191535/efficiently-plot-set-of-coordinatevalues-to-numpy-array-bitmap
# convert time,price to pixel x,y coords
x = pX(time_ms)
y = pY(price)
brightness = vol
rgb_channel = np.where(buyer_is_maker, 2, 1) # cv2 uses BGR not RGB
# make a clear canvas
f = np.zeros((ᬑ.pixelsY, ᬑ.pixelsX, 3))
# additively plot trades
for i in range(len(ᬑ.ᘐA)):
try:
f[y[i],x[i],rgb_channel[i]] += brightness[i]
except:
# don't plot offscreen coords
# try/catch is waaay faster than doing if on_screen(x[i],y[i]):
pass
# flatten dynamic range (as some trades are huge)
# ... by doing `w -> log(1+w)` 3 times
# # This was the original (slow) code
# for _ in range(3):
# f = np.log(1+f) # any 0 pixel maps back to 0 (log 1 = 0)
# sped up!
sparse_red = coo_matrix(f[:,:,2])
sparse_green = coo_matrix(f[:,:,1])
for _ in range(3):
np.log(1+sparse_red.data, sparse_red.data) # perform operation in place
np.log(1+sparse_green.data, sparse_green.data) # perform operation in place
f[:,:,2] = sparse_red.todense()
f[:,:,1] = sparse_green.todense()
# normalize canvas
sup = np.max(f)
if sup > 0:
f /= sup
What I'm doing isn't great. I'm writing sparse data to a bitmap so as to solve this "multiple trades on the same pixel" problem, then sparsifying the bitmap to flatten the trades, then recombining.
I need to be working with sparse data all the way to the end, I think.
