<commit_before>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by <NAME>, 03/12/09.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "app.h"
#include "image/voxel.h"
#include "image/buffer.h"
#include "image/buffer_scratch.h"
#include "math/rng.h"
#include "image/loop.h"
#include "image/threaded_loop.h"
#include "image/threaded_copy.h"
#include "image/stride.h"

MRTRIX_APPLICATION

using namespace MR;
using namespace App;


void usage () {
DESCRIPTION
  + "apply generic voxel-wise mathematical operations to images."

  + "This command will only computer per-voxel operations. "
  "Use 'mrmath' to compute summary statistics across images or "
  "along image axes."
  
  + "This command uses a stack-based syntax, with operators "
  "(specified using options) operating on the top-most entries "
  "(i.e. images or values) in the stack. Operands (values or "
  "images) are pushed onto the stack in the order they appear "
  "(as arguments) on the command-line, and operands (specified "
  "as options) operate on and comsume the top-most entries in "
  "the stack, and push their output as a new entry on the stack. "
  "For example:"
  
  + "$ mrmath a.mif 2 -mult r.mif"
  
  + "performs the operation r = a x 2 for every voxel a,r in "
  "images a.mif and r.mif respectively. Similarly:"
  
  + "$ mrmath a.mif -neg b.mif -div -exp 9.3 -mult r.mif"
  
  + "performs the operation r = 9.3*exp(-a/b), and:"
  
  + "$ mrmath a.mif b.mif -add c.mif d.mif -mult 4.2 -add -div r.mif"
  
  + "performs r = (a+b)/(c*d+4.2)."
  
  + "As an additional feature, this command will allow images with different "
  "dimensions to be processed, provided they satisfy the following "
  "conditions: for each axis, the dimensions match if they are the same size, "
  "or one of them has size one. In the latter case, the entire image will be "
  "replicated along that axis. This allows for example a 4D image of  "
  "size [ X Y Z N ] to be added to a 3D image of size [ X Y Z ], as if it "
  "consisted of N copies of the 3D image along the 4th axis (the missing "
  "dimension is assumed to have size 1). Another example would a "
  "single-voxel 4D image of size [ 1 1 1 N ], multiplied by a 3D image of  "
  "size [ X Y Z ], which would allow the creation of a 4D image where each "
  "volume consists of the 3D image scaled by the corresponding value for "
  "that volume in the single-voxel image.";

ARGUMENTS
  + Argument ("operand", "an input image or intensity.").allow_multiple();

OPTIONS
  + OptionGroup ("Unary operators")

  + Option ("abs", "absolute value").allow_multiple()
  + Option ("neg", "negative value").allow_multiple()
  + Option ("sqrt", "square root").allow_multiple()
  + Option ("exp", "exponential function").allow_multiple()
  + Option ("log", "natural logarithm").allow_multiple()
  + Option ("log10", "common logarithm").allow_multiple()
  + Option ("cos", "cosine").allow_multiple()
  + Option ("sin", "sine").allow_multiple()
  + Option ("tan", "tangent").allow_multiple()
  + Option ("cosh", "hyperbolic cosine").allow_multiple()
  + Option ("sinh", "hyperbolic sine").allow_multiple()
  + Option ("tanh", "hyperbolic tangent").allow_multiple()
  + Option ("acos", "inverse cosine").allow_multiple()
  + Option ("asin", "inverse sine").allow_multiple()
  + Option ("atan", "inverse tangent").allow_multiple()
  + Option ("acosh", "inverse hyperbolic cosine").allow_multiple()
  + Option ("asinh", "inverse hyperbolic sine").allow_multiple()
  + Option ("atanh", "inverse hyperbolic tangent").allow_multiple()
  + Option ("round", "round to nearest integer").allow_multiple()
  + Option ("ceil", "round up to nearest integer").allow_multiple()
  + Option ("floor", "round down to nearest integer").allow_multiple()
  + Option ("isnan", "true (1) is operand is not-a-number (NaN)").allow_multiple()
  + Option ("isinf", "true (1) is operand is infinite (Inf)").allow_multiple()
  + Option ("finite", "true (1) is operand is finite (i.e. not NaN or Inf)").allow_multiple()

  + Option ("real", "real part of complex number").allow_multiple()
  + Option ("imag", "imaginary part of complex number").allow_multiple()
  + Option ("phase", "phase of complex number").allow_multiple()
  + Option ("conj", "complex conjugate").allow_multiple()

  + OptionGroup ("Binary operators")

  + Option ("add", "add values").allow_multiple()
  + Option ("subtract", "subtract nth operand from (n-1)th").allow_multiple()
  + Option ("multiply", "multiply values").allow_multiple()
  + Option ("divide", "divide (n-1)th operand by nth").allow_multiple()
  + Option ("pow", "raise (n-1)th operand to nth power").allow_multiple()
  + Option ("min", "smallest of last two operands").allow_multiple()
  + Option ("max", "greatest of last two operands").allow_multiple()
  + Option ("lt", "true (1) if (n-1)th operand is smaller than nth, false (0) otherwise").allow_multiple()
  + Option ("gt", "true (1) if (n-1)th operand is greater than nth, false (0) otherwise").allow_multiple()
  + Option ("le", "true (1) if (n-1)th operand is smaller than or equal to nth, false (0) otherwise").allow_multiple()
  + Option ("ge", "true (1) if (n-1)th operand is greater than or equal to nth, false (0) otherwise").allow_multiple()
  + Option ("eq", "true (1) if last two operands are equal, false (0) otherwise").allow_multiple()
  + Option ("neq", "true (1) if last two operands are not equal, false (0) otherwise").allow_multiple()

  + Option ("complex", "create complex number using the last two operands as real,imaginary components").allow_multiple()

  + OptionGroup ("Ternary operators")

  + Option ("if", "if first operand is true (non-zero), return second operand, otherwise return third operand").allow_multiple()


  + DataType::options();
}


