ANTs icon indicating copy to clipboard operation
ANTs copied to clipboard

antsMotionCorr output data type and optional no inverse

Open s-kash opened this issue 4 years ago • 3 comments

Is your feature request related to a problem? Please describe.

  1. I want to use antsMotionCorr with high-resolution time-series datasets. These files are very large in size and saving the output with double precision is really not that important.
  2. The Warp and InverseWarp are also extremely large (12GB!! each).

Describe the solution you'd like

  1. A flag for --output-data-type similar to antsApplyTransforms
  2. A flag to optionally not write Inverse transforms.

Describe alternatives you've considered ConvertImage unfortunately does not work for 4 dimensional data.

s-kash avatar May 27 '20 21:05 s-kash

this is an open source project that is driven by volunteer efforts. as such, features like this are usually provided by those who need/want them. good opportunity to learn a little C++ development and how to contribute to projects such as this one. do you have any interest in trying to contribute these features? if so, please make a pull request.

stnava avatar May 27 '20 22:05 stnava

Thanks for the kind reply. Unfortunately, I've never coded in C++ before but I am very willing to give it a go with some help.

I took the interpolation option contribution by @dangom in https://github.com/ANTsX/ANTs/issues/931#issuecomment-573274200_ as a guide and have managed to do the following in the antsMotionCorr.cxx file on my fork https://github.com/s-kash/ANTs/commit/8bccbc6bfe4c004ce698ee8046a94abbdfb516c3:

Added the following lines from antsApplyTransforms for cli parser:

{
  std::string description =
    std::string( "Output image data type. " )
    + std::string( "This is a direct typecast; output values are not rescaled. " )
    + std::string( "Default is to use the internal data type (float or double). " )
    + std::string( "uchar is unsigned char; others are signed. " )
    + std::string( "WARNING: Outputs will be incorrect (overflowed/reinterpreted) " )
    + std::string( "if values exceed the range allowed by your choice. " )
    + std::string( "Note that some pixel types are not supported by some image " )
    + std::string( "formats. e.g. int is not supported by jpg. " );


  OptionType::Pointer option = OptionType::New();
  option->SetLongName( "output-data-type" );
  // u is used by antsApplyTranforms but is already in use by --useFixedReferenceImage. No short name is offered.
  option->SetUsageOption( 0, "char" );
  option->SetUsageOption( 1, "uchar" );
  option->SetUsageOption( 2, "short" );
  option->SetUsageOption( 3, "int" );
  option->SetUsageOption( 4, "float" );
  option->SetUsageOption( 5, "double" );
  option->SetUsageOption( 6, "default" );
  option->SetDescription( description );
  parser->AddOption( option );
  }

However, this is the part I'm very unclear on. I adapted these lines from antsApplyTransforms but I'm not sure if I'm doing this right:

// Get the output data type and possible parameters
   std::string whichOutputDataType( "float" );
   typename OptionType::Pointer outputDataTypeOption = parser->GetOption( "output-data-type" );
   if( outputOutputDataTypeOption && outputDataTypeOption->GetNumberOfFunctions() )
    {
    whichDataType = outputDataTypeOption->GetFunction( 0 )->GetName();
    ConvertToLowerCase( whichOutputDataType );
    }

  typename itk::ants::CommandLineParser::OptionType::Pointer defaultOption =
    parser->GetOption( "default-value" );
  if( defaultOption && defaultOption->GetNumberOfFunctions() )
    {
    defaultValue = parser->Convert<PixelType>( defaultOption->GetFunction( 0 )->GetName() );
    }
  	if( !std::strcmp( whichOutputDataType.c_str(), "char" ) )
            return antsMotionCorr<double, 3, char>( parser, ImageType );
          else if( !std::strcmp( whichOutputDataType.c_str(), "uchar" ) )
            return antsMotionCorr<double, 3, unsigned char>( parser, ImageType );
          else if( !std::strcmp( whichOutputDataType.c_str(), "short" ) )
            return antsMotionCorr<double, 3, short>( parser, ImageType );
          else if( !std::strcmp( whichOutputDataType.c_str(), "int" ) )
            return antsMotionCorr<double, 3, int>( parser, ImageType );
          else if( !std::strcmp( whichOutputDataType.c_str(), "float" ) )
            return antsMotionCorr<double, 3, float>( parser, ImageType );
          else if( !std::strcmp( whichOutputDataType.c_str(), "double" ) )
            return antsMotionCorr<double, 3, double>( parser, ImageType );
          else
            return antsMotionCorr<double, 3, double>( parser, ImageType );	

Am I on the right track?

Thanks!

s-kash avatar May 28 '20 09:05 s-kash

There's a bit more to it than that, maybe the best example would be this PR which shows how antsApplyTransforms was modified to accept different output data types

https://github.com/ANTsX/ANTs/pull/926

cookpa avatar May 28 '20 21:05 cookpa