;+
; NAME: sp1dobs__define
;
;
;
; PURPOSE: Definition of the sp1d (SOT/SP level 1D observation) class, a
;          subclass of sotobs, which is a subclass of hinobs, which again is a
;          subclass of anyobs. Please note that sp1dobs differs significantly
;          from the other subclasses of hinobs (eisobs, sotobs and xrtobs),
;          since a sp1dobs object is a SP scan built up of several hundred
;          (typically 512 or 1024) individual files. The data and header of a
;          sp1dobs object are pointers to the output from sp_prep et al, _not_
;          the actual header or data in individual fits files. ::plot_image
;          will display an image only if the file given as input is part of a
;          scan. ::extract_data(/all) will return the data contents of the
;          input fits file if the file is not a part of the scan.
;
;
;
;                                           (sdc_util)
;                                              |
;                                            anyobs
;                                          /       \
;                                    hinobs         irisobs
;                                  /   |   \ 
;                            xrtobs  sotobs eisobs
;                                     /  \
;                              sp1dobs    spl2obs
;
;
;
; METHODS: See spobs__define, hinobs__define and anyobs__define
;
;
;
; COMMON BLOCKS: none
;
;
;
; WRITTEN: Terje Fredvik, UiO, January 2008
;
;
;
;
; MODIFICATION HISTORY:
;          1. Sep 2010 Terje Fredvik: Removed old modification history.
;          1. Sep 2010 Terje Fredvik: Rewrote ::read_data to find all fits
;                                     files that belong to the scan of the
;                                     input file. 
;          7. Sep 2010 Terje Fredvik: # Added method ::extract_header.
;                                     # ::extract_image: added input parameter
;                                     data to  to make ::extract_data work.
;                                     # ::read_data: added keyword CLEANUP,
;                                     delete temporary files if set (set by default)
;                                     # Change name of sp1dfile IDL save file
;         11. Feb 2011 Terje Fredvik: # sp1dobs is now a subclass of spobs.
;         11. Apr 2013 Terje Fredvik: added info about new superclass anyobs
;         06. Mar 2015 Terje Fredvik: Minor re-structuring of ::read_data
;         09. Mar 2015 Terje Fredvik: Try to download L1D file from LMSAL 3
;                                     times before giving up and run sp_prep
;                                     instead. Download first, middle and last
;                                     L0 file of scan initially, download the
;                                     rest if sp_prep must be run.
;         12. Mar 2015 Terje Fredvik: Try downloading L1D file once from
;                                     LMSAL, if it fails try to process L0
;                                     files loally, if this fails (without
;                                     crashing) try downloading L1D file from 
;                                     LMSAL a final time.
;         27. Mar 2015 Terje Fredvik: First try downloading L1D file from
;                                     Oslo, then LMSAL, then process L0 files
;                                     and then finally try downloading from
;                                     LMSAL one final time. If file doesn't
;                                     belong to a scan, do not set data and
;                                     header tags.
;-

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


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



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

PRO sp1dobs::_ensure_instrume
  self->private
  header = *(self->get(/header))
  self.instrume = trim(gt_fkw(reform(header[0,*]),'INSTRUME'))
END

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



PRO sp1dobs::_ensure_title
  o = self
  o->private
  nicons = o->get(/nicons)
  data = *(o->get(/data))
  o.title = ptr_new(strarr(nicons))
  images = o->images_indices()
  FOR i=0,nicons-1 DO BEGIN
     abbrev = (tag_names(data))[images[i]]
     CASE abbrev OF 
        ;; From  $SSW/hinode/sot/idl/sp/util/stksimages_sbsp.pro
        'BTAPP'   : title = 'Transverse apparent flux density'                ;0
        'BLAPP'   : title = 'Longitudinal apparent flux density'              ;1
        'CONTI'	  : title = 'Continuum intensity'                             ;2
        'CTRLINE' : title = 'Velocity (6301.5 Å)'                             ;3
	'DCLNTN'  : title = 'Solar declination'                               ;4
	'MUVAL'	  : title = 'Cosine of heliocentric angle'                    ;5
	'PII'	  : title = 'Stokes I integrated over lines/conti'            ;6
	'PLC'	  : title = 'SQRT(Q!u2!n+U!u2!n) integrated over CONTINUUM/conti'
	'PLL'     : title = 'SQRT(Q!u2!n+U!u2!n) integrated over lines/conti' ;8
	'POLNET'  : title = 'Measure of linear polarization'                  ;9
	'PQ'	  : title = 'Stokes Q integrated over lines/conti'            ;10
	'PTOT'    : title = 'SQRT(Q!u2!n+U!u2!n+V!u2!N) integrated over lines/conti'
	'PU'	  : title = 'Stokes U integrated over lines/conti'            ;12
	'PV'	  : title = 'Stokes V integrated over lines/conti'            ;13
	'RGTASN'  : title = 'Solar right ascension, arcsec W of disk center'  ;14
        'RUFAZ'	  : title = 'Rough guess for field azimuth angle'             ;15
	'SLAT'	  : title = 'Solar latitude (carrington) degrees'             ;17
	'SLONG'	  : title = 'Solar longitude (carrington) degrees (from CM)'  ;18
	'UTIMED'  : title = 'Universal time from start of day, fractional hours'
        ELSE:title = abbrev
     ENDCASE
     (*o.title)[i] = title
  ENDFOR
