Skip to content
Snippets Groups Projects
Commit e3a647f3 authored by Stephen Smith's avatar Stephen Smith
Browse files

Initial revision

parents
No related branches found
No related tags found
No related merge requests found
/* slicetimer.cc - FMRIB's Slice Timing Utility
Peter Bannister and Stephen Smith, FMRIB Image Analysis Group
Copyright (C) 2001-2002 University of Oxford */
/* CCOPYRIGHT */
#include <math.h>
#include <iostream.h>
#include <iomanip>
#include <fstream.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <strstream>
#include <unistd.h>
#include <vector.h>
#include "optimise.h"
#include "newmatap.h"
#include "newmatio.h"
#include "newimageall.h"
#include "options.h"
#include "kernel.h"
using namespace MISCMATHS;
using namespace NEWMAT;
using namespace NEWIMAGE;
using namespace Utilities;
string title="slicetimer (Version 1.8)\nFMRIB's Interpolation for Slice Timing\nCopyright(c) 2001-2002, University of Oxford";
string examples="slicetimer -i <timeseries> [-o <corrected_timeseries>] [options]\n";
Option<bool> help(string("-h,--help"), false,
string("display this message"),
false, no_argument);
Option<bool> verbose(string("-v,--verbose"), false,
string("switch on diagnostic messages"),
false, no_argument);
Option<bool> odd(string("--odd"), false,
string("use interleaved acquisition"),
false, no_argument);
Option<bool> down(string("--down"), false,
string("reverse slice indexing"),
false, no_argument);
Option<string> inputname(string("-i,--in"), string(""),
string("filename of input timeseries"),
true, requires_argument);
Option<string> outputname(string("-o,--out"), string(""),
string("filename of output timeseries"),
false, requires_argument);
Option<string> tcustom(string("--tcustom"), string(""),
string("filename of single-column custom interleave timing file"),
false, requires_argument);
Option<string> ocustom(string("--ocustom"), string(""),
string("filename of single-column custom interleave order file"),
false, requires_argument);
Option<int> direction(string("-d,--direction"), 3,
string("direction of slice acquisition (x=1,y=2,z=3) - default is z"),
false, requires_argument);
Option<float> repeat(string("-r,--repeat"), 3.0,
string("Specify TR of data - default is 3s"),
false, requires_argument);
int do_slice_correction()
{
volume4D<float> timeseries;
volumeinfo in_info;
ColumnVector voxeltimeseries, interpseries;
Matrix timings;
int no_volumes, no_slices;
float repeat_time, offset, slice_spacing, recenter;
if (inputname.set()) {
if (verbose.value()) { cout << "Reading input volume" << endl; }
read_volume4D(timeseries,inputname.value(),in_info);
if (!outputname.set())
outputname.set_value(inputname.value() + "_st");
} else if (outputname.set()) {
cerr << "Must specify an input volume (-i or --in) to generate corrected data."
<< endl;
return -1;
}
no_slices = timeseries.zsize();
no_volumes = timeseries.tsize();
repeat_time = timeseries.tdim();
if (repeat_time ==0){
cerr << "Zero TR in file header - fixing ... " ;
repeat_time = repeat.value();
}
cerr << "TR = " << repeat_time << endl;
slice_spacing = repeat_time / no_slices;
if (direction.value() == 1) timeseries. swapdimensions(3,2,1); // Flip z and x
if (direction.value() == 2) timeseries. swapdimensions(1,3,2); // Flip z and y
if (tcustom.set()) {
timings.ReSize(1, timeseries.zsize());
timings = read_ascii_matrix(tcustom.value(), timeseries.zsize(), 1);
} else if (ocustom.set()) {
timings.ReSize(1, timeseries.zsize());
timings = read_ascii_matrix(ocustom.value(), timeseries.zsize(), 1);
}
offset = 0.0;
ColumnVector userkernel = sinckernel1D("hanning", 7, 1201);
// if (down.value())
// recenter = (((float) no_slices)/2 + 0.5)/ no_slices;
//else
recenter = (((float) no_slices)/2 - 0.5)/ no_slices;
for (int slice=1; slice<=no_slices; slice++) {
if (tcustom.set()) {
offset = -timings(slice, 1);
} else if (ocustom.set()) {
int local_count=1;
while (local_count <= no_slices) {
if (timings(local_count, 1) == slice) {
offset = -(local_count -1)* (slice_spacing / repeat_time);
local_count = no_slices + 1;
} else
local_count++;
}
} else if (odd.value()) { // acquisition order: 1,3,5, ..., 2,4,6 ...
if ((slice % 2) == 0) // even
offset = -( ceil((float)no_slices / 2) + ((slice -1)/ 2)) * (slice_spacing / repeat_time);
else
offset = -((slice -1) / 2) * (slice_spacing / repeat_time);
} else if (down.value()) {
offset = -(no_slices - slice)* (slice_spacing / repeat_time);
} else {
offset = -(slice -1)* (slice_spacing / repeat_time);
}
for (int x_pos = 0; x_pos < timeseries. xsize(); x_pos++)
for (int y_pos = 0; y_pos < timeseries. ysize(); y_pos++){
voxeltimeseries = timeseries.voxelts(x_pos,y_pos,slice-1);
interpseries = voxeltimeseries;
for (int time_step=1; time_step <= no_volumes; time_step++)
interpseries(time_step) = interpolate_1d(voxeltimeseries, time_step + offset + recenter);
timeseries.setvoxelts(interpseries,x_pos,y_pos,slice-1);
}
if (verbose.value())
cerr << "Slice / Offset (s) " << slice << " / " << offset *repeat_time * -1 << endl;
}
if (direction.value() == 1) timeseries. swapdimensions(3,2,1); // reverse Flip z and x
if (direction.value() == 2) timeseries. swapdimensions(1,3,2); // reverse Flip z and y
save_volume4D(timeseries, outputname.value());
return 0;
}
int main (int argc,char** argv)
{
Tracer tr("main");
OptionParser options(title, examples);
try {
options.add(inputname);
options.add(outputname);
options.add(help);
options.add(verbose);
options.add(down);
options.add(repeat);
options.add(direction);
options.add(odd);
options.add(tcustom);
options.add(ocustom);
options.parse_command_line(argc, argv);
if ( (help.value()) || (!options.check_compulsory_arguments(true)) )
{
options.usage();
exit(EXIT_FAILURE);
}
if ( inputname.unset())
{
options.usage();
cerr << endl
<< "--in or -i MUST be used."
<< endl;
exit(EXIT_FAILURE);
}
} catch(X_OptionError& e) {
options.usage();
cerr << endl << e.what() << endl;
exit(EXIT_FAILURE);
} catch(std::exception &e) {
cerr << e.what() << endl;
}
int retval = do_slice_correction();
if (retval!=0) {
cerr << endl << endl << "Error detected: try -h for help" << endl;
}
return retval;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment