Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion applications/pctfdk/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
wrap_ggo(pctfdk_GGO_C pctfdk.ggo)
wrap_ggo(pctfdk_GGO_C pctfdk.ggo ../pctinputprojections_section.ggo)
add_executable(
pctfdk
pctfdk.cxx
Expand Down
20 changes: 2 additions & 18 deletions applications/pctfdk/pctfdk.cxx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "pctfdk_ggo.h"
#include "pctGgoFunctions.h"
#include "rtkGgoFunctions.h"

#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
Expand All @@ -7,7 +8,6 @@
#include "pctFDKDDConeBeamReconstructionFilter.h"
#include "pctFDKDDConeBeamVarianceReconstructionFilter.h"

#include <itkRegularExpressionSeriesFileNames.h>
#include <itkImageFileWriter.h>

int
Expand All @@ -23,26 +23,10 @@ main(int argc, char * argv[])
itk::MultiThreaderBase::SetGlobalMaximumNumberOfThreads(
std::min<double>(8, itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads()));

// Generate file names
itk::RegularExpressionSeriesFileNames::Pointer names = itk::RegularExpressionSeriesFileNames::New();
names->SetDirectory(args_info.path_arg);
names->SetNumericSort(false);
names->SetRegularExpression(args_info.regexp_arg);
names->SetSubMatch(0);

if (args_info.verbose_flag)
std::cout << "Regular expression matches " << names->GetFileNames().size() << " file(s)..." << std::endl;

// Projections reader
using ProjectionImageType = itk::Image<OutputPixelType, Dimension + 1>;
auto reader = rtk::ProjectionsReader<ProjectionImageType>::New();
reader->SetFileNames(names->GetFileNames());
if (args_info.wpc_given)
{
std::vector<double> coeffs;
coeffs.assign(args_info.wpc_arg, args_info.wpc_arg + args_info.wpc_given);
reader->SetWaterPrecorrectionCoefficients(coeffs);
}
pct::SetProjectionsReaderFromGgo<rtk::ProjectionsReader<ProjectionImageType>, args_info_pctfdk>(reader, args_info);

// Geometry
if (args_info.verbose_flag)
Expand Down
3 changes: 0 additions & 3 deletions applications/pctfdk/pctfdk.ggo
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ version "Reconstruct a 3D volume from a sequence of projections [Feldkamp, David

option "verbose" v "Verbose execution" flag off
option "geometry" g "XML geometry file name" string yes
option "path" p "Path containing projections" string yes
option "regexp" r "Regular expression to select projection files in path" string yes
option "output" o "Output file name" string yes
option "lowmem" l "Load only one projection per thread in memory" flag off
option "wpc" - "Water precorrection coefficients (default is no correction)" double multiple no

section "Ramp filter"
option "pad" - "Data padding parameter to correct for truncation" double no default="0.0"
Expand Down
32 changes: 4 additions & 28 deletions applications/pctfdk/pctfdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@ def build_parser():
parser.add_argument(
"--geometry", "-g", help="XML geometry file name", type=str, required=True
)
parser.add_argument(
"--path", "-p", help="Path containing projections", type=str, required=True
)
parser.add_argument(
"--regexp",
"-r",
help="Regular expression to select projection files in path",
type=str,
required=True,
)
parser.add_argument(
"--output", "-o", help="Output file name", type=str, required=True
)
Expand All @@ -35,12 +25,6 @@ def build_parser():
help="Load only one projection per thread in memory",
action="store_true",
)
parser.add_argument(
"--wpc",
help="Water precorrection coefficients (default is no correction)",
type=float,
nargs="+",
)

# Ramp filter
parser.add_argument(
Expand Down Expand Up @@ -81,29 +65,21 @@ def build_parser():
help="Copy info from image (origin, size, spacing, direction)",
type=str,
)

pct.add_pctinputprojections_group(parser)

return parser


def process(args_info: argparse.Namespace):
from itk import RTK as rtk

# Generate file names
names = itk.RegularExpressionSeriesFileNames.New()
names.SetDirectory(args_info.path)
names.SetNumericSort(False)
names.SetRegularExpression(args_info.regexp)
names.SetSubMatch(0)
if args_info.verbose:
print(f"Regular expression matches {len(names.GetFileNames())} file(s)...")

# Projections reader
OutputPixelType = itk.F
ProjectionImageType = itk.Image[OutputPixelType, 4]
ReaderType = rtk.ProjectionsReader[ProjectionImageType]
reader = ReaderType.New()
reader.SetFileNames(names.GetFileNames())
if args_info.wpc:
reader.SetWaterPrecorrectionCoefficients([float(c) for c in args_info.wpc])
pct.SetProjectionsReaderFromArgParse(reader, args_info)

# Geometry
if args_info.verbose:
Expand Down
183 changes: 183 additions & 0 deletions applications/pctinputprojections_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import itk
from itk import PCT as pct
import numpy as np

__all__ = [
"add_pctinputprojections_group",
"GetProjectionsFileNamesFromArgParse",
]


