function retn = adj_tripod_depth(new_struct, tripod_struct) % adj_tripod_depth adjust all global metadata and depth variable to a new depth % % function to adjust all global metadata to be consistent for one tripod % using a scientist-supplied water_depth. The default value should be % that from the mooring log, but ofter a pressure based one is preferred. % % usage : retn_status = adj_tripod_depth(new_struct, tripod_struct) % where the retn_status is 1 if no problems % two input structure are needed- one is for the new info % new_struct: tripod number (.tripod_no), % new water depth (.new_water_depth) % comment describing source of new water depth (.cmnt) % tripod_struct: (made by running extract_hab on the mooring log with additions for varname_cmab) % tripod_struct may contain the data from one or more tripods % tripod number (.tirpodid) % new inst. height (.hab) % name of sensor to which the height applies (.habname) % serial number of instrument (.sn) % hab, habname and sn may be row arrays if more than one sensor/instrument % the sensor_depth attribute done with new water depth and instrument hab % a sensor_hab attribute is added to hold deployment inst. heights. % nc{'depth'} variable is changed along with the attributes- if it is a % MIDAS or ADV logger, the depth of the velocity measurement is used. A % note is added saying which variable is the source for depth. % % emontgomery@usgs.gov 1/12/09 % % Program written in Matlab v7.4.0336 (R2007a) % Program updated in Matlab 7.6.0.324 (R2008a) % Program ran on PC with Windows XP Professional OS. % % "Although this program has been used by the USGS, no warranty, % expressed or implied, is made by the USGS or the United States % Government as to the accuracy and functioning of the program % and related program material nor shall the fact of distribution % constitute any such warranty, and no responsibility is assumed % by the USGS in connection therewith." % % check for arguments and exit if the right number aren't present if nargin ~= 2; help (mfilename); retn=0; return; end retn = 1; tripno=num2str(new_struct.tripod_no); % NOTE : this only works on files in the cwd- % it doesn't traverse dirs to find files to modify !! if ispc eval(['d=dir(''*' tripno '*.nc'');']) for jj=1:length(d) fn{jj}=d(jj).name; end else % for unix eval(['[stat,fnames]=unix(''ls ' tripno '*.nc'');']) xx=findstr(tripno,fnames); xx=[xx length(fnames)+1]; knt=1; for ik=1:length(xx)-1 vv=char(deblank(fnames(xx(ik):xx(ik+1)-1))); if findstr(vv,'old') disp(['not processing ' vv]); else fn{knt}=deblank(fnames(xx(ik):xx(ik+1)-1)); knt=knt+1; end end end % loop through to manipulate each file on the tripod for ik=1:length(fn) ncfilename=fn{ik}; perloc=findstr('.',ncfilename); new_nm=[ncfilename(1:perloc-1) '_old.nc']; result=copyfile(ncfilename,new_nm); nc = netcdf(ncfilename, 'write'); if isempty(nc), disp('read of nc_file failed, try another name') retn=0; return end % a few have no depth dimension- this can't work on those files if isempty(nc{'depth'}) disp(['no depth dimension in ' ncfilename '. Remedy this first!']) retn=0; return end % save all the original values to compare later: [r,dval]=extract_ncdepth(nc); % modify history & modification date: lfeed = char(10); nc.CREATION_DATE = ncchar(datestr(now,0)); history = ['WATER_DEPTH related attributes corrected by ', mfilename , ': ' nc.history(:)]; ifeed = findstr(history,lfeed); history(ifeed) = ':'; nc.history = ncchar(history); flg=0; % fix global attributes related to WATER_DEPTH ga=att(nc); % save the original value, insert new WATER_DEPTH & add comments if ~isempty(nc.WATER_DEPTH) water_depth_ori = nc.WATER_DEPTH(:); elseif ~isempty(nc.water_depth) water_depth_ori = nc.water_depth(:); else water_depth_ori = 'unknown'; end % if water_depth doesn't exist it shows up as empty % we don't want the lc. water_depth anyway- use WATER_DEPTH if ~isempty(nc.water_depth(:)); nc.water_depth=[]; end % remove the other option, if it exists lx=strmatch('water_depth(m)',[ncnames(ga)]); % because of the (m) the above syntax won't remove the attribute if ~isempty(lx); disp(['water_depth(m) attribute present- remove with ncatted later']) end nc.WATER_DEPTH=ncfloat(new_struct.new_water_depth); if(isempty(nc.WATER_DEPTH_NOTE)) nc.WATER_DEPTH_NOTE = ncchar([new_struct.cmnt ': (m) ']); else nc.WATER_DEPTH_NOTE = ncchar([new_struct.cmnt ': (m) ' nc.WATER_DEPTH_NOTE]); end % not doing inst_depth as a global attribute- see hab for each sensor % nc.inst_depth_note=ncchar('inst_depth = (water_depth - variable_depth)'); % select which information is appropriate to the file: resp='n'; fls=0; fidx=find(strncmp([tripod_struct.tripodid],cellstr(ncfilename(1:4)),3)); if length(fidx) ~=1 disp(['did not get an exact match to use on ' ncfilename '- select which should be used.']) for k=1:length(fidx) resp=input(['how about: ' char(tripod_struct(fidx(k)).tripodid) ' ? (y or n)\n'],'s'); if strncmpi(resp,'y',1) fidx(1)=fidx(k); fidx(2:end)=[]; flg=1; end if flg==1; break; end end end % Aanderraa rcm's are a bit different- they have t, ox and u,v in 1 file % now deal with adjusting the variable attributes ... vn=var(nc); ncnms=ncnames(var(nc)); % set up names that map possible variable names in our files names_for_pressure={'p_1' 'p_4' 'p_4023' 'sdp_850' 'p_4022' 'p_4020'}; names_for_velocity={'u_1205' 'v_1206' 'w_1204' 'werr_1201' 'cd_310' 'cs_300'}; names_for_var1={'uvar_4050' 'uvcov_4051' 'vvar_4052' 'uwcov_4053' 'vwcov_4054' 'wvar_4055'}; names_for_var2={'nav_105' 'peru_4056' 'perv_4057' }; names_for_var3={'ustd_' 'vstd_' 'wstd_' 'agc' 'cor' 'hsd_' 'psd_' 'rsd_' 'tx_1211'}; names_for_velvar=[names_for_var1 names_for_var2 names_for_var3]; names_for_vel=[names_for_velocity]; names_for_t={'t_24' 't_20' 't_28'}; names_for_c={'c_50','c_51' 's_40', 's_41' 'sth_71'}; names_for_ox={'o_60' 'o2raw' 'ost_62'}; names_for_trans={'attn_55' 'tran_4010' 'trn_107'}; names_for_obs={'neph_56' 'nep1' 'nep2'}; %names_for_abss={}; names_for_orientation={'tiltx_4017' 'tilty_4018' 'comp_1406' 'comp_1404'}; names_for_orientn2={'hdg_1215' 'ptch_1216' 'roll_1217'}; % it's really critical that it found the right _cmab's for the data in the % .xls. If your file has a temperature variable, but there's no TEMP_cmab % displayed, it won't treat the T_xx variable, and it won't be in the % output file. SO check this carefully! disp('this was read- are all the needed params here???') [ tripod_struct(fidx).tripodid tripod_struct(fidx).habname] resp=input('(y or n?) ','s'); if strcmp(lower(resp),'y') for g=6:length(vn) sval=char(lower(ncnms(g))); if (length(sval)> 3) sval=sval(1:3); end matches_vel=~isempty(strmatch(sval,names_for_vel)); matches_velvar=~isempty(strmatch(sval,names_for_velvar)); matches_ori1=~isempty(strmatch(sval,names_for_orientation)); matches_ori2=~isempty(strmatch(sval,names_for_orientn2)); if (strmatch(lower(ncnms(g)),names_for_pressure)) j=find(strncmpi([tripod_struct(fidx).habname],'pres',4)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif (matches_vel || matches_velvar) if ~isempty(strfind(ncfilename,'_d1')) % midas with bass, pod1 j=find(strncmpi([tripod_struct(fidx).habname],'basspod1',8)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif ~isempty(strfind(ncfilename,'_d2')) % midas with bass, pod2 j=find(strncmpi([tripod_struct(fidx).habname],'basspod2',8)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif ~isempty(strfind(ncfilename,'adv')) % adv j=find(strncmpi([tripod_struct(fidx).habname],'adv',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif ~isempty(strfind(ncfilename,'pca')) % pcadp j=find(strncmpi([tripod_struct(fidx).habname],'pca',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif ~isempty(strfind(ncfilename,'rcm')) % aanderraa j=find(strncmpi([tripod_struct(fidx).habname],'opt',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif find(strncmpi([tripod_struct(fidx).habname],'dlcm',4)) % dlcm j=find(strncmpi([tripod_struct(fidx).habname],'dlcm',4)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters else disp([lower(ncnms(g)) 'this current measurement did not find a category, so nothing done']) end elseif (matches_ori1 || matches_ori2) % MIDAS with bass orientation is 1.3m above pod1 and 1.9 above % pod2 if ~isempty(strfind(ncfilename,'_d1')) % midas with bass, pod1 j=find(strncmpi([tripod_struct(fidx).habname],'basspod1',8)); nih=(tripod_struct(fidx).hab(j)/100)+1.29; %must convert to meters elseif ~isempty(strfind(ncfilename,'_d2')) % midas with bass, pod2 j=find(strncmpi([tripod_struct(fidx).habname],'basspod2',8)); nih=(tripod_struct(fidx).hab(j)/100)+1.89; %must convert to meters elseif ~isempty(strfind(ncfilename,'_d0')) % might be any data % bass orientation was usually 2.29mab, so use this value nih=2.29; %must convert to meters % use instrument height for these elseif ~isempty(strfind(ncfilename,'adv')) % adv j=find(strncmpi([tripod_struct(fidx).habname],'adv',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif ~isempty(strfind(ncfilename,'pca')) % adv j=find(strncmpi([tripod_struct(fidx).habname],'pca',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters else disp([lower(ncnms(g)) 'this current measurement did not find a category, so nothing done']) end elseif (strmatch(lower(ncnms(g)),names_for_t)) j=find(strncmpi([tripod_struct(fidx).habname],'temp',4)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif (strmatch(lower(ncnms(g)),names_for_c)) j=find(strncmpi([tripod_struct(fidx).habname],'cond',4)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif (strmatch(sval,names_for_trans)) j=find(strncmpi([tripod_struct(fidx).habname],'tran',4)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif (strmatch(sval,names_for_obs)) j=find(strncmpi([tripod_struct(fidx).habname],'obs',3)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters elseif (strmatch(lower(ncnms(g)),names_for_ox)) j=find(strncmpi([tripod_struct(fidx).habname],'o2',2)); nih=tripod_struct(fidx).hab(j)/100; %must convert to meters else disp(['no match for ' char(ncnms(g)) ' in ' char(ncfilename) ]) nih=input('Enter the instrument height (m) to use\n','s'); nih=str2double(nih); end %now put the outcome into the variable attributes if (~exist('nih')) disp('no instrument height known- please enter one (m):') disp(' use: nih=###; return') keyboard end nc{name(vn{g})}.sensor_hab=ncfloat(nih); nc{name(vn{g})}.sensor_depth=ncfloat(new_struct.new_water_depth-nih); if ~isempty(nc{name(vn{g})}.initial_sensor_height(:)) nc{name(vn{g})}.initial_sensor_height=ncfloat(nih); end clear j nih end % for each variable else disp('OK, time to go back to the drawing board') return end [r2,dval2]=extract_ncdepth(nc); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % this section changes the contents of the depth() coordinate variable % so keep the original depth info in attributes nc{'depth'}.ori_water_depth=water_depth_ori; dp=nc{'depth'}(:); % should be the original measurement_depth dnp=num2str(dp(1)); if length(dp) > 1 for kk=2:length(dp) dnp=[dnp ', ' num2str(dp(kk))]; end end nc{'depth'}.oridepth=dnp; % save the original measurement depth(s) % Finally insert adjusted measurement depths- in almost all cases % it should be the depth of the measurement(s) % for velocity files isvel=union(strfind(ncfilename,'v-'), strfind(ncfilename,'v')); %midas and adv isvel2=union(strfind(ncfilename,'s1-'), strfind(ncfilename,'spd')); %midas and adv isvar=strfind(ncfilename,'var-'); % variance stats ispr=union(strfind(ncfilename,'p-'), strfind(ncfilename,'psd')); %pr ispca=strfind(ncfilename,'pca'); %pcadp istcp=union(strfind(ncfilename,'tc'), strfind(ncfilename,'tp-')); % older temp and cond issb=union(strfind(ncfilename,'mc'), strfind(ncfilename,'sc')); % seacat isaanderaa=union(strfind(ncfilename,'rcm'), strfind(ncfilename,'aa')); % rcm ctd istct=strfind(ncfilename,'tct-'); % tct can have just about anything in it iscs=strfind(ncfilename,'cs'); % these only have c & s, no t isatt=strfind(ncfilename,'att'); % rcm ctd isox=strfind(ncfilename,'ox'); % any oxygen isysi=strfind(ncfilename,'ysi'); % any ysi if (~isvel & ~isvar & ~istcp & ~issc & ~ismc & ~isatt & ~isox ... & ~isvel2 & ~ispca & ~istct & ~iscs & ~isaanderaa) disp (['Cannot identify file type for ' ncfilname]); end if (~isempty(isvar)) % must be before vel- var will be true for both tx=(strmatch('uvar_4050',lower(ncnms))); eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of u_variance measurement'); elseif (~isempty(isvel) || ~isempty(isvel2)) tx=(strmatch('u_',lower(ncnms))); eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx(1))) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of velocity measurement'); elseif (~isempty(ispr)) tx=(strmatch('p_4',lower(ncnms))); % might be p_1, p_4, p_4023 if isempty(tx) tx=(strmatch('p_1',lower(ncnms))); if isempty(tx) tx=(strmatch('p_4023',lower(ncnms))); end end eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx(1))) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of pressure sensor'); elseif (~isempty(istct)) % has to be before the ones looking for t_ tx=length(lower(ncnms)); % use the last variable name eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of last variable'); elseif (~isempty(issb) || ~isempty(istcp) || ~isempty(isysi)) tx=(strmatch('t_20',lower(ncnms))); % might be t_20 or t_24 if isempty(tx) tx=(strmatch('t_24',lower(ncnms))); if isempty(tx) tx=(strmatch('t_28',lower(ncnms))); end end if ~isempty(tx) eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of temperature measurement'); end elseif (~isempty(iscs)) tx=(strmatch('s_40',lower(ncnms))); eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of attn measurement'); elseif (~isempty(isatt)) tx=(strmatch('attn_55',lower(ncnms))); eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of attn measurement'); elseif (~isempty(isox)) tx=(strmatch('o_60',lower(ncnms))); eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); nc{'depth'}.CMNT=ncchar('adjusted using depth of oxygen measurement'); elseif (~isempty(ispca)) wd_dif=nc.WATER_DEPTH(:)-water_depth_ori new_dp=dp+wd_dif nc{'depth'}.CMNT=ncchar('adjusted using dufference between original and new water_depth'); elseif (~isempty(isaanderaa)) tx=(strmatch('u_1205',lower(ncnms))); nc{'depth'}.CMNT=ncchar('adjusted using depth of velocity measurement'); if isempty(tx) tx=(strmatch('t_',lower(ncnms))); nc{'depth'}.CMNT=ncchar('adjusted using depth of temperature measurement'); if isempty(tx) tx=(strmatch('o_60',lower(ncnms))); nc{'depth'}.CMNT=ncchar('adjusted using depth of oxygen measurement'); end end eval(['nc{''depth''}(:)=nc{''' char(ncnms(tx)) '''}.sensor_depth(:);']); else disp('not accounted for yet- please modify nc{''depth''} as appropriate') keyboard end % file names with _d3, _d4 will land here, along with any other name % that's not "normal" if isempty(tx) %means depth was unchanged disp('bad depth variable, trying to fix') tnm=ncnames(var(nc)); [p,q]=size(tnm); td=eval(['nc{''' char(tnm(q)) '''}.sensor_depth(:);']); eval(['nc{''depth''}(:)=nc{''' char(tnm(q)) '''}.sensor_depth(:);']); cmnt=['nc{''depth''}.CMNT=ncchar(''adjusted using depth of ' char(tnm(q)) ' measurement.'')']; eval(cmnt); % return disp ('fixed....') end if isempty(strmatch('oridepth',ncnames(att(nc{'depth'})))) %depth NOT adjusted disp ('unable to repair. exiting') return end [r3,dval3]=extract_ncdepth(nc); % check the new file has the right stuff **uncomment for debugging % [char(fn{ik}) ': '] % disp([dval.strs{1:2} dval.strs{3}]) % disp(dval.vals) % disp(dval2.vals) % disp(dval3.vals) % since depth is accounted for, don't do a inst_height in the global % metadata- just use the sensor_hab info in each variable close(nc) end % finally, verify that all the variables seem reasonable and match eval(['diary log' tripno '.txt']) for jj=1:length(fn) disp_ncdepth(fn{jj}); end diary off