; $Id: data_set__DEFINE.pro,v 1.6 2001/01/15 22:26:36 scottm Exp $
;
; Copyright (c) 2003, Max Planck Institute for Aeronomy
;	Unauthorized reproduction prohibited.
;+
; CLASS_NAME:
;	data_set
;
; PURPOSE:
;	The purpose of this routine is to implement a data_set Object class
;	as part of the Main Module. The Main Module is a component
;	of the MHD analysis Software as specified in
;	http://www.linmpi.mpg.de/~cheung/MHDGUI/SoftwareSpec.htm
;
; CATEGORY:
;	Main Module
;	
;
; SUPERCLASSES:
;       List classes this class inherits from.
;
; SUBCLASSES:
;       List classes that inherit from this class, if any.
;
; CREATION:
;       Note how an object of this class is created.
;       Generally, this is just a reference to the class'
;       Init method.
;
; METHODS:
;       List the methods intrinsic to this class. There is no
;       need to list the inherited methods.
;
; MODIFICATION HISTORY:
; 	Written by:	Mark Cheung, April 2003.
;			Any additional mods get described here.  Remember to
;			change the stuff above if you add a new keyword or
;			something!
;


FUNCTION data_set::axis, dir, index=index
   IF N_ElEMENTS(index) NE 1 THEN BEGIN
   case dir of
	'x': return, (*(self.xaxis_ptr))
	'y': return, (*(self.yaxis_ptr))
	'z': return, (*(self.zaxis_ptr))
	else: return, -1
   end
   ENDIF ELSE BEGIN
   case dir of
	'x': IF index LT N_ELEMENTS(*(self.xaxis_ptr)) THEN return, (*(self.xaxis_ptr))[index,*]
	'y': IF index LT N_ELEMENTS(*(self.yaxis_ptr)) THEN return, (*(self.yaxis_ptr))[index,*]
	'z': IF index LT N_ELEMENTS(*(self.zaxis_ptr)) THEN return, (*(self.zaxis_ptr))[index,*]
	else: return, -1
   end
   ENDELSE
   return, -1
END

FUNCTION data_set::coord, dir, index, z
   case dir of
	'x': IF index LT N_ELEMENTS(*(self.xaxis_ptr)) THEN return, (*(self.xaxis_ptr))[index,z]
	'y': IF index LT N_ELEMENTS(*(self.yaxis_ptr)) THEN return, (*(self.yaxis_ptr))[index,z]
	else: return, -1
   end
   return, -1
END


PRO data_set::LoadData, $
	filenames=filenames

Nfiles=N_ELEMENTS(filenames)
read_sot, filenames, index
Nx   = MAX(index.Naxis1)
Ny   = MAX(index.Naxis2)
Nz   = Nfiles
data = intarr(Nx,Ny,Nz)
xcen = index.xcen
ycen = index.ycen

FOR M=0,Nslices-1 DO BEGIN
   read_sot, filenames[m], index, slice
   slice_size = size(slice)
   nxslice = slice_size[1]
   nyslice = slice_size[2]
   CASE (index.obs_type)[0] OF
   'SP IQUV 4D array' : BEGIN
	IF M EQ 0 THEN BEGIN
   	   data2=data
	   data3=data
	   data4=data
	   variable_name[0] = "SOT: "+"Stokes I"
	   variable_name[1] = "SOT: "+"Stokes Q"
	   variable_name[2] = "SOT: "+"Stokes U"
	   variable_name[3] = "SOT: "+"Stokes V"
	ENDIF
	data[0:nxslice-1,0:nyslice-1,M]  = slice[0:nxslice-1,0:nyslice-1,0,0]
	data2[0:nxslice-1,0:nyslice-1,M] = slice[0:nxslice-1,0:nyslice-1,0,1]
	data3[0:nxslice-1,0:nyslice-1,M] = slice[0:nxslice-1,0:nyslice-1,0,2]
	data4[0:nxslice-1,0:nyslice-1,M] = slice[0:nxslice-1,0:nyslice-1,0,3]
   ENDCASE
   'FG shuttered I and V': BEGIN
	IF M EQ 0 THEN BEGIN
	   data2=data
	   variable_name[0] = "SOT: "+"Stokes I"
	   variable_name[1] = "SOT: "+"Stokes V"
	ENDIF
	data[0:nxslice-1,0:nyslice-1,M]  = slice[0:nxslice-1,0:nyslice-1,0]
	data2[0:nxslice-1,0:nyslice-1,M] = slice[0:nxslice-1,0:nyslice-1,1]
   ENDCASE
   'FG shutterless I and V': BEGIN
	IF M EQ 0 THEN BEGIN
	   data2 = data
	   variable_name[0] = "SOT: "+"Stokes I"
	   variable_name[1] = "SOT: "+"Stokes V"
	ENDIF
	data[0:nxslice-1,0:nyslice-1,M]  = slice[0:nxslice-1,0:nyslice-1,0]
	data2[0:nxslice-1,0:nyslice-1,M] = slice[0:nxslice-1,0:nyslice-1,1]
   ENDCASE 
   ELSE: BEGIN
	IF M EQ 0 THEN variable_name[0] = "SOT: "+wavelength[wave_index]
	data[0:nxslice-1,0:nyslice-1,M]  = slice[0:nxslice-1,0:nyslice-1]
   ENDCASE
   END
   deltax = float(this_index.fovx)/this_index.naxis1
   deltay = float(this_index.fovy)/this_index.naxis2
   xaxis[0:nxslice-1,M] = (findgen((size(data))[1])-(size(data))[1]/2)*deltax[M]+this_index.xcen[M]
   yaxis[0:nyslice-1,M] = (findgen((size(data))[2])-(size(data))[2]/2)*deltay[M]+this_index.ycen[M] 
