;+
; NAME:
;   rbsp_cotrans (procedure)
;
; PURPOSE:
;   A wrapper of cotrans for RBSP, with a few mission-specific features added.
;
; CATEGORIES:
;
; CALLING SEQUENCE:
;   rbsp_cotrans, from_tvar, to_tvar $
;     , gse2gsm = gse2gsm $
;     , gsm2gse = gsm2gse $
;     , dsc2gse = dsc2gse $
;     , dsc2mgse = dsc2mgse $
;     , dsc2gsm = dsc2gsm $
;     , gse2dsc = gse2dsc $
;     , gse2mgse = gse2mgse $
;     , gsm2dsc = gsm2dsc $
;     , dsc2fac = dsc2fac $
;     , mat_dsc = mat_dsc $
;     , tmag    = tmag    $
;     , vectype = vectype $
;     , verbose = verbose

;   NOTES:
;   1. A tplot variable of magnetic field in DSC, specified with tmag keyword,
;      is required to perfrom dsc2fac. The default value of tmag is something
;      like 'rbspa_mag_dsc'.
;   2. A tplot variable of rotation matrix from DSC to GSE, specified with the
;      mat_dsc keyword, is required to perform dsc2gse, gse2dsc, dsc2gsm,
;      and gsm2dsc. The rotation matrix is usually generated by
;      *rbsp_load_state*. The default value of mat_dsc is something like
;      'rbspa_mat_dsc'.
;
; ARGUMENTS:
;   from_tvar: (In, required) A tplot variable to which the rotation is applied.
;   to_tvar: (Out, required) A tplot name for storing the rotation results.
;
; KEYWORDS:
;   The following keywords enable the transformations indicated by their names.
;   /gse2gsm, /gsm2gse, /dsc2gse, /dsc2gsm, /gse2dsc, /gsm2dsc
;
;   mat_dsc: (In, optional) A tplot name of the rotation matrix between DSC and
;         GSE. It is usually loaded in rbsp_load_state. By default, this name is
;         derived as
;                 strmid(from_tvar, 0, 6) + 'mat_dsc'
;   vectype: (In, optional) The type of the vectors being transformed. Valid
;         types are 'E', 'B', and 'V'. By default, vectype = ''. This string is
;         used for labelling the to_tvar.
;   verbose: (In, optional) A number to indicate the verbose level. See dprint.
;
; COMMON BLOCKS:
;
; EXAMPLES:
;
; SEE ALSO:
;
; HISTORY:
;   2012-11-03: Created by Jianbao Tao (JBT), SSL, UC Berkley.
;   2012-11-05: JBT, SSL, UC Berkley.
;               Initial release to TDAS.
;   2012-11-20: JBT, SSL, UC Berkley.
;               1. Added dsc-to-fac transformation.
;
; VERSION:
; $LastChangedBy: aaronbreneman $
; $LastChangedDate: 2019-12-19 12:45:43 -0800 (Thu, 19 Dec 2019) $
; $LastChangedRevision: 28129 $
; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/trunk/general/missions/rbsp/efw/rbsp_cotrans.pro $
;
;-

pro rbsp_cotrans, from_tvar, to_tvar $
  , gse2gsm = gse2gsm $
  , gsm2gse = gsm2gse $
  , dsc2gse = dsc2gse $
  , dsc2mgse = dsc2mgse $
  , dsc2gsm = dsc2gsm $
  , gse2dsc = gse2dsc $
  , gse2mgse = gse2mgse $
  , gsm2dsc = gsm2dsc $
  , dsc2fac = dsc2fac $
  , mat_dsc = mat_dsc $
  , tmag    = tmag    $
  , vectype = vectype $
  , verbose = verbose

compile_opt idl2

type = 'dum2dum'
if keyword_set(gse2gsm) then type = 'gse2gsm'
if keyword_set(gse2dsc) then type = 'gse2dsc'
if keyword_set(dsc2gsm) then type = 'dsc2gsm'
if keyword_set(dsc2gse) then type = 'dsc2gse'
if keyword_set(gsm2gse) then type = 'gsm2gse'
if keyword_set(gsm2dsc) then type = 'gsm2dsc'

if keyword_set(dsc2mgse) then type = 'dsc2mgse'
if keyword_set(gse2mgse) then type = 'gse2mgse'

if keyword_set(dsc2fac) then type = 'dsc2fac'

if keyword_set(gse2gsm) then to_coord = 'gsm'
if keyword_set(gse2dsc) then to_coord = 'dsc'
if keyword_set(dsc2gsm) then to_coord = 'gsm'
if keyword_set(dsc2gse) then to_coord = 'gse'
if keyword_set(gsm2gse) then to_coord = 'gse'
if keyword_set(gsm2dsc) then to_coord = 'dsc'
if keyword_set(dsc2fac) then to_coord = 'fac'

if keyword_set(dsc2mgse) then to_coord = 'mgse'
if keyword_set(gse2mgse) then to_coord = 'mgse'

rbx = strlowcase(strmid(from_tvar, 0, strpos(from_tvar, '_')+1))

; Default name for the rotation matrix from DSC to GSE.
if ~keyword_set(mat_dsc) then begin
  mat_dsc = rbx + 'mat_dsc'
endif

; Default name for background magnetic field
if ~keyword_set(tmag) then begin
  tmag = rbx + 'mag_dsc'
