first whoosher version
authorA.M. Thurnherr <athurnherr@yahoo.com>
Fri, 06 Jan 2012 09:42:24 +0000
changeset 3 5e3caf9c0f2e
parent 2 06bf500b8e22
child 4 b99280de1642
first whoosher version
ANTS2mat.m
LDEO_LADCP2ANTS.m.orig
UH_LADCP2ANTS.m
UH_LADCPshear2ANTS.m
loadANTS.m
loadANTS_simple.m
struct2ANTS.m
new file mode 100644
--- /dev/null
+++ b/ANTS2mat.m
@@ -0,0 +1,12 @@
+%======================================================================
+%                    A N T S 2 M A T . M 
+%                    doc: Thu Aug  4 11:04:13 2011
+%                    dlm: Thu Aug  4 11:04:19 2011
+%                    (c) 2011 A.M. Thurnherr
+%                    uE-Info: 11 0 NIL 0 0 72 0 2 4 NIL ofnI
+%======================================================================
+
+function [] = ANTS2mat(in_file,var_name,out_basename)
+	eval(sprintf('%s = loadANTS(''%s'');',var_name,in_file));
+	eval(sprintf('save %s %s',out_basename,var_name));
+
new file mode 100644
--- /dev/null
+++ b/LDEO_LADCP2ANTS.m.orig
@@ -0,0 +1,156 @@
+%======================================================================
+%                    L D E O _ L A D C P 2 A N T S . M 
+%                    doc: Sun Jan 22 15:19:00 2006
+%                    dlm: Fri Jan  6 09:21:58 2012
+%                    (c) 2006 A.M. Thurnherr
+%                    uE-Info: 77 0 NIL 0 0 72 2 2 4 NIL ofnI
+%======================================================================
+%
+% export LDEO LADCP output to ANTS file
+%
+% USAGE: LDEO_LADCP2ANTS(dr,f,p,outBaseName)
+%
+
+% HISTORY:
+%  Jan 22, 2006: - created
+%  Feb  4, 2006: - added BT & SADCP profiles
+%  Feb  8, 2006: - made compatible with V7
+%  Feb 26, 2006: - made ensemble_vel_err optional (not set on ps.shear = 2)
+%  Apr 25, 2006: - suppress output of empty SADCP,BT files
+%  Aug 21, 2006: - added additional lat/lon output
+%  Nov  9, 2006: - added additional time output (requiring p input)
+%  Jul 17, 2008: - added cruise, software, magdecl, procdir info
+%  Apr 23, 2009: - added globarl var EXPORT_CTD_DATA
+%  Oct 12, 2009: - adapted to new struct2ANTS
+
+function [] = LDEO_LADCP2ANTS(dr,f,p,obn)
+
+	%----------------------------------------------------------------------
+	% INVERSE SOLUTION
+	%----------------------------------------------------------------------
+
+	prof.name = dr.name;
+	prof.cruise = p.cruise_id;
+	prof.software = p.software;
+	prof.magdecl = p.drot;
+	prof.procdir = pwd;
+	
+	prof.start_date  = sprintf('%d/%02d/%02d',p.time_start(1),p.time_start(2),p.time_start(3));
+	prof.start_time	 = sprintf('%02d:%02d:%02d',p.time_start(4),p.time_start(5),p.time_start(6));
+
+	prof.end_date    = sprintf('%d/%02d/%02d',p.time_end(1),p.time_end(2),p.time_end(3));
+	prof.end_time	 = sprintf('%02d:%02d:%02d',p.time_end(4),p.time_end(5),p.time_end(6));
+
+	prof.median_time = sprintf('%02d:%02d:%02d',dr.date(4),dr.date(5),dr.date(6));
+
+	prof.lat 		= dr.lat; 			  prof.lon  	  = dr.lon;				% (start+end)/2
+	prof.mean_lat 	= mean(dr.shiplat);   prof.mean_lon   = mean(dr.shiplon);
+	prof.median_lat = median(dr.shiplat); prof.median_lon = median(dr.shiplon);
+	prof.start_lat	= dr.shiplat(1);	  prof.start_lon  = dr.shiplon(1);
+	prof.end_lat	= dr.shiplat(end);	  prof.end_lon	  = dr.shiplon(end);
+	i_bot = find(dr.zctd==min(dr.zctd));
+	prof.bot_lat	= dr.shiplat(i_bot);  prof.bot_lon    = dr.shiplon(i_bot);
+
+	prof.depth = dr.z;
+	prof.max_depth = max(prof.depth);
+	
+	prof.u	   = dr.u;
+	prof.dn_u  = dr.u_do;
+	prof.up_u  = dr.u_up;
+	prof.v     = dr.v;
+	prof.dn_v  = dr.v_do;
+	prof.up_v  = dr.v_up;
+	
+	prof.u_fromshear = dr.u_shear_method;
+	prof.v_fromshear = dr.v_shear_method;
+
+	prof.samp  = dr.nvel;
+	prof.err   = dr.uerr;
+	prof.range = dr.range;
+	if existf(dr,'ensemble_vel_err')
+		prof.ensemble_vel_err = dr.ensemble_vel_err;
+	end
+
+	prof.temp  = dr.ctd_t;
+	prof.salin = dr.ctd_s;
+	
+	struct2ANTS(prof,sprintf('%s.mat',f.res),sprintf('%s.prof',obn));
+
+	%----------------------------------------------------------------------
+	% SADCP
+	%----------------------------------------------------------------------
+
+	if existf(dr,'u_sadcp')
+
+		SADCP.name = prof.name;
+		SADCP.cruise = prof.cruise;
+		SADCP.software = prof.software;
+	    SADCP.magdecl = prof.magdecl;
+		SADCP.procdir = prof.procdir;
+		SADCP.date = sprintf('%d/%02d/%02d',dr.date(1),dr.date(2),dr.date(3)); % median
+		SADCP.time = prof.median_time;
+		SADCP.lat  = prof.lat; SADCP.lon  = prof.lon;
+		SADCP.start_lat  = prof.start_lat; SADCP.start_lon  = prof.start_lon;
+		SADCP.end_lat  = prof.end_lat; SADCP.end_lon  = prof.end_lon;
+		SADCP.mean_lat  = prof.mean_lat; SADCP.mean_lon  = prof.mean_lon;
+		SADCP.median_lat  = prof.median_lat; SADCP.median_lon  = prof.median_lon;
+
+		SADCP.depth = dr.z_sadcp;
+		SADCP.max_depth = max(dr.z_sadcp);
+
+		SADCP.u		= dr.u_sadcp;
+		SADCP.v		= dr.v_sadcp;
+		if existf(dr,'uerr_sadcp')			% V7 does not have this
+			SADCP.err	= dr.uerr_sadcp;
+		end
+		
+		struct2ANTS(SADCP,sprintf('%s.mat',f.res),sprintf('%s.SADCP',obn));
+		
+	end
+
+	%----------------------------------------------------------------------
+	% BT
+	%----------------------------------------------------------------------
+
+	if existf(dr,'ubot')
+		BT.name = prof.name;
+		BT.cruise = prof.cruise;
+		BT.software = prof.software;
+		BT.magdecl = prof.magdecl;
+		BT.procdir = prof.procdir;
+		BT.date = sprintf('%d/%02d/%02d',dr.date(1),dr.date(2),dr.date(3)); % median
+		BT.time = prof.median_time;
+		BT.lat  = prof.bot_lat;
+		BT.lon  = prof.bot_lon;
+
+		BT.depth = dr.zbot;
+		BT.max_depth = max(dr.zbot);
+
+		BT.u		= dr.ubot;
+		BT.v		= dr.vbot;
+		BT.err		= dr.uerrbot;
+		
+		struct2ANTS(BT,sprintf('%s.mat',f.res),sprintf('%s.BT',obn));
+	end
+	
+	%----------------------------------------------------------------------
+	% CTD Data
+	%----------------------------------------------------------------------
+
+	global EXPORT_CTD_DATA;
+	if EXPORT_CTD_DATA
+		CTD.name = prof.name;
+		CTD.cruise = prof.cruise;
+		CTD.software = prof.software;
+		CTD.procdir = prof.procdir;
+		CTD.date = sprintf('%d/%02d/%02d',dr.date(1),dr.date(2),dr.date(3)); % median
+		CTD.time = prof.median_time;
+		CTD.lat  = prof.bot_lat;
+		CTD.lon  = prof.bot_lon;
+		CTD.ITS = 90;
+		CTD.depth = dr.z;
+		CTD.temp  = dr.ctd_t;
+		CTD.salin = dr.ctd_s;
+
+		struct2ANTS(CTD,sprintf('%s.mat',f.res),sprintf('%s.CTD',obn));
+	end
--- a/UH_LADCP2ANTS.m
+++ b/UH_LADCP2ANTS.m
@@ -1,26 +1,33 @@
 %======================================================================
 %                    U H _ L A D C P 2 A N T S . M 
 %                    doc: Sun Jan 22 15:19:00 2006