ENDFOR

filenames = Ptr_New(filenames,/no_copy)
xaxis_ptr = Ptr_new(xaxis, /no_copy)
yaxis_ptr = Ptr_new(yaxis, /no_copy)
zaxis_ptr = Ptr_new(time_obs, /no_copy)

data_obj[0] = Obj_New("data_set", data_type=2, dir=dir, $
   filenames=filenames, vertex1=[0,0,0], vertex2=[Nx-1,Ny-1,Nz-1], $
   cube_size=[Nx,Ny,Nz], cube_ptr=PTR_NEW(data, /no_copy), axes_units = ["arcsec","arcsec","Time"], $
   xaxis_ptr=xaxis_ptr, yaxis_ptr=yaxis_ptr, zaxis_ptr=zaxis_ptr, variable_name=variable_name[0])

IF N_ELEMENTS(data2) NE 0 THEN BEGIN
   data_obj[1] = Obj_New("data_set", data_type=2, dir=dir, $
          filenames=filenames, vertex1=[0,0,0], vertex2=[Nx-1,Ny-1,Nz-1], $
          cube_size=[Nx,Ny,Nz], cube_ptr=Ptr_New(data2, /no_copy), axes_units = ["arcsec","arcsec","Time"], $
	  xaxis_ptr=xaxis_ptr, yaxis_ptr=yaxis_ptr, zaxis_ptr=zaxis_ptr, variable_name=variable_name[1])
ENDIF
IF N_ELEMENTS(data3) NE 0 THEN BEGIN
   data_obj[2] = Obj_New("data_set", data_type=2, dir=dir, $
          filenames=filenames, vertex1=[0,0,0], vertex2=[Nx-1,Ny-1,Nz-1], $
          cube_size=[Nx,Ny,Nz], cube_ptr=Ptr_New(data3, /no_copy), axes_units = ["arcsec","arcsec","Time"], $
	  xaxis_ptr=xaxis_ptr, yaxis_ptr=yaxis_ptr, zaxis_ptr=zaxis_ptr, variable_name=variable_name[2])
ENDIF
IF N_ELEMENTS(data4) NE 0 THEN BEGIN
   data_obj[3] = Obj_New("data_set", data_type=2, dir=dir, $
     	  filenames=filenames, vertex1=[0,0,0], vertex2=[Nx-1,Ny-1,Nz-1], $
          cube_size=[Nx,Ny,Nz], cube_ptr=Ptr_New(data4, /no_copy), axes_units = ["arcsec","arcsec","Time"], $
	  xaxis_ptr=xaxis_ptr, yaxis_ptr=yaxis_ptr, zaxis_ptr=zaxis_ptr, variable_name=variable_name[3])
ENDIF

okay_to_start_DW = 1

END


