;+
; NAME:
;         p3d_tracing_calculate_lprofs
;
;         $Id: p3d_tracing_calculate_lprofs.pro 181 2010-04-21 08:44:03Z christersandin $
;
; PURPOSE:
;         This routine calculates cross-dispersion line profiles for every
;         spectrum and every wavelength bin in the input image (specified with
;         FILENAME). The centroid positions of TRACES are used as starting
;         central positions for every line profile.
;
;         In fitting routines of Craig Markwardt are used. The necessary
;         routines (mpfit.pro and mpcurvefit.pro) can be downloaded from:
;           http://purl.com/net/mpfit
;         Also see: Markwardt, C.B. 2009, "Non-Linear Least Squares Fitting
;         in IDL with MPFIT," in Astronomical Data Analysis Software and
;         Systems XVIII, Quebec, Canada, eds. D. Bohlender, P. Dowler &
;         D. Durand (ASP: San Francisco), ASP Conf. Ser., 411, 251
;
; AUTHOR:
;         Christer Sandin and Joris Gerssen
;         Astrophysikalisches Institut Potsdam (AIP)
;         An der Sternwarte 16
;         D-14482 Potsdam, GERMANY
;
; COPYRIGHT:
;         p3d: a general data-reduction tool for fiber-fed IFSs
;
;         Copyright 2009,2010 Astrophysikalisches Institut Potsdam (AIP)
;
;         This program 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.
;
;         This program 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 this program; if not, see <http://www.gnu.org/licenses>.
;
;         Additional permission under GNU GPL version 3 section 7
;
;         If you modify this Program, or any covered work, by linking or
;         combining it with IDL (or a modified version of that library),
;         containing parts covered by the terms of the IDL license, the
;         licensors of this Program grant you additional permission to convey
;         the resulting work.
;
; CATEGORY:
;         p3d :: tracing of spectra on the CCD
;
; CALLING SEQUENCE:
;         p3d_tracing_calculate_lprofs,filename,masterbias,traces,lprofs, $
;             dmbias=,gaps=,xstr=,xbin=,ybin=,gain=,rdnoise=,detector=, $
;             title=,kwrdlist=,parfile=,userparfile=,/monitor,oprof=,daxis=, $
;             /fixcenter,fixprofs=, $
;             stawid=,topwid=,logunit=,verbose=,error=,/debug,/help
;
; INPUTS:
;         filename        - A scalar string with the name of a file with data
;                           that will be used to calculate the cross-dispersion
;                           line profiles.
;         masterbias      - A scalar string with the name of a masterbias file.
;         traces          - A two-dimensional array of decimal type that
;                           contains the (starting) centroids of every spectrum
;                           and every wavelength bin.
;
; KEYWORD PARAMETERS:
;         dmbias          - This scalar decimal value specifies the error in
;                           the data of MASTERBIAS [ADU].
;         gaps            - This array of decimal values is used to determine
;                           the set of spectra which is used to calculate line
;                           profiles for simultaneously.
;         xstr ['']       - An empty string, or a three character string that
;                           is appended to some of the tracing parameter names.
;         xbin [1]        - Dispersion axis binning factor.
;         ybin [1]        - Cross-dispersion axis binning factor.
;         gain            - This scalar decimal value specifies the gain factor
;                           of the data in FILENAME [e-/ADU].
;         rdnoise         - This scalar (or array of) decimal value(s)
;                           specifies the readout noise of the data in
;                           FILENAME [ADU].
;         detector [0]    - A scalar integer that specifies the currently
;                           selected detector; DETECTOR is a zero-based value.
;         title ['Cross-dispersion line profiles of: '+FILENAME+'.']
;                         - A scalar string that is used in the GUI header
;                           when visualizing the line profiles.
;         kwrdlist        - A scalar string with the name of a file, that
;                           contains a two-column list of p3d-names and
;                           instrument-specific names for fits-header keywords.
;         parfile         - A scalar string with the name of a file, that
;                           contains a two-column list of instrument-specific
;                           parameters.
;         userparfile     - A scalar string with the name of a file with user-
;                           defined parameters (cf. p3d_misc_detsec for its
;                           use here).
;         monitor [1]     - If this keyword is set then a line profiles viewer
;                           is shown after all profiles are fitted.
;         oprof           - On output this variable contains the name of the
;                           function that was used in the fitting procedure.
;         daxis [1]       - Defines the dispersion direction dimension of
;                           the data in FILENAME. The default, 1, is in the
;                           x-direction.
;         fitcenter [0]   - If this keyword is set then it is only the profile
;                           center positions that are fitted, for -one-
;                           wavelength bin. The outcome is in this case a one-
;                           dimensional array with the center positions (see
;                           LPROFS). The profile width is taken from FIXPROFS.
;         fixprofs        - This variable is only used if /FITCENTER. It must
;                           then have the same format as LPROFS (when used with
;                           FITCENTER=0) and is used to set fixed values of
;                           profile widths when fitting the line center
;                           positions.
;         stawid          - If set to a valid ID then a log message is written
;                           using this ID for relevant actions.
;         topwid          - If set, then error messages are displayed using
;                           DIALOG_MESSAGE, using this widget id as
;                           DIALOG_PARENT, instead of MESSAGE.
;         logunit         - Messages are saved to the file pointed to by this
;                           logical file unit, if it is defined.
;         verbose         - Show more information on what is being done.
;         error           - Returns an error code if set.
;         debug           - The error handler is not setup if debug is set.
;         help            - Show this routine documentation, and exit.
;
; OUTPUTS:
;         lprofs          - A three-dimensional array with the line profile
;                           parameters (3rd dimension) of every spectrum and
;                           every wavelength bin.
;                           Note! If /FITCENTER then lprofs is a one-
;                           dimensional array with the fitted center positions
;                           of each spectrum for the center wavelength bin.
;
; COMMON BLOCKS:
;         none
;
; SIDE EFFECTS:
;         none
;
; RESTRICTIONS:
;         IDL version 6.2 or higher is required.
;
; MODIFICATION HISTORY:
;         09.07.2009 - A new routine. /CS & /JAG
;-
PRO p3d_tracing_calculate_lprofs,filename,masterbias,traces_,lprofs, $
        dmbias=dmbias,gaps=gaps,xstr=xstr,xbin=xbin_,ybin=ybin_,gain=gain, $
        rdnoise=rdnoise,detector=d,title=title,kwrdlist=kwrdlist, $
        parfile=parfile,userparfile=userparfile,monitor=monitor,oprof=oprof, $
        daxis=daxis,fitcenter=fitcenter,fixprofs=fixprofs_,stawid=stawid, $
        topwid=topwid,logunit=logunit,verbose=verbose, $
        error=error,debug=debug,help=help
  compile_opt hidden,IDL2

  if !version.release lt 6.2 then message,'IDL Version <6.2. Cannot continue.'
  error=0 & rname='p3d_tracing_calculate_lprofs: '
  if ~n_elements(verbose) then verbose=0
  usestawid=~n_elements(stawid)?0L:widget_info(stawid,/valid_id)
  debug=keyword_set(debug)

  if keyword_set(help) then begin
    doc_library,'p3d_tracing_calculate_lprofs'
    return
  endif

  ;;========================================------------------------------
  ;; Setting up an error handler:

  if ~debug then begin
    catch,error_status
    if error_status ne 0L then begin
      p3d_misc_errors,error_status,rname=rname,topwid=topwid
      catch,/cancel
      error=-1
      return
    endif
  endif ;; ~debug

  ;;========================================------------------------------
  ;; Checking the input arguments:

  if ~n_elements(daxis) then daxis=1L
  s=size(daxis)
  if s[s[0L]+2L] ne 1L or (s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L) then begin
    errmsg='DAXIS must be a scalar integer; 1||2.'
    goto,error_handler
  endif
  if daxis ne 1L and daxis ne 2L then begin
    errmsg='DAXIS must be a scalar integer; 1||2.'
    goto,error_handler
  endif
  sid=daxis?2L:1L

  if ~keyword_set(fitcenter) then fitcenter=0L
  s=size(fitcenter)
  if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L then begin
    errmsg='FITCENTER must be a scalar integer; FITCENTER=0||1.'
    goto,error_handler
  endif
  if fitcenter ne 0L and fitcenter ne 1L then begin
    errmsg='FITCENTER must be a scalar integer; FITCENTER=0||1.'
    goto,error_handler
  endif

  s=size(filename)
  if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ne 7L then begin
    errmsg='FILENAME [1] must be a scalar string.'
    goto,error_handler
  endif
  if ~file_test(filename,/regular,/read) then begin
    errmsg='FILENAME [1], cannot read "'+filename+'".'
    goto,error_handler
  endif
  data=readfits(filename,dhdr,silent=verbose lt 3,/no_unsigned)
  data=double(data)

  s=size(masterbias)
  if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ne 7L then begin
    errmsg='MASTERBIAS [2] must be a scalar string.'
    goto,error_handler
  endif
  if ~file_test(masterbias,/regular,/read) then begin
    errmsg='MASTERBIAS [2], cannot read "'+masterbias+'".'
    goto,error_handler
  endif
  mbias=readfits(masterbias,mbhdr,silent=verbose lt 3,/no_unsigned)
  mbias=double(mbias)

  sd=size(data)
  sb=size(mbias)
  if sb[sb[0L]+2L] ne sd[sd[0L]+2L] or sb[1L] ne sd[1L] then begin
    errmsg='The data of FILENAME {'+strtrim(sd[sd[0L]+1L],2L)+', ['+ $
           strtrim(sd[1L],2L)+','+strtrim(sd[2L],2L)+']} and MASTERBIAS {' + $
           strtrim(sb[sb[0L]+1L],2L)+', ['+strtrim(sb[1L],2L)+','+ $
           strtrim(sb[2L],2L)+']} must have the same size.'
    goto,error_handler
  endif

  if ~fitcenter then begin
    st=size(traces_)
    if ~st[st[0L]+2L] or $
       (st[st[0L]+1L] ge 6L and st[st[0L]+1L] le 11L) then begin
      errmsg='TRACES must be a two-dimensional array of decimal values.'
      goto,error_handler
    endif
    if st[daxis] ne sd[daxis] then begin
      tmp =daxis?'[{'+strtrim(st[1L],2L)+'},'+strtrim(st[2L],2L)+ ']': $
                 '[' +strtrim(st[1L],2L)+',{'+strtrim(st[2L],2L)+'}]'
      tmp2=daxis?'[{'+strtrim(sd[1L],2L)+'},'+strtrim(sd[2L],2L)+ ']': $
                 '[' +strtrim(sd[1L],2L)+',{'+strtrim(sd[2L],2L)+'}]'
      errmsg='TRACES '+tmp+' must have the same number of elements on the' + $
             ' dispersion axis as the data of FILENAME '+tmp2+'.'
      goto,error_handler
    endif
  endif ;; ~fitcenter

  s=size(parfile)
  if s[s[0L]+1L] ne 7L or ~s[s[0L]+2L] then begin
    errmsg='PARFILE must, if set, be the name of an instrument-specific' + $
           ' parameter file.'
    goto,error_handler
  endif
  if ~file_test(kwrdlist,/read,/regular) then begin
    errmsg='PARFILE, cannot read the file "'+parfile+'".'
    goto,error_handler
  endif

  if n_elements(userparfile) ne 0L then begin
    s=size(userparfile)
    if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ne 7L then begin
      errmsg='USERPARFILE must, if set, be a scalar string.'
      goto,error_handler
    endif
    if userparfile ne '' then begin
      if ~file_test(userparfile,/regular,/read) then begin
        errmsg='USERPARFILE, cannot read the file "'+userparfile+'".'
        goto,error_handler
      endif

      readcol,userparfile,uparname,uparvalue,format='a,a',comment=';', $
          silent=verbose lt 3,delimiter=' '
    endif
  endif ;; n_elements(userparfile) ne 0L

  p3d_misc_detsec,dhdr,kwrdlist,parfile,detsec,userparfile=userparfile, $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then return
  sdt=size(detsec,/n_dimensions)
  nblocks=sdt eq 2L?(size(detsec,/dimensions))[1L]:1L
  tmp=sdt eq 2L?strtrim(nblocks,2L)+'-element array':'scalar'

  sb=size(dmbias)
  if ~sb[sb[0L]+2L] or $
     (sb[sb[0L]+1L] ge 6L and sb[sb[0L]+1L] le 11L) then begin
    errmsg='DMBIAS must be set to a decimal '+tmp+'; DMBIAS>0.'
    goto,error_handler
  endif
  if min(dmbias) lt 0d0 then begin
    errmsg='DMBIAS must be set to a decimal '+tmp+'; DMBIAS>0.'
    goto,error_handler
  endif

  sb=size(gain)
  if sb[sb[0L]+2L] ne 1L or $
    (sb[sb[0L]+1L] ge 6L and sb[sb[0L]+1L] le 11L) then begin
    errmsg='GAIN must be set to a decimal scalar; GAIN>0.'
    goto,error_handler
  endif
  if gain lt 0d0 then begin
    errmsg='GAIN must be set to a decimal scalar; GAIN>0.'
    goto,error_handler
  endif

  sb=size(rdnoise)
  if ~sb[sb[0L]+2L] or $
     (sb[sb[0L]+1L] ge 6L and sb[sb[0L]+1L] le 11L) then begin
    errmsg='RDNOISE must be set to a decimal '+tmp+'; RDNOISE>0.'
    goto,error_handler
  endif
  if min(rdnoise) lt 0d0 then begin
    errmsg='RDNOISE must be set to a decimal '+tmp+'; RDNOISE>0.'
    goto,error_handler
  endif

  sb=size(gaps)
  if ~sb[sb[0L]+2L] or $
     (sb[sb[0L]+1L] ge 4L and sb[sb[0L]+1L] le 11L) then begin
    errmsg='GAPS must be set to a scalar or array of integer values; GAPS>0.'
    goto,error_handler
  endif
  if min(gaps) le 0L then begin
    errmsg='GAPS must be set to a scalar or array of integer values; GAPS>0.'
    goto,error_handler
  endif

  if ~n_elements(xstr) then xstr=''
  s=size(xstr)
  if s[0L] ne 0L or s[s[0L]+2L] ne 1L or s[s[0L]+1L] ne 7L then begin
    errmsg='XSTR, if set, must be a two- or three-character scalar string.'
    goto,error_handler
  endif
  if strlen(xstr) ne 0L and $
     strlen(xstr) ne 3L and strlen(xstr) ne 2L then begin
    errmsg='XSTR, if set, must be a two- or three-character scalar string.'
    goto,error_handler
  endif

  xbin=~n_elements(xbin_)?1L:xbin_
  s=size(xbin)
  if s[s[0L]+2L] ne 1L or $
    (s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L) then begin
    errmsg='XBIN must be a scalar integer; XBIN>=1.'
    goto,error_handler
  endif
  if xbin lt 1L then begin
    errmsg='XBIN must be a scalar integer; XBIN>=1.'
    goto,error_handler
  endif

  ybin=~n_elements(ybin_)?1L:ybin_
  s=size(ybin)
  if s[s[0L]+2L] ne 1L or $
    (s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L) then begin
    errmsg='YBIN must be a scalar integer; YBIN>=1.'
    goto,error_handler
  endif
  if ybin lt 1L then begin
    errmsg='YBIN must be a scalar integer; YBIN>=1.'
    goto,error_handler
  endif

  ;; Swapping the binning parameters if DAXIS==2:
  if daxis eq 2L then begin & tmp=ybin & ybin=xbin & xbin=tmp & endif

  if ~n_elements(d) then d=0L
  s=size(d)
  if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L then begin
    errmsg='DETECTOR must be a scalar integer; DETECTOR>=0.'
    goto,error_handler
  endif
  if d lt 0L then begin
    errmsg='DETECTOR must be a scalar integer; DETECTOR>=0.'
    goto,error_handler
  endif

  ;; Creating a shortened title for the widget base container, if possible:
  if n_elements(title) ne 1L or size(title,/type) ne 7L then $
     title='Cross-dispersion line profiles of: '+filename+'.'
  title=p3d_misc_pathify(title,/dpath)

  if ~n_elements(monitor) then monitor=1L
  s=size(monitor)
  if s[s[0L]+2L] ne 1L or s[s[0L]+1L] ge 4L and s[s[0L]+1L] le 11L then begin
    errmsg='MONITOR must be a scalar integer; MONITOR=0||1.'
    goto,error_handler
  endif
  if monitor ne 0L and monitor ne 1L then begin
    errmsg='MONITOR must be a scalar integer; MONITOR=0||1.'
    goto,error_handler
  endif

  ;;========================================------------------------------
  ;; Reading default parameters from the PARFILE and/or the USERPARFILE:

  ppath=strmid(parfile,0L,strpos(parfile,path_sep(),/reverse_search)+1L)
  parname='' & parvalue=''
  readcol,parfile,parname,parvalue,format='a,a',delimiter=' ', $
      silent=verbose lt 3,comment=';'

  p3d_misc_read_params,parname,parvalue,'ndetector',ndetector,/nou, $
      type='integer',topwid=topwid,logunit=logunit, $
      verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  if ~n_elements(ndetector) then ndetector=1L

  p3d_misc_read_params,parname,parvalue,'lproffun_tr',proffun, $
      /must_exist,uparname=uparname,uparvalue=uparvalue, $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  proffun=strlowcase(proffun)

  p3d_misc_read_params,parname,parvalue,'lprofendmin_tr',groupend_forcemin, $
      /must_exist,uparname=uparname,uparvalue=uparvalue, $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  groupend_forcemin=strlowcase(groupend_forcemin) eq 'yes'?1L:0L

  p3d_misc_read_params,parname,parvalue,'lprofn_tr',lprofn,/must_exist, $
      uparname=uparname,uparvalue=uparvalue,type='integer', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler

  p3d_misc_read_params,parname,parvalue,'lprofmaxiter_tr',lprofmaxiter, $
      /must_exist,uparname=uparname,uparvalue=uparvalue,type='integer', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler

  p3d_misc_read_params,parname,parvalue,'lprofdint_tr',lprofdint, $
      /must_exist,uparname=uparname,uparvalue=uparvalue,type='integer', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  lprofdint/=xbin

  p3d_misc_read_params,parname,parvalue,'lprofdwid_tr',lprofdwid, $
      /must_exist,uparname=uparname,uparvalue=uparvalue,type='integer', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  lprofdwid/=xbin

  if fitcenter then lprofcenter=1L else begin
    p3d_misc_read_params,uparname,uparvalue,'lprofcenter',lprofcenter,/upo, $
        logunit=logunit,topwid=topwid,verbose=verbose,error=error,debug=debug
    if error ne 0 then goto,error_handler
    lprofcenter=~n_elements(lprofcenter)?0L: $
                (strlowcase(lprofcenter) eq 'yes'?1L:0L)
  endelse ;; fitcenter then lprofcenter=1L

  p3d_misc_read_params,uparname,uparvalue,'lprofcoffset',lprofcoffset,/upo, $
      type='float',logunit=logunit,topwid=topwid,verbose=verbose, $
      error=error,debug=debug
  if error ne 0 then goto,error_handler
  if ~n_elements(lprofcoffset) then lprofcoffset=0.5d0

  p3d_misc_read_params,parname,parvalue,'dist_tr'+xstr,dist, $
      /must_exist,uparname=uparname,uparvalue=uparvalue,type='float', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then return
  dist/=ybin

  p3d_misc_read_params,parname,parvalue,'fwhm_tr',fwhm, $
      /must_exist,uparname=uparname,uparvalue=uparvalue,type='float', $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then return
  fwhm/=ybin

  str=ndetector eq 1L?'':'_'+strtrim(d+1L,2L)
  p3d_misc_read_params,parname,parvalue,'deadfibersfile'+str,deadfibersfile, $
      uparname=uparname,uparvalue=uparvalue, $
      topwid=topwid,logunit=logunit,verbose=verbose,error=error,debug=debug
  if error ne 0 then goto,error_handler
  if n_elements(deadfibersfile) eq 1L then begin
    deadfibersfile=ppath+deadfibersfile
    if ~file_test(deadfibersfile,/regular,/read) then begin
      errmsg='The dead fibers file "'+deadfibersfile+'" does not exist.'
      goto,error_handler
    endif

    readcol,deadfibersfile,deadfibers_array,sdeadfibers_,format='l,a', $
        delimiter=' ',silent=verbose lt 3,comment=';'
    if n_elements(deadfibers_array) ge 1L then begin
       deadfibers=deadfibers_array

      for i=0L,n_elements(sdeadfibers_)-1L do begin
        tmp=sdeadfibers_[i]
        iterate=1L & while iterate do begin
          idx=strpos(tmp,'_')
          if idx ge 0L then strput,tmp,' ',idx
          if idx eq -1L then iterate=0L
        endwhile ;; iterate
        sdeadfibers_[i]=tmp
      endfor ;; i=0L,n_elements(sdeadfibers_)-1L
      sdeadfibers=sdeadfibers_
    endif
  endif ;; n_elements(deadfibersfile) eq 1L

  msg=[' Line profile function: '+proffun, $
       ' Use minimum value at the lower and upper ends of the data: '+ $
       (groupend_forcemin?'yes':'no')]
  msg=[msg,' Fitting profile center positions in addition to intensities: '+ $
       (lprofcenter?'yes':'no')]
  if lprofcenter then begin
    msg=[msg,' Allowed offset when fitting profile center positions '+ $
         string(format='(f5.2)',lprofcoffset)+' [px]']
  endif ;; lprofcenter
  error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
      verbose=verbose ge 1)

  ;;========================================------------------------------
  ;; Subtracting the bias from the data and calc. the corresponding variance:

  data-=mbias

  if size(detsec,/n_dimensions) eq 1L then begin
    ddata=abs(data)/gain+rdnoise^2+dmbias^2

    ;;========================================------------------------------
    ;; Trimming the data of prescan and overscan regions (so that those regions
    ;; won't affect the results):

      data= data[detsec[0L]:detsec[1L],detsec[2L]:detsec[3L]]
     ddata=ddata[detsec[0L]:detsec[1L],detsec[2L]:detsec[3L]]
    sd=size(data)

    if ~fitcenter then $
       traces=daxis?traces_[detsec[0L]:detsec[1L],*]: $
                    traces_[*,detsec[2L]:detsec[3L]]
  endif else begin

    ;;========================================------------------------------
    ;; Trimming the data of prescan and overscan regions (so that those regions
    ;; won't affect the results):

    xmin=min(min(detsec[0L:1L,*],dimension=1L),minjx)
    xmax=max(max(detsec[0L:1L,*],dimension=1L),maxjx)
    tmp=min(detsec[0L:1L,maxjx])-max(detsec[0L:1L,minjx])-1L
    xoff=~tmp?0L:tmp
    xmax-=xoff

    ymin=min(min(detsec[2L:3L,*],dimension=1L),minjy)
    ymax=max(max(detsec[2L:3L,*],dimension=1L),maxjy)
    tmp=min(detsec[2L:3L,maxjy])-max(detsec[2L:3L,minjy])-1L
    yoff=~tmp?0L:tmp
    ymax-=yoff

    data=data[xmin:xmax,ymin:ymax]
    if ~fitcenter then traces=daxis?traces_[xmin:xmax,*]:traces_[*,ymin:ymax]

    ;;========================================------------------------------
    ;; Calculating the error:

    ddata=data ;; initializing ddata

    ;; Treating the individual blocks separately:
    xmint=xmin
    ymint=ymin
    for j=0L,nblocks-1L do begin
      xmin=~(min(detsec[0L:1L,j])-xmint)?0L:(max(detsec[0L:1L,minjx])+1L-xmint)
      xmax=xmin+max(detsec[0L:1L,j])-min(detsec[0L:1L,j])

      ymin=~(min(detsec[2L:3L,j])-ymint)?0L:(max(detsec[2L:3L,minjy])+1L-ymint)
      ymax=ymin+max(detsec[2L:3L,j])-min(detsec[2L:3L,j])

      ddata[xmin:xmax,ymin:ymax]= $
         abs(data[xmin:xmax,ymin:ymax])/gain+rdnoise[j]^2+dmbias[j]^2
    endfor ;; j=0L,nblocks-1L

  endelse ;;  size(detsec,/n_dimensions) eq 1L

  ;; Transposing data if daxis==2:
  if daxis eq 2L then begin
      data=transpose(data)
     ddata=transpose(ddata)
    if ~fitcenter then traces=transpose(traces)
  endif

  if fitcenter then begin
    s=size(fixprofs_)
    if s[0L] ne 3L then begin
      errmsg='FIXPROFS must be a three-dimensional array.'
      goto,error_handler
    endif
    fixprofs=daxis eq 1L?fixprofs_:transpose(fixprofs_,[1L,0L,2L])
    sb=size(fixprofs_)
    if ~sb[sb[0L]+2L] or $
       (sb[sb[0L]+1L] ge 6L and sb[sb[0L]+1L] le 11L) then begin
      errmsg='FIXPROFS must be set to a three-dimensional array of decimal' + $
             ' type.'
      goto,error_handler
    endif
    traces=reform(fixprofs[*,*,0L])
  endif ;; fitcenter

  st=size(traces)
  ntr=st[2L]
  nbn=st[1L]

  usedeadfibers=0L
  spc=size(deadfibers)
  farr=lindgen(ntr) & usedeadfibers=0L & dfmask=lonarr(ntr)+1L
  if spc[spc[0L]+2L] ge 1L then begin
    if spc[spc[0L]+1L] ge 4L and spc[spc[0L]+1L] le 11L then begin
      errmsg='DEADFIBERS must, if set, be an array of integer type.'
      goto,error_handler
    endif

    spc=size(sdeadfibers)
    if spc[spc[0L]+2L] ne n_elements(deadfibers) or $
       spc[spc[0L]+1L] ne 7L then begin
      errmsg='SDEADFIBERS must be an array of string type with as' + $
             'many elements as DEADFIBERS.'
       goto,error_handler
    endif

    deadfibers=deadfibers-1L
    count=0L
    for i=0L,n_elements(deadfibers)-1L do begin
      tmp=where(farr eq deadfibers[i],count_)
      if count_ eq 1L and $
         (strlowcase(strmid(sdeadfibers[i],0L,1L)) eq 'd' or $
          strlowcase(strmid(sdeadfibers[i],0L,1L)) eq 'u') then begin
        dfmask[tmp[0L]]=0L
        count++
      endif
    endfor ;; i=0L,n_elements(deadfibers)
    if count eq ntr then begin
      errmsg='All spectra are masked as dead, cannot continue.'
      goto,error_handler
    endif
    usedeadfibers=1L
  endif ;; spc[spc[0L]+2L] ge 1L

  ;;========================================------------------------------
  ;; Setting up the wavelength bins to use in the line profile fitting process:
  ;;
  ;; lprofdint - The separation between wavelength bins which are used
  ;;             when calculating the line profiles (the rest is interpolated).

  col0=nbn/2L ;; Set for logging purposes of TRI (see below)
  colf=156L ;; testing testing testing

  if fitcenter then begin
    ;; Only performing the fitting for one wavelength bin (the center one):
    nbins=1L
    wbins=colf
  endif else begin
    nbins=nbn/lprofdint
    wbins=lonarr(nbins)
    for i=0L,nbins-1L do wbins[i]=lprofdint/2L+i*lprofdint 

    ;; Adding the first and last wavelength bins:
    nbins+=2L
    wbins=[0L,wbins,nbn-1L]
  endelse

  ;;========================================------------------------------
  ;; Setting up the groups of spectra which are calculated simultaneously:
  ;;
  ;; ngroups - The number of groups of spectra to fit separately.
  ;; trp[]   - The number of the last spectrum of every group.
  ;; trn[]   - The number of spectra in every group.
  ;; trr[][] - The range of traces to use with every group.
  ;; tri[][] - The pixel range in the raw data of every group.

  idx=where(gaps ge lprofn,count)
  if count ne 0L then begin
    if gaps[idx[0L]] gt lprofn then begin
      trp=idx[0L] ne 0L?gaps[idx[0L]-1L]:gaps[idx[0L]]
    endif else trp=gaps[idx[0L]]
    idx=where(gaps eq trp,count) ;; recalculating COUNT, in case
    trp=[trp]
    nval=groupend_forcemin?[count+2d0]:[0.5d0*(count+1d0)]
    tri=[0L,floor(traces[col0,trp-1L]+nval*dist)<(sd[2L]-1L)] ;; the px. i.val
    trn=[trp]
    trr=[0L,trp[0L]-1L]

    ;; Setting up the remaining groups:
    notdone=1L & i=1L
    while notdone do begin
      idx=where(gaps ge trp[i-1L]+lprofn,count)

      if count gt 0L then begin
        tmp=gaps[idx[0L]] gt trp[i-1L]+lprofn?gaps[idx[0L]-1L]:gaps[idx[0L]]
        idx=where(gaps eq tmp,count) ;; recalculating COUNT, in case
        trp=[trp,tmp]
        trn=[trn,tmp-trp[i-1L]]
        trr=[[trr],[trp[i]+[-trn[i],-1L]]]

        nval=groupend_forcemin?[nval,count+1d0]:[nval,0.5d0*(count+1d0)]
        tri=[[tri],[ ceil(traces[col0,trp[i]-trn[i]-1L]-nval[i]*dist), $
                    floor(traces[col0,trp[i]       -1L]+nval[i]*dist)< $
                    (sd[2L]-1L)]]
        i++
      endif else begin
        ;; Adding the remaining spectra:
        trp=[trp,ntr]
        trn=[trn,ntr-trp[i-1L]]
        trr=[[trr],[trp[i]+[-trn[i],-1L]]]
        nval=[nval,nval[i-1L]]
        tri=[[tri],[ ceil(traces[col0,trp[i]-trn[i]-1L]-nval[i]*dist), $
                     sd[2L]-1L]]
        i++
        notdone=0L
      endelse
    endwhile ;; notdone
    ngroups=i
  endif else begin
    trp=[ntr]
    trn=[trp]
    trr=reform([0L,trp-1L],2L,1L)
    tri=reform([0L,sd[2L]-1L],2L,1L)
    ngroups=1L
  endelse ;; count ne 0L

  ;; Logging the information:
  msg=['Setting up groups of spectra to fit simultaneously:', $
       '       ngroups='+string(ngroups     ,format='(i4)')]
  for i=0L,ngroups-1L do begin
    smax=strtrim(strlen(strtrim(ngroups,2L)),2L)
    istr=string(i+1L,format='(i'+smax+')')+'/'+strtrim(ngroups,2L)
    sstr=string(trr[0L,i]+1L,trr[1L,i]+1L,trn[i], $
                format='(i4,"-",i4,", n=",i3)')
    pstr=string(tri[0L,i]+1L,tri[1L,i]+1L,format='(i4,"-",i4,".")')
    msg=[msg,'  group '+istr+' :: spectra '+sstr+' :: pixel range '+pstr]
  endfor
  msg=[msg,'Line profiles are calculated for the following wavelength bins:']
  msg=[msg,'  '+strjoin(strtrim(wbins,2L),', ')]
  error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
      verbose=verbose ge 1)

  ;;========================================------------------------------
  ;; Calculating the cross-dispersion line profiles:

  fwhmconst=sqrt(8d0*alog(2d0))

  case proffun of
    'lorentzian':    rlprofs=dblarr(nbins,ntr,5L)
    'gauss/lorentz': rlprofs=dblarr(nbins,ntr,6L)
    'doublegauss':   rlprofs=dblarr(nbins,ntr,7L)
    else:            rlprofs=dblarr(nbins,ntr,5L) ;; 'gaussian'
  endcase ;; proffun

  rwidths=dblarr(ngroups) & rwidths2=dblarr(ngroups)
  rzeros =dblarr(ngroups) & rfactor =dblarr(ngroups)
  rslopes=dblarr(ngroups)

  tstart=systime(1L)

  ;;========================================------------------------------
  ;; Looping over all wavelength bins of the resized array WBINS:

   nstr=strtrim(nbins,2L) &  nlen=strlen(nstr)
  nnstr=strtrim(nbn,2L)   & nnlen=strlen(nnstr)
  remt='' & itimes=dblarr(nbins)
  for i=0L,nbins-1L do begin
    itimes[i]=systime(1L)

    wblow=(wbins[i]-lprofdwid)>0L
    wbhig=(wbins[i]+lprofdwid)<(nbn-1L)
    wbnum=wbhig-wblow+1L

    if usestawid and ~fitcenter then begin
      msg='Fitting profiles: w.l.bin='+strtrim(i+1L,2L)+'/'+nstr
      if i gt 0L then begin
        tmp=total(itimes[0L:i-1L])
        tmp=strtrim(round(tmp*(double(nbins)/i-1d0)),2L)
        msg+=' :: the remaining time is ~'+strtrim(tmp,2L)+'s.'
      endif
      widget_control,stawid,set_value=msg
    endif ;; usestawid and ~fitcenter

    msg='  '+string(i+1L,format='(i'+strtrim(nlen,2L)+')')+'/'+nstr+ $
        ' :: for the center wavelength bin '+ $
        string(wbins[i],format='(i'+strtrim(nnlen,2L)+')')+'/'+nnstr
    msg+=' ['+string(wblow,format='(i4)')+'--'+string(wbhig,format='(i4)')+']'
    error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
              verbose=verbose ge 1)

    ;; Loop over all groups of the current wavelength bin:
    for j=0L,ngroups-1L do begin

      ;; Extracting the trace pixel positions of the current bin and group:
      trlow= ceil(traces[wbins[i],trr[0L,j]]-nval[j]*dist)>0L
      trhig=floor(traces[wbins[i],trr[1L,j]]+nval[j]*dist)<(sd[2L]-1L)

      ;; Preparing the x, y, and dy (variance) arrays for the profiles:
      xspc=groupend_forcemin and trhig eq sd[2L]-1L?6*dist:0L ;; '6' is ad hoc

       x=trlow+dindgen(trhig+xspc-trlow+1L) 
       y=reform(total( data[wblow:wbhig,trlow:trhig],1L)/wbnum)
      dy=reform(total(ddata[wblow:wbhig,trlow:trhig],1L)/wbnum)

      ;; Setting elements at either end to the minimum value:
      if groupend_forcemin then begin
        tmp=y[0L:long(nval[j]*dist)] & minval=min(tmp,pos)
        y[0L:pos]=minval

        if xspc gt 0L then begin
           y=[ y,rebin( [minval],xspc)]
          dy=[dy,rebin([dy[pos]],xspc)]
        endif ;; xspc gt 0L

        num=trhig+xspc-trlow
        tmp=y[num-long(nval[j]*dist):num]
        minval=min(tmp,pos)
         y[num-long(nval[j]*dist)+pos:num]=minval
        dy[num-long(nval[j]*dist)+pos:num]=dy[pos]
      endif ;; groupend_forcemin

      ;; Define vector listing the centroid of each trace in yprof
      cen=reform(traces[wbins[i],trr[0L,j]:trr[1L,j]])

      ;; parameter order: zero-point, sigma, normalization_i
      ntrg=1L+trr[1L,j]-trr[0L,j]
      case proffun of
        'lorentzian': begin
          par=dblarr(3L+ntrg*(lprofcenter?2L:1L))
          if fitcenter then begin
            par[2L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],1L])
          endif else begin
            par[2L]=fwhm                     ;; The default value of FWHM
          endelse
          par[3L:trr[1L,j]-trr[0L,j]+3L]=1d3 ;; The default intensity
          if lprofcenter then par[(3L+ntrg):(2L*ntrg+2L)]=cen
          offset=3L
        end
        'gauss/lorentz': begin
          par=dblarr(4L+ntrg*(lprofcenter?2L:1L))
          if fitcenter then begin
            par[2L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],1L])
            par[3L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],2L])
          endif else begin
            par[2L]=fwhm/fwhmconst           ;; The default value of sigma
            par[3L]=0.5d0                    ;; The default value of m
          endelse
          par[4L:trr[1L,j]-trr[0L,j]+4L]=1d3 ;; The default intensity
          if lprofcenter then par[(4L+ntrg):(2L*ntrg+3L)]=cen
          offset=4L
        end
        'doublegauss': begin
          par=dblarr(5L+ntrg*(lprofcenter?2L:1L))
          if fitcenter then begin
            par[2L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],1L])
            par[3L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],2L])
            par[4L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],3L])
          endif else begin
            par[2L]=fwhm/fwhmconst           ;; The default value of sigma1
            par[3L]=par[2L]*2d0              ;; The default value of sigma2
            par[4L]=0.5d0                    ;; The default value of A
          endelse
          par[5L:trr[1L,j]-trr[0L,j]+5L]=1d3 ;; The default intensity
          if lprofcenter then par[(5L+ntrg):(2L*ntrg+4L)]=cen
          offset=5L
        end
        else: begin ;; 'gaussian'
          par=dblarr(3L+ntrg*(lprofcenter?2L:1L))
          if fitcenter then begin
            par[2L]=median(fixprofs[colf,trr[0L,j]:trr[1L,j],1L])
          endif else begin
            par[2L]=fwhm/fwhmconst           ;; The default value of sigma
          endelse
          par[3L:trr[1L,j]-trr[0L,j]+3L]=1d3 ;; The default intensity
          if lprofcenter then par[(3L+ntrg):(2L*ntrg+2L)]=cen
          offset=3L
        end
      endcase ;; proffun

      ;; Removing dead and no-use fiber entries, so that they are not fitted:
      if ~min(dfmask[trr[0L,j]:trr[1L,j]]) then begin
        idx=where(dfmask[trr[0L,j]:trr[1L,j]],n)
        cen_=cen[idx]
        if lprofcenter then $
             par=[par[0L:offset-1L],par[offset+idx],par[offset+n+idx]] $
        else par=[par[0L:offset-1L],par[offset+idx]]
      endif else begin
        n=trn[j]
        idx=lindgen(n)
        cen_=cen
      endelse ;; total(dfmask[trr[0L:j]:trr[1L:j]]) gt 0L

      p3d_tracing_calculate_lprofs_fits,x,y,dy,cen_,par,out,dout, $
          fixw=fitcenter,mpmaxiter=lprofmaxiter,proffun=proffun, $
          full=lprofcenter,foffset=lprofcoffset,topwid=topwid, $
          logunit=logunit,verbose=verbose,error=error,debug=debug
      if error ne 0 then return

      case proffun of
        'lorentzian': begin
          if lprofcenter then begin
            rlprofs[i,trr[0L,j]+idx,0L]    =transpose(par[(3L+n):(2L*n+2L)])
          endif else begin
            rlprofs[i,trr[0L,j]:trr[1L,j],0L]=transpose(cen)
          endelse
          rlprofs[i,trr[0L,j]:trr[1L,j],1L]=transpose(dblarr(trn[j])+par[2L])
          rlprofs[i,trr[0L,j]+idx,2L]      =transpose(par[3L:2L+n])
          rlprofs[i,trr[0L,j]:trr[1L,j],3L]=transpose(dblarr(trn[j])+par[0L])
          rlprofs[i,trr[0L,j]:trr[1L,j],4L]=transpose(dblarr(trn[j])+par[1L])

          rzeros [j]=par[0L]
          rslopes[j]=par[1L]
          rwidths[j]=par[2L]
        end
        'gauss/lorentz': begin
          if lprofcenter then begin
            rlprofs[i,trr[0L,j]+idx,0L]    =transpose(par[(4L+n):(2L*n+3L)])
          endif else begin
            rlprofs[i,trr[0L,j]:trr[1L,j],0L]=transpose(cen)
          endelse
          rlprofs[i,trr[0L,j]:trr[1L,j],1L]=transpose(dblarr(trn[j])+par[2L])
          rlprofs[i,trr[0L,j]:trr[1L,j],2L]=transpose(dblarr(trn[j])+par[3L])
          rlprofs[i,trr[0L,j]+idx,3L]      =transpose(par[4L:3L+n])
          rlprofs[i,trr[0L,j]:trr[1L,j],4L]=transpose(dblarr(trn[j])+par[0L])
          rlprofs[i,trr[0L,j]:trr[1L,j],5L]=transpose(dblarr(trn[j])+par[1L])

          rzeros [j]=par[0L]
          rslopes[j]=par[1L]
          rwidths[j]=par[2L]
          rfactor[j]=par[3L]
        end
        'doublegauss': begin
          if lprofcenter then begin
            rlprofs[i,trr[0L,j]+idx,0L]    =transpose(par[(5L+n):(2L*n+4L)])
          endif else begin
            rlprofs[i,trr[0L,j]:trr[1L,j],0L]=transpose(cen)
          endelse
          rlprofs[i,trr[0L,j]:trr[1L,j],1L]=transpose(dblarr(trn[j])+par[2L])
          rlprofs[i,trr[0L,j]:trr[1L,j],2L]=transpose(dblarr(trn[j])+par[3L])
          rlprofs[i,trr[0L,j]:trr[1L,j],3L]=transpose(dblarr(trn[j])+par[4L])
          rlprofs[i,trr[0L,j]+idx,4L]      =transpose(par[5L:4L+n])
          rlprofs[i,trr[0L,j]:trr[1L,j],5L]=transpose(dblarr(trn[j])+par[0L])
          rlprofs[i,trr[0L,j]:trr[1L,j],6L]=transpose(dblarr(trn[j])+par[1L])

          rzeros  [j]=par[0L]
          rslopes [j]=par[1L]
          rwidths [j]=par[2L]
          rwidths2[j]=par[3L]
          rfactor [j]=par[4L]
        end
        else: begin ;; 'gaussian'
          if lprofcenter then begin
            rlprofs[i,trr[0L,j]+idx,0L]    =transpose(par[(3L+n):(2L*n+2L)])
          endif else begin
            rlprofs[i,trr[0L,j]:trr[1L,j],0L]=transpose(cen)
          endelse
          rlprofs[i,trr[0L,j]:trr[1L,j],1L]=transpose(dblarr(trn[j])+par[2L])
          rlprofs[i,trr[0L,j]+idx,2L]      =transpose(par[3L:2L+n])
          rlprofs[i,trr[0L,j]:trr[1L,j],3L]=transpose(dblarr(trn[j])+par[0L])
          rlprofs[i,trr[0L,j]:trr[1L,j],4L]=transpose(dblarr(trn[j])+par[1L])

          rzeros [j]=par[0L]
          rslopes[j]=par[1L]
          rwidths[j]=par[2L]
        end
      endcase ;; proffun

    endfor ;; j=0L,ngroups-1L

    if ~fitcenter then begin
      if proffun ne 'lorentzian' then begin
        tmp=string(rwidths,format='(e8.1)')
        tmp2=string(rwidths*fwhmconst,format='(e8.1)')
        msg=['  The spectrum group widths are (sigma) : '+strjoin(tmp ,', '), $
             '                                 (fwhm) : '+strjoin(tmp2,', ')]
      endif else begin
        tmp =string(rwidths,format='(e8.1)')
        msg=['                                 (fwhm) : '+strjoin(tmp,', ')]
      endelse

      if proffun eq 'gauss/lorentz' then begin
        tmp=string(rfactor,format='(e8.1)')
        msg=[msg,'  The spectrum group factors are (m):     '+ $
             strjoin(tmp ,', ')]
      endif

      if proffun eq 'doublegauss' then begin
        tmp =string(rwidths2,format='(e8.1)')
        tmp2=string(rwidths2*fwhmconst,format='(e8.1)')
        tmp3=string(rfactor,format='(e8.1)')
        msg=[msg, $
             '  The spectrum group widths are (sigma2): '+strjoin(tmp ,', '), $
             '                                 (fwhm2): '+strjoin(tmp2,', '), $
             '  The spectrum sec.mult.factors are  (A): '+strjoin(tmp3,', ')]
      endif ;; proffun eq 'doublegauss'

      tmp3=string(rzeros ,format='(e8.1)')
      tmp4=string(rslopes,format='(e8.1)')
      msg=[msg, $
           '  The spectrum group zero levels are:     '+strjoin(tmp3,', '), $
           '  The spectrum group slopes are:          '+strjoin(tmp4,', ')]
      error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
          loglevel=2,verbose=verbose ge 2)

