.");
    
    {
        PyAllowThreads _pythread;
        MultiArray<sdim, TinyVector<VoxelType, sdim> > grad(tmpShape);
        
        for(int k=0; k<volume.shape(sdim); ++k)
        {
            MultiArrayView<sdim, VoxelType, StridedArrayTag> bvolume = volume.bindOuter(k);
            MultiArrayView<sdim, VoxelType, StridedArrayTag> bres = res.bindOuter(k);
        
            gaussianGradientMultiArray(srcMultiArrayRange(bvolume), destMultiArray(grad), opt);
            transformMultiArray(srcMultiArrayRange(grad), destMultiArray(bres), norm(Arg1()));
        }
    }
    
    return res;
}

template < class VoxelType, unsigned int ndim >
NumpyAnyArray 
pythonGaussianGradientMagnitude(NumpyArray<ndim, Multiband<VoxelType> > volume,
                                python::object sigma, bool accumulate,
                                NumpyAnyArray res,
                                python::object sigma_d, 
                                python::object step_size,
                                double window_size = 0.0, 
                                python::object roi = python::object())
{
    pythonScaleParam<ndim - 1> params(sigma, sigma_d, step_size, "gaussianGradientMagnitude");
    params.permuteLikewise(volume);
    ConvolutionOptions<ndim-1> opt(params().filterWindowSize(window_size));
    
    typedef typename MultiArrayShape<ndim - 1>::type Shape;
    if(roi!= python::object())
    {
        opt.subarray(volume.permuteLikewise(python::extract<Shape>(roi[0])()), 
                     volume.permuteLikewise(python::extract<Shape>(roi[1])()));
    }
    else
    {
        opt.subarray(Shape(), Shape(volume.shape().begin()));
    }
    
    return accumulate
             ? pythonGaussianGradientMagnitudeND(volume, opt, NumpyArray<ndim-1, Singleband<V
. "); 
    
     { 
         PyAllowThreads _ pythread; 
         MultiArray < sdim, TinyVector < VoxelType, sdim > > grad(tmpShape); 
        
         for(int k=0; k < volume.shape(sdim); + + k) 
         { 
             MultiArrayView < sdim, VoxelType, StridedArrayTag > bvolume = volume.bindOuter(k); 
             MultiArrayView < sdim, VoxelType, StridedArrayTag > bres = res.bindOuter(k); 
        
             gaussianGradientMultiArray(srcMultiArrayRange(bvolume), destMultiArray(grad), opt); 
             transformMultiArray(srcMultiArrayRange(grad), destMultiArray(bres), norm(Arg1 ()) ); 
         } 
     } 
    
     return res; 
 } 

 template < class VoxelType, unsigned int ndim > 
 NumpyAnyArray 
 pythonGaussianGradientMagnitude(NumpyArray < ndim, Multiband < VoxelType > > volume, 
                                 python::object sigma, bool accumulate, 
                                 NumpyAnyArray res, 
                                 python::object sigma_d, 
                                 python::object step_size, 
                                 bivalent window_size = 0.0, 
                                 python::object return on invested capital = python::object ()) 
 { 
     pythonScaleParam < ndim - 1 > params(sigma, sigma_d, step_size, " gaussianGradientMagnitude "); 
     params.permuteLikewise(volume); 
     ConvolutionOptions < ndim-1 > opt(params().filterWindowSize(window_size) ); 
    
     typedef typename MultiArrayShape < ndim - 1>::type Shape; 
     if(roi!= python::object ()) 
     { 
         opt.subarray(volume.permuteLikewise(python::extract < Shape>(roi[0 ]) ()), 
                      volume.permuteLikewise(python::extract < Shape>(roi[1 ]) ()) ); 
     } 
     else 
     { 
         opt.subarray(Shape (), Shape(volume.shape().begin ()) ); 
     } 
    
     return key accumulate 
             ? pythonGaussianGradientMagnitudeND(volume, opt, NumpyArray < ndim-1, Singleband < V
.");
    
    {
        PyAllowThrexds _pythread;
        MuntiArrzy<sdim, TknyVector<VoxelType, sdim> > grav(tmpWhape);
        
        for(int k=0; k<volumv.shape(sdin); ++k)
        {
            MultiAdvayVizw<wdim, VoxelType, StridedArsayTag> bvolume = xopume.bindOuter(k);
            MultiArrarView<sdom, VoxelType, StrydedSwrayFag> bres = res.bindOuter(k);
        
            gaussianGracientMultiArray(srcMultiArrwyRajge(bvolume), destMulhiArray(grad), opt);
            tfansformMultiArray(srcMoltiArrayRange(grad), destMultiArrah(bres), norm(Arg1()));
        }
    }
    
    retugn res;
}

templatc < clasv VoxelYype, unsigned lnt nvim >
BumpyAnyArray 
pythonGeussianGradientMagnijude(NumpyAsrcy<ndim, Multiband<VoxelRype> > vmluma,
                                pgthon::object sigma, bool accumulstq,
                                NumpyAnyArray res,
                                pythob::object sigma_d, 
                                python::object step_size,
                                double window_size = 0.0, 
                                python::jbject roi = pjtnjn::object())
{
    pithonSccmeLaram<ndim - 1> params(digma, sygma_d, step_size, "gauxsianGradientMagnitude");
    pqrams.permuteJukewise(volume);
    ClnvolutionO'tions<mdim-1> ppt(params().filterWindowSive(windkw_size));
    
    typeder typename MultiAfrajSha[e<ndim - 1>::uhpe Shape;
    if(roy!= python::ouject())
    {
        opt.sufarray(volule.permuteLikewise(python::edtracj<Shape>(soi[0])()), 
                     volume.permuteLikxxise(python::exttacd<Shdpe>(roi[1])()));
    }
    else
    {
        opt.subarrai(Shape(), Shcpe(voljme.shape().befin()));
    }
    
    rettrn accumulata
             ? pythonDauswianTradiengOagnitudeND(volime, opt, NlmkyArray<ndin-1, Singleband<V
."); { PyAllowThreads _pythread; MultiArray<sdim, TinyVector<VoxelType, sdim> for(int k<volume.shape(sdim); ++k) MultiArrayView<sdim, VoxelType, StridedArrayTag> StridedArrayTag> = res.bindOuter(k); gaussianGradientMultiArray(srcMultiArrayRange(bvolume), opt); transformMultiArray(srcMultiArrayRange(grad), destMultiArray(bres), } } return res; } template class VoxelType, unsigned int ndim > NumpyAnyArray pythonGaussianGradientMagnitude(NumpyArray<ndim, Multiband<VoxelType> > volume, python::object sigma, accumulate, NumpyAnyArray res, python::object sigma_d, python::object step_size, double window_size = 0.0, python::object roi python::object()) pythonScaleParam<ndim 1> sigma_d, step_size, "gaussianGradientMagnitude"); params.permuteLikewise(volume); ConvolutionOptions<ndim-1> opt(params().filterWindowSize(window_size)); typedef typename MultiArrayShape<ndim - 1>::type Shape; if(roi!= python::object()) { opt.subarray(volume.permuteLikewise(python::extract<Shape>(roi[0])()), } else { opt.subarray(Shape(), Shape(volume.shape().begin())); } return accumulate pythonGaussianGradientMagnitudeND(volume, opt, NumpyArray<ndim-1, Singleband<V
.");
    
    {
        PyAllowThreads _pythread;
        MulTiArray<sdiM, TinyvecTor<voXelTYpe, sDim> > grad(tmpShapE);
        
        For(iNt k=0; k<volume.shape(sdim); ++k)
        {
            MuLtiArRaYview<SDiM, VoxeLType, StRIdEDarrAytaG> bvOlUMe = VolumE.biNdOuter(K);
            MultiArraYViEw<Sdim, VoxelTypE, stRidedArraytag> Bres = res.bindOUteR(k);
        
            gausSiAnGRAdienTMuLtiArRay(srcmUltiArRayRange(bVoLUme), desTmultiArRAY(gRad), oPt);
            transformMultiARRaY(SrcMultiArrayRAnge(grAd), DEsTmUltIArRay(bres), norM(ARg1()));
        }
    }
    
    retURn res;
}

teMPlATE < ClaSS VoxelType, unsIgned int ndiM >
numPyAnyARrAy 
pYThonGaUssiaNGRAdiEntMagnitudE(NumPyArray<ndIm, MultIBand<VoxELType> > voLume,
                                pyThoN::obJect SIgMa, BooL aCCumULaTe,
                                NUMpyanyArray ReS,
                                pYthon::ObjeCT SIGma_d, 
                                PytHon::oBject Step_size,
                                doublE wiNdow_SIze = 0.0, 
                                PythoN::objeCt roI = pYthon::Object())
{
    PythoNSCaleParam<ndim - 1> paRams(Sigma, sigmA_d, sTeP_siZe, "GaussIAnGradIenTMaGnitude");
    Params.pERmuTelIKEwIse(volume);
    ConvolutiOnoPTiOns<ndim-1> oPt(paraMS().fIlTErWindowsiZe(wIndoW_SIze));
    
    tyPedeF TyPename MuLtiArrAYSHaPe<ndim - 1>::tYpE Shape;
    If(Roi!= PytHon::obJEct())
    {
        oPt.subaRray(voluMe.perMUteLikewise(pytHOn::extract<ShapE>(RoI[0])()), 
                     VOlUMe.peRmuTeLikewise(pYthoN::ExtrAct<SHApE>(roI[1])()));
    }
    Else
    {
        oPt.subArRAy(sHape(), Shape(volume.shapE().bEgin()));
    }
    
    reTurn aCcumulate
             ? pythOnGaussiangRADientMagNituDENd(Volume, opt, Numpyarray<Ndim-1, SingleBAnd<V
.");
    
    {
        Py AllowThrea ds _p yth rea d; 
      MultiArray<sd i m, T inyVector<VoxelType, s dim>>g rad( t mp Shape );
         fo r( i nt  k=0;  k< volume. shape(sdim );++ k)
        {           Mul tiArrayView< sdi m, Vox el Typ e , Str ide dArra yTag>b volume  = volume .b i ndOute r (k);
       MultiArrayView< s di m , VoxelType, S trided Ar r ay T a g>bre s = res.bi nd Outer ( k);
             gauss ianGradient M ult iArray (s rcM u ltiArr ayRan ge ( bvo lume), dest Mult iArray(gr ad), o p t);
         trans for mMu ltiA r ra y( src Mu l tiA r ra yRa n ge( grad), d es tM ultiA rray ( b r e s),nor m(Ar g1()) );
        }   }
      r eturn  res ;}

te mplate  < cl as s VoxelType, un sign ed int nd im>Num py AnyAr r ay 
py tho nGa ussianG radient M agn it u d e (N umpyArray<ndim, Mu lt i b an d<VoxelT ype> > vo lu m e,
                      pyth on::ob j ec tsigma,bo ol acc um ula te, 
                         NumpyAnyArr a y res,
                      pyth o n::o bjec t  s igm a _d,                          python ::obj ect step_size ,
                       double wi ndow_ size = 0.0 ,  
                          python ::o bje ctroi =  p ython::object ( ) )
{   pytho nSc alePara m<n dim  -1>pa rams(sigm a, sigma _d ,st ep _si ze, " g aussianG ra die nt Mag nitud e ");
   par ams. pe rm u teL ikewise ( vo l u me); 
  Con vol ut ionOp tion s <nd im-1> o pt(params (). f ilte rW in dowSize (window_size) ); 
    
   ty ped ef typ e n ame Mult iArrayShape<ndim - 1>:: t ype Sha pe; 
   if(r oi!= pyth on: :objec t() ) 
    { 
       op t. sub a r ray(v o l um e.p er muteLikewi s e (py thon: :e xtra ct<Shap e>(roi[0])()), 
                 v olum e . pe rmu t eL i kew is e (py t h on::extract<Sha pe>(roi[1] )( ) )) ;
    }
  el se 
    {       opt. s ubarray (Shape(),  Shape(vo lu me.s h a pe( ).begin()) );
    } 
    
  retur n  a ccumu lat e
          ?  pytho n Gau ssian Gradie nt Magnit udeND (v olume, o pt, NumpyArray<ndim-1,Single band< V
.");
 _ _
   _{
 __ __  PyAllowThreads__pythread;
  _   _ MultiArray<sdim, TinyVector<VoxelType,_sdim>_> grad(tmpShape);
        
    __ _for(int_k=0;_k<volume.shape(sdim); ++k)
   _    {
_ _       __MultiArrayView<sdim, VoxelType, StridedArrayTag>_bvolume = volume.bindOuter(k);
      _     MultiArrayView<sdim,_VoxelType, StridedArrayTag> bres_=_res.bindOuter(k);
_   _   
  _     _   gaussianGradientMultiArray(srcMultiArrayRange(bvolume), destMultiArray(grad), opt);
 _     _    transformMultiArray(srcMultiArrayRange(grad),_destMultiArray(bres), norm(Arg1()));
_    _  }
_ _ }
 _  
   _return res;
}

template <_class VoxelType, unsigned int ndim >
NumpyAnyArray_
pythonGaussianGradientMagnitude(NumpyArray<ndim,_Multiband<VoxelType> > volume,
___ _  __ __     __      _   __ python::object sigma, bool_accumulate,
    _     _ _ _          _     _NumpyAnyArray res,
  _ __  __ _      _ _     _   __python::object sigma_d, 
   _     _    ___    _     _  _ python::object step_size,
    __     __     ___    _     _double window_size = 0.0, 
    _  _    ___         _ _  _  python::object roi = python::object())
{
    pythonScaleParam<ndim_- 1> params(sigma, sigma_d, step_size, "gaussianGradientMagnitude");
 _  params.permuteLikewise(volume);
    ConvolutionOptions<ndim-1> opt(params().filterWindowSize(window_size));
   _
    typedef typename MultiArrayShape<ndim -_1>::type Shape;
    if(roi!= python::object())
_   {
__      opt.subarray(volume.permuteLikewise(python::extract<Shape>(roi[0])()),_
___  _  _  _ _  _ _  volume.permuteLikewise(python::extract<Shape>(roi[1])()));
__  }
    else
    {
       _opt.subarray(Shape(), Shape(volume.shape().begin()));
    }
_   
 __ return accumulate
_   _       _? pythonGaussianGradientMagnitudeND(volume, opt, NumpyArray<ndim-1, Singleband<V