;+
; NAME:  spl2obs_define
;
;
;
; PURPOSE: Definition of the spl2 (SOT/SP level 2 observations) class, a 
;          subclass of sotobs, which is a subclass of hinobs which again is a
;          subclass of anyobs. Please note that spl2obs differs
;          significantly from the other subclasses of hinobs (eisobs, sotobs
;          and xrtobs), since a spl2obs object is a SP scan built up of
;          several hundred (typically 512 or 1024) individual files. The
;          SOT/SP calibration research and software implementation is largely 
;          due to the work of Bruce Lites of HAO. The Level 2 inversions are
;          the work of HAO/SP members Scott McIntosh, Alfred de Wijn, and Rob 
;          Markel. All level 2 files are downloaded from LMSAL. 
;
;
;
;                                           (sdc_util)
;                                              |
;                                            anyobs
;                                          /       \
;                                    hinobs         irisobs
;                                  /   |   \ 
;                            xrtobs  sotobs eisobs
;                                     /  \
;                              sp1dobs    spl2obs
;
;
; METHODS: See sotobs__define, hinobs__define and anyobs__define
;
;
; WRITTEN: Terje Fredvik, UiO, January 2011
;
;
;
; MODIFICATION HISTORY:
;          4. Jan 2011 Terje Fredvik: wrote doc header, yeah!
;         10. Feb 2011 Terje Fredvik: it works!
;         11. Apr 2013 Terje Fredvik: added info about new superclass anyobs
;
;-

FUNCTION spl2obs::init, file, destdir=destdir, _ref_extra=extra
  IF self->spobs::init(file, destdir=destdir, _extra=extra) EQ 0 $
  THEN return,0
  
  self.lmsal_file = self->_lmsal_file()
    
  return,1 
END


PRO spl2obs::cleanup
  self->hinobs::cleanup
 
  print,"Cleaning up (sp1dobs)"
END


;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;      <overridden _ensure_properties help methods
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++

PRO spl2obs::_ensure_instrume
  self->private
  header = *(self->get(/header))
  self.instrume = 'SOT/SP Level 2 ('+header[0].invcode+' '+header[0].invvers+')'
END

PRO spl2obs::_ensure_nexp
  self->private
  data = *(self->get(/data))
  self.nexp = (size(data))[1]
END

FUNCTION spl2obs::_data_products_wanted
  self->private
  data = *(o->get(/data))
  n = (size(data))[1]
  return,intarr(n)
END

PRO spl2obs::_ensure_title
  o = self
  o->private
  nicons = o->get(/nicons)
  header = *(o->get(/header))
  o.title = ptr_new(strarr(nicons))
  FOR i=0,nicons-1 DO (*(o.title))[i] = strmid(header[i].instrume,7,40)
END


FUNCTION spl2obs::_image_scale_x
  self->private
  header =  *(self->get(/header))
  return, header[0].xscale
END

FUNCTION spl2obs::_image_scale_y
  self->private
  header =  *(self->get(/header))
  return,header[0].yscale
END

FUNCTION spl2obs::_image_origin_x
  self->private
  header = *(self->get(/header))
  return, header[0].xcen - self->get(/nexp)*self->_image_scale_x()/2.
END

FUNCTION spl2obs::_image_origin_y 
  self->private
  header = *(self->get(/header))
  return, header[0].ycen - header[0].naxis2*self->_image_scale_y()/2.
END


;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;      </overridden _ensure_properties help methods
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++




;; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;   <overridden extract_image and other plot_image help methods
;; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

FUNCTION spl2obs::extract_image, i, data, _extra=extra
  
  o = self
  
  data = *(o->get(/data))
  
  returndata = (n_params() EQ 2) ? 1 : 0
    
  o->_image_number_exist, i
  
  images = o->images_indices()
  
  im = data[*,*,i]
  IF returndata THEN data = im ELSE $
     im = o->_image_final_touch(im)
  
  return,im
END


PRO spl2obs::read_header
  self->read_data
END


PRO spl2obs::read_data, cleanup=cleanup
  o = self
  
  destdir = o->get(/destdir)
  lmsal_file = o->get(/lmsal_file) ;; SP Level 2 LMSAL URL based on Level 0 file name
  
  ;; Is the Level 2 file already downloaded from LMSAL?
  local_file = concat_dir(destdir, file_basename(lmsal_file))
  
  IF file_test(local_file) THEN read_sotsp, local_file, header, data ELSE BEGIN
     ;; The Level 2 file can't be found, download to destdir
     time = strmid(file_basename(lmsal_file),0,15)
     sotsp_stks2index, time, header, data, status=status, outdir=destdir,/level2
     IF ~status THEN message,'Level 2 file '+ file_basename(lmsal_file) +' not found at LMSAL.'

  ENDELSE
  
  o->set, data=ptr_new(data,/no_copy)
  o->set, header=ptr_new(header,/no_copy)
  
  
  default, cleanup, 0
END


FUNCTION spl2obs::_lmsal_file
  ;; Based on the Level 0 file name, find the Level 2 file name in the LMSAL
  ;; archive. For the time being the actual URL to the L2 file in this archive
  ;; isn't used, in spl2obs__define, we will use the base name only. But just
  ;; in case we'll return the full URL...
  
  self->private
  sdc_file = self->get(/file)
  date = strmid(sdc_file,stregex(sdc_file,'SP4D2')+4,15)
  y = strmid(date,0,4)
  m = strmid(date,4,2)
  d = strmid(date,6,2)
  base = 'http://sot.lmsal.com/data/sot/level2hao_new/'
  return, base + y + '/' + m + '/' + d + '/' + 'SP3D/' + date + '/' + $
               date+'.fits'
END

PRO spl2obs::downlaod_lmsal_file, lmsal_file, status, err
  ;;   N O T   I N   U S E ! !
  self->private
  http = obj_new('http')
  http->open,'sot.lmsal.com'
  IF http->file_found(lmsal_file, response, err=err) THEN $
     http->copy,lmsal_file, out_dir=o->get(/destdir), status=status, err=err ELSE $
        status = 0
  obj_destroy,http
  
END

FUNCTION spl2obs::images_indices
  header = *(self->get(/header))
  return,indgen((size(header))[1])
END

FUNCTION spl2obs::_color_table_txt, i, _extra=extra
  self->private
  title  = (*(self->get(/title)))[i]
  
  wanted_ct_txt = 'STOKESQUV'
  
  IF title EQ 'Doppler Shift of 630.15nm' OR title EQ 'Doppler Shift of 630.25nm' THEN $
     wanted_ct_txt = 'VELOCITY'
  IF title EQ 'Magnetic Field Azimuth' THEN wanted_ct_txt = 'RUFAZ'
  IF title EQ 'Continuum Intensity' THEN wanted_ct_txt = 'INTENSITY'
  return, wanted_ct_txt  
END


FUNCTION spl2obs::_image_final_touch, im
  self->private
  
  IF min(im) GE 0 THEN BEGIN 
     IF min(im) GT 0 THEN im = bytscl(sigrange(im),/nan) ELSE $
        im = self->_final_touch_mask0(im)
    
  ENDIF ELSE BEGIN
     im = self->_final_touch_bytscl(im)
     im = im > 1 < 254
  ENDELSE
  
  return, im
END


PRO spl2obs__define
  STR = ''
  d = {spl2obs, $
       lmsal_file: STR, $
       inherits spobs}
END