END

FUNCTION sp1dobs::_image_scale_x
  self->private
  header =  *(self->get(/header))
  nexp = self->get(/nexp)
  return, (gt_fkw(reform(header[2,*]),'xcen') - $
           gt_fkw(reform(header[0,*]),'xcen'))/(nexp-1)
END

FUNCTION sp1dobs::_image_scale_y
  self->private
  header =  *(self->get(/header))
  ;; if FOVY is from first to last pixel centre, must subtract 1 from naxis2
  return, gt_fkw(reform(header[0,*]),'fovy')/$
                 (gt_fkw(reform(header[0,*]),'naxis2')-1.)
END

FUNCTION sp1dobs::_image_origin_x ; Overridden in eisobs__define
  self->private
  header = *(self->get(/header))
  return, gt_fkw(reform(header[0,*]),'xcen')
END

FUNCTION sp1dobs::_image_origin_y  ; Overridden in eisobs__define
  self->private
  header = *(self->get(/header))
  return, gt_fkw(reform(header[0,*]),'ycen') - $
          gt_fkw(reform(header[0,*]),'fovy')/2.
END

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



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

FUNCTION sp1dobs::_data_products_wanted
  ;  The contents of the data structure *(o->get(/data)) with corresponding indices:
;     0     AVCTR           FLOAT     Array[1024]
;     1     BLAPP           FLOAT     Array[1024, 512]
;     2     BTAPP           FLOAT     Array[1024, 512]
;     3     CONTI           FLOAT     Array[1024, 512]
;     4     CTRLINE         FLOAT     Array[1024, 512, 2]
;     5     DCLNTN          FLOAT     Array[1024, 512]
;     6     DOPCV           FLOAT     Array[1024]
;     7     DTHRM           FLOAT     Array[1024]
;     8     FITAV           FLOAT     Array[1024]
;     9     FITSP           FLOAT     Array[1024]
;    10     FITWW           FLOAT     Array[1024]
;    11     FTIME           FLOAT     Array[1024]
;    12     MUVAL           FLOAT     Array[1024, 512]
;    13     PII             FLOAT     Array[1024, 512]
;    14     PLC             FLOAT     Array[1024, 512]
;    15     PLL             FLOAT     Array[1024, 512]
;    16     POLNET          FLOAT     Array[1024, 512]
;    17     PQ              FLOAT     Array[1024, 512]
;    18     PTOT            FLOAT     Array[1024, 512]
;    19     PU              FLOAT     Array[1024, 512]
;    20     PV              FLOAT     Array[1024, 512]
;    21     RGTASN          FLOAT     Array[1024, 512]
;    22     RUFAZ           FLOAT     Array[1024, 512]
;    23     SCATLP          DOUBLE    Array[112]
;    24     SLAT            FLOAT     Array[1024, 512]
;    25     SLONG           FLOAT     Array[1024, 512]
;    26     SLTDR           FLOAT     Array[1024]
;    27     SPCDR           FLOAT     Array[1024]
;    28     TEMPF           FLOAT     Array[1024]
;    29     UTIMED          FLOAT     Array[1024, 512]
;    30     VCS             FLOAT     Array[1024, 512, 2]
;    31     WDELW           FLOAT     Array[1024]            
;; We want plot_image to try to plot 2D images only. Return the indices of
;; these arrays: return, [1,2,3,5,12,13,14,15,16,17,18,19,20,21,22,24,25,29]
;; Nah, it's not that easy. I don't know if the number of tags in the savefile
;; that this list is based on is constant. Actually I know that it is NOT:
;; stksimages_sbsp got changed while I was working on this procedure, and
;; suddenly the DTHRM tag was gone, and all my indices GT 7 where
;; wrong... Instead I find the indices of the 2D images by searching for the
;: tag name:
  
   ;; These are the names of ALL 2D arrays (plus CTRLINE which is 3D (one 2D
  ;; image for each line)) in the data structure (I assume that none of these
  ;; arrays are removed from the data structure)
  self->private
  return,  ['BLAPP', 'BTAPP', 'CONTI', 'CTRLINE', 'DCLNTN', 'MUVAL', 'PII', 'PLC',$
            'PLL', 'POLNET', 'PQ', 'PTOT', 'PU', 'PV', 'RGTASN', 'RUFAZ', 'SLAT', $
            'SLONG', 'UTIMED']
