docs: def calc_signal(self, ff, t=None, ani=None, fkwdargs={}, Brightness=True,
                      res=0.005, DL=None, resMode='abs', method='sum',
                      ind=None, out=object, plot=True, dataname=None,
                      fs=None, dmargin=None, wintit=None, invert=True,
                      units=None, draw=True, connect=True):
          """ Return the line-integrated emissivity
  
          Beware, by default, Brightness=True and it is only a line-integral !
  
          Indeed, to get the received power, you need an estimate of the Etendue
          (previously set using self.set_Etendues()) and use Brightness=False.
  
          Hence, if Brightness=True and if
          the emissivity is provided in W/m3 (resp. W/m3/sr),
          => the method returns W/m2 (resp. W/m2/sr)
          The line is sampled using :meth:`~tofu.geom.LOS.get_sample`,
  
          The integral can be computed using three different methods:
              - 'sum':    A numpy.sum() on the local values (x segments lengths)
              - 'simps':  using :meth:`scipy.integrate.simps`
              - 'romb':   using :meth:`scipy.integrate.romb`
  
          Except ff, arguments common to :meth:`~tofu.geom.LOS.get_sample`
  
          Parameters
          ----------
          ff :    callable
              The user-provided
  
          Returns
          -------
          sig :   np.ndarray
              The computed signal, a 1d or 2d array depending on whether a time
              vector was provided.
          units:  str
              Units of the result
  
          """
          msg = "Arg out must be in [object,np.ndarray]"
          assert out in [object,np.ndarray], msg
          assert type(Brightness) is bool, "Arg Brightness must be a bool !"
          if Brightness is False and self.Etendues is None:
              msg = "Etendue must be set if Brightness is False !"
              raise Exception(msg)
  
          # Preformat ind
          ind = self._check_indch(ind)
          # Preformat DL
          kIn, kOut = self.kIn, self.kOut
          if DL is None:
              DL = np.array([kIn[ind], kOut[ind]])
          elif np.asarray(DL).size==2:
              DL = np.tile(np.asarray(DL).ravel()[:,np.newaxis],len(ind))
          DL = np.ascontiguousarray(DL).astype(float)
          assert type(DL) is np.ndarray and DL.ndim==2
          assert DL.shape==(2,len(ind)), "Arg DL has wrong shape !"
  
          # check limits
          ii = DL[0,:] < kIn[ind]
          DL[0,ii] = kIn[ind][ii]
          ii[:] = DL[0,:] >= kOut[ind]
          DL[0,ii] = kOut[ind][ii]
          ii[:] = DL[1,:] > kOut[ind]
          DL[1,ii] = kOut[ind][ii]
          ii[:] = DL[1,:] <= kIn[ind]
          DL[1,ii] = kIn[ind][ii]
  
          # Preformat Ds, us and Etendue
          Ds, us = self.D[:,ind], self.u[:,ind]
          if Brightness is False:
              E = self.Etendues
              if E.size==self.nRays:
                  E = E[ind]
  
          # Preformat signal
          if len(ind)==1:
              Ds, us = Ds.reshape((3,1)), us.reshape((3,1))
          if t is None or len(t)==1:
              sig = np.full((Ds.shape[1],),np.nan)
          else:
              sig = np.full((len(t),Ds.shape[1]),np.nan)
          indok = ~(np.any(np.isnan(DL),axis=0) | np.any(np.isinf(DL),axis=0)
                    | ((DL[1,:]-DL[0,:])<=0.))
  
          if np.any(indok):
              Ds, us, DL = Ds[:,indok], us[:,indok], DL[:,indok]
              if indok.sum()==1:
                  Ds, us = Ds.reshape((3,1)), us.reshape((3,1))
                  DL = DL.reshape((2,1))
              Ds, us = np.ascontiguousarray(Ds), np.ascontiguousarray(us)
              DL = np.ascontiguousarray(DL)
              # Launch    # NB : find a way to exclude cases with DL[0,:]>=DL[1,:] !!
              # Exclude Rays not seeing the plasma
              s = _GG.LOS_calc_signal(ff, Ds, us, res, DL,
                                      dLMode=resMode, method=method,
                                      t=t, Ani=ani, fkwdargs=fkwdargs, Test=True)
              if t is None or len(t)==1:
                  sig[indok] = s
              else:
                  sig[:,indok] = s
  
          # Format output
          if Brightness is False:
              if dataname is None:
                  dataname = r"LOS-integral x Etendue"
              if t is None or len(t)==1 or E.size==1:
                  sig = sig*E
              else:
                  sig = sig*E[np.newaxis,:]
              if units is None:
                  units = r"origin x $m^3.sr$"
          else:
              if dataname is None:
                  dataname = r"LOS-integral"
              if units is None:
                  units = r"origin x m"
  
          if plot or out in [object,'object']:
              kwdargs = dict(data=sig, t=t, lCam=self, Name=self.Id.Name,
                             dlabels={'data':{'units':units, 'name':dataname}},
                             Exp=self.Id.Exp, Diag=self.Id.Diag)
              import tofu.data as tfd
              if self._is2D():
                  osig = tfd.DataCam2D(**kwdargs)
              else:
                  osig = tfd.DataCam1D(**kwdargs)
              if plot:
                  kh = osig.plot(fs=fs, dmargin=dmargin, wintit=wintit,
                                 plotmethod=plotmethod, invert=invert,
                                 draw=draw, connect=connect)
  
          if out in [object, 'object']:
              return osig
          else:
              return sig, units