-%                    dlm: Mon Oct 12 22:57:17 2009
+%                    dlm: Thu Aug  4 14:10:58 2011
 %                    (c) 2006 A.M. Thurnherr
-%                    uE-Info: 53 24 NIL 0 0 72 0 2 4 NIL ofnI
+%                    uE-Info: 37 0 NIL 0 0 72 2 2 4 NIL ofnI
 %======================================================================
 %
 % export LDEO LADCP output to ANTS file
 %
-% USAGE: LADCP2ants(inFile,outBaseName)
+% USAGE: UH_LADCP2ANTS(inFile,outBaseName)
 %
 
 % HISTORY:
-%  Jan 22, 2006: - created
-%  Nov  2, 2008: - BUG: v_var vas not exported because of typo
-%  Oct 12, 2009: - adapted to new struct2ANTS
+%	Jan 22, 2006: - created
+%	Nov  2, 2008: - BUG: v_var had not been exported because of typo
+%	Oct 12, 2009: - adapted to new struct2ANTS
+%	Aug  4, 2011: - added usage message on zero args
+%				  - updated output field names
 
-function [] = LADCP2ANTS(ifn,obn)
+function [] = UH_LADCP2ANTS(ifn,obn)
+
+	if nargin ~= 2
+		help UH_LADCP2ANTS
+		return
+	end
 
 	eval(sprintf('load %s',ifn));
 
