Python: modulus using anding - python

I'm writing a program using bitarray
for example:
bytePerInt = sys.getsizeof(1)
class BitMap(object):
def __init__(self,bits):
self.bitsPerInt = 8*bytePerInt
size = bits/self.bitsPerInt+1
self.bitarray = [0]*size
#set the bit of pos as 1
def setBit(self,pos):
index = pos/self.bitsPerInt
shift = pos%self.bitsPerInt
operator = self.bitarray[index]
mask = 1<<shift
operator|=mask
self.bitarray[index] = operator
I want to get the modulus with adding instead of %, such as num&31 instead of num%32.
However, bytePerInt is 24 in my computer, bitsPerInt is 24*8=192, which is not a power-of-2-number, as a result, I can't anding 191 to get the modulus, so what I can do?

Like others I'm not sure what you mean by and the essential element in the array is Int, but if you are creating a bit array of booleans (1 and 0), use bitarray.

Related

What is the equivalent way of doing this type of pythonic vectorized assignment in MATLAB?

I'm trying to translate this line of code from Python to MATLAB:
new_img[M[0, :] - corners[0][0], M[1, :] - corners[1][0], :] = img[T[0, :], T[1, :], :]
So, naturally, I wrote something like this:
new_img(M(1,:)-corners(2,1),M(2,:)-corners(2,2),:) = img(T(1,:),T(2,:),:);
But it gives me the following error when it reaches that line:
Requested 106275x106275x3 (252.4GB) array exceeds maximum array size
preference. Creation of arrays greater than this limit may take a long
time and cause MATLAB to become unresponsive. See array size limit or
preference panel for more information.
This has made me believe that it is not assigning things correctly. Img is at most a 1000 × 1500 RGB image. The same code works in less than 5 seconds in Python. How can I do vector assignment like the code in the first line in MATLAB?
By the way, I didn't paste all lines of my code for this post not to get too long. If I need to add anything else, please let me know.
Edit:
Here's an explanation of what I want my code to do (basically, this is what the Python code does):
Consider this line of code. It's not a real MATLAB code, I'm just trying to explain what I want to do:
A([2 3 5], [1 3 5]) = B([1 2 3], [2 4 6])
It is interpreted like this:
A(2,1) = B(1,2)
A(3,1) = B(2,2)
A(5,1) = B(3,2)
A(2,3) = B(1,4)
A(3,3) = B(2,4)
A(5,3) = B(3,4)
...
...
...
Instead, I want it to be interpreted like this:
A(2,1) = B(1,2)
A(3,3) = B(2,4)
A(5,5) = B(3,6)
When you do A[vector1, vector2] in Python, you index the set:
A[vector1[0], vector2[0]]
A[vector1[1], vector2[1]]
A[vector1[2], vector2[2]]
A[vector1[3], vector2[3]]
...
In MATLAB, the similar-looking A(vector1, vector2) instead indexes the set:
A(vector1(1), vector2(1))
A(vector1(1), vector2(2))
A(vector1(1), vector2(3))
A(vector1(1), vector2(4))
...
A(vector1(2), vector2(1))
A(vector1(2), vector2(2))
A(vector1(2), vector2(3))
A(vector1(2), vector2(4))
...
That is, you get each combination of indices. You should think of it as a sub-array composed of the rows and columns specified in the two vectors.
To accomplish the same as the Python code, you need to use linear indexing:
index = sub2ind(size(A), vector1, vector2);
A(index)
Thus, your MATLAB code should do:
index1 = sub2ind(size(new_img), M(1,:)-corners(2,1), M(2,:)-corners(2,2));
index2 = sub2ind(size(img), T(1,:), T(2,:));
% these indices are for first 2 dims only, need to index in 3rd dim also:
offset1 = size(new_img,1) * size(new_img,2);
offset2 = size(img,1) * size(img,2);
index1 = index1.' + offset1 * (0:size(new_img,3)-1);
index2 = index2.' + offset2 * (0:size(new_img,3)-1);
new_img(index1) = img(index2);
What the middle block does here is add linear indexes for the same elements along the 3rd dimension. If ii is the linear index to an element in the first channel, then ii + offset1 is an index to the same element in the second channel, and ii + 2*offset1 is an index to the same element in the third channel, etc. So here we're generating indices to all those matrix elements. The + operation is doing implicit singleton expansion (what they call "broadcasting" in Python). If you have an older version of MATLAB this will fail, you need to replace that A+B with bsxfun(#plus,A,B).