END


FUNCTION sp1dobs::_data_products_all
  self->private
  return,tag_names(*(self->get(/data)))
END



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

FUNCTION sp1dobs::extract_image, i, data, _extra=extra
  o = self
  
  data = *(o->get(/data))
  
  IF ~o->get(/scan) THEN BEGIN 
     message,'The file ' + prune_filename(o->get(/file)) + $
             ' is not a part of a scan. Returning.',/info
     return,-1
  ENDIF
  
  returndata = (n_params() EQ 2) ? 1 : 0
    
  o->_image_number_exist, i
  
  images = o->images_indices()
  
  im = data.(images[i])
  IF returndata THEN data = im ELSE $
     im = o->_image_final_touch(im)
  
  return,im
END


FUNCTION sp1dobs::images_indices

;  The contents of the data structure *(o->get(/data)) with corresponding indices:
;     0     AVCTR           FLOAT     Array[1024]
;     1     BLAPP           FLOAT     Array[1024, 512]
;     2     BTAPP           FLOAT     Array[1024, 512]
;     3     CONTI           FLOAT     Array[1024, 512]
;     4     CTRLINE         FLOAT     Array[1024, 512, 2]
;     5     DCLNTN          FLOAT     Array[1024, 512]
;     6     DOPCV           FLOAT     Array[1024]
;     7     DTHRM           FLOAT     Array[1024]
;     8     FITAV           FLOAT     Array[1024]
;     9     FITSP           FLOAT     Array[1024]
;    10     FITWW           FLOAT     Array[1024]
;    11     FTIME           FLOAT     Array[1024]
;    12     MUVAL           FLOAT     Array[1024, 512]
;    13     PII             FLOAT     Array[1024, 512]
;    14     PLC             FLOAT     Array[1024, 512]
;    15     PLL             FLOAT     Array[1024, 512]
;    16     POLNET          FLOAT     Array[1024, 512]
;    17     PQ              FLOAT     Array[1024, 512]
;    18     PTOT            FLOAT     Array[1024, 512]
;    19     PU              FLOAT     Array[1024, 512]
;    20     PV              FLOAT     Array[1024, 512]
;    21     RGTASN          FLOAT     Array[1024, 512]
;    22     RUFAZ           FLOAT     Array[1024, 512]
;    23     SCATLP          DOUBLE    Array[112]
;    24     SLAT            FLOAT     Array[1024, 512]
;    25     SLONG           FLOAT     Array[1024, 512]
;    26     SLTDR           FLOAT     Array[1024]
;    27     SPCDR           FLOAT     Array[1024]
;    28     TEMPF           FLOAT     Array[1024]
;    29     UTIMED          FLOAT     Array[1024, 512]
;    30     VCS             FLOAT     Array[1024, 512, 2]
;    31     WDELW           FLOAT     Array[1024]            
;; We want plot_image to try to plot 2D images only. Return the indices of
;; these arrays: return, [1,2,3,5,12,13,14,15,16,17,18,19,20,21,22,24,25,29]
;; Nah, it's not that easy. I don't know if the number of tags in the savefile
;; that this list is based on is constant. Actually I know that it is NOT:
;; stksimages_sbsp got changed while I was working on this procedure, and
;; suddenly the DTHRM tag was gone, and all my indices GT 7 where
;; wrong... Instead I find the indices of the 2D images by searching for the
;: tag name:
  
  ;; These are the names of ALL 2D arrays (plus CTRLINE which is 3D (one 2D
  ;; image for each line)) in the data structure (I assume that none of these
  ;; arrays are removed from the data structure)
  abbrev = ['BLAPP', 'BTAPP', 'CONTI', 'CTRLINE', 'DCLNTN', 'MUVAL', 'PII', 'PLC',$
            'PLL', 'POLNET', 'PQ', 'PTOT', 'PU', 'PV', 'RGTASN', 'RUFAZ', 'SLAT', $
            'SLONG', 'UTIMED']
  n = n_elements(abbrev)
  indices = intarr(n)
  
  ;; Here all the 2D images I want
  tags = tag_names(*(self->get(/data)))
  
  ;; Find the correct indices
  FOR i=0,n-1 DO indices[i] = where(tags EQ abbrev[i])
     
  return, indices
  
