function output=charge_VARS(ROVdive,liste_concepts,varargin)

% CHARGE_VARS : récupère des données à partir de VARS et d'une query SQL. 
% Renvoie [] s'il y a moins de 3 standard depths pour le ROVdive, sinon un obj_intTS avec 0 si aucune annotation n'est trouvée, NaN pour les depths non sampled.
% Note que ROVdive est en référence au numéro dans la midwater table, qui peut être faux (on ne query pas dessus, c'est juste pour référence).
%
% output=charge_VARS(ROVdive,liste_concepts,varargin)				 % (si liste_concepts={}, renvoie toutes les annotations trouvées dans VARS)
% sql=charge_VARS(ROVdive,liste_concepts,'sql')
% 
% 'outputdiff' (implique speciesRob) 	renvoie la différence entre cette fonction et les données de Rob, au lieu des données
% 'speciesRob'									renvoie une table avec les mêmes espèces que la table de Rob (au lieu du défaut présent dans VARS - mettre liste_concepts à {})
% 'depth'										pour ne charger que certaines profondeurs
% 'nofiltredepth'								pour supprimer le filtrage des mauvaises profondeurs (cf problèmes time dans VARS) pour être consistent avec Rob's table
% 'noquantity'									pour ne pas prendre en compte les flag population-quantity
% 'silent'
% 'plot'											figure du profil w/ depths et profondeurs aberrantes
%
% Monique, octobre 2014, MBARI
% mars 2015 : gérage population-quantity & volume manuel


global rep_heckel_global
[arg,flag]=read_varargin(varargin,{'depth',[50 100:100:1000]},{'outputdiff','speciesRob','silent','nofiltredepth','noquantity','plot','sql'});
arg.depth=reshape_col(arg.depth); 



% -------------- input

if nargin<2, liste_concepts={}; 
elseif ischar(liste_concepts) && strcmp(liste_concepts,'speciesRob'), liste_concepts={}; varargin=[varargin,{'speciesRob'}];
else if ~iscell(liste_concepts), liste_concepts={liste_concepts}; end 
	liste_concepts=reshape_ligne(liste_concepts); 
end
if flag.speciesRob || flag.outputdiff, data_transects=charge_transectsMidW('Rob','counts3D','transect'); liste_concepts=data_transects.species; end

liste_ROV={'Ventana','Doc Ricketts','Tiburon'}; irov=1;
while isempty(strfind(ROVdive,liste_ROV{irov})), irov=irov+1; end
ROV=liste_ROV{irov}; divenumber=str2num(ROVdive(length(ROV)+1:end));



% -------------- query the midwater database & récupère volumes

% find times for each depth and keep only standard depths
v=sqlquery(['SELECT id, depth_m, start_datetime_gmt, end_datetime_gmt, volume_m3, day_night FROM transect_data WHERE dive = ',num2str(divenumber),' AND rov = ''',ROV,''' ORDER BY depth_m'],'midwater');
if isempty(v.depth_m), if ~flag.silent, disp([ROVdive,' ~ No data in VARS?']), end, output=[]; return, end
if isempty(arg.depth), arg.depth=trie_vecteur(v.depth_m); end
iok = eqtot(v.depth_m,arg.depth) & eqStrtot(v.day_night,'D'); 		% ajout filtre sur D à cause du "dive" Ventana3750 qui en contient 2 en fait
for varname=permute(fieldnames(v),[2 1]), varname=varname{:}; v.(varname)=v.(varname)(iok); end
depth_sampled=v.depth_m; liste_depth_sampled=trie_vecteur(depth_sampled);
if isempty(depth_sampled), if ~flag.silent, disp([ROVdive,' ~ Not a day dive or not standard depths']), end, output=[]; return, end
if length(liste_depth_sampled)<3 && length(arg.depth)>3, if ~flag.silent, disp([ROVdive,' ~ Less than 3 standard depths sampled - not loaded']), end, output=[]; return, end

% construct output (pour pouvoir renvoyer le volume même si aucune annotation n'est trouvée) 
if length(arg.depth)==1, liste_bornesdepths=[arg.depth-10 arg.depth+10];
else dz=(arg.depth(2:end)-arg.depth(1:end-1))/2; liste_bornesdepths=[arg.depth(1)-dz(1);arg.depth(1:end-1)+dz;arg.depth(end)+dz(end)];
end
output_final=obj_intTS(liste_concepts,'depth',arg.depth,'time',floor(min(v.start_datetime_gmt)),'datablank'); output_final.attributs.ROVdive=ROVdive; 
output_final.attributs.volume = histcn(v.depth_m,liste_bornesdepths,'AccumData',v.volume_m3);
output_final.attributs.duration = histcn(v.depth_m,liste_bornesdepths,'AccumData',(v.end_datetime_gmt-v.start_datetime_gmt)*24*60);
output_final.attributs.volume_manuel=output_final.attributs.volume*NaN;

% combination avec volumes manuels
%volumes=read_file2([rep_heckel_global,'data_California/intTS/midwater/Transect_vol-copy.csv']);
%eval(['save ',rep_heckel_global,'data_California/intTS/midwater/Transect_vol-copy.mat volumes'])
load([rep_heckel_global,'data_California/intTS/midwater/Transect_vol-copy.mat'])
for depth_encours=reshape_ligne(liste_depth_sampled), iv = v.depth_m==depth_encours; idepth = output_final.depth==depth_encours;
	output_final.attributs.volume_manuel(idepth)=sum(volumes.Vol_m3(eqtot(volumes.start_date,v.start_datetime_gmt(iv))));
end



% -------------- query the VARS database

% sql based on ROV & concepts. Note - AssociationID_FK permet le lien avec la table Association, mais LinkName/LinkValue ont l'air de contenir les infos déjà.
sql=['SELECT ConceptName,DEPTH,RecordedDate,ObservationID_FK,AssociationID_FK,LinkName,LinkValue,VideoArchiveName,DiveNumber FROM Annotations ' ...
	'WHERE (RovName = ''',ROV,''') AND ('];
if ~isempty(liste_concepts), liste_concepts_sqlstr='';
	for concept=liste_concepts, liste_concepts_sqlstr=[liste_concepts_sqlstr,'ConceptName = ''',concept{:},''' OR ']; end
	sql=[sql,liste_concepts_sqlstr(1:end-4),') AND (']; 
end
for idepth=1:length(depth_sampled), 
	sql=[sql,'((RecordedDate >= ''',datestr(v.start_datetime_gmt(idepth),'yyyy-mm-dd HH:MM:SS'),''') AND (RecordedDate <= ''',datestr(v.end_datetime_gmt(idepth),'yyyy-mm-dd HH:MM:SS'),''')) OR '];
end
sql=[sql(1:end-4),')'];
if flag.sql, output=sql; return, end

% query all (légèrement plus rapide qu'en loop) et ensuite changement des depths
output_ini=sqlquery(sql,'VARS'); if trie_vecteur(output_ini.DiveNumber)~=divenumber, if ~flag.silent, disp(['DiveNumber in VARS = ',num2str(trie_vecteur(output_ini.DiveNumber))]), end, end
ibad=logical(ones(length(output_ini.DEPTH),1)*0); depth_ini=output_ini.DEPTH; 
for idepth=1:length(depth_sampled), itime=output_ini.RecordedDate>=v.start_datetime_gmt(idepth) & output_ini.RecordedDate<=v.end_datetime_gmt(idepth);
	ibad (itime & abs(output_ini.DEPTH-depth_sampled(idepth))>40 ) = true;		% filtre pour repérer les depths aberrantes à cause d'un mauvais timestamp par ex
	output_ini.DEPTH(itime)=depth_sampled(idepth); 
end
if flag.plot		% affichage des profils foireux
	aa = sqlquery(['SELECT RecordedDate,DEPTH From Annotations WHERE (RovName = ''',ROV,''') AND (DiveNumber = ',num2str(divenumber),')'],'VARS'); 
	ii=aa.RecordedDate>datenum(1990,1,1); 
	affiche_series(trie_matrice([aa.RecordedDate(ii),aa.DEPTH(ii)]),[],'yreverse','titre',[ROV,num2str(divenumber),' ~ ',num2str(sum(ibad))],'xlabel','time','ylabel','depth'), hold on, global style_global
	for idepth=1:length(depth_sampled), 
		plot([v.start_datetime_gmt(idepth) v.start_datetime_gmt(idepth)],get(gca,'YLim'),'Color',couleur2rgb(style_global.couleurs{idepth+1}),'LineWidth',2), 
		plot([v.end_datetime_gmt(idepth) v.end_datetime_gmt(idepth)],get(gca,'YLim'),'Color',couleur2rgb(style_global.couleurs{idepth+1}),'LineWidth',2), 
		plot([v.start_datetime_gmt(idepth) v.end_datetime_gmt(idepth)],[v.depth_m(idepth) v.depth_m(idepth)],'Color',couleur2rgb(style_global.couleurs{idepth+1}),'LineWidth',2)
	end
	scatter(output_ini.RecordedDate(ibad),depth_ini(ibad),30,'r')
	ROVdivestr=ROVdive; ROVdivestr(strfind(ROVdivestr,' '))='';
	try print_fig(ROVdivestr,'/home/monique/mbarinet/home_MBARI/dives/'), end
end
if max(ibad), 
	if ~flag.nofiltredepth, if ~flag.silent, disp(['Annotations supprimées pour cause de depths foireuses (',ROVdive,') : ',num2str(sum(ibad))]), end
		for varname=permute(fieldnames(output_ini),[2 1]), varname=varname{:}; output_ini.(varname)=output_ini.(varname)(~ibad); end, end
end

% no data found
if isempty(output_ini.DEPTH) 
	if isempty(liste_concepts), 
		sql=['SELECT RecordedDate FROM Annotations WHERE (RovName = ''',ROV,''') ' ...
			'AND (RecordedDate >= ''',datestr(min(v.start_datetime_gmt),'yyyy-mm-dd HH:MM:SS'),''') AND (RecordedDate <= ''',datestr(max(v.end_datetime_gmt),'yyyy-mm-dd HH:MM:SS'),''')'];
		output_ini = sqlquery(sql,'VARS');
		datestr(minmax(output_ini.RecordedDate))
		datestr(minmax([v.start_datetime_gmt;v.end_datetime_gmt]))
		error(['no data? ',ROVdive])
	else 	% note - attention ça peut être un dive non encore annoté
		if flag.outputdiff, output=sum(aplat(data_transects.data.counts(:,:,eqStrtot(data_transects.attributs.ROVdive,ROVdive))));
		else
			output=output_final;
			output.data.counts(:)=0; output.data.counts(:,~eqtot(output.depth,depth_sampled))=NaN; 
		end
		return
	end
end



% -------------- clean up query by removing duplicates

% finds annotations tagged with identity-reference
itocheck=find(eqStrtot(output_ini.LinkName,'identity-reference'));
iassociation=eqStrtot(output_ini.LinkName,'population-quantity');

if ~isempty(itocheck), % disp([ROVdive,': ',num2str(length(itocheck)),' ~ ',num2str(length(trie_vecteur(output_ini.LinkValue(itocheck))))])
% construct uniqueID for annotations to check, based on referenceID, concept name and video archive name
	uniqueID=output_ini.ObservationID_FK*NaN;
	for icheck=reshape_ligne(itocheck)
		VideoArchiveName=output_ini.VideoArchiveName{icheck}; iHD=strfind(VideoArchiveName,'HD'); VideoArchiveName(iHD:iHD+1)='';
		s = java.lang.String([output_ini.ConceptName{icheck},VideoArchiveName,output_ini.LinkValue{icheck}]); uniqueID(icheck)=s.hashCode(); 
	end

% for each unique ID, finds the corresponding ObservationsID_FK and replace them by an unique number
	for id=permute(unique(uniqueID(~isnan(uniqueID))),[2 1]), iid = uniqueID==id;	
		observationsID=unique(output_ini.ObservationID_FK(iid));
		iIDs=eqtot(output_ini.ObservationID_FK,observationsID); 			% différent de iid qui ne contient que les observationsID avec une identity-reference
		associationID = iIDs & iassociation; 
		output_ini.ObservationID_FK(iIDs)=min(observationsID);	
		if sum(associationID)==1, save_encours, error('à voir2'), 		% normalement pas de population-quantity pour les doublets, mais on vérifie au cas où
			output_ini.LinkName(iIDs)=output_ini.LinkName(associationID); output_ini.LinkValue(iIDs)=output_ini.LinkValue(associationID);	% preserving associations	
		elseif sum(associationID)>1, save_encours, error('à voir'), end
	end
end

% clean up duplicate ObservationsID_FK (both due to processing above or other duplicates)
[~,iok]=unique(output_ini.ObservationID_FK); for varname=permute(fieldnames(output_ini),[2 1]), varname=varname{:}; output_ini.(varname)=output_ini.(varname)(iok); end



% -------------- informations on population quantity from the flags 'population-quantity'

output_ini.counts=ones(length(output_ini.ConceptName),1);
iassociation=eqStrtot(output_ini.LinkName,'population-quantity');
output_ini.PopulationQuantity=cell(length(output_ini.ConceptName),1); 
output_ini.PopulationQuantity(iassociation) = output_ini.LinkValue(iassociation);
%{
% méthode en passant par la table Association (inutile)
if max(~isnan(output_ini.AssociationID_FK)), output_ini.PopulationQuantity2=output_ini.PopulationQuantity;
	liste_associations=trie_vecteur(output_ini.AssociationID_FK);
	for iobs=reshape_ligne(liste_associations);
		sql_association=['SELECT id,ObservationID_FK,LinkName,ToConcept,LinkValue,LAST_UPDATED_TIME,rowguid FROM Association WHERE id = ',num2str(iobs)];
		output_association=sqlquery(sql_association,'VARS'); 
		if eqStrtot(output_association.LinkName{:},'population-quantity'), 			% note: aussi des 'suspect-navigation-ctd-other-data' à garder en tête
			output_ini.PopulationQuantity2{output_ini.AssociationID_FK==iobs} = output_association.LinkValue{:}; end			
	end
end
%}
has_annotations=cellfun(@(x) ~isempty(x), output_ini.PopulationQuantity);
annotations_num=cellfun(@(x) str2double(x), output_ini.PopulationQuantity); if sum(isnan(annotations_num(has_annotations))), error([ROVdive,' annotations non numériques !!']), end
if ~isempty(output_ini.PopulationQuantity(has_annotations & isnan(annotations_num))), save_encours, error('à voirrrr'), end
if ~flag.noquantity, output_ini.counts(has_annotations)=annotations_num(has_annotations); end
output_ini.counts(output_ini.counts==999) = 50;		% more realistic number per Rob & Kris emails on Mar 18 2015



% -------------- get the counts at each depth

liste_ConceptNameQuery=trie_vecteur(output_ini.ConceptName);
if isempty(liste_concepts), liste_concepts=liste_ConceptNameQuery; output_final=obj_intTS(liste_concepts,output_final); end
non_rentres=liste_ConceptNameQuery(~eqStrtot(liste_ConceptNameQuery,output_final.species));
if ~isempty(non_rentres) && ~flag.silent, disp([num2str(divenumber),' ~ ConceptName non rentrés ?']), non_rentres, end
liste_concepts=liste_ConceptNameQuery(eqStrtot(liste_ConceptNameQuery,output_final.species));

output_ini.idConcept=output_ini.DEPTH*NaN; 
for iconcept=reshape_ligne(find(eqStrtot(output_final.species,liste_ConceptNameQuery))), output_ini.idConcept(eqStrtot(output_ini.ConceptName,output_final.species{iconcept}))=iconcept; end

output_final.data.counts = histcn([output_ini.idConcept,output_ini.DEPTH], 0.5:length(output_final.species)+0.5, liste_bornesdepths, 'AccumData', output_ini.counts); 
output_final.data.counts(isnan(output_final.data.counts))=0;
output_final.data.counts(:,~eqtot(output_final.depth,depth_sampled))=NaN;		% depths that were not sampled



% -------------- final output

if flag.outputdiff
	mat_transects=data_transects.data.counts(eqStrtot(data_transects.species,output_final.species),eqtot(data_transects.depth,output_final.depth),eqStrtot(data_transects.attributs.ROVdive,ROVdive));
	difference=abs((mat_transects-output_final.data.counts));
	diff_max=max(aplat(difference));
	if diff_max>0, [ispecies,idepth]=find(difference==diff_max); output_final.species{ispecies(1)}, output_final.depth(idepth(1)), end
	output=diff_max;
else
	output=output_final;
end



return








