Write numpy arrays to lmdb - python

I'm trying to write some numpy arrays in python to lmdb:
import numpy as np
import lmdb
def write_lmdb(filename):
lmdb_env = lmdb.open(filename, map_size=int(1e9))
lmdb_txn = lmdb_env.begin(write=True)
X= np.array([[1.0, 0.0], [0.1, 2.0]])
y= np.array([1.4, 2.1])
#Put first pair of arrays
lmdb_txn.put('X', X)
lmdb_txn.put('y', y)
#Put second pair of arrays
lmdb_txn.put('X', X+1.6)
lmdb_txn.put('y', y+1.2)
def read_lmdb(filename):
lmdb_env = lmdb.open(filename)
lmdb_txn = lmdb_env.begin()
lmdb_cursor = lmdb_txn.cursor()
for key, value in lmdb_cursor:
print type(key)
print type(value)
print key
print value
write_lmdb('temp.db')
read_lmdb('temp.db')
but read_lmdb prints nothing, what is the proper way to write numpy arrays to lmdb?
Update:
Based on #frankyjuang answer I manage to do it, howewer not in very elegant way: multidimensional array lose it's shape, each array should have it's own name.
import numpy as np
import lmdb
def write_lmdb(filename):
print 'Write lmdb'
lmdb_env = lmdb.open(filename, map_size=int(1e9))
n_samples= 2
X= (255*np.random.rand(n_samples,3,4,3)).astype(np.uint8)
y= np.random.rand(n_samples).astype(np.float32)
for i in range(n_samples):
with lmdb_env.begin(write=True) as lmdb_txn:
lmdb_txn.put('X_'+str(i), X)
lmdb_txn.put('y_'+str(i), y)
print 'X:',X
print 'y:',y
def read_lmdb(filename):
print 'Read lmdb'
lmdb_env = lmdb.open(filename)
lmdb_txn = lmdb_env.begin()
lmdb_cursor = lmdb_txn.cursor()
n_samples=0
with lmdb_env.begin() as lmdb_txn:
with lmdb_txn.cursor() as lmdb_cursor:
for key, value in lmdb_cursor:
print key
if('X' in key):
print np.fromstring(value, dtype=np.uint8)
if('y' in key):
print np.fromstring(value, dtype=np.float32)
n_samples=n_samples+1
print 'n_samples',n_samples
write_lmdb('temp.db')
read_lmdb('temp.db')
Test script output should be something like:
Write lmdb
X: [[[[ 48 224 119]
[ 76 87 174]
[ 14 88 183]
[ 76 234 56]]
[[234 223 65]
[ 63 85 175]
[184 252 125]
[100 7 225]]
[[134 159 41]
[ 2 146 221]
[ 99 74 225]
[169 57 59]]]
[[[100 202 3]
[ 88 204 131]
[ 96 238 243]
[103 58 30]]
[[157 125 107]
[238 207 99]
[102 220 64]
[ 27 240 33]]
[[ 74 93 131]
[107 88 206]
[ 55 86 35]
[212 235 187]]]]
y: [ 0.80826157 0.01407595]
X: [[[[ 48 224 119]
[ 76 87 174]
[ 14 88 183]
[ 76 234 56]]
[[234 223 65]
[ 63 85 175]
[184 252 125]
[100 7 225]]
[[134 159 41]
[ 2 146 221]
[ 99 74 225]
[169 57 59]]]
[[[100 202 3]
[ 88 204 131]
[ 96 238 243]
[103 58 30]]
[[157 125 107]
[238 207 99]
[102 220 64]
[ 27 240 33]]
[[ 74 93 131]
[107 88 206]
[ 55 86 35]
[212 235 187]]]]
y: [ 0.80826157 0.01407595]
Read lmdb
X_0
[ 48 224 119 76 87 174 14 88 183 76 234 56 234 223 65 63 85 175
184 252 125 100 7 225 134 159 41 2 146 221 99 74 225 169 57 59
100 202 3 88 204 131 96 238 243 103 58 30 157 125 107 238 207 99
102 220 64 27 240 33 74 93 131 107 88 206 55 86 35 212 235 187]
X_1
[ 48 224 119 76 87 174 14 88 183 76 234 56 234 223 65 63 85 175
184 252 125 100 7 225 134 159 41 2 146 221 99 74 225 169 57 59
100 202 3 88 204 131 96 238 243 103 58 30 157 125 107 238 207 99
102 220 64 27 240 33 74 93 131 107 88 206 55 86 35 212 235 187]
y_0
[ 0.80826157 0.01407595]
y_1
[ 0.80826157 0.01407595]
n_samples 4