; METHODNAME:
;       data_set::GetProperty
;
; PURPOSE:
;	Retrive one or more property/ies of a data_set object
;
; CALLING SEQUENCE:
;	Obj->[Display_Window::]GetProperty, property=value
;
; INPUTS:
;	property: the property of the object to be returned
;
; OPTIONAL INPUTS:
;	Parm2:	Describe optional inputs here. If you don't have any, just
;		delete this section.
;	
; KEYWORD PARAMETERS:
;	KEY1:	Document keyword parameters like this. Note that the keyword
;		is shown in ALL CAPS!
;
;	KEY2:	Yet another keyword. Try to use the active, present tense
;		when describing your keywords.  For example, if this keyword
;		is just a set or unset flag, say something like:
;		"Set this keyword to use foobar subfloatation. The default
;		 is foobar superfloatation."
;
; OPTIONAL OUTPUTS:
;	Describe optional outputs here.  If the routine doesn't have any, 
;	just delete this section.
;
; COMMON BLOCKS:
;	BLOCK1:	Describe any common blocks here. If there are no COMMON
;		blocks, just delete this entry. Object methods probably
;               won't be using COMMON blocks.
;
; SIDE EFFECTS:
;	Describe "side effects" here.  There aren't any?  Well, just delete
;	this entry.
;
; RESTRICTIONS:
;	Describe any "restrictions" here.  Delete this section if there are
;	no important restrictions.
;
; PROCEDURE:
;	You can describe the foobar superfloatation method being used here.
;	You might not need this section for your routine.
;
; EXAMPLE:
;	The following example creates a Display_Window object named DW and retrives the
;	widget ID of the Display Window using the GetProperty function of this object.
;
;	cube_obj = Obj_New("data_set", parameters ...)
;	cube_obj->GetProperty, cube_ptr = cube_ptr
;	
; MODIFICATION HISTORY:
; 	Written by:	Mark Cheung, April 2003
;	April, 2003	Any additional mods get described here.  Remember to
;			change the stuff above if you add a new keyword or
;			something!

PRO data_set::GetProperty, $
	data_type=data_type, $
	cube_ptr=cube_ptr, $
	variable=variable, $
	variable_name = variable_name, $
	variable_object = variable_object, $
	minValue = minValue, $
	maxValue = maxValue, $
        colormin = colormin, $
	colormax = colormax, $
	filename = filename, $
	dir = dir, $
	nmod = nmod, $
	vertex1 = vertex1, $
	vertex2 = vertex2, $
	cube_size = cube_size, $
	unit = unit, $
	grid_ptr = grid_ptr, $
	axes_units = axes_units, $
	dx_vec = dx_vec, $
	cat_ptr= cat_ptr, $
	comments = comments, $
        filenames=filenames

;Error Handling
Catch, theError
IF theError NE 0 THEN BEGIN
   Catch, Cancel=1
   ok = Dialog_Message('Error in GetProperty Method. Returning...')
   Print, ''
   Print, 'data_set::GetProperty Method: ' + !Error_State.Msg
ENDIF

;Return the value of the self object

data_type= self.data_type
cube_ptr = self.cube_ptr
variable = self.variable
variable_name = self.variable_name
variable_object = self.variable_object
nmod = self.nmod
minValue = self.minValue
maxValue = self.maxValue
filename = self.filename
dir = self.dir
nmod = self.nmod
unit = self.unit
vertex1 = self.vertex1			; vertices defining sub-region
vertex2 = self.vertex2			;
cube_size = self.cube_size		;Size of cube in data file
grid_ptr = self.grid_ptr
axes_units = self.axes_units
dx_vec = self.dx_vec
comments = self.comments
colormin = self.colormin
colormax = self.colormax
cat_ptr = self.cat_ptr
filenames=self.filenames
END
;=======================================================================
; METHODNAME:
;       data_set::SetProperty
;
; PURPOSE:
;	Sets one or more property/ies of a data_set object
;
; CALLING SEQUENCE:
;	Obj->[Display_Window::]SetProperty, property=value
;
; INPUTS:
;	property: name of object attribute to set} More than one pair is allow
;	value: the value that property will store} for each call of this method.
;
; EXAMPLE:
;	The following example creates a Display_Window object named DW and retrives the
;	widget ID of the Display Window using the SetProperty function of this object.
;
;	cube_obj = Obj_New("data_set", parameters ...)
;	cube_obj->SetProperty, cube_ptr = cube_ptr
;	
; MODIFICATION HISTORY:
; 	Written by:	Mark Cheung, April 2003
;	April, 2003	Any additional mods get described here.  Remember to
;			change the stuff above if you add a new keyword or
;			something!

