%MISFIT class definition
%
%   Usage:
%      misfit=misfit();
%      misfit=misfit('name','SurfaceAltimetry',...
%                    'model_enum',SurfaceEnum,...
%                    'observation_enum',SurfaceObservationsEnum,...
%                    'observation',md.geometry.surface,...
%                    'timeinterpolation','nearestneighbor',...
%                    'weights',ones(md.mesh.numberofvertices,1),...
%                    'weights_enum',WeightsSurfaceObservationsEnum);
%
%

classdef misfit
	properties (SetAccess=public)
		%misfit
		name              = '';
		model_enum        = NaN; %enum for field that is modeled
		observation       = NaN; %observed field that we compare the model against
		observation_enum  = NaN; %enum for observed field.
		timeinterpolation = '';
		weights           = NaN; %weight coefficients for every vertex
		weights_enum      = NaN; %enum to identify this particular set of weights
		cumulated         = NaN; %do we cumulate misfit through time?
	end
	
	methods
		function obj = misfit(varargin) % {{{
			if nargin==0,
				obj=setdefaultparameters(obj);
			else
				%use provided options to change fields
				options=pairoptions(varargin{:});

				%get name
				obj.name=getfieldvalue(options,'name','');
				obj.model_enum=getfieldvalue(options,'model_enum');
				obj.observation=getfieldvalue(options,'observation',NaN);
				obj.observation_enum=getfieldvalue(options,'observation_enum');
				obj.timeinterpolation=getfieldvalue(options,'timeinterpolation','nearestneighbor');
				obj.weights=getfieldvalue(options,'weights',NaN);
				obj.weights_enum=getfieldvalue(options,'weights_enum',NaN);

			end
		end % }}}
		function obj = setdefaultparameters(obj) % {{{
			obj.timeinterpolation='nearestneighbor';
		end % }}}
		function md = checkconsistency(obj,md,solution,analyses) % {{{

			if ~ischar(obj.name),
				error('misfit error message: ''name'' field should be a string!');
			end

			if ~ischar(obj.timeinterpolation),
				error('misfit error message: ''timeinterpolation'' field should be a string!');
			end
			md = checkfield(md,'fieldname','obj.observation','field',obj.observation,'forcing',1,'NaN',1);
			md = checkfield(md,'fieldname','obj.timeinterpolation','field',obj.timeinterpolation,'values',{'nearestneighbor'});
			md = checkfield(md,'fieldname','obj.weights','field',obj.weights,'forcing',1,'NaN',1);

		end % }}}
		function md = disp(obj) % {{{
		
			disp(sprintf('   Misfit:\n'));

			fielddisplay(obj,'name','identifier for this misfit response');
			fielddisplay(obj,'model_enum','enum for field that is modeled');
			fielddisplay(obj,'observation','observed field that we compare the model against');
			fielddisplay(obj,'observation_enum','observation enum');
			fielddisplay(obj,'timeinterpolation','interpolation routine used to interpolate misfit between two time steps (default is ''nearestneighbor''');
			fielddisplay(obj,'weights','weights (at vertices) to apply to the misfit');
			fielddisplay(obj,'weights_enum','enum for weights for identification purposes');

		end % }}}
		function md = marshall(obj,md,fid) % {{{

		WriteData(fid,'object',obj,'fieldname','name','format','String');
		WriteData(fid,'object',obj,'fieldname','model_enum','format','Integer');
		WriteData(fid,'object',obj,'fieldname','observation','format','DoubleMat','mattype',1,'forcinglength',md.mesh.numberofvertices+1);
		WriteData(fid,'object',obj,'fieldname','observation_enum','format','Integer');
		WriteData(fid,'object',obj,'fieldname','timeinterpolation','format','String');
		WriteData(fid,'object',obj,'fieldname','weights','format','DoubleMat','mattype',1,'forcinglength',md.mesh.numberofvertices+1);
		WriteData(fid,'object',obj,'fieldname','weights_enum','format','Integer');

		end % }}}
	end
end