-	prof.yrday = mean(txy_start_end(:,1));
+	prof.dayno = mean(txy_start_end(:,1));
 
 	prof.lon = mean(txy_start_end(find(isfinite(txy_start_end(:,2))),2));
 	prof.lat = mean(txy_start_end(find(isfinite(txy_start_end(:,3))),3));
@@ -33,22 +40,22 @@
 	up_bad = find(sm_up_i == 0);
 
 	prof.u = su_mn_i(good);
-	su_dn_i(dn_bad) = NaN; prof.dn_u = su_dn_i(good);
-	su_up_i(up_bad) = NaN; prof.up_u = su_up_i(good);
+	su_dn_i(dn_bad) = NaN; prof.dc_u = su_dn_i(good);
+	su_up_i(up_bad) = NaN; prof.uc_u = su_up_i(good);
 	prof.v = sv_mn_i(good);
-	sv_dn_i(dn_bad) = NaN; prof.dn_v = sv_dn_i(good);
-	sv_up_i(up_bad) = NaN; prof.up_v = sv_up_i(good);
+	sv_dn_i(dn_bad) = NaN; prof.dc_v = sv_dn_i(good);
+	sv_up_i(up_bad) = NaN; prof.uc_v = sv_up_i(good);
 
 	prof.u_var = su_var_mn_i(good);
-	su_var_dn_i(dn_bad) = NaN; prof.dn_u_var = su_var_dn_i(good);
-	su_var_up_i(up_bad) = NaN; prof.up_u_var = su_var_up_i(good);
+	su_var_dn_i(dn_bad) = NaN; prof.dc_u_var = su_var_dn_i(good);
+	su_var_up_i(up_bad) = NaN; prof.uc_u_var = su_var_up_i(good);
 	prof.v_var = sv_var_mn_i(good);