PRO data_set::SetProperty, $
	data_type=data_type, $
	cube_ptr=cube_ptr, $
	variable=variable, $
	variable_name = variable_name, $
	variable_object = variable_object, $
	minValue = minValue, $
	maxValue = maxValue, $
        colormin = colormin, $
        colormax = colormax, $
	filename = filename, $
	dir = dir, $
	nmod = nmod, $
	vertex1 = vertex1, $
	vertex2 = vertex2, $
	cube_size = cube_size, $
	unit = unit, $
	axes_units = axes_units, $
	dx_vec = dx_vec, $
	comments = comments

;Error Handling
Catch, theError
IF theError NE 0 THEN BEGIN
   Catch, Cancel=1
   ok = Dialog_Message('Error in SetProperty Method. Returning...')
   Print, ''
   Print, 'data_set::GetProperty Method: ' + !Error_State.Msg
ENDIF

;Return the value of the self object
IF N_ELEMENTS(data_type) NE 0 THEN self.data_type=data_type
IF N_ELEMENTS(cube_ptr) NE 0 THEN self.data_type=cube_ptr
IF N_ELEMENTS(variable) NE 0 THEN self.variable=variable
IF N_ELEMENTS(variable_name) NE 0 THEN self.variable_name=variable_name
IF N_ELEMENTS(variable_object) NE 0 THEN self.variable_object=variable_object
IF N_ELEMENTS(nmod) NE 0 THEN self.nmod=nmod
IF N_ELEMENTS(vertex1) NE 0 THEN self.vertex1=vertex1
IF N_ELEMENTS(vertex2) NE 0 THEN self.vertex2=vertex2
IF N_ELEMENTS(cube_size) NE 0 THEN self.cube_size=cube_size
IF N_ELEMENTS(unit) NE 0 THEN self.unit=unit
IF N_ELEMENTS(axes_units) EQ 3 THEN self.axes_units=axes_units
IF N_ELEMENTS(dx_vec) EQ 3 THEN self.dx_vec=dx_vec
IF N_ELEMENTS(comments) EQ 3 THEN self.comments=comments
IF N_ELEMENTS(colormin) NE 0 THEN self.colormin=colormin
IF N_ELEMENTS(colormax) NE 0 THEN self.colormax=colormax
END

FUNCTION data_set::INIT, $
	data_type=data_type, $		     	; Whether the data cube is a raw cube or custom cube
	cube_ptr=cube_ptr, $			; Pointer to the date sube
	variable = variable, $		        ; The variable stored in the cube (index)
	variable_name = variable_name, $	; Text describing variable
	variable_object = variable_object, $	; 
	nmod = nmod, $				; the time step in simulation
	minValue = minValue, $		    	; Global minimum of cube
	maxValue = maxValue, $		     	; Global maximum of cube
	dir = dir, $				; Directory in which the file is located
	filenames = filenames, $		; The filename of the 
	vertex1 = vertex1, $
	vertex2 = vertex2, $
	cube_size = cube_size, $
	unit = unit, $
	grid_ptr = grid_ptr, $
	dx_vec   = dx_vec, $
	axes_units=axes_units, $
	xaxis_ptr = xaxis_ptr, $
	yaxis_ptr = yaxis_ptr, $
	zaxis_ptr = zaxis_ptr, $
	cat_ptr = cat_ptr

;;Error Handling
;Catch, theError
;IF theError NE 0 THEN BEGIN
;   Catch, Cancel=1
;   ok = Dialog_Message('Error in INIT Method. Returning...')
;   Print, ''
;   Print, 'data_set::INIT Method: ' + !Error_State.Msg
;   RETURN, 0
;ENDIF

;Check keywords and define default values if not supplied.
IF N_Elements(data_type) EQ 0 THEN data_type = 0
IF N_Elements(variable) EQ 0 THEN variable = 0
IF N_Elements(variable_name) EQ 0 THEN variable_name = 'Default'
IF N_Elements(variable_object) EQ 0 THEN variable_object = Obj_New("variable_type")
IF N_Elements(maxValue) EQ 0 THEN maxValue = 0.
IF N_Elements(minValue) EQ 0 THEN minValue = 0.
IF N_Elements(dir) EQ 0 THEN dir = ''
IF N_Elements(filenames) EQ 0 THEN filenames = ' '
IF N_Elements(nmod) EQ 0 THEN nmod = ' '
IF N_Elements(vertex1) NE 3 THEN vertex1 = [0,0,0]
IF N_Elements(vertex2) NE 3 THEN vertex2 = [287,99,287]
self.cube_size = [N_ELEMENTS((*cube_ptr)[*,0,0]),N_ELEMENTS((*cube_ptr)[0,*,0]),N_ELEMENTS((*cube_ptr)[0,0,*])]
IF N_ELEMENTS(cube_ptr) EQ 0 THEN cube_ptr=Ptr_New()
IF N_ELEMENTS(unit) EQ 0 THEN unit=''
IF N_ELEMENTS(grid_ptr) EQ 0 THEN grid_ptr=Ptr_New()
IF N_ELEMENTS(dx_vec) EQ 0 THEN self.dx_vec = [1,1,1]
IF N_ELEMENTS(axes_units) EQ 0 THEN axes_units = ['km','km','km']
IF N_ELEMENTS(xaxis_ptr) EQ 0 THEN xaxis_ptr = Ptr_new(indgen(self.cube_size[0]), /no_copy)
IF N_ELEMENTS(yaxis_ptr) EQ 0 THEN yaxis_ptr = Ptr_new(indgen(self.cube_size[1]), /no_copy)
IF N_ELEMENTS(zaxis_ptr) EQ 0 THEN zaxis_ptr = Ptr_new(indgen(self.cube_size[2]), /no_copy)

