grid_tests,
make_grid,
slow_tests,
- zoom,
- zoom_chunk
+ zoom
)
where
-import Data.Array (Array, array, (!))
import qualified Data.Array.Repa as R
import Test.HUnit
import Test.Framework (Test, testGroup)
import Values (Values3D, dims, empty3d, zoom_shape)
-type CubeGrid = Array (Int,Int,Int) Cube
-
-
-- | Our problem is defined on a Grid. The grid size is given by the
-- positive number h. The function values are the values of the
-- function at the grid points, which are distance h from one
-- another in each direction (x,y,z).
data Grid = Grid { h :: Double, -- MUST BE GREATER THAN ZERO!
- function_values :: Values3D,
- cube_grid :: CubeGrid }
+ function_values :: Values3D }
deriving (Eq, Show)
make_grid :: Double -> Values3D -> Grid
make_grid grid_size values
| grid_size <= 0 = error "grid size must be positive"
- | otherwise = Grid grid_size values (cubes grid_size values)
-
-
--- | Returns a three-dimensional array of cubes centered on the grid
--- points (h*i, h*j, h*k) with the appropriate 'FunctionValues'.
-cubes :: Double -> Values3D -> CubeGrid
-cubes delta fvs
- = array (lbounds, ubounds)
- [ ((i,j,k), cube_ijk)
- | i <- [0..xmax],
- j <- [0..ymax],
- k <- [0..zmax],
- let tet_vol = (1/24)*(delta^(3::Int)),
- let fvs' = make_values fvs i j k,
- let cube_ijk =
- Cube delta i j k fvs' tet_vol]
- where
- xmax = xsize - 1
- ymax = ysize - 1
- zmax = zsize - 1
- lbounds = (0, 0, 0)
- ubounds = (xmax, ymax, zmax)
- (xsize, ysize, zsize) = dims fvs
+ | otherwise = Grid grid_size values
+
-- | Takes a grid and a position as an argument and returns the cube
| j >= ysize = error "j >= ysize in cube_at"
| k < 0 = error "k < 0 in cube_at"
| k >= zsize = error "k >= zsize in cube_at"
- | otherwise = (cube_grid g) ! (i,j,k)
- where
+ | otherwise = Cube delta i j k fvs' tet_vol
+ where
fvs = function_values g
(xsize, ysize, zsize) = dims fvs
+ fvs' = make_values fvs i j k
+ delta = h g
+ tet_vol = (1/24)*(delta^(3::Int))
-- The first cube along any axis covers (-h/2, h/2). The second
-- covers (h/2, 3h/2). The third, (3h/2, 5h/2), and so on.
{-# INLINE zoom_lookup #-}
-zoom_lookup :: Grid -> ScaleFactor -> a -> (R.DIM3 -> Double)
-zoom_lookup g scale_factor _ =
- zoom_result g scale_factor
+zoom_lookup :: Values3D -> ScaleFactor -> a -> (R.DIM3 -> Double)
+zoom_lookup v3d scale_factor _ =
+ zoom_result v3d scale_factor
{-# INLINE zoom_result #-}
-zoom_result :: Grid -> ScaleFactor -> R.DIM3 -> Double
-zoom_result g (sfx, sfy, sfz) (R.Z R.:. m R.:. n R.:. o) =
+zoom_result :: Values3D -> ScaleFactor -> R.DIM3 -> Double
+zoom_result v3d (sfx, sfy, sfz) (R.Z R.:. m R.:. n R.:. o) =
f p
where
+ g = make_grid 1 v3d
offset = (h g)/2
m' = (fromIntegral m) / (fromIntegral sfx) - offset
n' = (fromIntegral n) / (fromIntegral sfy) - offset
f = polynomial t
-zoom :: Grid -> ScaleFactor -> Values3D
-zoom g scale_factor
- | xsize == 0 || ysize == 0 || zsize == 0 = empty3d
- | otherwise =
- R.force $ R.unsafeTraverse arr transExtent (zoom_lookup g scale_factor)
- where
- arr = function_values g
- (xsize, ysize, zsize) = dims arr
- transExtent = zoom_shape scale_factor
-
-
-
-
-{-# INLINE zoom_chunk_lookup #-}
-zoom_chunk_lookup :: Grid -> ScaleFactor -> a -> (R.DIM3 -> Double)
-zoom_chunk_lookup g scale_factor _ =
- zoom_chunk_result g scale_factor
-
-
-{-# INLINE zoom_chunk_result #-}
-zoom_chunk_result :: Grid -> ScaleFactor -> R.DIM3 -> Double
-zoom_chunk_result g (sfx, sfy, sfz) (R.Z R.:. m R.:. n R.:. o)
- | m /= 1 = 0 -- We're going to drop these anyway.
- | otherwise = f p
- where
- offset = (h g)/2
- sfx' = fromIntegral sfx
- sfy' = fromIntegral sfy
- sfz' = fromIntegral sfz
- m' = (fromIntegral m) / sfx' - offset
- n' = (fromIntegral n) / sfy' - offset
- o' = (fromIntegral o) / sfz' - offset
- p = (m', n', o') :: Point
- cube = find_containing_cube g p
- t = find_containing_tetrahedron cube p
- f = polynomial t
-
-
-zoom_chunk :: Grid -> ScaleFactor -> Values3D
-zoom_chunk g scale_factor
+zoom :: Values3D -> ScaleFactor -> Values3D
+zoom v3d scale_factor
| xsize == 0 || ysize == 0 || zsize == 0 = empty3d
| otherwise =
- R.force $ R.unsafeTraverse arr transExtent (zoom_chunk_lookup g scale_factor)
+ R.force $ R.unsafeTraverse v3d transExtent (zoom_lookup v3d scale_factor)
where
- arr = function_values g
- (xsize, ysize, zsize) = dims arr
+ (xsize, ysize, zsize) = dims v3d
transExtent = zoom_shape scale_factor
import qualified Data.Array.Repa as R
import System.Environment (getArgs)
-import Grid (make_grid, zoom, zoom_chunk)
+import Grid (zoom)
import MRI
main :: IO ()
-main = main2d_chunk
-
-
-main2d_chunk :: IO ()
-main2d_chunk = do
- (s:_) <- getArgs
- let scale = read s :: Int
- let zoom_factor = (1, scale, scale)
- let out_file = "output.bmp"
- arr <- read_word16s in_file
- let arr' = swap_bytes arr
- let arrInv = flip_x $ flip_y arr'
- let arrSlice = z_slice3 50 arrInv
- let dbl_data = R.map fromIntegral arrSlice
- let g = make_grid 1 dbl_data
- let output = zoom_chunk g zoom_factor
- write_values_chunk_to_bitmap output out_file
-
+main = main3d
main3d :: IO ()
let out_file = "output.bin"
arr <- read_word16s in_file
let arr' = swap_bytes arr
--- let arrInv = flip_x $ flip_y arr'
let arrMRI = R.reshape mri_shape arr'
let dbl_data = R.force $ R.map fromIntegral arrMRI
- let g = make_grid 1 dbl_data
- let output = zoom g zoom_factor
+ let output = zoom dbl_data zoom_factor
let word16_output = bracket_array output
write_word16s out_file word16_output
let arrSlice = z_slice 50 arrInv
let arrSlice' = R.reshape mri_slice3d arrSlice
let dbl_data = R.map fromIntegral arrSlice'
- let g = make_grid 1 dbl_data
- let output = zoom g zoom_factor
+ let output = zoom dbl_data zoom_factor
write_values_slice_to_bitmap (z_slice 0 output) out_file