-	sv_var_dn_i(dn_bad) = NaN; prof.dn_v_var = sv_var_dn_i(good);
-	sv_var_up_i(up_bad) = NaN; prof.up_v_var = sv_var_up_i(good);
+	sv_var_dn_i(dn_bad) = NaN; prof.dc_v_var = sv_var_dn_i(good);
+	sv_var_up_i(up_bad) = NaN; prof.uc_v_var = sv_var_up_i(good);
 
-	prof.samp = sn_mn_i(good);
-	sn_dn_i(dn_bad) = NaN; prof.dn_samp = sn_dn_i(good);
-	sn_up_i(up_bad) = NaN; prof.up_samp = sn_up_i(good);
+	prof.nsamp = sn_mn_i(good);
+	sn_dn_i(dn_bad) = NaN; prof.dc_nsamp = sn_dn_i(good);
+	sn_up_i(up_bad) = NaN; prof.uc_nsamp = sn_up_i(good);
 
 	struct2ANTS(prof,ifn,sprintf('%s.prof',obn));
 
new file mode 100644
--- /dev/null
+++ b/UH_LADCPshear2ANTS.m
@@ -0,0 +1,76 @@
+%======================================================================
+%                    U H _ L A D C P S H E A R 2 A N T S . M 
+%                    doc: Thu Sep 30 11:06:14 2010
+%                    dlm: Wed Oct 13 11:45:10 2010
+%                    (c) 2006 A.M. Thurnherr
+%                    uE-Info: 24 56 NIL 0 0 72 2 2 4 NIL ofnI
+%======================================================================
+%
+% export UH-processed LADCP shear output to ANTS file
+%
+% USAGE: UH_LADCPshear2ANTS(stn|[stns])
+%
+% NOTES:
+%	- execute this function in [./casts] subdir
+%	- output files <stn>.sh are written in current directory
+%	- run_name = 'h' (defined in [proc/set_da.m]) is assumed
+
+% HISTORY:
+%	Sep 30, 2010: - created
+%	Oct 11, 2010: - BUG: merge output is variance, rather than stddev
+%	Oct 13, 2010: - modified to be callable from [./casts] subdir
+%				  - added usage info when called without args
+%				  - added option to call with vector
+%				  - adapted to include both dependencies
+
+function [] = UH_LADCPshear2ANTS(stn)
+
+	if nargin~=1
+		help UH_LADCPshear2ANTS
+		return
+	end
+
+	if length(stn) > 1
+		for i=1:length(stn)
+			UH_LADCPshear2ANTS(stn(i))
+		end
+		return
+	end
+
+	run_name = 'h';
+
+	subdir = dir(sprintf('*%03d',stn));
+	if length(subdir) ~= 1
+		error Cannot determine cast subdirectory
+	end
+	
+	dc_file = sprintf('%s/merge/%s_dn.mat',subdir.name,run_name);
+	uc_file = sprintf('%s/merge/%s_up.mat',subdir.name,run_name);
+	
+	load(dc_file)
+	dc_U = U; dc_V = V; dc_W = W;
+	load(uc_file)
+	uc_U = U; uc_V = V; uc_W = W;
+
+	goodbins = find(dc_U(:,2)>0 | uc_U(:,2)>0);
+	i1 = min(goodbins); i2 = max(goodbins);
+
+	prof.depth 		= dc_U(i1:i2,1);
+
+	prof.dc_nshear	= dc_U(i1:i2,2);
+	prof.dc_u_z		= dc_U(i1:i2,3);
+	prof.dc_u_z_sig	= sqrt(dc_U(i1:i2,4));
+	prof.dc_v_z		= dc_V(i1:i2,3);
+	prof.dc_v_z_sig	= sqrt(dc_V(i1:i2,4));
+	prof.dc_w_z		= dc_W(i1:i2,3);
+	prof.dc_w_z_sig	= sqrt(dc_W(i1:i2,4));
+
+	prof.uc_nshear	= uc_U(i1:i2,2);
+	prof.uc_u_z		= uc_U(i1:i2,3);
+	prof.uc_u_z_sig	= sqrt(uc_U(i1:i2,4));
+	prof.uc_v_z		= uc_V(i1:i2,3);
+	prof.uc_v_z_sig	= sqrt(uc_V(i1:i2,4));
+	prof.uc_w_z		= uc_W(i1:i2,3);
+	prof.uc_w_z_sig	= sqrt(uc_W(i1:i2,4));
+
+	struct2ANTS(prof,{dc_file,uc_file},sprintf('%03d.sh',stn));
--- a/loadANTS.m
+++ b/loadANTS.m
@@ -1,66 +1,111 @@
 %======================================================================
 %                    L O A D A N T S . M 
 %                    doc: Thu Jul 21 22:53:21 2011
