1 ################################################################################
5 # Copyright (C) 2005 Mike Kost <contact@povray.tashcorp.net>
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ################################################################################
25 # __init__(x=1, y=1, z=1) : default constructor
26 # clone(indf3) : make this df3 look like indf3
29 # sizeX(): returns X dimension
30 # sizeY(): returns Y dimension
31 # sizeZ(): returns Z dimension
36 # max(): returns highest voxel value in df3
37 # min(): returns lowest voxel value in df3
41 # Import/Export functions
45 ################################################################################
53 # -+-+-+- Start df3 Class -+-+-+-
60 __struct4byte__
= '>I'
61 __struct2byte__
= '>H'
62 __struct2byte3__
= '>HHH'
63 __struct1byte__
= '>B'
68 def __init__(self
, x
=1, y
=1, z
=1):
72 self
.voxel
= self
.__create
__(x
, y
, z
)
74 def clone(self
, indf3
):
75 self
.voxel
= array
.array(self
.__arraytype
__)
76 for i
in range(indf3
.sizeX()*indf3
.sizeY()*indf3
.sizeZ()):
77 self
.voxel
[i
] = indf3
.voxel
[i
]
93 tmp
.append(self
.sizeX())
94 tmp
.append(self
.sizeY())
95 tmp
.append(self
.sizeZ())
98 #### Voxel Access Functions
100 def get(self
, x
, y
, z
):
101 return self
.voxel
[self
.__voxa
__(x
,y
,z
)]
103 def getB(self
, x
, y
, z
):
104 if (x
> self
.sizeX() or x
< 0): return 0
105 if (y
> self
.sizeX() or y
< 0): return 0
106 if (z
> self
.sizeX() or z
< 0): return 0
108 return self
.voxel
[self
.__voxa
__(x
,y
,z
)]
110 def set(self
, x
, y
, z
, val
):
111 self
.voxel
[self
.__voxa
__(x
,y
,z
)] = val
113 def setB(self
, x
, y
, z
, val
):
114 if (x
> self
.sizeX() or x
< 0): return
115 if (y
> self
.sizeX() or y
< 0): return
116 if (z
> self
.sizeX() or z
< 0): return
118 self
.voxel
[self
.__voxa
__(x
,y
,z
)] = val
120 #### Scalar Functions
123 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
124 self
.voxel
[i
] = self
.voxel
[i
] * val
129 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
130 self
.voxel
[i
] = self
.voxel
[i
] + val
137 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
138 if (self
.voxel
[i
] > tmp
):
146 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
147 if (self
.voxel
[i
] < tmp
):
152 #### Vector Functions
154 def compare(self
, indf3
):
155 if (self
.__samesize
__(indf3
) == 0): return 0
157 if (self
.voxel
== indf3
.voxel
):
162 def multV(self
, indf3
):
163 if (self
.__samesize
__(indf3
) == 0):
164 print("Cannot multiply voxels - not same size")
167 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
168 self
.voxel
[i
] = self
.voxel
[i
]*indf3
.voxel
[i
]
172 def addV(self
, indf3
):
173 if (self
.__samesize
__(indf3
) == 0):
174 print("Cannot add voxels - not same size")
177 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
178 self
.voxel
[i
] = self
.voxel
[i
]+indf3
.voxel
[i
]
182 def convolveV(self
, filt
):
187 print("Incompatible filter - must be odd number of X")
190 print("Incompatible filter - must be odd number of Y")
193 print("Incompatible filter - must be odd number of Z")
201 newV
= self
.__create
__(self
.sizeX(), self
.sizeY(), self
.sizeZ());
203 for x
in range(self
.sizeX()):
204 for y
in range(self
.sizeY()):
205 for z
in range(self
.sizeZ()):
206 rip
= self
.__rip
__(x
-fdx
, x
+fdx
, y
-fdy
, y
+fdy
, z
-fdz
, z
+fdz
)
208 for i
in range(flen
):
209 tmp
+= rip
[i
]*filt
.voxel
[i
]
210 newV
[self
.__voxa
__(x
,y
,z
)] = tmp
216 #### Import/Export Functions
218 def exportDF3(self
, file, depth
=8, rescale
=1):
224 f
= open(file, 'wb');
226 print("Could not open " + file + " for write");
229 f
.write(struct
.pack(self
.__struct
2byte
3__, x
, y
, z
));
231 tmp
= self
.__toInteger
__(pow(2,depth
)-1, rescale
)
233 if (depth
> 16): # 32-bit
234 for i
in range( x
*y
*z
):
235 f
.write(struct
.pack(self
.__struct
4byte
__, tmp
[i
]))
236 elif (depth
> 8): # 16-bit
237 for i
in range( x
*y
*z
):
238 f
.write(struct
.pack(self
.__struct
2byte
__, tmp
[i
]))
240 for i
in range( x
*y
*z
):
241 f
.write(struct
.pack(self
.__struct
1byte
__, tmp
[i
]))
243 def importDF3(self
, file, scale
=1):
245 f
= open(file, 'rb');
246 size
= os
.stat(file)[stat
.ST_SIZE
]
249 print("Could not open " + file + " for read");
252 (x
, y
, z
) = struct
.unpack(self
.__struct
2byte
3__, f
.read(6) )
254 self
.voxel
= self
.__create
__(x
, y
, z
)
260 if (size
== x
*y
*z
): format
= 8
261 elif (size
== 2*x
*y
*z
): format
= 16
262 elif (size
== 4*x
*y
*z
): format
= 32
265 for i
in range(x
*y
*z
):
266 self
.voxel
[i
] = float(struct
.unpack(self
.__struct
4byte
__, f
.read(4) )[0])
268 for i
in range(x
*y
*z
):
269 self
.voxel
[i
] = float(struct
.unpack(self
.__struct
2byte
__, f
.read(2) )[0])
271 for i
in range(x
*y
*z
):
272 self
.voxel
[i
] = float(struct
.unpack(self
.__struct
1byte
__, f
.read(1) )[0])
276 #### Local classes not intended for user use
278 def __rip__(self
, minX
, maxX
, minY
, maxY
, minZ
, maxZ
):
283 tmpV
= self
.__create
__(sizeX
, sizeY
, sizeZ
)
285 for x
in range(sizeX
):
286 for y
in range(sizeY
):
287 for z
in range(sizeZ
):
290 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
291 elif ((minX
+ x
) > self
.sizeX()-1):
292 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
294 elif ((minY
+ y
) < 0):
295 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
296 elif ((minY
+ y
) > self
.sizeY()-1):
297 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
299 elif ((minZ
+ z
) < 0):
300 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
301 elif ((minZ
+ z
) > self
.sizeZ()-1):
302 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = 0.0
304 tmpV
[(z
*sizeZ
+y
)*sizeY
+x
] = self
.get(minX
+x
,minY
+y
,minZ
+z
)
308 def __samesize__(self
, indf3
):
309 if (self
.sizeX() != indf3
.sizeX()): return 0
310 if (self
.sizeY() != indf3
.sizeY()): return 0
311 if (self
.sizeZ() != indf3
.sizeZ()): return 0
314 def __voxa__(self
, x
, y
, z
):
315 return ((z
*self
.sizeY()+y
)*self
.sizeX()+x
)
317 def __create__(self
, x
, y
, z
, atype
='0', init
=1):
319 tmp
= self
.__arraytype
__
325 voxel
= array
.array(tmp
, [0.0 for i
in range(x
*y
*z
)])
327 voxel
= array
.array(tmp
, [0 for i
in range(x
*y
*z
)])
329 voxel
= array
.array(tmp
)
333 def __toInteger__(self
, scale
, rescale
=1):
334 if (scale
< pow(2,8)): # 8-bit
335 tmp
= self
.__create
__(self
.sizeX(), self
.sizeY(), self
.sizeZ(), self
.__array
1byte
__)
336 elif (scale
< pow(2,16)): # 16-bit
337 tmp
= self
.__create
__(self
.sizeX(), self
.sizeY(), self
.sizeZ(), self
.__array
2byte
__)
339 tmp
= self
.__create
__(self
.sizeX(), self
.sizeY(), self
.sizeZ(), self
.__array
4byte
__)
345 for i
in range(self
.sizeX()*self
.sizeY()*self
.sizeZ()):
347 tmp
[i
] = max(0,int(round(scale
*self
.voxel
[i
]/maxVal
)))
349 tmp
[i
] = max(0,min(scale
,int(round(self
.voxel
[i
]))))
353 # -=-=-=- End df3 Class -=-=-=-
354 ##########DEFAULT EXAMPLES
355 # if __name__ == '__main__':
359 ## Generate an output
360 # temp = df3(localX, localY, localZ)
362 # for i in range(localX):
363 # for j in range(localY):
364 # for k in range(localZ):
365 # if (i >= (localX/2)):
366 # temp.set(i, j, k, 1.0)
368 # temp.exportDF3('temp.df3', 16)
369 ###############################################################################
371 # temp2 = df3().importDF3('temp.df3')
372 # temp2.mult(1/temp2.max())
375 # print(temp2.size())
377 # if (temp.compare(temp2) == 0): print("DF3's Do Not Match")
379 ###############################################################################
382 # 08/09/05: 0.20 released
383 # + Change internal representation to floating point
384 # + Rewrite import/export for speed
385 # + Convert from 3-d list structure to Array class for data storage
386 # + Add element access, scalar, and vector functions
387 # 07/13/05: 0.10 released
388 ###############################################################################