END


PRO sp1dobs::_cenAndfov, xcen, ycen, fovx, fovy
  self->private
  
  header =  *(self->get(/header))
  xcen = gt_fkw(reform(header[1,*]), 'XCEN')
  ycen = gt_fkw(reform(header[0,*]), 'YCEN')
  fovx = gt_fkw(reform(header[2,*]), 'XCEN')-gt_fkw(reform(header[0,*]), 'XCEN')+$
         gt_fkw(reform(header[0,*]), 'FOVX')
  fovy = gt_fkw(reform(header[0,*]), 'FOVY')
END

FUNCTION sp1dobs::_image_final_touch, im
  self->private
  ;; If 3D array: CTRLINE - pixel of minimum intensity for 6301.5, 6302.5. We
  ;;              follow the webpages of LMSAL and choose the 6301.5 line
  ctrline = ((size(im))[0] EQ 3) ? 1 : 0
  IF ctrline THEN BEGIN
     im = reform(im[*,*,0])
     
     ;; The pixel of minimum intensity _must_ be between 0 and NAXIS1, NAXIS1
     ;; being 112 in all SOT/SP files in the archive as of April 7 2008. Some
     ;; values stored in the array are extreme and unphysical (e.g. -1e15) and
     ;; messes up sigrange; they must be removed!
     im = im > 0 < 112 
     
     offlimb = where(im EQ 0, nofflimb, complement=ondisc, ncomplement=nondisc)
     IF nondisc GT 0 THEN im -= median(im[ondisc])
     IF nofflimb GT 0 THEN im[offlimb] = 0
    ENDIF
  
  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)
     IF ctrline THEN BEGIN 
        im = im > 1 < 254
        IF nofflimb GT 0 THEN im[offlimb] = 0
     ENDIF
  ENDELSE
  
  return, im
END


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


;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++
;              <_color_table and help methods>
;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++
FUNCTION sp1dobs::_color_table_txt, i, _extra=extra
  self->private
  images = self->images_indices()
  data = *(self->get(/data))
  abbrev = (tag_names(data))[images[i]]
  
  wanted_ct_txt = 'STOKESQUV'
  IF abbrev EQ 'CONTI' OR abbrev EQ 'PII' THEN wanted_ct_txt = 'INTENSITY'
  IF abbrev EQ 'RUFAZ' THEN wanted_ct_txt = 'RUFAZ'
  IF abbrev EQ 'CTRLINE' THEN wanted_ct_txt = 'VELOCITY'
  
  RETURN, wanted_ct_txt
END
;; ------------------------------------------------------
;             </_color_table and help methods>
;; ------------------------------------------------------

PRO sp1dobs::read_header
  self->read_data
END


