Now that we know the Image3D and Field3D types, we will next talk about how they interact with each other. Many of these examples apply to Image3Ds and Field3Ds, so I will restrict the examples to Image3Ds. First lets declare several Image3Ds.
import PyCA.Core as ca
grid = ca.GridInfo(ca.Vec3Di(10, 10, 10))
mType = ca.MEM_DEVICE
Im0 = ca.Image3D(grid, mType)
Im1 = ca.Image3D(grid, mType)
Im2 = ca.Image3D(grid, mType)
Im3 = ca.Image3D(grid, mType)
Imout = ca.Image3D(grid, mType)
ca.SetMem(Im0, 1)
ca.SetMem(Im1, 2)
ca.SetMem(Im2, 3)
ca.SetMem(Im3, 4)
c0 = 1 #just a constant
c1 = 2
c2 = 3
We do have support for the typical binary operations '+', '-', '*', and '\', but we recommend against using them. The reason is this: suppose we run Imout = Im0 + Im1 + Im2 + Im3
. This will be legal, but it will be slow and memory intensive because we need to allocate and deallocate memory (the size of each image) 3 times. Therefore, we have pre defined functions that perform most of these operations. The typical binary operations are fairly straightforward, with the first argument being the output argument. Note that the C
in the function name reflects that you are performing the opeartion with a constant. (With a field, the C represents either a constant or a Vec3Df)
ca.Add(Imout, Im0, Im1) #Imout = Im0 + Im1
ca.Sub(Imout, Im0, Im1) #Imout = Im0 - Im1
ca.Mul(Imout, Im0, Im1) #Imout = Im0 * Im1
ca.Div(Imout, Im0, Im1) #Imout = Im0 / Im1
ca.AddC(Imout, Im0, c0) #Imout = Im0 + c0
ca.SubC(Imout, Im0, c0) #Imout = Im0 - c0
ca.MulC(Imout, Im0, c0) #Imout = Im0 * c0
ca.DivC(Imout, Im0, c0) #Imout = Im0 / c0
We also have in-place operations, that are named as Oper_I
:
ca.SetMem(Imout, 1.0)
ca.Add_I(Imout, Im0) #Imout += Im0
ca.Sub_I(Imout, Im0) #Imout -= Im0
ca.Mul_I(Imout, Im0) #Imout *= Im0
ca.Div_I(Imout, Im0) #Imout /= Im0
ca.AddC_I(Imout, c0) #Imout += c0
ca.SubC_I(Imout, c0) #Imout -= c0
ca.MulC_I(Imout, c0) #Imout *= c0
ca.DivC_I(Imout, c0) #Imout /= c0
For the Unary operations, += maps directly to Add_I or AddC_I, so there is no performance difference in using the unary operator. Therefore, the following commands are equivalent to the last set of commands, and in fact they are usually preferred (for clarity).
Imout += Im0
Imout -= Im0
Imout *= Im0
Imout /= Im0
Imout += c0
Imout -= c0
Imout *= c0
Imout /= c0
For longer series of these arithmetic operations, the naming scheme for the functions fits the following order of operations
_
are done lastFor example,
Add_AddMulC(Imout, Im1, Im2, Im3, c0)
is equivalent to Imout = Im1 + (Im2 + Im3)*c0
and
Add_AddMulC_I(Imout, Im1, Im2, c0)
is equivalent to Imout = Imout + (Im1 + Im2)*c0
Below is a comprehensive list (along with definitions) of the N-ary Arithmetic operations. Each operation should have a corresponding in-place version.
ca.AddDiv(Imout, Im0, Im1, Im2) # Imout = (Im0+Im1)/Im2
ca.AddMul(Imout, Im0, Im1, Im2) # Imout = (Im0+Im1)*Im2
ca.AddMulC(Imout, Im0, Im1, c0) # Imout = (Im0+Im1)*c0
ca.AddCMulC(Imout, Im0, c0, c1) # Imout = (Im0+c0)*c1
ca.AddCMulCAddC(Imout, Im0, c0, c1, c2) # Imout = (Im0+c0)*c1 + c2
ca.Add_AddMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 + (Im1+Im2)*c0
ca.Add_Mul(Imout, Im0, Im1, Im2) # Imout = (Im0+Im1)*Im2
ca.Add_MulC(Imout, Im0, Im1, c0) # Imout = Im0 + Im1*c0
ca.Add_MulMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 + Im1*Im2*c0
ca.Add_SubMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 + (Im1-Im2)*c0
ca.MulAdd(Imout, Im0, Im1, Im2) # Imout = Im0*Im1 + Im2
ca.MulCAdd(Imout, Im0, c0, Im1) # Imout = Im0*c0 + Im1
ca.MulCAddC(Imout, Im0, c0, c1) # Imout = Im0*c0 + c1
ca.MulCSub(Imout, Im0, c0, Im1) # Imout = Im0*c0 - Im1
ca.MulC_Add_MulC(Imout, Im0, c0, Im1, c1) # Imout = Im0*c0 + Im1+c1
ca.MulMul(Imout, Im0, Im1, Im2) # Imout = Im0*Im1*Im2
ca.MulMulC(Imout, Im0, Im1, c0) # Imout = Im0*Im1*c0
ca.MulSub(Imout, Im0, Im1, Im2) # Imout = Im0*Im1 - Im2
ca.SubDiv(Imout, Im0, Im1, Im2) # Imout = (Im0-Im1)/Im2
ca.SubMul(Imout, Im0, Im1, Im2) # Imout = (Im0-Im1)*Im2
ca.SubMulC(Imout, Im0, Im1, c0) # Imout = (Im0-Im1)*c0
ca.Sub_AddMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 - (Im1+Im2)*c0
ca.Sub_Mul(Imout, Im0, Im1, Im2) # Imout = Im0 - Im1*Im2
ca.Sub_MulMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 - Im1*Im2*c0
ca.Sub_SubMulC(Imout, Im0, Im1, Im2, c0) # Imout = Im0 - (Im1-Im2)*c0
We also have trigonometry functions, defined the same was as the C++ cmath library. Once again, we also have corresponding in-place opeartions.
ca.Sin(Imout, Im0)
ca.Cos(Imout, Im0)
ca.Tan(Imout, Im0)
ca.Cot(Imout, Im0)
ca.Sec(Imout, Im0)
ca.Csc(Imout, Im0)
ca.Asin(Imout, Im0)
ca.Acos(Imout, Im0)
ca.Atan(Imout, Im0)
ca.Atan2(Imout, Im0, Im1)
ca.Atan2C(Imout, Im0, c0)
We have relational functions (==, !=, >, >=, etc.). Image3D's only hold float values (and not bools), so these operations return 1.0 for True and 0.0 for False. As before, we have corresponding in-place operations.
ca.EQ(Imout, Im0, Im1) # Imout = (Im0 == Im1)
ca.EQC(Imout, Im0, c0) # Imout = (Im0 == c0)
ca.NEQ(Imout, Im0, Im1) # Imout = (Im0 != Im1)
ca.NEQC(Imout, Im0, c0) # Imout = (Im0 != c0)
ca.LT(Imout, Im0, Im1) # Imout = (Im0 < Im1)
ca.LTC(Imout, Im0, c0) # Imout = (Im0 < c0)
ca.LTE(Imout, Im0, Im1) # Imout = (Im0 <= Im1)
ca.LTEC(Imout, Im0, c0) # Imout = (Im0 <= c0)
ca.GT(Imout, Im0, Im1) # Imout = (Im0 > Im1)
ca.GTC(Imout, Im0, c0) # Imout = (Im0 > c0)
ca.GTE(Imout, Im0, Im1) # Imout = (Im0 >= Im1)
ca.GTEC(Imout, Im0, c0) # Imout = (Im0 >= c0)
We also have many other operators that don't fit into the above categories. They have in-place versions.
ca.Abs(Imout, Im0) # Imout = |Im0|
ca.AbsDiff(Imout, Im0, Im1) # Imout = |Im0 - Im1|
ca.SqrDiff(Imout, Im0, Im1) # Imout = (Im0 - Im1)^2
ca.Ramp(Imout, Im0) # Imout(x<0) = 0; Imout(x>=0) = Imout(x)
ca.Sgn(Imout, Im0) # Imout(x<0) = -1; Imout(x>0) = Imout(1)
ca.Step(Imout, Im0) # Imout(x<0) = 0; Imout(x>0) = Imout(1)
ca.Ceil(Imout, Im0)
ca.Floor(Imout, Im0)
ca.Round(Imout, Im0)
ca.Copy(Imout, Im0) # Imout = Im0
ca.Neg(Imout, Im0) # Imout = -Im0
ca.Sqr(Imout, Im0) # Imout = Im0^2
ca.Cube(Imout, Im0) # Imout = Im0^3
ca.PowC(Imout, Im0, c0) # Imout = Im0^c0
ca.Sqrt(Imout, Im0)
ca.Exp(Imout, Im0) # Imout = e^Im0
ca.Log(Imout, Im0) # natural log
ca.Min(Imout, Im0, Im1) # element-wise minimum
ca.MinC(Imout, Im0, c0) # element-wise minimum with a constant
ca.Max(Imout, Im0, Im1) # element-wise maximum
ca.MaxC(Imout, Im0, c0) # element-wise maximum with a constant
The past operations have always had an Image3D as an output, but we also have summary functions that return either a float or two floats:
print ca.Sum(Im2) # sum(Im2)
print ca.Sum2(Im2) # sum2(Im2^2)
print ca.Min(Im2)
print ca.Max(Im2)
print ca.MinMax(Im2)
3000.0 9000.0 3.0 3.0 [3.0, 3.0]