endif
; print, 'tmag = ', tmag

if n_elements(vectype) eq 0 then vectype = ''

; Prefix for component labels
case strupcase(vectype) of
  'E': prefix = 'E'
  'B': prefix = 'B'
  'V': prefix = 'V'
  else: prefix = ''
endcase
labels = prefix + ['x ', 'y ', 'z '] + strupcase(to_coord)

tmpname = 'rbsp_cotrans_tmp'
case type of
  'gse2gsm': begin
;       dprint, verbose = verbose, 'GSE -> GSM...'
      cotrans, from_tvar, to_tvar, /gse2gsm
    end
  'gse2dsc': begin
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      dprint, verbose = verbose, 'GSE -> DSC...'
      tvector_rotate, mat_dsc, from_tvar, /invert, newname = to_tvar,/vector_skip_nonmonotonic
    end
  'dsc2gse': begin
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      dprint, verbose = verbose, 'DSC -> GSE...'
      tvector_rotate, mat_dsc, from_tvar, newname = to_tvar,/vector_skip_nonmonotonic
    end
  'dsc2mgse': begin
      ; dsc to gse, and construct wgse for rbsp_gse2mgse
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      get_data, from_tvar, data = dtmp
      tarr = dtmp.x
      y = dblarr(n_elements(tarr), 3)
      y[*,2] = 1d
      store_data, 'tmp_wgse_in_dsc', data = {x:tarr, y:y}, $
        dlim = {data_att:{coord_sys:'dsc'}}

      dprint, verbose = verbose, 'DSC -> GSE...'
      tvector_rotate, mat_dsc, from_tvar, newname = tmpname,/vector_skip_nonmonotonic
      tvector_rotate, mat_dsc, 'tmp_wgse_in_dsc', newname = 'tmp_wgse_in_gse',/vector_skip_nonmonotonic
      get_data, 'tmp_wgse_in_gse', data = dtmp
      wgse = dtmp.y
      store_data, 'tmp_wgse_in_gse', /del
      store_data, 'tmp_wgse_in_dsc', /del
      ; gse to mgse
      rbsp_gse2mgse, tmpname, wgse,newname = to_tvar
      store_data, tmpname, /del
    end
  'gse2mgse': begin
      ; dsc to gse, and construct wgse for rbsp_gse2mgse
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      get_data, from_tvar, data = dtmp
      tarr = dtmp.x
      y = dblarr(n_elements(tarr), 3)
      y[*,2] = 1d
      store_data, 'tmp_wgse_in_dsc', data = {x:tarr, y:y}, $
        dlim = {data_att:{coord_sys:'dsc'}}

      dprint, verbose = verbose, 'DSC -> GSE...'
      tvector_rotate, mat_dsc, 'tmp_wgse_in_dsc', newname = 'tmp_wgse_in_gse',/vector_skip_nonmonotonic
      get_data, 'tmp_wgse_in_gse', data = dtmp
      wgse = dtmp.y
      store_data, 'tmp_wgse_in_gse', /del
      store_data, 'tmp_wgse_in_dsc', /del
      ; gse to mgse
      rbsp_gse2mgse, from_tvar, wgse,newname = to_tvar
    end
  'dsc2gsm': begin
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      dprint, verbose = verbose, 'DSC -> GSE...'
      tvector_rotate, mat_dsc, from_tvar, newname = tmpname,/vector_skip_nonmonotonic
      cotrans, tmpname, to_tvar, /gse2gsm
      store_data, tmpname, /del
    end
  'gsm2gse': begin
      cotrans, from_tvar, to_tvar, /gsm2gse
    end
  'gsm2dsc': begin
      if ~spd_check_tvar(mat_dsc) then begin
        dprint, 'ERROR: ' + $
          'The rotation matrix between GSE and DSC is not available.'
        return
      endif
      cotrans, from_tvar, tmpname, /gsm2gse
      dprint, verbose = verbose, 'GSE -> DSC...'
      tvector_rotate, mat_dsc, tmpname, /invert, newname = to_tvar,/vector_skip_nonmonotonic
      store_data, tmpname, /del
    end
  'dsc2fac': begin
      if ~spd_check_tvar(tmag) then begin
        dprint, 'ERROR: ' + $
          'Background magnetic field not available. Abort.'
        return
      endif
      thm_fac_matrix_make, tmag, other_dim = 'Zdsl', $
        newname = rbx + 'dsc2fac_matrix', error = error
;       print, 'error = ', error
      if error eq 0 then begin
        dprint, 'ERROR: ' + $
          'Fail to make rotation matrix. Abort.'
        return
      endif
      tvector_rotate, rbx + 'dsc2fac_matrix', from_tvar, $
        newname = to_tvar,/vector_skip_nonmonotonic
      store_data, rbx + 'dsc2fac_matrix', /del
      get_data, to_tvar, dlim = dl
      str_element, dl, 'data_att.coord_sys', 'fac', /add
      str_element, dl, 'data_att.coord_note', $
        'FAC: Z->parallel, X->spin-plane perp', /add
      store_data, to_tvar, dlim = dl
    end
  else: begin
      dprint, verbose = verbose, 'The transformation type ' + type + $
        ' is not yet supported. Probably never will be. Sorry.'
      return
    end
endcase
options, to_tvar, colors = [2, 4, 6], labels = labels, labflag = 1

end