PRO sp1dobs::read_data, cleanup=cleanup
  o = self
  
  default, cleanup, 1
  
  
  
  self->set, scan=1
  
  fullfilename = o->get(/file)
  
  openr,lun,fullfilename,/get_lun,/compress
  fxhread, lun, hdr
  free_lun,lun
  
  filename = prune_filename(fullfilename)
  
  destdir = o->get(/destdir)
  
  sp1dfile = destdir + $
             'sp1d_'+strmid(gt_fkw(hdr,'DATE_OBS'),0,10) +$
             '_macroid'+trim(gt_fkw(hdr,'MACROID'))+'.save'
  
  IF file_test(sp1dfile) THEN $
     print,destdir+' Already prepped, skipping downloading from LMSAL/sp_prep.'$
  ELSE BEGIN
     ;; We don't have the level1D structure. We must download it from LMSAL or
     ;; create it. 
    
     ;; Find all files belonging to the scan, and some header info
     files = o->_gt_scanfiles(filename)
     nfiles =  n_elements(files) 
     
     headers = o->_gt_scanheaders(files) ;; Contains the header of the first, middle and last file in scan
     leadfile = prune_filename(files[0])
     
     IF nfiles GT 1 THEN BEGIN
        ;; This is a scan

        ;; 1) Try to download the level1D structure from the Oslo archive
        mapID = time2file(gt_fkw(reform(headers[0,*]),'date_obs'),/sec) 
        osdc_fs = getenv("OSDC_FS")
        IF osdc_fs EQ '' THEN osdc_fs = 'sdc.uio.no'
        oslo_url = 'http://'+osdc_fs+'/vol/fits/hao/level1/'
        stokes = sotsp_stks2struct(mapID, http_parent = oslo_url,/complete_path) 
        
        ;; 2) Try to download the level1D structure from LMSAL if downloading
        ;; from Oslo failed
        IF NOT is_struct(stokes) THEN BEGIN
           print,'SOT/SP Level1D file not found in the Oslo archive. Trying LMSAL.'
           stokes = sotsp_stks2struct(mapID,/no_delete)
        ENDIF 
        
        IF NOT is_struct(stokes) THEN BEGIN 
           print,'SOT/SP Level1D file not found at LMSAL. Trying to process L0 files.'    
           ;; 3) The level1D structure wasn't found in Oslo nor at LMSAL; let's create one!
           ;; Check if the files already have been prepped (simple check; check
           ;; if the number of (prepped) fits files stored in destdir is equal to
           ;; nfiles), create stksimg.save file and stokes structure
           prepped_files = find_files('SP3D*.fits',destdir)
           thermdrift_files = find_files('*thermdrift.save', destdir)
           thermdriftOK = (thermdrift_files[0] NE '') ? 1 : 0
           IF thermdriftOK AND n_elements(prepped_files) EQ nfiles THEN $
              stksimages_sbsp, destdir, stokes, $ 
                               outdir=destdir $   
           ELSE BEGIN 
              ;; 3) The number of level1D fits files didn't match nfiles or
              ;; thermdrift.save wasn't found, so let's do all the dirty work
              ;; ourselves and run sp_prep. 
              ;; First we need to download all level 0 files of the scan (the 
              ;; previous call to ::_gt_scanfiles() only downloaded the first, 
              ;; middle and last file of the scan for header creation purposes)
              files = o->_gt_scanfiles(filename,/fetch_all)
              
              ;; Now that the files are in place, run sp_prep:
              sp_prep, files, outdir=destdir, /quiet
              ;; Create level1D structure based on stksimg.save output from
              ;; sp_prep
              stokes_file = concat_dir(destdir, 'stksimg.save')
              ;; If-test to avoid IDL core dump??
              IF NOT file_test(stokes_file,/read) THEN message,'Ugh... core dump?'
              stokes = ssw_save2struct(stokes_file)
           ENDELSE
        ENDIF
        
        IF NOT is_struct(stokes) THEN BEGIN
           ;; Downloading from Oslo failed, downloading from LMSAL failed,
           ;; processing of L0 file also failed. Try downloading from LMSAL
           ;; one final time before giving up.
           print,'Downloading of L1D file and L0 processing failed. Final try LMSAL'
           mapID = time2file(gt_fkw(reform(headers[0,*]),'date_obs'),/sec)  
           stokes = sotsp_stks2struct(mapID) 
        ENDIF 
           
        IF NOT is_struct(stokes) THEN message,'Argh... could neither download L1D from Oslo/LMSAL nor process L0 files locally. Giving up.'
        ;;Delete preliminary fits files created by sp_prep/downloaded from
        ;;lmsal (unless keepfits set):
        IF NOT keyword_set(keepfits) THEN BEGIN
           prelimfits = file_search(destdir +'*.fits')
           IF prelimfits[0] NE '' THEN $
              file_delete,prelimfits,/allow_nonexistent
        ENDIF
        
     ENDIF ELSE BEGIN
        self->set, scan=0
        ;; The file doesn't belong to a scan. Read the contents of the single
        ;; fits file. Do not use self->set to set the data and header, since
        ;; this requires the data and the header to be fetched from a sp1dfile
        ;; save file!
        message,'The file '+filename+' does not belong to a scan',/info
        self.data = ptr_new(-1)
        self.header = ptr_new(-1)
        return
     ENDELSE
    
     IF self->get(/scan) THEN BEGIN 
        ensure_dir, destdir
        save,file=sp1dfile, stokes, headers, leadfile,/compress
        IF keyword_set(cleanup) THEN BEGIN
           ;; Delete temp files that have been created or downloaded:
           
           ;; Delete files that have been created if sp_prep has been run locally
           thermdriftfiles = file_search(destdir+'*thermdrift.save') 
           IF thermdriftfiles[0] NE '' THEN $
              file_delete,thermdriftfiles,/allow_nonexistent
           
           IF n_elements(stokes_file) EQ 1 AND NOT is_string(stokes_file) THEN $
              message,/info,"*** File "+sp1dfile $
                      +" involved in stokes_file variable anomaly"
           
           ;; Delete L1D file downloaded from LMSAL:
           IF n_elements(stokes_file) EQ 1 AND is_string(stokes_file) THEN $
              file_delete,stokes_file,/allow_nonexistent
           
           ;;Delete preliminary fits files created by sp_prep/downloaded from
           ;;lmsal:
           prelimfits = file_search(destdir+'*.fits')
           IF prelimfits[0] NE '' THEN $
              file_delete,prelimfits,/allow_nonexistent
        END
     ENDIF
     
  ENDELSE
  
  IF self->get(/scan) THEN BEGIN 
     self->set, file=sp1dfile
     
     restore, self.file
     data = stokes
     header = headers
  ENDIF
  
  IF ptr_valid(self.header) THEN ptr_free, self.header
  self->set, data=ptr_new(data,/no_copy)
  self->set, header=ptr_new(header,/no_copy)
  self->set, leadfile=leadfile