How to efficiently mutate certain num of values in an array?

Given an initial 2-D array:
initial = [
[0.6711999773979187, 0.1949000060558319],
[-0.09300000220537186, 0.310699999332428],
[-0.03889999911189079, 0.2736999988555908],
[-0.6984000205993652, 0.6407999992370605],
[-0.43619999289512634, 0.5810999870300293],
[0.2825999855995178, 0.21310000121593475],
[0.5551999807357788, -0.18289999663829803],
[0.3447999954223633, 0.2071000039577484],
[-0.1995999962091446, -0.5139999985694885],
[-0.24400000274181366, 0.3154999911785126]]
The goal is to multiply some random values inside the array by a random percentage. Lets say only 3 random numbers get replaced by a random multipler, we should get something like this:
output = [
[0.6711999773979187, 0.52],
[-0.09300000220537186, 0.310699999332428],
[-0.03889999911189079, 0.2736999988555908],
[-0.6984000205993652, 0.6407999992370605],
[-0.43619999289512634, 0.5810999870300293],
[0.84, 0.21310000121593475],
[0.5551999807357788, -0.18289999663829803],
[0.3447999954223633, 0.2071000039577484],
[-0.1995999962091446, 0.21],
[-0.24400000274181366, 0.3154999911785126]]
I've tried doing this:
def mutate(array2d, num_changes):
for _ in range(num_changes):
row, col = initial.shape
rand_row = np.random.randint(row)
rand_col = np.random.randint(col)
cell_value = array2d[rand_row][rand_col]
array2d[rand_row][rand_col] = random.uniform(0, 1) * cell_value
return array2d
And that works for 2D arrays but there's chance that the same value is mutated more than once =(
And I don't think that's efficient and it only works on 2D array.
Is there a way to do such "mutation" for array of any shape and more efficiently?
There's no restriction of which value the "mutation" can choose from but the number of "mutation" should be kept strict to the user specified number.
One fairly simple way would be to work with a raveled view of the array. You can generate all your numbers at once that way, and make it easier to guarantee that you won't process the same index twice in one call:
def mutate(array_anyd, num_changes):
raveled = array_anyd.reshape(-1)
indices = np.random.choice(raveled.size, size=num_changes, replace=False)
values = np.random.uniform(0, 1, size=num_changes)
raveled[indices] *= values
I use array_anyd.reshape(-1) in favor of array_anyd.ravel() because according to the docs, the former is less likely to make an inadvertent copy.
The is of course still such a possibility. You can add an extra check to write back if you need to. A more efficient way would be to use np.unravel_index to avoid creating a view to begin with:
def mutate(array_anyd, num_changes):
indices = np.random.choice(array_anyd.size, size=num_changes, replace=False)
indices = np.unravel_indices(indices, array_anyd.shape)
values = np.random.uniform(0, 1, size=num_changes)
raveled[indices] *= values
There is no need to return anything because the modification is done in-place. Conventionally, such functions do not return anything. See for example list.sort vs sorted.
Using shuffle instead of random_choice, this would be a different solution. It works on an array of any shape.
def mutate(arrayIn, num_changes):
mult = np.zeros(arrayIn.ravel().shape[0])
mult[:num_changes] = np.random.uniform(0,1,num_changes)
np.random.shuffle(mult)
mult = mult.reshape(arrayIn.shape)
arrayIn = arrayIn + mult*arrayIn
return arrayIn

Python:16 bit one's complement addition implementation

