From 02df1d5763a5d2bfe750bbc30b5c001ee9b23b17 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 22 Aug 2012 16:07:12 -0400 Subject: [PATCH] Move the last two MRI-specific variables out of MRI.hs and into the command-line configuration. Rename MRI to Volumetric. --- src/CommandLine.hs | 66 ++++++++++++++++++++++++++++------- src/Everything.hs | 2 +- src/Main.hs | 46 ++++++++++++++---------- src/{MRI.hs => Volumetric.hs} | 58 +++++++++++++----------------- 4 files changed, 107 insertions(+), 65 deletions(-) rename src/{MRI.hs => Volumetric.hs} (73%) diff --git a/src/CommandLine.hs b/src/CommandLine.hs index 6479145..f413e2f 100644 --- a/src/CommandLine.hs +++ b/src/CommandLine.hs @@ -45,9 +45,11 @@ data Args = Args { depth :: Int, height :: Int, input :: FilePath, + lower_threshold :: Int, + output :: FilePath, scale :: Int, slice :: Maybe Int, - output :: FilePath, + upper_threshold :: Int, width :: Int } deriving (Show, Data, Typeable) @@ -65,35 +67,75 @@ spline3_summary :: String spline3_summary = program_name ++ "-" ++ (showVersion version) +depth_default :: Int +depth_default = 109 + depth_help :: String -depth_help = "The size of the z dimension (default: 109)" +depth_help = + "The size of the z dimension (default: " ++ (show depth_default) ++ ")" + +height_default :: Int +height_default = 256 height_help :: String -height_help = "The size of the y dimension (default: 256)" +height_help = + "The size of the y dimension (default: " ++ (show height_default) ++ ")" + +lower_threshold_default :: Int +lower_threshold_default = 1400 + +lower_threshold_help :: String +lower_threshold_help = + "The lower limit for voxel values, only used in 2D (default: " ++ + (show lower_threshold_default) ++ ")" + +scale_default :: Int +scale_default = 2 scale_help :: String scale_help = "The magnification scale. A scale of 2 would result " ++ - "in an image twice as large as the original. (default: 2)" + "in an image twice as large as the original. (default: " ++ + (show scale_default) ++ ")" slice_help :: String slice_help = "The index of the two-dimensional slice to use if no depth is specified" +upper_threshold_default :: Int +upper_threshold_default = 2500 + +upper_threshold_help :: String +upper_threshold_help = + "The upper limit for voxel values, only used in 2D (default: " ++ + (show upper_threshold_default) ++ ")" + +width_default :: Int +width_default = 256 + width_help :: String -width_help = "The size of the x dimension (default: 256)" +width_help = + "The size of the x dimension (default: " ++ (show width_default) ++ ")" arg_spec :: Mode (CmdArgs Args) arg_spec = cmdArgsMode $ Args { - depth = 109 &= groupname "Dimensions" &= help depth_help, - height = 256 &= groupname "Dimensions" &= help height_help, - input = def &= typ "INPUT" &= argPos 0, - output = def &= typ "OUTPUT" &= argPos 1, - scale = 2 &= help scale_help, - slice = Nothing &= groupname "2D options" &= help slice_help, - width = 256 &= groupname "Dimensions" &= help width_help + depth = depth_default &= groupname "Dimensions" &= help depth_help, + height = height_default &= groupname "Dimensions" &= help height_help, + input = def &= typ "INPUT" &= argPos 0, + + lower_threshold = lower_threshold_default &= groupname "2D options" + &= help lower_threshold_help, + + output = def &= typ "OUTPUT" &= argPos 1, + scale = scale_default &= help scale_help, + slice = Nothing &= groupname "2D options" &= help slice_help, + + upper_threshold = upper_threshold_default &= groupname "2D options" + &= help upper_threshold_help, + + width = width_default &= groupname "Dimensions" &= help width_help } &= program program_name &= summary spline3_summary diff --git a/src/Everything.hs b/src/Everything.hs index 5225c74..242aabe 100644 --- a/src/Everything.hs +++ b/src/Everything.hs @@ -13,8 +13,8 @@ import Face as X hiding (v0,v1,v2,v3) import FunctionValues as X import Grid as X import Misc as X -import MRI as X import Point as X import RealFunction as X import Tetrahedron as X import Values as X +import Volumetric as X \ No newline at end of file diff --git a/src/Main.hs b/src/Main.hs index 951c9c3..5e10d6c 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -14,13 +14,14 @@ import System.Exit (exitSuccess, exitWith, ExitCode(..)) import CommandLine (Args(..), apply_args) import ExitCodes import Grid (zoom) -import MRI ( +import Volumetric ( + bracket_array, flip_x, flip_y, read_word16s, round_array, swap_bytes, - write_values_slice_to_bitmap, + write_values_to_bmp, write_word16s, z_slice ) @@ -67,12 +68,12 @@ main = do -- Determine whether we're doing 2d or 3d. If we're given a slice, -- assume 2d. - let mri_shape = (R.Z R.:. depth R.:. height R.:. width) :: R.DIM3 + let shape = (R.Z R.:. depth R.:. height R.:. width) :: R.DIM3 if (isJust slice) then - main2d args mri_shape + main2d args shape else - main3d args mri_shape + main3d args shape exitSuccess @@ -81,35 +82,42 @@ main = do main3d :: Args -> R.DIM3 -> IO () -main3d Args{..} mri_shape = do +main3d Args{..} shape = do let zoom_factor = (scale, scale, scale) - arr <- read_word16s input mri_shape - let arr' = swap_bytes arr - let arrMRI = R.reshape mri_shape arr' - dbl_data <- R.computeUnboxedP $ R.map fromIntegral arrMRI + arr <- read_word16s input shape + let arr_swapped = swap_bytes arr + let arr_shaped = R.reshape shape arr_swapped + dbl_data <- R.computeUnboxedP $ R.map fromIntegral arr_shaped raw_output <- zoom dbl_data zoom_factor word16_output <- R.computeUnboxedP $ round_array raw_output write_word16s output word16_output main2d :: Args -> R.DIM3 -> IO () -main2d Args{..} mri_shape = do +main2d Args{..} shape = do let zoom_factor = (1, scale, scale) - arr <- read_word16s input mri_shape + arr <- read_word16s input shape arrSlice <- R.computeUnboxedP $ z_slice (fromJust slice) $ flip_x width $ flip_y height $ swap_bytes arr - let arrSlice' = R.reshape mri_slice3d arrSlice + let arrSlice' = R.reshape slice3d arrSlice -- If zoom isn't being inlined we need to extract the slice before hand, -- and convert it to the require formed. - dbl_data <- R.computeUnboxedP $ R.map fromIntegral arrSlice' - raw_output <- zoom dbl_data zoom_factor - arrSlice0 <- R.computeUnboxedP $ z_slice 0 raw_output + dbl_data <- R.computeUnboxedP $ R.map fromIntegral arrSlice' + raw_output <- zoom dbl_data zoom_factor + arrSlice0 <- R.computeUnboxedP $ z_slice 0 raw_output + + -- Make doubles from the thresholds which are given as Ints. + let lt = fromIntegral lower_threshold + let ut = fromIntegral upper_threshold + + let arr_bracketed = bracket_array lt ut arrSlice0 + values <- R.computeUnboxedP $ R.map fromIntegral arr_bracketed + write_values_to_bmp output values - write_values_slice_to_bitmap arrSlice0 output where - mri_slice3d :: R.DIM3 - mri_slice3d = (R.Z R.:. 1 R.:. height R.:. width) + slice3d :: R.DIM3 + slice3d = (R.Z R.:. 1 R.:. height R.:. width) diff --git a/src/MRI.hs b/src/Volumetric.hs similarity index 73% rename from src/MRI.hs rename to src/Volumetric.hs index 1c244c1..24bc13b 100644 --- a/src/MRI.hs +++ b/src/Volumetric.hs @@ -1,16 +1,17 @@ {-# LANGUAGE FlexibleContexts #-} --- | The MRI module contains functionsd and definitions relevant (and --- specific) to the MRI data files found at, +-- | The Volumetric module contains functions for manipulating the +-- volumetric data files found at, -- --- +-- -- -module MRI ( +module Volumetric ( + bracket_array, flip_x, flip_y, read_word16s, round_array, swap_bytes, - write_values_slice_to_bitmap, + write_values_to_bmp, write_word16s, z_slice ) @@ -28,14 +29,8 @@ import Data.Array.Repa.IO.BMP as R (writeImageToBMP) import Values -mri_lower_threshold :: Double -mri_lower_threshold = 1400 - -mri_upper_threshold :: Double -mri_upper_threshold = 2500 - --- | RawData is an array of words (16 bits), as contained in the MRI --- data files. +-- | RawData is an array of words (16 bits), as contained in the +-- volumetric data files. type RawData sh = Array U sh Word16 -- | A specialization of the 'RawData' type, to three dimensions. @@ -47,21 +42,21 @@ type ColorData sh = Array U sh RGB {-# INLINE read_word16s #-} read_word16s :: FilePath -> DIM3 -> IO RawData3D -read_word16s path mri_shape = do - arr <- R.readArrayFromStorableFile path mri_shape +read_word16s path shape = do + arr <- R.readArrayFromStorableFile path shape c <- R.copyP arr now $ c -bracket :: Double -> Word16 -bracket x - | x < mri_lower_threshold = 0 - | x > mri_upper_threshold = 255 +bracket :: Double -> Double -> Double -> Word16 +bracket lower_threshold upper_threshold x + | x < lower_threshold = 0 + | x > upper_threshold = 255 | otherwise = truncate (r * 255) where - numerator = x - mri_lower_threshold - denominator = mri_upper_threshold - mri_lower_threshold + numerator = x - lower_threshold + denominator = upper_threshold - lower_threshold r = numerator/denominator @@ -77,9 +72,9 @@ swap_bytes = R.map flip16 -bracket_array :: Shape sh => Values sh -> Array D sh Word16 -bracket_array = - R.map bracket +bracket_array :: Shape sh => Double -> Double -> Values sh -> Array D sh Word16 +bracket_array lt ut = + R.map (bracket lt ut) {-# INLINE round_array #-} @@ -131,15 +126,12 @@ values_to_colors arr = b' = truncate (b * 255) +write_values_to_bmp :: FilePath -> Values2D -> IO () +write_values_to_bmp path values = do + colors <- values_to_colors values + R.writeImageToBMP path colors + + z_slice :: (R.Unbox a, Source r a) => Int -> Array r DIM3 a -> Array D DIM2 a z_slice n arr = slice arr (Any :. n :. All :. All) - - -write_values_slice_to_bitmap :: Values2D -> FilePath -> IO () -write_values_slice_to_bitmap v3d path = do - values <- R.computeUnboxedP $ R.map fromIntegral arr_bracketed - colors <- values_to_colors $ values - R.writeImageToBMP path colors - where - arr_bracketed = bracket_array v3d -- 2.43.2