END



FUNCTION sp1dobs::_gt_scanfiles, file, fetch_all=fetch_all
  self->private
  
  ;;+ 
  ;; Find all SOT/SP files that belongs to the same scan as the input
  ;; file. Fetch all files if keyword fetch_all is set, if not fetch only
  ;; first, middle and last file of the scan. 
  ;; NOTE: The input file name should be without path or suffixes!  
  ;;-
  
  ;; Find all files which has the sq_study_seq of the input file, return file 
  ;; paths to caller
  
  o=obj_new('osdc')
  o->limit,0
  o->condition,'SQ_STUDY_SEQ: '+ file
  o->condition,'anon: y'  ;; Prevents filling of cache space
  o->order,''
  o->search,out
  
  paths = o->paths(out,fetch=fetch_all) ;; paths is always returned
  paths = paths[sort(paths)] ;; b/c order in query is blank in order not to crash backup server!
     
  obj_destroy,o
  
  IF NOT keyword_set(fetch_all) THEN BEGIN 
     ;; We don't download all L0 files (since we're trying to download the
     ;; L1D-file from LMSAL first). However, we need the first, middle and
     ;; last file when we'll create the sot/sp object's header. We still need
     ;; to return the paths of all files to caller
     ind = [0, n_elements(paths)/2.,n_elements(paths)-1]
     hpaths = prune_filename(paths[ind])
         
     o=obj_new('osdc')
     o->condition,'anon: y'  ;; Prevents filling of cache space
     o->condition,'FILE: ,'+hpaths[0]+','+hpaths[1]+','+hpaths[2]
     o->order,''
     o->search,out
     dummypaths = o->paths(out,/fetch) ;; Download three files, dummypaths isn't returned to caller
     
     obj_destroy, o
  ENDIF
  
  
  return, paths
  
END


FUNCTION sp1dobs::_gt_scanheaders, files
  self->private
  ;;+
  ;;   Return the header of the first, middle and last of the files in the input
  ;;   array
  ;;-
  
  dir = getenv('HINODE_DATA')+'/sot/level0/'
  
  ind = [0, n_elements(files)/2.,n_elements(files)-1]

  openr,lun,files[ind[0]],/get_lun,/compres
  fxhread, lun, hdr
  free_lun, lun

  ;; Due to errors the number of structure tags in the headers of the files in a single scan may differ. Let's
  ;; allow the biggest header of the scan to be 20 elements bigger than the
  ;; header of the first file.
  headers = strarr(3, n_elements(hdr)+20)
  headers[0,0:n_elements(hdr)-1] = hdr
     
  FOR i=1,n_elements(ind)-1 DO BEGIN
     openr,lun,files[ind[i]],/get_lun,/compres
     fxhread, lun, hdr
     headers[i,0:n_elements(hdr)-1] = hdr
     free_lun,lun
  ENDFOR
  
  return, headers
END

FUNCTION sp1dobs::extract_header
  return, reform((*(self->get_header()))[0,*])
END


PRO sp1dobs__define
  INT = 0
  STR = ''
  d = {sp1dobs, $
       leadfile: STR, $
       scan: INT, $
       inherits spobs}
END