;     ;; Calculate the median best-fit width and use it as the best-fit
;     ;; width for all traces (along a column)
;     median_bestfit_width = median(bestwidthpar)
;       tmp = moment(bestwidthpar, mdev=mdev)  ;; calculate median deviation
;     print, 'Median of best-fit width parameters: ',median_bestfit_width, mdev
;     bestpar[1] = median_bestfit_width 

      itimes[i]=systime(1L)-itimes[i]
    endif ;; ~fitcenter
  endfor ;;  i=0L,nbins-1L

  if ~fitcenter then begin
    tfinal=systime(1L)
    msg='The time that was required to fit line profiles of every waveleng' + $
        'th bin and group was:'+strtrim(tfinal-tstart,2L)+'s.'
    error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
        verbose=verbose ge 1)
  endif ;; ~fitcenter

  ;;========================================------------------------------
  ;; Fitting the spectrum width in the dispersion direction:

  ;; To BE DONE, maybe

  ;;========================================------------------------------
  ;; Interpolating the width and intensity for all wavelength bins:
  ;;
  ;; Note! Sometimes the blue and red ends are vignetted (as with the PMAS
  ;;       4kx4k CCD. In this case it is not always possible to interpolate
  ;;       the line profiles across wavelength bins keeping the intensity
  ;;       positive at all times. The interpolated intensity is therefore
  ;;       set explicitly to be >=0.0.

  if fitcenter then begin
    lprofs=reform(rlprofs[*,*,0L])

;   print,'shift:',[dindgen(1,382)+1,transpose(reform(lprofs-traces[colf,*]))]
;   stop
  endif else begin

    if usestawid then begin
      msg='Cross-disp. profiles: interpolating for all wavelength bins.'
      widget_control,stawid,set_value=msg
    endif

    wx=dindgen(nbn)

    tstart=systime(1L)
    case proffun of
      'lorentzian': begin
        lprofs=dblarr(nbn,ntr,5L)

        if ~lprofcenter then begin
          lprofs[*,*,0L]=traces
        endif else begin
          for j=0L,ntr-1L do $
             lprofs[*,j,0L]=spline(wbins,rlprofs[*,j,0L],wx)  ;; line center
        endelse ;; ~lprofcenter

        for j=0L,ntr-1L do begin
          lprofs[*,j,1L]=spline(wbins,rlprofs[*,j,1L],wx)     ;; width
          lprofs[*,j,2L]=spline(wbins,rlprofs[*,j,2L],wx)>0d0 ;; intensity
          lprofs[*,j,3L]=spline(wbins,rlprofs[*,j,3L],wx)     ;; zero-level
          lprofs[*,j,4L]=spline(wbins,rlprofs[*,j,4L],wx)     ;; slope
        endfor ;; j=0L,ntr-1L
      end ;; 'lorentzian'
      'gauss/lorentz': begin
        lprofs=dblarr(nbn,ntr,6L)

        if ~lprofcenter then begin
          lprofs[*,*,0L]=traces
        endif else begin
          for j=0L,ntr-1L do $
             lprofs[*,j,0L]=spline(wbins,rlprofs[*,j,0L],wx)  ;; line center
        endelse ;; ~lprofcenter

        for j=0L,ntr-1L do begin
          lprofs[*,j,1L]=spline(wbins,rlprofs[*,j,1L],wx)     ;; width
          lprofs[*,j,2L]=spline(wbins,rlprofs[*,j,2L],wx)     ;; factor
          lprofs[*,j,3L]=spline(wbins,rlprofs[*,j,3L],wx)>0d0 ;; intensity
          lprofs[*,j,4L]=spline(wbins,rlprofs[*,j,4L],wx)     ;; zero-level
          lprofs[*,j,5L]=spline(wbins,rlprofs[*,j,5L],wx)     ;; slope
        endfor ;; j=0L,ntr-1L
      end ;; 'gauss/lorentz'
      'doublegauss': begin
        lprofs=dblarr(nbn,ntr,7L)

        if ~lprofcenter then begin
          lprofs[*,*,0L]=traces
        endif else begin
          for j=0L,ntr-1L do $
             lprofs[*,j,0L]=spline(wbins,rlprofs[*,j,0L],wx)  ;; line center
        endelse ;; ~lprofcenter

        for j=0L,ntr-1L do begin
          lprofs[*,j,1L]=spline(wbins,rlprofs[*,j,1L],wx)     ;; width1
          lprofs[*,j,2L]=spline(wbins,rlprofs[*,j,2L],wx)     ;; width2
          lprofs[*,j,3L]=spline(wbins,rlprofs[*,j,3L],wx)     ;; int.factor
          lprofs[*,j,4L]=spline(wbins,rlprofs[*,j,4L],wx)>0d0 ;; intensity
          lprofs[*,j,5L]=spline(wbins,rlprofs[*,j,5L],wx)     ;; zero-level
          lprofs[*,j,6L]=spline(wbins,rlprofs[*,j,6L],wx)     ;; slope
        endfor ;; j=0L,ntr-1L
      end ;; 'doublegauss'
      else: begin ;; 'gaussian'
        lprofs=dblarr(nbn,ntr,5L)

        if ~lprofcenter then begin
          lprofs[*,*,0L]=traces
        endif else begin
          for j=0L,ntr-1L do $
             lprofs[*,j,0L]=spline(wbins,rlprofs[*,j,0L],wx)    ;; line center
        endelse ;; ~lprofcenter

        for j=0L,ntr-1L do begin
          lprofs[*,j,1L]=spline(wbins,rlprofs[*,j,1L],wx,5)     ;; width
          lprofs[*,j,2L]=spline(wbins,rlprofs[*,j,2L],wx,5)>0d0 ;; intensity
          lprofs[*,j,3L]=spline(wbins,rlprofs[*,j,3L],wx,5)     ;; zero-level
          lprofs[*,j,4L]=spline(wbins,rlprofs[*,j,4L],wx,5)     ;; slope
        endfor ;; j=0L,ntr-1L
;if debug and j eq 40 then begin
;  window,0,xsize=1200,ysize=800
;  pm=!p.multi & !p.multi=[0,2,2,0,0]
;  plot,wbins,rlprofs[*,j,1L],xtitle='Dispersion axis',ytitle='Width'
;  oplot,wx,lprofs[*,j,1L],linestyle=3
;  plot,wbins,rlprofs[*,j,2L],xtitle='Dispersion axis',ytitle='Intensity'
;  oplot,wx,lprofs[*,j,2L],linestyle=3
;  plot,wbins,rlprofs[*,j,3L],xtitle='Dispersion axis',ytitle='Zero-level'
;  oplot,wx,lprofs[*,j,3L],linestyle=3
;  plot,wbins,rlprofs[*,j,4L],xtitle='Dispersion axis',ytitle='Slope'
;  oplot,wx,lprofs[*,j,4L],linestyle=3
;  !p.multi=pm
;stop
;endif
      end ;; else
    endcase ;; proffun
    tfinal=systime(1L)

    msg='Interpolated the widths and intensities for all wavelength bins.'
    msg=[msg,'  Used splines to do the fitting.']
    msg=[msg,'  This took '+strtrim(round(1d1*(tfinal-tstart))/1d1,2L)+'s.']
    error=p3d_misc_logger(msg,logunit,rname=rname,topwid=topwid, $
        verbose=verbose ge 1)
    if error ne 0 then return

    if keyword_set(monitor) then begin
      p3d_display_lineprofiles,data,traces,lprofs,rawdarray=ddata, $
          filename=filename,proffun=proffun,topwid=topwid,logunit=logunit, $
          verbose=verbose,error=error,debug=debug
      if error ne 0 then return
    endif ;; keyword_set(monitor)

    lprofs[*,*,0L]+=0.5d0 ;; Offseting all center positions by 0.5 pixels.
    oprof=proffun

    if daxis eq 2L then lprofs=transpose(lprofs,[1L,0L,2L])
  endelse ;; fitcenter

  return

error_handler:
  error=p3d_misc_logger(errmsg,logunit,rname=rname,topwid=topwid, $
      verbose=verbose,/error)
  return
END ;;; procedure: p3d_tracing_calculate_lprofs