-%                    dlm: Thu Jul 21 23:43:06 2011
+%                    dlm: Thu Aug  4 10:54:24 2011
 %                    (c) 2011 A.M. Thurnherr
-%                    uE-Info: 61 60 NIL 0 0 72 2 2 4 NIL ofnI
+%                    uE-Info: 18 71 NIL 0 0 72 2 2 4 NIL ofnI
 %======================================================================
 
 % NOTES:
-%	- very restrictive subset of ANTS standard:
-%		= no empty lines
-%		- no in-record comments
+%   - very restrictive subset of ANTS standard:
+%       - no empty lines
+%       - no in-record comments
 
 % HISTORY:
-%	Jul 21, 2011: - began working on it
+%   Jul 21, 2011: - began working on it
+%	Jul 23, 2011: - made it work
+%	Aug  4, 2011: - replaced "creator" by "Matlab_import"
+%				  - BUG: %PARAM names with . were not handled correctly
 
 function dta_struct = loadANTS(file_name)
 
-fid = fopen(file_name);										% open file
+fid = fopen(file_name);                                     % open file
 if fid < 0
-	error(ferror(fid));
+    error(sprintf('%s: not such file',file_name));
 end
 
-dta_struct = struct([]);
+dta_struct = struct('Matlab_import',sprintf('loadANTS(''%s'')',file_name));
 
-l = fgetl(fid);												% handle metadata
+l = fgetl(fid);                                             % handle metadata
 while ischar(l) & regexp(l,'^#')
-	if regexp(l,'^#ANTS#ERROR#')
-		error(l);
-	elseif regexp(l,'^#ANTS#PARAMS#')
-		params = regexp(l,'(\w+){([^}]*)}','tokens');
-		for i=1:length(params)
-			if strcmp(params{i}{2},'')
-				dta_struct = rmfield(dta_struct,params{i}{1});
+    if regexp(l,'^#ANTS#ERROR#')
+        error(l);
+    elseif regexp(l,'^#ANTS#PARAMS#')
+        [tmp,tmp,ptk] = regexp(l,'([\w\.]+){([^}]*)}');
+        for i=1:length(ptk)
+        	pname = matlabotomize(token1(i,l,ptk));
+			if sum(size(ptk{i})) < 4	% empty def
+				if isfield(dta_struct,pname)
+					dta_struct = rmfield(dta_struct,pname);
+				end
 			else
-				dta_struct = setfield(dta_struct,params{i}{1},params{i}{2});
-			end % if
-		end % for
-	elseif regexp(l,'^#ANTS#FIELDS#')
-		field = regexp(l,'{([^}]*)}','tokens');
-	end % elseif
-	l = fgetl(fid);
+				numval = str2double(token2(i,l,ptk));
+				if isfinite(numval) | strcmpi(token2(i,l,ptk),'nan')
+					dta_struct = setfield(dta_struct,pname,numval);
+				else
+					dta_struct = setfield(dta_struct,pname,token2(i,l,ptk));
+				end
+			end
+        end
+		
+    elseif regexp(l,'^#ANTS#FIELDS#')
+        [tmp,tmp,ftk] = regexp(l,'{([^}]*)}');
+        fields = cell(1,length(ftk));
+        for i=1:length(ftk)
+             fields{i} = matlabotomize(token(i,l,ftk));
+        end
+    end % elseif
+    l = fgetl(fid);
 end % while
 