I implemented one's complement addition of 16 bit integers in python, however I am trying to see if there is a better way to do it.
# This function returns a string of the bits (exactly 16 bits)
# for the number (in base 10 passed to it)
def get_bits(some_num):
binar = bin(some_num)[2::]
zeroes = 16 - len(binar)
padding = zeroes*"0"
binar = padding + binar
return binar
# This function adds the numbers, and handles the carry over
# from the most significant bit
def add_bits(num1, num2):
result = bin(int(num1,2) + int(num2,2))[2::]
# There is no carryover
if len(result) <= 16 :
result = get_bits(int(result,2))
# There is carryover
else :
result = result[1::]
one = '0000000000000001'
result = bin(int(result,2) + int(one,2))[2::]
result = get_bits(int(result,2))
return result
And now an example of running it would be:
print add_bits("1010001111101001", "1000000110110101")
returns :
0010010110011111
Is what wrote safe as far as results (Note I didn't do any negation here since that part is trivial, I am more interested in the intermediate steps)? Is there a better pythonic way to do it?
Thanks for any help.
Converting back and forth between string and ints to do math is inefficient. Do the math in integers and use formatting to display binary:
MOD = 1 << 16
def ones_comp_add16(num1,num2):
result = num1 + num2
return result if result < MOD else (result+1) % MOD
n1 = 0b1010001111101001
n2 = 0b1000000110110101
result = ones_comp_add16(n1,n2)
print('''\
{:016b}
+ {:016b}
------------------
{:016b}'''.format(n1,n2,result))
Output:
1010001111101001
+ 1000000110110101
------------------
0010010110011111
Converting back and forth between numbers, lists of one-bit strings, and strings probably doesn't feel like a very Pythonic way to get started.
More specifically, converting an int to a sequence of bits by using bin(i)[2:] is pretty hacky. It may be worth doing anyway (e.g., because it's more concise or more efficient than doing it numerically), but even if it is, it would be better to wrap it in a function named for what it does (and maybe even add a comment explaining why you did it that way).
You've also got unnecessarily complexifying code in there. For example, to do the carry, you do this:
one = '0000000000000001'
result = bin(int(result,2) + int(one,2))[2::]
But you know that int(one,2) is just the number 1, unless you've screwed up, so why not just use 1, which is shorter, more readable and obvious, and removes any chance of screwing up?
And you're not following PEP 8 style.
So, sticking with your basic design of "use a string for the bits, use only the basic string operations that are unchanged from Python 1.5 through 3.5 instead of format, and do the basic addition on integers instead of on the bits", I'd write it something like this:
def to_bits(n):
return bin(n)[2:]
def from_bits(n):
return int(n, 2)
def pad_bits(b, length=16):
return ["0"*length + b][-length:]
def add_bits(num1, num2):
result = to_bits(from_bits(num1) + from_bits(num2))
if len(result) <= 16: # no carry
return pad_bits(result)
return pad_bits(to_bits(from_bits(result[1:]) + 1))
But an even better solution would be to abstract out the string representation completely. Build a class that knows how to act like an integer, but also knows how to act like a sequence of bits. Or just find one on PyPI. Then your code becomes trivial. For example:
from bitstring import BitArray
def add_bits(n1, n2):
"""
Given two BitArray values of the same length, return a BitArray
of the same length that's the one's complement addition.
"""
result = n1.uint + n2.uint
if result >= (1 << n1.length):
result = result % n1.length + 1
return BitArray(uint=result, length=n1.length)
I'm not sure that bitstring is actually the best module for what you're doing. There are a half-dozen different bit-manipulating libraries on PyPI, all of which have different interfaces and different strengths and weaknesses; I just picked the first one that came up in a search and slapped together an implementation using it.

what are the cv.Scalar (min) and (max) used in cv.IntRanges

I've searched and searched but couldn't find:
When I use cv.InRanges I need to place a min and max HSV values. In all the examples I have seen so far they use Cv.Scalar on constants
i tried using it myself but couldnt figure what should be there i tried a list, a tuple and numpy.array all with three values and i keep getting errors.
"a float is requierd" for a list
"a float is required" for tuple
"only length -1 arrays can be converted to python scalars" for numpy.array
Though come to think of it array and list should be the same....
Can anyone please tell me how to use it properly, this is a sample of one of many tries:
def thresh(img, pixel):
hsv_min = pixel
hsv_min[0] = hsv_min[0] - 5
hsv_min[1] = hsv_min[1] - 20
hsv_min[2] = hsv_min[2] - 20
hsv_max[0] = hsv_max[0] + 5
hsv_max[1] = 255
hsv_max[2] = 255
cv.InRangeS(ingHSV, cv.Scalar(hsv_min), cv,Scalar(hsv_max), imgThreshold)
So i figured it out:
using:
cv.Scalar(float(hsv_min[0]),float(hsv_min[1]),float(hsv_min[2]))
and then Cv.InRangeS works fine.
Maybe this code can help you, but it uses numpy & opencv2, I've never tried with opencv first.
import cv2
import numpy
def thresh(img, pixel):
hsv_min = pixel
low_threshold = numpy.array(( hsv_min[0] - 5, hsv_min[1] - 20, hsv_min[2] - 20), dtype=numpy.uint8, ndmin=1)
high_threshold = numpy.array(( hsv_max[0] + 5, 255, 255), dtype=numpy.uint8, ndmin=1)
cv2.InRange(ingHSV, low_threshold, high_threshold, imgThreshold)

Round in numpy to Nearest Step

I would like to know how I can round a number in numpy to an upper or lower threshold which is function of predefined step size. Hopefully stated in a clearer way, if I have the number 123 and a step size equal to 50, I need to round 123 to the closest of either 150 or 100, in this case 100. I came out with function below which does the work but I wonder if there is a better, more succint, way to do this.
Thanks in advance,
Paolo
def getRoundedThresholdv1(a, MinClip):
import numpy as np
import math
digits = int(math.log10(MinClip))+1
b = np.round(a, -digits)
if b > a: # rounded-up
c = b - MinClip
UpLow = np.array((b,c))
else: # rounded-down
c = b + MinClip
UpLow = np.array((c,b))
AbsDelta = np.abs(a - UpLow)
return UpLow[AbsDelta.argmin()]
getRoundedThresholdv1(143, 50)
The solution by pb360 is much better, using the second argument of builtin round in python3.
I think you don't need numpy:
def getRoundedThresholdv1(a, MinClip):
return round(float(a) / MinClip) * MinClip
here a is a single number, if you want to vectorize this function you only need to replace round with np.round and float(a) with np.array(a, dtype=float)
Summary: This is a correct way to do it, the top answer has cases that do not work:
def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
"""Rounds a given quantity to a specific step size
:param quantity: required
:param step_size: required
:return: decimal
"""
precision: int = int(round(-math.log(step_size, 10), 0))
return float(round(quantity, precision))
My reputation is too low to post a comment on the top answer from Ruggero Turra and point out the issue. However it has cases which did not work for example:
def getRoundedThresholdv1(a, MinClip):
return round(float(a) / MinClip) * MinClip
getRoundedThresholdv1(quantity=13.200000000000001, step_size=0.0001)
Returns 13.200000000000001 right back whether using numpy or the standard library round. I didn't even find this by stress testing the function. It just came up when using it in production code and spat an error.
Note full credit for this answer comes out of an open source github repo which is not mine found here
Note that round() in Ruggero Turra his answer rounds to the nearest even integer. Meaning:
a= 0.5
round(a)
Out: 0
Which may not be what you expect.
In case you want 'classical' rounding, you can use this function, which supports both scalars and Numpy arrays:
import Numpy as np
def getRoundedThresholdv1(a, MinClip):
scaled = a/MinClip
return np.where(scaled % 1 >= 0.5, np.ceil(scaled), np.floor(scaled))*MinClip
Alternatively, you could use Numpy's method digitize. It requires you to define the array of your steps. digitize will kind of ceil your value to the next step. So in order to round in a 'classical' way we need an intermediate step.
You can use this:
import Numpy as np
def getRoundedThresholdv1(a, MinClipBins):
intermediate = (MinClipBins[1:] + MinClipBins[:-1])/2
return MinClipBins[np.discritize(a, intermediate)]
You can then call it like:
bins = np.array([0, 50, 100, 150])
test1 = getRoundedThresholdv1(74, bins)
test2 = getRoundedThresholdv1(125, bins)
Which gives:
test1 = 50
test2 = 150

Categories

Resources