function out = realtimeobservationdatamaker(inpath) % out = realtimeobservationdatamaker(inpath) % inputs: % - inpath : string with full path to .csv file created by realtimeobservationdatamaker.pl; can just be name if % this is run from directory where .csv files live (preferred usage) % outputs: % - out : vintage data array % % This program prompts the user to enter additional information after evaluating the .csv file; gives user opportunity % to save file in current directory or designated directory. % % The data must be annual, semiannual, quarterly, or monthly -- cannot handle higher freq than monthly. % % This program assumes that the first vintage date of all is listed for the first observation: this is typically done in % ALFRED. % % This program is ignorant of which months have 31, 30, or 28/29 days. Moreover, entered dates will be floored before % using. % % Author: Seth Pruitt, 1/21/07 % sjpruitt@ucsd.edu mtchr = '(\w+)[\.]'; mtchd = regexp(inpath,mtchr,'tokens'); rootname = char(mtchd{1,1}); data = importdata(inpath); freqnames = cell(12,1); freqnames{1,1}='ANNUAL';freqnames{1,2}='SEMIANNUAL';freqnames{1,4}='QUARTERLY';freqnames{1,12}='MONTHLY'; disp(' ') disp('****************************************************************************************') disp('*** realtimeobservationdatamaker ***') disp(' ') % Test for the frequency of the observations on the phenomena (which may be different from the frequency of the % vintages) if data.colheaders{1,1} ~= 'observation_date_year' error('The first entry of the data colheaders was not "observation_date_year,", indicating that there may be an error') end obsdates = unique(data.data(:,1:3),'rows'); tmp1 = diff(unique(obsdates(:,1))); if tmp1 ~= ones(length(tmp1),1) error('The unique year values seem to be missing a year') end %%% Vintages frequency if data.colheaders{1,2} ~= 'observation_date_month' error('The second entry of the data colheaders was not "observation_date_month,", indicating that there may be an error') end tmp1 = diff(unique(obsdates(:,2))); if tmp1 == zeros(length(tmp1),1) obsfreq = 1; disp(['* It appears that the OBSERVATION frequency of the data is ',freqnames{1,obsfreq}]) elseif tmp1 == 6*ones(length(tmp1),1) obsfreq = 2; disp(['* It appears that the OBSERVATION frequency of the data is ',freqnames{1,obsfreq}]) elseif tmp1 == 3*ones(length(tmp1),1) obsfreq = 4; disp(['* It appears that the OBSERVATION frequency of the data is ',freqnames{1,obsfreq}]) elseif tmp1 == ones(length(tmp1),1) obsfreq = 12; disp(['* It appears that the OBSERVATION frequency of the data is ',freqnames{1,obsfreq}]) else error('The vector of month entries has properties that make frequency determination fail') end disp(' ') desfreq = []; while isempty(desfreq) disp(' ') disp('> Given the identified observation frequency, please specify a desired vintage/realtime frequency') disp(' - enter 1 for annual, 2 for semiannual, 4 for quarterly, 12 for monthly') desfreq = input(' ---> '); if (desfreq ~= 1) & (desfreq ~= 2) & (desfreq ~= 4) & (desfreq ~= 12) disp(' ');disp(' !! YOUR INPUT IS UNRECOGNIZED !!');disp(' '); desfreq = []; end end disp(' ') disp(['* You have selected a VINTAGE/REALTIME frequency that is ',freqnames{1,desfreq}]) disp(' ');disp(' ');disp(' ') disp('*************') disp(' ') disp(' The first year of observation dates are') disp(obsdates(1:obsfreq,1:3)) disp(' The first few vintage dates are') vindates = unique(data.data(:,5:7),'rows'); tmp1 = vindates(1,:); disp(vindates(1:10,:)) %%% Vintage start date desbegdate = []; while isempty(desbegdate) disp(' ') disp('> Given this information, please specify a desired beginning vintage date') disp(' This should be sometime at or after the first vintage date') disp(' - enter a row date vector as seen above to specify the desired beginning date') desbegdate = input(' ---> '); if ~isnumeric(desbegdate) disp(' ');disp(' !! YOUR INPUT IS NOT A NUMERIC ARRAY');disp(' '); desbegdate = []; elseif ~(size(desbegdate,1) == 1 & size(desbegdate,2) == 3) disp(' ');disp(' !! YOUR INPUT IS NOT A ROW VECTOR WITH 3 ENTRIES');disp(' '); desbegdate = []; elseif (desbegdate(1) < tmp1(1)) || (desbegdate(1) == tmp1(1) & desbegdate(2) < tmp1(2)) || ... (desbegdate(1) == tmp1(1) & desbegdate(2) == tmp1(2) & desbegdate(3) < tmp1(3)) disp(' ');disp(' !! YOUR INPUT IS EARLIER THAN THE FIRST VINTAGE DATE');disp(' '); desbegdate = []; elseif desbegdate(2) > 12 | desbegdate(2) < 1 disp(' ');disp(' !! YOUR INPUT MONTH IS NOT BETWEEN 1 AND 12');disp(' '); desbegdate = []; elseif desbegdate(3) > 31 | desbegdate(3) < 1 disp(' ');disp(' !! YOUR INPUT DAY IS NOT BETWEEN 1 AND 31');disp(' '); desbegdate = []; else desbegdate = floor(desbegdate); end end %%% Observation later start date option desobsbeg = []; while isempty(desobsbeg) disp(' ') disp('> Do you want to use all the observations or begin later than the first observation?') disp(' - answer "y" to USE ALL or "n" to SPECIFY A LATER FIRST OBSERVATION (repl double quotes with single)') desobsbeg = input(' ---> '); if ~isstr(desobsbeg) disp(' ');disp(' !! YOUR INPUT IS NOT A STRING (bracketed by single quotes)');disp(' '); desobsbeg = []; elseif max(desobsbeg ~= 'y') & max(desobsbeg ~= 'n') disp(' ');disp(' !! YOUR INPUT MUST be "y" or "n"');disp(' '); desobsbeg =[]; end end switch desobsbeg case 'y'; disp(' '); disp('* You have chosen to USE ALL the observation dates possible') case 'n'; disp(' '); desobsbeg2=[]; while isempty(desobsbeg2) disp('* You have chosen to SPECIFY A LATER FIRST OBSERVATION') disp('> Enter a row date vector as seen above to specify the desired beginning date') desobsbeg2 = input(' ---> '); if ~isnumeric(desobsbeg2) disp(' ');disp(' !! YOUR INPUT IS NOT A NUMERIC ARRAY');disp(' '); desobsbeg2 = []; elseif ~(size(desobsbeg2,1) == 1 & size(desobsbeg2,2) == 3) disp(' ');disp(' !! YOUR INPUT IS NOT A ROW VECTOR WITH 3 ENTRIES');disp(' '); desobsbeg2 = []; elseif (desobsbeg2(1) < obsdates(1,1)) || (desobsbeg2(1) == obsdates(1,1) & desobsbeg2(2) < obsdates(1,2)) || ... (desobsbeg2(1) == obsdates(1,1) & desobsbeg2(2) == obsdates(1,2) & desobsbeg2(3) < obsdates(1,3)) disp(' ');disp(' !! YOUR INPUT IS EARLIER THAN THE FIRST OBSEVATION DATE');disp(' '); desobsbeg2 = []; elseif desobsbeg2(2) > 12 | desobsbeg2(2) < 1 disp(' ');disp(' !! YOUR INPUT MONTH IS NOT BETWEEN 1 AND 12');disp(' '); desobsbeg2 = []; elseif desobsbeg2(3) > 31 | desobsbeg2(3) < 1 disp(' ');disp(' !! YOUR INPUT DAY IS NOT BETWEEN 1 AND 31');disp(' '); desobsbeg2 = []; else desobsbeg2 = floor(desobsbeg2); jnk = find(ismember(obsdates,desobsbeg2,'rows') == 1); if isempty(jnk) disp(' ');disp(' !! YOUR INPUT DATE DID NOT EXACTLY MATCH ONE OF THE EXISTING OBS DATES');disp(' '); odn = obsdates(:,1) + obsdates(:,2)/12 + obsdates(:,3)/(12*31); don = desobsbeg2(1) + desobsbeg2(2)/12 + desobsbeg2(3)/(12*31); before = find( odn < don ,1,'last'); after = find( odn > don ,1, 'first'); disp(' The first obs date before your input date is:') disp([' ---- ',num2str(obsdates(before,:)),' ---- if empty, it means your input date is before all obs dates']) disp(' The first obs date after your input date is:') disp([' ---- ',num2str(obsdates(after,:)),' ---- if empty, it means your input date is after all obs dates']) desobsbeg2=[]; end end end obsdates = obsdates(jnk:end,:); disp(' ');disp([' - The observation dates have been changed to start at ',num2str(jnk)]);disp(' '); otherwise error('Something unexpected has happened at observation start step'); end %%% Data calculation disp(' ');disp('* The desired vintage/realtime date series has been created using a conventional regular frequency'); disp(' ') years = [desbegdate(1):1:vindates(end,1)]'; months = [1:desfreq]'*(12/desfreq) + desbegdate(2); months = months.*(months <= 12) + (months-12).*(months > 12); months = [desbegdate(2);months]; unimonths = unique(months); days = desbegdate(3); tmp3 = vindates(end,1) + vindates(end,2)/12 + vindates(end,3)/(12*31); jnk = find( ( (diff(months)>0) == 0 ), 1);% this is the entry in months that is the last of the year jnk_1m = months(1:jnk); jnk_1m = [ones(length(jnk_1m),1)*years(1), jnk_1m]; years = years(2:end); jnk_rm = [kron(years,ones(desfreq,1)) kron(ones(length(years),1),unimonths)]; jnk_months = [jnk_1m;jnk_rm]; jnk_dates = [jnk_months desbegdate(3)*ones(size(jnk_months,1),1)]; jnk_whrlss = find( ( ( jnk_dates(:,1) + jnk_dates(:,2)/12 + jnk_dates(:,3)/(12*31) ) >= tmp3 ), 1 ); desdates = jnk_dates(1:jnk_whrlss,:); ddn = desdates(:,1) + desdates(:,2)/12 + desdates(:,3)/(12*31); drawnow out.x = NaN(size(obsdates,1),size(desdates,1)); out.t = obsdates;out.v = desdates';or=1; waba = waitbar(0,['This proportion of the ',num2str(size(obsdates,1)),' obs dates have had their vintage data calculated']); for obs = obsdates' % obs is a col vec oi = find( ismember(data.data(:,1:3),obs','rows') == 1 ); od = data.data(oi,:); os = od(:,5) + od(:,6)/12 + od(:,7)/(12*31); oe = od(:,8) + od(:,9)/12 + od(:,10)/(12*31); if max(max(isnan(od(:,1:3)))) > 0 | max(max(isnan(od(:,5:7)))) > 0 error('We has found NaN entries in the observation dates or vin start dates') elseif max(sum(isnan(od(:,8:10)),1)) > 1 error(['There was more than one vin end date with NaNs for obs date ',num2str(obs'),' in data rows ',num2str(oi')]) end on = find( mean(isnan(od(:,8:10))')' == 1); if on ~= size(od,1) error(['The vin date with NaNs should have been the last one found for obs date ',num2str(obs'),... ' in data rows ',num2str(oi'),' but it was not']) elseif max(os(on) < oe(1:on-1)) > 0 error(['The vin date with NaNs has a vin start date that is not after the preceding vin end dates for obs date ',... num2str(obs'),' in data rows ',num2str(oi')]) else oe(on) = Inf; end %% "larger-than" method lt = zeros(size(ddn)); for ojjj = (1:size(od,1)) lt = lt + (ddn >= os(ojjj)); end tmp=[]; tmp = [NaN(1,size(od,2));od];lt=lt+1; ltc = tmp(lt,4); out.x(or,:) = ltc'; or=or+1; waitbar((or-1)/size(obsdates,1)) end close(waba) disp(' ');disp(' ');disp(' ') disp('*************') disp(' ') %%% Save option dessave = []; while isempty(dessave) disp(' ') disp('> Do you want to save the output structure realtimeobservationdatamaker created?') disp(' - answer "y" for SAVE or "n" for NO SAVE (repl double quotes with single)') dessave = input(' ---> '); if ~isstr(dessave) disp(' ');disp(' !! YOUR INPUT IS NOT A STRING (bracketed by single quotes)');disp(' '); dessave = []; elseif max(dessave ~= 'y') & max(dessave ~= 'n') disp(' ');disp(' !! YOUR INPUT MUST be "y" or "n"');disp(' '); dessave =[]; end end switch dessave case 'n'; disp(' '); disp('* You have chosen to NOT SAVE the output structure') case 'y'; disp(' '); desfilename=[]; while isempty(desfilename) disp('* You have chosen to SAVE the output structure') disp('> You can specify the filename with a whole path from the root (e.g. "c:/data/thisfile"),') disp([' a path from the Matlab current directory (which is "',cd,'") (e.g. "somedir/thisfile"),']) disp(' or just the filename (e.g. "thisfile")') disp(' Or you can input the word "default" for the default naming (preferred option)') disp(' (in all of these, replace the examples double quotes with single') desfilename = input(' ---> '); if ~isstr(desfilename) disp(' ');disp(' !! YOUR INPUT IS NOT A STRING (bracketed by single quotes)');disp(' '); desfilename = []; end end if isempty(strmatch(desfilename,'default')) save(desfilename,'out'); disp(' '); disp('* An empty workspace file has been saved in the current directory noting when this file was created') mtchr = '[\\](\w+)[\.]'; mtchd = regexp(inpath,mtchr,'tokens'); if isempty(mtchd) inputfile = inpath; else inputfile = mtchd{1,1}; end mtchd = regexp(desfilename,mtchr,'tokens'); if isempty(mtchd) outputfile = desfilename; else outputfile = match{1,1} end now = datestr(clock,30); mrkdfl = [rootname,'_TO_',outputfile,'_',now]; save([mrkdfl,'.mat'],'inpath','desfilename','inputfile','outputfile','rootname','obsdates','desdates','obsfreq','desfreq') else disp(' '); disp('* An empty workspace file has been saved in the current directory noting when this file was created') outputfile = [rootname,'_',freqnames{1,desfreq}]; save(outputfile,'out'); now = datestr(clock,30); mrkdfl = [rootname,'_TO_',outputfile,'_',now]; save([mrkdfl,'.mat'],'inpath','desfilename','outputfile','rootname','obsdates','desdates','obsfreq','desfreq') end otherwise error('Something unexpected has happened at the save step'); end disp(' ') disp('****************************************************************************************');disp(' ') %% END