-if ~ischar(l)												% EOF
-	close(fid);
-	return
+if ischar(l)												% not empty file
+	isnumeric = zeros(1,length(fields));					% determine data types
+    [tmp,tmp,tk] = regexp(l,'([^ \t]+)');					% split into tokens
+	for i=1:length(fields)
+		numval = str2double(token(i,l,tk));
+		if isfinite(numval) | strcmpi(token(i,l,tk),'nan')
+			isnumeric(i) = 1;
+		end
+	end
 end
 
-fmt = '';													% construct scanf format
-for i=1:length(field)
-	fmt = [fmt ' %f'];
+dta = cell(length(fields),1);								% init data cell array
+
+while ischar(l)                                             % loop through records
+    [tmp,tmp,tk] = regexp(l,'([^ \t]+)');					% split into tokens
+    for i=1:length(tk)
+    	if isnumeric(i)
+    		dta{i} = [dta{i} str2double(token(i,l,tk))];
+    	else
+    		dta{i} = [dta{i} {token(i,l,tk)}];
+    	end
+    end
+    l = fgetl(fid);
 end
 
-rec1 = sscanf(l,fmt);										% split first record
-dta = fscanf(fid,fmt);										% read & split remaining records
-
-for i=1:length(field)										% copy to structure
-	disp(field{i});
-	keyboard
-	dta_struct = setfield(dta_struct,field{i},[rec1(i); dta(:,i)]);
+for i=1:length(fields)                                       % copy to structure
+	dta_struct = setfield(dta_struct,fields{i},dta{i});
 end
 
-flose(fid);
+fclose(fid);
+
+return
+
+%----------------------------------------------------------------------
+
+function tk = token(i,str,tki)
+	tk = str(tki{i}(1):tki{i}(2));
+	return;
 
-return 
+function tk = token1(i,str,tki)
+	tk = str(tki{i}(1,1):tki{i}(1,2));
+	return;
+
+function tk = token2(i,str,tki)
+	tk = str(tki{i}(2,1):tki{i}(2,2));
+	return
+
+function s = matlabotomize(s)
+	s = strrep(s,'.','_');
+	s = strrep(s,'3','three');
+
new file mode 100644
--- /dev/null
+++ b/loadANTS_simple.m
@@ -0,0 +1,46 @@
+% Usage: D = loadANTS(filename[,fieldname[,...]]);
+%
+% Examples:
+%	prof = loadANTS('070.2db');
+%		- read all fields from file 070.2db into matrix prof
+%		- each field becomes a column
+%	prof = loadANTS('070.2db','press','temp','salin');
+%		- read pressure, temperature, and salinity fields from file 070.2db
+%		  into matrix prof
+%		- 1st column is pressure, 2nd column is temperature, 3rd column is
+%		  salinity
+
+%======================================================================
+%                    L O A D A N T S . M 
+%                    doc: Fri Sep 17 11:12:44 2010
+%                    dlm: Fri Sep 17 11:41:01 2010
+%                    (c) 2010 A.M. Thurnherr
+%                    uE-Info: 25 29 NIL 0 0 72 2 2 4 NIL ofnI
+%======================================================================
+
+function D = loadANTS(file,varargin)
+
+if nargin==1
+	cmd = sprintf('data -Qw %s',file);
+	[status,dta] = system(cmd);
+	if status~=0
+		error(sprintf('cmd "%s" failed',cmd));
+	end
+	nfields = sscanf(dta,'%d');
+	cmd = sprintf('Cat -Q %s',file);
+else
+	nfields = nargin-1;
+	cmd = 'list -Q';
+	for i=1:nfields
+	  cmd = sprintf('%s %s',cmd,varargin{i});
+	end
+	cmd = sprintf('%s %s',cmd,file);
+end
+
+[status,dta] = system(cmd);
+if status~=0
+	error(sprintf('cmd "%s" failed',cmd));
+end
+
+D = sscanf(dta,'%f',[nfields,inf])';
+	
--- a/struct2ANTS.m
+++ b/struct2ANTS.m
@@ -1,16 +1,17 @@
 %======================================================================
 %                    S T R U C T 2 A N T S . M 
 %                    doc: Thu Oct 20 11:48:17 2005