Wrap your transactions under with. And remember to convert the value from bytes (string) back to numpy array using np.fromstring.
To be honest, it is not a good idea to store numpy array in lmdb since conversion from array to bytes back to array will lose some informations (ex. shape). You can try storing a dict of numpy arrays using pickle.
def write_lmdb(filename):
...
with lmdb_env.begin(write=True) as lmdb_txn:
...
def read_lmdb(filename):
...
with lmdb_env.begin() as lmdb_txn:
with lmdb_txn.cursor() as lmdb_cursor:
...
print np.fromstring(value, dtype=np.float64)

Related

How to read binary file and convert it to text in Python

I have a time series from 1946-2020 for the discharges of gauge. The file is binary and if I open it in a text editor, or even in a hex-editor, I see values which do not make sense. I have searched a lot and found some code but I don't see any time series and values.
I can imagine that the time series is looking like that:
These values are also correct and are in the data.
t Q
17.11.1972 8,66
04.02.2020 28,2
I copied the beginning part of the file:
##4.00
à?š™™™™™é?ÍÌÌÌÌÌì?ffffffî?¸…ëQ¸î?\Âõ(\ï?®Gáz®ï?×£p=
×ï?V-²ïï?§èH.ÿï?Sš ä ÍÌL= ÿÿÍÌL= _ B €#
## NASIM26760601m³/sffûB°FAˆ¢A ¥¼x?  §=,ðñ=ÿ9jŒA´¯DA;Âò#¿‡Ø½ =|?0¥‡=?1=ÿ]”:A þA ¨ï¿eV4#)¡? i3|?`d‹=ek=ÿ‘_î#5Ý#¼˜DA
©]? cÂ{?Œ%¿=+>ÿÚÍ# %µ#À#•9AN? ýô{?h«=×Í­=ÿð½¢#»MAòöî# ¤¼x?¸~=Xä—=ÿ9jŒA
+BAïÕ#yBѾ ‚Äw?èrÈ=¯k“=ÿ]”:A¼/±#>. #„×9AG€
I copied the last part of the file, because I know there must be the time-discharge of 2020. Maybe it is in the end of the file.
×ï?V-²ïï?+‡ÙÎ÷ï? ÍÌL= ÿÿÍÌL= _ B €#
##
in the following screenshot you see the data , when I open it in Notepad++.
here is my python code and output
with open("time-serie_1946 bis 2020.hqr", "rb") as file:
data = file.read()
with open("out.txt", "w") as f:
f.write(" ".join(map(str,data)))
f.write("\n")
the beginning of output:
6 64 64 52 46 48 48 10 0 0 0 0 0 0 0 224 63 154 153 153 153 153 153 233 63 205 204 204 204 204 204 236 63 102 102 102 102 102 102 238 63 184 30 133 235 81 184 238 63 92 143 194 245 40 92 239 63 174 71 225 122 20 174 239 63 215 163 112 61 10 215 239 63 86 14 45 178 157 239 239 63 30 167 232 72 46 255 239 63 83 78 101 117 98 101 114 101 99 104 110 117 110 103 32 98 105 115 32 50 48 50 48 32 109 105 116 32 117 110 98 101 115 116 228 116 105 103 116 101 110 32 72 81 32 118 111 110 32 49 57 52 54 45 49 57 55 50 32 40 65 110 102 114 97 103 101 32 83 99 104 117 104 109 97 99 104 101 114 44 32 84 82 41 154 7 0 0 228 7 0 0 0 0 0 0
How can I decode it to get the time series?

How to turn a dictionary into a dataframe with all the keys in a column

def weights():
saved = {}
for i in range(len(bread_pairs["key_id"])):
drawing = np.array(bread_pairs['bitmap'][i], dtype=np.uint8)
new_test_cnn = drawing.reshape(1, 28, 28, 1).astype('float32')
new_cnn_predict = model.predict(new_test_cnn, batch_size=32, verbose=0)
w = model.layers[8].get_weights()
w = list(w[0].flatten())
saved[bread_pairs["key_id"][i]] = w
return saved
I have this function that is creating a dictionary of key_ids and mapping them to an associated list of values of length 200. So for example my dictionary looks something like saved = {key_id_1: [1,2,3...200], key_id_2: [1,2,...,200], ....}
I would like to turn this dictionary into a dataframe with a column of key_ids and each element in the associated list of 200 becomes its own column. So there is a total of 201 columns where the first column is the first key_id and then the second column is the first element of the list, the third column is the second element of the list etc. And then the second row first column is the second key_id and then the second row second column is the first element of the key_id's second list and so on. Is there a way to convert this dictionary to a df? I have 10000 key_ids do the dimensions would be 10000x201. Thanks!
Load the dict into a DataFrame using pandas.DataFrame.from_dict with the orient parameter, and reset the index with .reset_index()
This will create the DataFrame as requested, however, I recommend leaving the keys as the index, which should make it easier to perform calculations and address specific rows.
If the columns should be named 0...201, then use df.columns = list(range(202)), or use pandas.DataFrame.rename to rename specific columns.
import pandas as pd
# test data
saved = {'key_id_1': list(range(201)), 'key_id_2': list(range(201))}
# create the DataFrame
df = pd.DataFrame.from_dict(saved, orient='index')
# reset the index
df = df.reset_index()
# display(df)
index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
0 key_id_1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
1 key_id_2 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
Alternative Implementation
Create the DataFrame with pandas.DataFrame, transpose the DataFrame with pandas.DataFrame.T, and then reset with .reset_index().
df = pd.DataFrame(saved)
df = df.T.reset_index()

Reshape 1d array to 3d array numpy

I have a array as:
[0 1 2 3 4 5 6 7 8 ....] #2560 positions
I'm trying to reshape this 1D array to 3D as:
A = np.arange(2560) #generating example data
B = np.reshape(A,(16,16,10)) # here, i's expect to be 16 rows 16 x columns x 10 "frames"
C = B[:,:,0]
However, the result is giving something like this
C = [[0, 10, 20, 30, .., 150]
[160, 170, 180, ..., 310]
...
[2510,...2550]
The correct would be
print(B[:,:,0])
[[0, 1, 2, 3, .., 15]
[16, 17, 18, ..., 31]
...
[240,241,..., 255]
print(B[:,:,1])
[[256, 257, , .., 271]
...
[496,497,..., 511]
What I'm doing wrong?
The idea is to not use for's in order to make it faster
I think you don't understand how your data is structured.
It is a 3D matrix.
First you have 16 rows, each row contains 16 columns, each columns contains 10 lists
However, the rows and columns do not contains any numbers, rows contain columns and columns contain lists. Only lists contain number.
So when you execute: print(B[:,:,0]), you ask: "I want the first number of the list contains in every columns of every row". So you obtain exactely what you ask for.
You can not obtain this:
print(B[:,:,0])
[[0, 1, 2, 3, .., 15]
[16, 17, 18, ..., 31]
...
[240,241,..., 255]
print(B[:,:,1])
[[256, 257, , .., 271]
...
[496,497,..., 511]
This is not the way data are stored, you have to manipulate your data to make them appear in this way.
You can do the following:
A = np.arange(2560)
B = np.reshape(A,(10,16,16))
print(B[0,:,:])
[[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
[ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[ 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47]
[ 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63]
[ 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79]
[ 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95]
[ 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111]
[112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127]
[128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143]
[144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159]
[160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175]
[176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191]
[192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207]
[208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223]
[224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239]
[240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255]]
Simply reshaping won't give you the desired format, as you found out yourself. To solve it, we need to reshape differently and then permute axes. The general theory could be followed here - Reshape and permute axes. The solution would be -
A.reshape(-1,16,16).transpose(1,2,0)
Sample run -
In [465]: A = np.arange(2560)
In [466]: B = A.reshape(-1,16,16).transpose(1,2,0)
In [467]: B[:,:,0]
Out[467]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15],
[ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31] ...
In [468]: B[:,:,1]
Out[468]:
array([[256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
269, 270, 271],
[272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287]...
We can also use np.moveaxis to perform the permuting -
np.moveaxis(A.reshape(-1,16,16), 0, -1)

Sliding a subarray along a 2d array

This is something I've been struggling with for a couple of weeks. The algorithm is the following:
Select a subarray as an array of rows and columns from a larger array
Compute the median of the subarray
Replace cells in subarray with median value
Move the subarray to the right by its own length
Repeat to end of array
Move subarray down by its own height
Repeat
I've got steps 1 to 3 as follows:
import numpy as np
w1 = np.arange(100).reshape(10,10)
side = 3
patch = w1[0:side, 0:side]
i, j = patch.shape
for j in range(side):
for i in range(side):
patch[i,j] = np.median(patch)
Eventually, I'll be using a 901x877 array from an image but I'm just trying to get a hold of this simple task first. How can I slide the array along and then down with a loop?
You can use scikit-image's view_as_blocks and NumPy broadcasting to vectorize the operation:
import numpy as np
import skimage
w1 = np.arange(144).reshape(12,12)
print(w1)
# [[ 0 1 2 3 4 5 6 7 8 9 10 11]
# [ 12 13 14 15 16 17 18 19 20 21 22 23]
# [ 24 25 26 27 28 29 30 31 32 33 34 35]
# [ 36 37 38 39 40 41 42 43 44 45 46 47]
# [ 48 49 50 51 52 53 54 55 56 57 58 59]
# [ 60 61 62 63 64 65 66 67 68 69 70 71]
# [ 72 73 74 75 76 77 78 79 80 81 82 83]
# [ 84 85 86 87 88 89 90 91 92 93 94 95]
# [ 96 97 98 99 100 101 102 103 104 105 106 107]
# [108 109 110 111 112 113 114 115 116 117 118 119]
# [120 121 122 123 124 125 126 127 128 129 130 131]
# [132 133 134 135 136 137 138 139 140 141 142 143]]
side = 3
w2 = skimage.util.view_as_blocks(w1, (side, side))
w2[...] = np.median(w2, axis=(-2, -1))[:, :, None, None]
print(w1)
# [[ 13 13 13 16 16 16 19 19 19 22 22 22]
# [ 13 13 13 16 16 16 19 19 19 22 22 22]
# [ 13 13 13 16 16 16 19 19 19 22 22 22]
# [ 49 49 49 52 52 52 55 55 55 58 58 58]
# [ 49 49 49 52 52 52 55 55 55 58 58 58]
# [ 49 49 49 52 52 52 55 55 55 58 58 58]
# [ 85 85 85 88 88 88 91 91 91 94 94 94]
# [ 85 85 85 88 88 88 91 91 91 94 94 94]
# [ 85 85 85 88 88 88 91 91 91 94 94 94]
# [121 121 121 124 124 124 127 127 127 130 130 130]
# [121 121 121 124 124 124 127 127 127 130 130 130]
# [121 121 121 124 124 124 127 127 127 130 130 130]]
Note that I had to change the size of your array to 12x12 so that all of your tiles of 3x3 actually fit in there.
Here are a few "code smells" I see.
Start with the range(side) since this number is set to 3 then you are going to have a result of [0,1,2]. Is that what you really want?
you set i,j = patch.size then immediately over write these values, in your for loops.
Finally, you're recalculating median every loop.
Ok, here's what I'd do.
figure out how many patches you'll need in both width and height. and multiply those by the size of the side.
slice your array (matrix) up into those pieces.
assign the patch to the median.
import numpy as np
w1 = np.arange(100).reshape(10,10)
side = 3
w, h = w1.shape
width_index = np.array(range(w//side)) * side
height_index = np.array(range(h//side)) * side
def assign_patch(patch, median, side):
"""Break this loop out to prevent 4 nested 'for' loops"""
for j in range(side):
for i in range(side):
patch[i,j] = median
return patch
for width in width_index:
for height in height_index:
patch = w1[width:width+side, height:height+side]
median = np.median(patch)
assign_patch(patch, median, side)
print w1

Efficient finite field multiplication with log-antilog-table lookup in numpy

I am trying to implement efficient multiplication in GF(2^8), which elements are most naturally represented as uint8-numpy-values, in a numpy-thonic way. Therefore, I implemented GF-Arithmetics (in pure Python, not numpy) in order to build log-antilog-tables (I took a ranom generator, 9); in particular, I implemented a (non-numpy) Python-Function multGF which implements GF-Multiplication, which works great but is slow (since it uses polynomial modulo calcs). A common trick to speed up multiplication is to use the following equation:
Building the log-antilog-uint8-ndarrays is easily performed like this:
gen = 9 ; K = [1] ; g = gen
for i in range(1,255):
K.append(g)
g = multGF(g,gen)
antilog = np.array(K, dtype='uint8')
log = np.full(256,0, dtype='uint8')
for i in range(255): log[antilog[i]] = i
But, and that is my question, how to implement the multiplication in a numpy-thonic way? Both, the log table and the antilog table are of size 255 (not 256; no log for 0) and the exponents have to be added modulo 255 - and not mod 256. I came up with the following IMHO non numpy-thonic solution:
def multGF2(a,b):
return antilog[(int(log[a]) + log[b]) % 255]
I had to convert the uint8-addition (which works mod-256 naturally) into an int-addtion in order to perform mod-255-addition. This is neither elegant nor efficient and I am quite sure, that any has a better solution?
For testing: here are both logtables as arrays:
log = [ nan 0 250 214 245 173 209 42 240 1 168 71 204 187 37 132 235 91
251 191 163 84 66 146 199 212 182 215 32 30 127 247 230 206 86 229
246 65 186 244 158 87 79 171 61 174 141 180 194 113 207 50 177 150
210 54 27 105 25 231 122 93 242 43 225 2 201 156 81 142 224 52
241 53 60 64 181 190 239 254 153 119 82 72 74 9 166 62 56 13
169 143 136 34 175 109 189 80 108 165 202 188 45 99 172 203 145 126
205 157 49 24 22 139 100 159 20 111 226 133 117 233 88 46 237 130
38 3 220 217 252 35 196 96 151 89 76 6 137 192 219 5 47 178
236 110 48 98 55 118 59 155 176 92 185 179 234 211 249 70 148 18
114 39 77 124 67 14 69 58 4 195 161 7 57 147 51 238 8 135
164 144 138 116 131 208 29 162 170 85 104 193 184 97 75 216 103 115
160 123 197 11 183 10 40 222 94 101 167 213 198 90 140 243 121 149
200 63 152 12 44 23 19 129 17 68 134 28 95 218 154 248 15 16
106 227 221 102 128 120 112 26 228 78 83 31 41 36 232 21 125 107
33 73 253 223]
antilog = [ 1 9 65 127 170 141 137 173 178 85 203 201 219 89 167 232 233 224
161 222 116 249 112 221 111 58 241 56 227 186 29 245 28 252 93 131
247 14 126 163 204 246 7 63 220 102 123 142 146 110 51 176 71 73
55 148 88 174 169 150 74 44 87 217 75 37 22 166 225 168 159 11
83 253 84 194 136 164 243 42 97 68 82 244 21 189 34 41 122 135
211 17 153 61 206 228 133 193 147 103 114 207 237 196 190 57 234 251
98 95 145 117 240 49 162 197 183 120 149 81 239 214 60 199 165 250
107 30 238 223 125 184 15 119 226 179 92 138 182 113 212 46 69 91
181 106 23 175 160 215 53 134 218 80 230 151 67 109 40 115 198 172
187 20 180 99 86 208 10 90 188 43 104 5 45 94 152 52 143 155
47 76 26 202 192 154 38 13 101 96 77 19 139 191 48 171 132 200
210 24 216 66 100 105 12 108 33 50 185 6 54 157 25 209 3 27
195 129 229 140 128 236 205 255 70 64 118 235 242 35 32 59 248 121
156 16 144 124 177 78 8 72 62 213 39 4 36 31 231 158 2 18
130 254 79 ]

Categories