# Mimicks pctinputprojections_section.ggo
def add_pctinputprojections_group(parser):
pctinputprojections_group = parser.add_argument_group(
"Input projections and their pre-processing"
)
pctinputprojections_group.add_argument(
"--path", "-p", help="Path containing projections", required=True
)
pctinputprojections_group.add_argument(
"--regexp",
"-r",
help="Regular expression to select projection files in path",
required=True,
)
pctinputprojections_group.add_argument(
"--nsort",
help="Numeric sort for regular expression matches",
action="store_true",
)
pctinputprojections_group.add_argument(
"--submatch",
help="Index of the submatch that will be used to sort matches",
type=int,
default=0,
)
pctinputprojections_group.add_argument(
"--newdirection",
help="New value of input projections (before pre-processing)",
type=float,
nargs="+",
)
pctinputprojections_group.add_argument(
"--neworigin",
help="New origin of input projections (before pre-processing)",
type=float,
nargs="+",
)
pctinputprojections_group.add_argument(
"--newspacing",
help="New spacing of input projections (before pre-processing)",
type=float,
nargs="+",
)
pctinputprojections_group.add_argument(
"--lowercrop",
help="Lower boundary crop size",
type=int,
nargs="+",
default=[0],
)
pctinputprojections_group.add_argument(
"--uppercrop",
help="Upper boundary crop size",
type=int,
nargs="+",
default=[0],
)
pctinputprojections_group.add_argument(
"--binning",
help="Shrink / Binning factos in each direction",
type=int,
nargs="+",
default=[1],
)
pctinputprojections_group.add_argument(
"--wpc",
help="Water precorrection coefficients (default is no correction)",
type=float,
nargs="+",
)
pctinputprojections_group.add_argument(
"--radius",
help="Radius of neighborhood for conditional median filtering",
type=int,
nargs="+",
default=[0],
)
pctinputprojections_group.add_argument(
"--multiplier",
help="Threshold multiplier for conditional median filtering",
type=float,
default=0,
)


# Mimicks GetProjectionsFileNamesFromGgo
def GetProjectionsFileNamesFromArgParse(args_info):
# Generate file names
names = itk.RegularExpressionSeriesFileNames.New()
names.SetDirectory(args_info.path)
names.SetNumericSort(args_info.nsort)
names.SetRegularExpression(args_info.regexp)
names.SetSubMatch(args_info.submatch)

if args_info.verbose:
print(f"Regular expression matches {len(names.GetFileNames())} file(s)...")

fileNames = []
for fn in names.GetFileNames():
imageio = itk.ImageIOFactory.CreateImageIO(
fn, itk.CommonEnums.IOFileMode_ReadMode
)
if imageio is None:
print(f"Ignoring file: {fn}")
continue
fileNames.append(fn)

return fileNames


def SetProjectionsReaderFromArgParse(reader, args_info):
fileNames = GetProjectionsFileNamesFromArgParse(args_info)

# Vector component extraction (not in PCT ggo)

# Change image information
Dimension = reader.GetOutput().GetImageDimension()
if args_info.newdirection is not None:
direction = [args_info.newdirection[0]] * 9
for i in range(min(9, len(args_info.newdirection))):
direction[i] = args_info.newdirection[i]
direction = np.array(direction).reshape((3, 3))
reader.SetDirection(itk.matrix_from_array(direction))

if args_info.newspacing is not None:
spacing = itk.Vector[itk.D, Dimension]()
spacing.Fill(args_info.newspacing[0])
for i in range(len(args_info.newspacing)):
spacing[i] = args_info.newspacing[i]
reader.SetSpacing(spacing)

if args_info.neworigin is not None:
origin = itk.Point[itk.D, Dimension]()
origin.Fill(args_info.neworigin[0])
for i in range(len(args_info.neworigin)):
origin[i] = args_info.neworigin[i]
reader.SetOrigin(origin)

# Crop boundaries
upperCrop = [0] * Dimension
lowerCrop = [0] * Dimension
if args_info.lowercrop is not None:
for i in range(len(args_info.lowercrop)):
lowerCrop[i] = args_info.lowercrop[i]
reader.SetLowerBoundaryCropSize(lowerCrop)
if args_info.uppercrop is not None:
for i in range(len(args_info.uppercrop)):
upperCrop[i] = args_info.uppercrop[i]
reader.SetUpperBoundaryCropSize(upperCrop)

# Conditional median
medianRadius = reader.GetMedianRadius()
if args_info.radius is not None:
for i in range(len(args_info.radius)):
medianRadius[i] = args_info.radius[i]
reader.SetMedianRadius(medianRadius)
if args_info.multiplier is not None:
reader.SetConditionalMedianThresholdMultiplier(args_info.multiplier)

# Shrink / Binning
binFactors = reader.GetShrinkFactors()
if args_info.binning is not None:
for i in range(len(args_info.binning)):
binFactors[i] = args_info.binning[i]
reader.SetShrinkFactors(binFactors)

# Water precorrection
if args_info.wpc is not None:
reader.SetWaterPrecorrectionCoefficients(args_info.wpc)

# Pass list to projections reader and update information
reader.SetFileNames(fileNames)
reader.UpdateOutputInformation()
14 changes: 14 additions & 0 deletions applications/pctinputprojections_section.ggo
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
section "Input projections and their pre-processing"
option "path" p "Path containing projections" string yes
option "regexp" r "Regular expression to select projection files in path" string yes
option "nsort" - "Numeric sort for regular expression matches" flag off
option "submatch" - "Index of the submatch that will be used to sort matches" int no default="0"
option "newdirection" - "New value of input projections (before pre-processing)" double multiple no
option "neworigin" - "New origin of input projections (before pre-processing)" double multiple no
option "newspacing" - "New spacing of input projections (before pre-processing)" double multiple no
option "lowercrop" - "Lower boundary crop size" int multiple no default="0"
option "uppercrop" - "Upper boundary crop size" int multiple no default="0"
option "binning" - "Shrink / Binning factos in each direction" int multiple no default="1"
option "wpc" - "Water precorrection coefficients (default is no correction)" double multiple no
option "radius" - "Radius of neighborhood for conditional median filtering" int multiple no default="0"
option "multiplier" - "Threshold multiplier for conditional median filtering" double no default="0"
Loading
Loading