-%                    dlm: Thu Oct 22 14:05:24 2009
+%                    dlm: Fri Jan  6 09:31:38 2012
 %                    (c) 2005 A.M. Thurnherr
-%                    uE-Info: 15 40 NIL 0 0 72 2 2 4 NIL ofnI
+%                    uE-Info: 50 0 NIL 0 0 72 2 2 4 NIL ofnI
 %======================================================================
 %
 % export Matlab structure to ANTS file
 %
-% USAGE: struct2ANTS(struct,depFileName,outFileName)
+% USAGE: struct2ANTS(struct,dependencies,outFileName)
 %
 % NOTES:
+%	- <dependencies> can be a string of a cell array of strings
 %	- scalar strings & numbers become %PARAMs
 %	- row and column vectors (which can be mixed) become FIELDs
 %	- incompatible vectors, as well as other data types, are skipped
@@ -25,14 +26,33 @@
 %				 - cosmetics
 %  Oct 12, 2009: - added ifn (ANTS 4.0: deps)
 %  Oct 13, 2009: - allowed for NULL ifn, ofn
+%  Oct 13, 2010: - allowed for multiple dependencies
+%				 - added usage help
+%  Jul 23: 2011: - BUG: empty dep did not work
+%  Jul 24, 2011: - BUG: PARAMS with % did not work
+%  Jul 25, 2011: - commented out diagnostic message about skipped incompatible vectors
+%  Dec 30, 2011: - workaround for Matlab R11b bug: /tmp/foo cannot be written, /../tmp/foo can
 
-function [] = struct2ANTS(struct,ifn,ofn)
+function [] = struct2ANTS(struct,deps,ofn)
+
+	if nargin ~= 3
+		help struct2ANTS
+		return
+	end
+
+	if iscell(deps)
+		dlist = sprintf('%s,',deps{:});
+	else
+		dlist = sprintf('%s',deps);
+	end
+	
 	[ldef,dta] = parseStruct(struct,'','',[],ofn);
-	save /tmp/.struct2ANTS dta -ASCII -DOUBLE;
+	save /../tmp/.struct2ANTS dta -ASCII -DOUBLE;	% ARGH Matlab R11b on Freebsd 8.2 requires this weird path
+	
 	if length(ofn) == 0
-		system(sprintf('list -M%%.15g -d,%s, %s /tmp/.struct2ANTS',ifn,ldef));
+		system(sprintf('list -M%%.15g -d ''%s'' %s /tmp/.struct2ANTS',dlist,ldef));
 	else
-		system(sprintf('list -M%%.15g -d,%s, %s /tmp/.struct2ANTS > %s',ifn,ldef,ofn));
+		system(sprintf('list -M%%.15g -d ''%s'' %s /tmp/.struct2ANTS > %s',dlist,ldef,ofn));
 	end
 
 %======================================================================
@@ -46,6 +66,8 @@
 		if isstruct(f)
 			[ldef,dta] = parseStruct(f,ldef,[fns '.'],dta,ofn);
 		elseif ischar(f)
+			f = strrep(f,'%','%%');				% must quote %s
+			f = strrep(f,'$','\\\$');			% presumably also $s
 			ldef = sprintf('%%%s%s="\\"%s\\"" %s',fpref,fns,f,ldef);
 		elseif isnumeric(f)
 			[r c] = size(f);
@@ -58,7 +80,7 @@
 				end
 				if 	   r==1 && length(f)==ndta, dta = [dta,f'];
 				elseif c==1 && length(f)==ndta, dta = [dta,f];
-				else, disp(sprintf('%s: incompatible %d x %d array %s skipped',ofn,r,c,fns));
+				else, 1; %disp(sprintf('%s: incompatible %d x %d array %s skipped',ofn,r,c,fns));
 				end
 			end
 		else