IF (data_type EQ 1) THEN begin
   print, "get_custom_cube"
   cube_ptr = get_custom_cube_ptr(dir=dir, filename=filename, $
	variable_name="Custom", min=vertex1, max=vertex2, cube_size=cube_size)
ENDIF

;ELSE BEGIN
;   print, "get_standard_cube"
;   cube_ptr = get_raw_cube_ptr(dir=dir, $
;	variable_name=variable_name, min=vertex1, max=vertex2, cube_size=cube_size)
;ENDELSE

variable_object->GetProperty, unit=unit

;Store the object projects in the self object

self.data_type = data_type		; Whether the data cube is a raw cube or custom cube
					; Goto http://www.linmpi.mpg.de/~cheung/MHDGUI/SoftwareSpec.htm for details
self.cube_ptr = cube_ptr		; Pointer to the date sube
self.variable = variable		; The variable stored in the cube (index)
self.variable_name = variable_name	; Text describing variable
self.variable_object = variable_object	; variable_type object 
self.unit = unit			; Unit of measurement for variable.
self.dir = dir				; Directory in which the file is located
self.filenames = filenames		; The filename in which the data is stored
self.nmod = nmod			; The time step
self.vertex1 = vertex1
self.vertex2 = vertex2
self.cube_size = cube_size
self.maxValue = max(*cube_ptr)
self.minValue = min(*cube_ptr)
self.colormin = self.minValue
self.colormax = self.maxValue
self.xaxis_ptr= xaxis_ptr
self.yaxis_ptr= yaxis_ptr
self.zaxis_ptr= zaxis_ptr
self.cat_ptr  = cat_ptr
self.axes_units=axes_units
RETURN, 1
END

PRO data_set__DEFINE

struct = { data_set, $		     	; The Display_Window object class definition
	data_type: 0, $		     	; Whether the data cube is a raw cube (0) or custom cube (1)
	$				; Goto http://www.linmpi.mpg.de/~cheung/MHDGUI/SoftwareSpec.htm for details
	cube_ptr: Ptr_New(), $		; Pointer to the date sube
	variable: 0, $		        ; The variable stored in the cube (index)
	variable_name: '', $		; Text describing variable
	variable_object: Obj_New(), $	; Object of type variable_type
	unit:'', $			; The units of the variable e.g. K for temp
	minValue: 0., $		    	; Global minimum of cube
	maxValue: 0., $		     	; Global maximum of cube
	colormin: 0., $		    	; User-defined min for color range
	colormax: 0., $		     	; User-defined max for color range
	dir: '', $			; Directory in which the file is located
	filename: '', $			; The filename in which the data is stored
	nmod: '', $			; The time step
	vertex1 : intarr(3), $		; The vertex of subcube
	vertex2 : intarr(3), $		; The two vertices define the subcube boundary
	cube_size : intarr(3),$		; The size of data cube stored in the file
	filenames : Ptr_New(),$         ; List of filenames, if applicable
	grid_ptr : Ptr_New(), $		; The pointer to a grid array for custom profiles, if it exists. 
	axes_units: strarr(3),$		; Array of strings describing axes units.
        xaxis_ptr: Ptr_New(),$
	yaxis_ptr: Ptr_New(),$
	zaxis_ptr: Ptr_New(),$
	cat_ptr: Ptr_New(),$
	dx_vec: fltarr(3), $		; The real distance between adjacent pixels in the 3 dims.
	comments: '' $			; Any comments about this cube.
	}
END
;--------------------------------------------------------------------------------------------------------