typedef float real_type;
typedef cfloat complex_type;

typedef Image::Buffer<real_type>::voxel_type real_vox_type;
typedef Image::Buffer<complex_type>::voxel_type complex_vox_type;




/**********************************************************************
  STACK FRAMEWORK:
 **********************************************************************/<commit_msg>Minor updates to inline doc for mrcalc<commit_after>/*
    Copyright 2009 Brain Research Institute, Melbourne, Australia

    Written by <NAME>, 03/12/09.

    This file is part of MRtrix.

    MRtrix is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MRtrix is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "app.h"
#include "image/voxel.h"
#include "image/buffer.h"
#include "image/buffer_scratch.h"
#include "math/rng.h"
#include "image/loop.h"
#include "image/threaded_loop.h"
#include "image/threaded_copy.h"
#include "image/stride.h"

MRTRIX_APPLICATION

using namespace MR;
using namespace App;


void usage () {
DESCRIPTION
  + "apply generic voxel-wise mathematical operations to images."

  + "This command will only compute per-voxel operations. "
  "Use 'mrmath' to compute summary statistics across images or "
  "along image axes."
  
  + "This command uses a stack-based syntax, with operators "
  "(specified using options) operating on the top-most entries "
  "(i.e. images or values) in the stack. Operands (values or "
  "images) are pushed onto the stack in the order they appear "
  "(as arguments) on the command-line, and operands (specified "
  "as options) operate on and consume the top-most entries in "
  "the stack, and push their output as a new entry on the stack. "
  "For example:"
  
  + "$ mrmath a.mif 2 -mult r.mif"
  
  + "performs the operation r = a x 2 for every voxel a,r in "
  "images a.mif and r.mif respectively. Similarly:"
  
  + "$ mrmath a.mif -neg b.mif -div -exp 9.3 -mult r.mif"
  
  + "performs the operation r = 9.3*exp(-a/b), and:"
  
  + "$ mrmath a.mif b.mif -add c.mif d.mif -mult 4.2 -add -div r.mif"
  
  + "performs r = (a+b)/(c*d+4.2)."
  
  + "As an additional feature, this command will allow images with different "
  "dimensions to be processed, provided they satisfy the following "
  "conditions: for each axis, the dimensions match if they are the same size, "
  "or one of them has size one. In the latter case, the entire image will be "
  "replicated along that axis. This allows for example a 4D image of "
  "size [ X Y Z N ] to be added to a 3D image of size [ X Y Z ], as if it "
  "consisted of N copies of the 3D image along the 4th axis (the missing "
  "dimension is assumed to have size 1). Another example would a "
  "single-voxel 4D image of size [ 1 1 1 N ], multiplied by a 3D image of "
  "size [ X Y Z ], which would allow the creation of a 4D image where each "
  "volume consists of the 3D image scaled by the corresponding value for "
  "that volume in the single-voxel image.";

ARGUMENTS
  + Argument ("operand", "an input image or intensity.").allow_multiple();

OPTIONS
  + OptionGroup ("Unary operators")

  + Option ("abs", "absolute value").allow_multiple()
  + Option ("neg", "negative value").allow_multiple()
  + Option ("sqrt", "square root").allow_multiple()
  + Option ("exp", "exponential function").allow_multiple()
  + Option ("log", "natural logarithm").allow_multiple()
  + Option ("log10", "common logarithm").allow_multiple()
  + Option ("cos", "cosine").allow_multiple()
  + Option ("sin", "sine").allow_multiple()
  + Option ("tan", "tangent").allow_multiple()
  + Option ("cosh", "hyperbolic cosine").allow_multiple()
  + Option ("sinh", "hyperbolic sine").allow_multiple()
  + Option ("tanh", "hyperbolic tangent").allow_multiple()
  + Option ("acos", "inverse cosine").allow_multiple()
  + Option ("asin", "inverse sine").allow_multiple()
  + Option ("atan", "inverse tangent").allow_multiple()
  + Option ("acosh", "inverse hyperbolic cosine").allow_multiple()
  + Option ("asinh", "inverse hyperbolic sine").allow_multiple()
  + Option ("atanh", "inverse hyperbolic tangent").allow_multiple()
  + Option ("round", "round to nearest integer").allow_multiple()
  + Option ("ceil", "round up to nearest integer").allow_multiple()
  + Option ("floor", "round down to nearest integer").allow_multiple()
  + Option ("isnan", "true (1) is operand is not-a-number (NaN)").allow_multiple()
  + Option ("isinf", "true (1) is operand is infinite (Inf)").allow_multiple()
  + Option ("finite", "true (1) is operand is finite (i.e. not NaN or Inf)").allow_multiple()

  + Option ("real", "real part of complex number").allow_multiple()
  + Option ("imag", "imaginary part of complex number").allow_multiple()
  + Option ("phase", "phase of complex number").allow_multiple()
  + Option ("conj", "complex conjugate").allow_multiple()

  + OptionGroup ("Binary operators")

  + Option ("add", "add values").allow_multiple()
  + Option ("subtract", "subtract nth operand from (n-1)th").allow_multiple()
  + Option ("multiply", "multiply values").allow_multiple()
  + Option ("divide", "divide (n-1)th operand by nth").allow_multiple()
  + Option ("pow", "raise (n-1)th operand to nth power").allow_multiple()
  + Option ("min", "smallest of last two operands").allow_multiple()
  + Option ("max", "greatest of last two operands").allow_multiple()
  + Option ("lt", "less-than operator (true=1, false=0)").allow_multiple()
  + Option ("gt", "greater-than operator (true=1, false=0)").allow_multiple()
  + Option ("le", "less-than-or-equal-to operator (true=1, false=0)").allow_multiple()
  + Option ("ge", "greater-than-or-equal-to operator (true=1, false=0)").allow_multiple()
  + Option ("eq", "equal-to operator (true=1, false=0)").allow_multiple()
  + Option ("neq", "not-equal-to operator (true=1, false=0)").allow_multiple()

  + Option ("complex", "create complex number using the last two operands as real,imaginary components").allow_multiple()

  + OptionGroup ("Ternary operators")

  + Option ("if", "if first operand is true (non-zero), return second operand, otherwise return third operand").allow_multiple()


  + DataType::options();
}


typedef float real_type;
typedef cfloat complex_type;

typedef Image::Buffer<real_type>::voxel_type real_vox_type;
typedef Image::Buffer<complex_type>::voxel_type complex_vox_type;




/**********************************************************************
  STACK FRAMEWORK:
 **********************************************************************/
{'fraction_non_alphanumeric': 0.14989564698867025, 'fraction_numerical': 0.008199165175909361, 'mean_word_length': 4.251272015655577, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2075307', 'n_tokens_mistral': 4185, 'n_tokens_neox': 3992, 'n_words': 1523}