function out = SPDFBREAKDOWNEPOCH16(epoch16) %SPDFBREAKDOWNEPOCH16 converts the CDF_EPOCH16 time, picoseconds since % 0000-01-01 to UTC date/time. % % OUT = SPDFBREAKDOWNEPOCH16(epoch16) returns the UTC date/time from CDF_EPOCH16 % time. OUT is an array with each row having ten (10) numerical values % for year, month, day, hour, minute, second, millisecond, microsecond, % nanosecond and picosecond.. % % epoch16 An array with each row having two (2) numerical % value in CDF_EPOCH16 of mxDOUBLE_CLASS (double). % % Examples: % % % breakdown three CDF_EPOCH16 times to their UTC form. % % data = spdfparseepoch16 (['2009-01-01T00:00:00.123456789123', ... % '2009-01-01T12:00:00.987654321123', ... % '2009-01-01T12:34:56.123456789123']); % out = SPDFBREAKDOWNEPOCH16(data) % ans = % % 2009 1 1 0 0 0 123 456 789 123 % 2009 1 1 12 0 0 987 654 321 123 % 2010 1 1 12 34 56 123 456 789 123 % % % See also SPDFENCODEEPOCH16, SPDFPARSEEPOCH16, SPDFCOMPUTEEPOCH16 % HISTORY: % August 16, 2014 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFBREAKDOWNEPOCH16:inputArgumentCount', ... 'SPDFBREAKDOWNEPOCH16 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFBREAKDOWNEPOCH16:outputArguments', ... 'SPDFBREAKDOWNEPOCH16 requires only one output argument.') end if (~isa(epoch16,'numeric')) error('MATLAB:SPDFBREAKDOWNEPOCH16:inputArguments', ... 'SPDFBREAKDOWNEPOCH16 requires the input to be in numeric.') end ss=size(epoch16); if (ss(1) < 1 || ss(2) ~= 2) error('MATLAB:SPDFBREAKDOWNEPOCH16:inputArguments', ... 'SPDFBREAKDOWNEPOCH16 requires each row to have just two (2) field.') end out = spdfbreakdownepoch16c (epoch16); end function out = SPDFBREAKDOWNEPOCH(epoch) %SPDFBREAKDOWNEPOCH converts the CDF_EPOCH time, milliseconds since % 0000-01-01 to UTC date/time. % % OUT = SPDFBREAKDOWNEPOCH(epoch) returns the UTC date/time from CDF_EPOCH % time. OUT is an array with each row having seven (7) numerical values % for year, month, day, hour, minute, second, millisecond. % % epoch A vector with each row having one (1) numerical % value in CDF_EPOCH of mxDOUBLE_CLASS (double). % % Examples: % % % breakdown three CDF_EPOCH times to their UTC form. % % data = spdfparseepoch (['2009-01-01T00:00:00.123', ... % '2009-01-01T12:00:00.987', ... % '2009-01-01T12:34:56.123']); % out = SPDFBREAKDOWNEPOCH(data) % ans = % % 2009 1 1 0 0 0 123 % 2009 1 1 12 0 0 987 % 2010 1 1 12 34 56 123 % % % See also CDFEPOCH, SPDFENCODEEPOCH, SPDFPARSEEPOCH, SPDFCOMPUTEEPOCH % HISTORY: % August 16, 2014 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFBREAKDOWNEPOCH:inputArgumentCount', ... 'SPDFBREAKDOWNEPOCH requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFBREAKDOWNEPOCH:outputArguments', ... 'SPDFBREAKDOWNEPOCH requires only one output argument.') end ss=size(epoch); if (ss(1) < 1 || ss(2) ~= 1) error('MATLAB:SPDFBREAKDOWNEPOCH:inputArguments', ... 'SPDFBREAKDOWNEPOCH requires each row to have just one (1) field.') end out = spdfbreakdownepochc (epoch); end function out = SPDFBREAKDOWNTT2000(tt2000) %SPDFBREAKDOWNTT2000 converts the CDF TT2000 time, nanoseconds since % 2000-01-01 12:00:00 to UTC date/time. % % OUT = SPDFBREAKDOWNTT2000(tt2000) returns the UTC date/time from CDF TT2000 % time. OUT is an array with each row having nine (9) numerical values % for year, month, day, hour, minute, second, millisecond, microsecond % and nanosecond. % % tt2000 A vector with each row having one (1) numerical % value in CDF TT2000 of mxINT64_CLASS (int64). % % Examples: % % % breakdown three CDF TT2000 times to their UTC form. % % data = [ 284040066307456789; 284083267171654321; 315621362307456789]; % out = SPDFBREAKDOWNTT2000(data) % ans = % % 2009 1 1 0 0 0 123 456 789 % 2009 1 1 12 0 0 987 654 321 % 2010 1 1 12 34 56 123 456 789 % % % See also CDFTT2000, SPDFENCODETT2000, SPDFPARSETT2000, SPDFCOMPUTETT2000 % HISTORY: % August 16, 2014 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFBREAKDOWNTT2000:inputArgumentCount', ... 'SPDFBREAKDOWNTT2000 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFBREAKDOWNTT2000:outputArguments', ... 'SPDFBREAKDOWNTT2000 requires only one output argument.') end if (~isa(tt2000,'numeric')) error('MATLAB:SPDFBREAKDOWNTT2000:inputArguments', ... 'SPDFBREAKDOWNTT2000 requires the input to be in numeric.') end ss=size(tt2000); if (ss(1) < 1 || ss(2) ~= 1) error('MATLAB:SPDFBREAKDOWNTT2000:inputArguments', ... 'SPDFBREAKDOWNTT2000 requires each row to have just one (1) field.') end if (~isa(tt2000, 'int64')) out = spdfbreakdowntt2000c (int64(tt2000(:))); else out = spdfbreakdowntt2000c (tt2000); end function info = spdfcdfinfo(filename, varargin) %SPDFCDFINFO Get details about a CDF file. % INFO = SPDFCDFINFO(FILE) gives information about a Common Data Format % (CDF) file. INFO is a structure containing the following fields: % % Filename A string containing the name of the file % % FileModDate A string containing the modification date of % the file % % FileSize An integer indicating the size of the file in % bytes % % Format A string containing the file format (CDF) % % FormatVersion A string containing the version of the CDF % library used to create the file % % FileSettings A structure containing the file settings % describing the file % % Subfiles A cell array of filenames which contain the % CDF file's data if it is a multifile CDF % % Variables A cell array containing details about the % variables in the file (see below) % % GlobalAttributes A structure containing the global meta-data % % VariableAttributes A structure containing meta-data for the % variables % % LibVersion A string containing the library version of % the CDF that is used to build the SPDFCDFinfo tool % % PatchVersion A string containing the patch version of % the MATLAB-CDF modules, e.g., spdfcdfinfo, % spdfcdfread, spdfcdfwrite, and its release % % Note: The CDF file name can be passed in as a null. In this case, INFO % contains only the CDF library version and MATLAB-CDF version. % % The "Variables" field contains a cell array of details about the % variables in the CDF file. There are two presentations that can be % acquired. The original form is presented as the following: % each row represents a variable in the file. The columns are: % % (1) The variable's name as a string. % % (2) The dimensions of the variable according to MATLAB's SIZE % function. % % (3) The number of records assigned for this variable. % % (4) The variable's data type as it is stored in the CDF file. % % (5) The record and dimension variance settings for the variable. % The value to the left of the slash designates whether values % vary by record; the values to the right designate whether % values vary at each dimension. % % (6) The sparsity of the variables records. Allowable values are % 'Full', 'Sparse(padded)', and 'Sparse(previous)'. % % (7) The compression of the variables. Allowable values are % 'None', 'RLE', 'HUFF', 'AHUFF', and 'GZIP.x' where x is the % GZIP compression level. % % (8) The blocking factors of the variables, if set. A blocking factor is % the chunk of records to be pre-allocated for a standard variable when % a record being written does not already exist, or the number of % records to be compressed together for a compressed variable. For % variables with large record size or number, providing a large % blocking factor would have a significant impact on I/O performance % over the defaults. % % (9) The pad values of the variables, if set. % (10) The FILLVAL attribute entry values of the variables, if set. % (11) The VALIDMIN attribute entry values of the variables, if set. % (12) The VALIDMAX attribute entry values of the variables, if set. % % varinfo = spdfcdfinfo (FILE, 'VARIABLES', {'var1', 'var2', ...}); % The optional 'VARIABLES' can be used to specify the variables that their % info is to be returned. The info includes only two varibale related fields: % Variables and VariableAttributes. No CDF info, e.g., Filename, Format, etc, % will be retrieved. A null is filled if a variable is not found in the CDF. % % info = spdfcdfinfo (FILE, 'VARSTRUCT', TF); % The returned Variable field can also be presented in a structure form, if % the option is provided with a true value. % % The structure has the following fields, each one is a cell array. % % Name A string containing the name of the variable % % Dimensions The dimensions of the variable % % NumRecords The number of written records for the variable % % DataType The data type of the variable % % RecDimVariance Record and dimensional variances of the variable % % Sparseness The sparseness of the variable % % Compression The Compression of the variablee % % BlockingFactor The blocking factor of the variable % % PadValue The pad value of the variable % % FILLVAL The FILLVAL attribute entry value for the variable % % VALIDMIN The VALIDMIN attribute entry value for the variable % % VALIDMAX The VALIDMAX attribute entry value for the variable % % The "GlobalAttributes" and "VariableAttributes" structures contain a % field for each attribute. Each field's name corresponds to the name % of the attribute, and the field contains a cell array containing the % entry values for the attribute. For variable attributes, the first % column of the cell array contains the Variable names associated with % the entries, and the second contains the entry values. % % NOTE: Attribute names which SPDFCDFINFO uses for field names in % "GlobalAttributes" and "VariableAttributes" may not match the names % of the attributes in the CDF file exactly. Because attribute names % can contain characters which are illegal in MATLAB field names, they % may be translated into legal field names. Illegal characters which % appear at the beginning of attributes are removed; other illegal % characters are replaced with underscores ('_'). If an attribute's % name is modified, the attribute's internal number is appended to the % end of the field name. For example, ' Variable%Attribute ' might % become 'Variable_Attribute_013'. % % To get the CDF library version that is used to build the current MATLAB % tool programs, e.g., spdfcdfread, spdfcdfwrite, spdfcdfinfo, you can % simply enter the command without providing a CDF file: % spdfcdfinfo() % % Library version may differ from a CDF file's version. A CDF file is % assigned with the library version when it is created or modified. % % Notes: % % SPDFCDFINFO creates temporary files when accessing CDF files. The % current working directory must be writable. % % % See also SPDFCDFREAD, SPDFCDFUPDATE, SPDFCDFWRITE, CDFEPOCH, CDFTT2000, % SPDFENCODEEPOCH, SPDFCOMPUTEEPOCH, SPDFPARSEEPOCH, % SPDFBREAKDOWNEPOCH, SPDFENCODEEPOCH16, SPDFCOMPUTEEPOCH16, % SPDFPARSEEPOCH16, SPDFBREAKDOWNEPOCH16, SPDFENCODETT2000, % SPDFCOMPUTETT2000, SPDFPARSETT2000, SPDFBREAKDOWNTT2000, % SPDFDATENUMTOEPOCH, SPDFDATENUMTOEPOCH16, SPDFDATENUMTOTT2000, % SPDFCDFLEAPSECONDSINFO % % HISTORY: % August 17, 2007 David Han Modified to handle CDF_EPOCH16. Look for % 'epoch16'. % July 17, 2009 Mike Liu Added a new field 'LibVersion' for the % returned structure to show the library % version. 'PatchVersion' will show the % patch version of the MATLAB release. % August 10, 2010 Mike Liu Added INT8 and TT2000 data types. % % % Process arguments. % %if (argin < 1) % if ~(nargin == 0) || ~(length(strtrim(filename)) == 0) % error('MATLAB:spdfcdfinfo:inputArguments', 'SPDFCDFINFO requires at least one input argument.') % end %end if ~(nargout == 1) if ~(nargin == 0) && ~(length(strtrim(filename)) == 0) error('MATLAB:spdfcdfinfo:outputArguments', 'SPDFCDFINFO requires one output argument.') end end % CDFlib creates temporary files in the current directory. Make sure PWD is % writable. %[attrib_success, attrib_mode] = fileattrib(pwd); % %if (~attrib_mode.UserWrite) % error('Cannot create temporary files. The current directory must be writable.') %end % % Returned structure % info1.Filename = ''; info1.FileModDate = ''; info1.FileSize = ''; info1.Format = ''; info1.FormatVersion = ''; info1.FileSettings = []; info1.FileSettings = {}; info1.Subfiles = {}; info1.Variables = {}; info1.GlobalAttributes = []; info1.VariableAttributes = []; info1.LibVersion = ''; info1.PatchVersion = '3.7.1.0'; info2.Variables = {}; info2.VariableAttributes = []; args.VarStruct = false; args.Variables = {}; variables = false; if (nargin == 0) || (length(strtrim(filename)) == 0) % Only for library info tmp = spdfcdfinfoc(' '); % Library version. theLibVersion = sprintf('%d.%d.%d', tmp.LibVersion.Version, ... tmp.LibVersion.Release, ... tmp.LibVersion.Increment); disp(['LibVersion: ',theLibVersion]); disp(['PatchVersion: ', info1.PatchVersion]); else % Parse arguments based on their number. if (nargin > 0) paramStrings = {'variables' 'varstruct'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'varstruct' varstruct = varargin{k + 1}; if (numel(varstruct) ~= 1) msg = 'The "varstruct" value must be a scalar logical.'; end if (islogical(varstruct)) args.VarStruct = varstruct; elseif (isnumeric(varstruct)) args.VarStruct = logical(varstruct); else msg = 'The "varstruct" value must be a scalar logical.'; end case 'variables' if (k == length(varargin)) msg = 'No variables specified.'; return else args.Variables = varargin{k + 1}; if (~iscell(args.Variables)) args.Variables = {args.Variables}; end for p = 1:length(args.Variables) if (~ischar(args.Variables{p})) msg = 'All variable names must be strings.'; return end end if (length(args.Variables) > 0) variables = true; end end end % switch end % for end % Get full filename. fid = fopen(filename); % % Verify existence of filename. % if (fid == -1) % Look for filename with extensions. fid = fopen([filename '.cdf']); if (fid == -1) fid = fopen([filename '.CDF']); end end if (fid == -1) error('MATLAB:spdfcdfinfo:fileOpen', 'Couldn''t open file (%s).', filename) else filename = fopen(fid); fclose(fid); end if ~variables % % Record the file details. % d = dir(filename); % Set the positions of the fields. info1.Filename = d.name; info1.FileModDate = d.date; info1.FileSize = d.bytes; info1.Format = 'CDF'; end % CDFlib's OPEN_ routine is flakey when the extension ".cdf" is used. % Strip the extension from the file before calling the MEX-file. if ((length(filename) > 4) && (isequal(lower(filename((end-3):end)), '.cdf'))) filename((end-3):end) = ''; end % Get the attribute, variable, and library details. tmp = spdfcdfinfoc(filename, args.VarStruct, args.Variables); if ~variables % Process file attributes. info1.FileSettings = parse_file_info(tmp.File); info1.FormatVersion = info1.FileSettings.Version; info1.FileSettings = rmfield(info1.FileSettings, 'Version'); % Handle multifile CDF's. if isequal(info1.FileSettings.Format, 'Multifile') d = dir([filename '.v*']); for p = 1:length(d) info1.Subfiles{p} = d(p).name; end end end if ~args.VarStruct % Process variable table. vars = tmp.Variables; types = vars(:, 4); otypes = vars(:, 4); sp = vars(:, 6); pv = vars(:, 9); for p = 1:length(types) types{p} = find_datatype(types{p}); sp{p} = find_sparsity(sp{p}); pv{p} = find_padvalue(otypes{p}, pv{p}); end vars(:, 4) = types; vars(:, 6) = sp; vars(:, 9) = pv; if ~variables info1.Variables = vars; else info2.Variables = vars; end else vars = tmp.Variables; types = vars.DataType; otypes = vars.DataType; sp = vars.Sparseness; pv = vars.PadValue; for p = 1:length(types) types{p} = find_datatype(types{p}); sp{p} = find_sparsity(sp{p}); pv{p} = find_padvalue(otypes{p}, pv{p}); end vars.DataType = types; vars.Sparseness = sp; vars.PadValue = pv; if ~variables info1.Variables = vars; else info2.Variables = vars; end end % Assign rest. if ~variables info1.GlobalAttributes = tmp.GlobalAttributes; end if ~variables info1.VariableAttributes = tmp.VariableAttributes; else info2.VariableAttributes = tmp.VariableAttributes; end if ~variables info1.LibVersion = sprintf('%d.%d.%d', tmp.LibVersion.Version, ... tmp.LibVersion.Release, ... tmp.LibVersion.Increment); end if ~variables info = info1; else info = info2; end end function out = parse_file_info(in) out = in; % Format. if (in.Format == 2) out.Format = 'Multifile'; else out.Format = 'Single-file'; end % Encoding. out.Encoding = find_encoding(in.Encoding); % Majority. if (in.Majority == 1) out.Majority = 'Row'; else out.Majority = 'Column'; end % Version. out.Version = sprintf('%d.%d.%d', in.Version, in.Release, in.Increment); out = rmfield(out, {'Release', 'Increment'}); % Compression. [comp_type, comp_param, comp_pct] = find_compression(in.Compression, ... in.CompressionParam, ... in.CompressionPercent); out.Compression = comp_type; out.CompressionParam = comp_param; out.CompressionPercent = comp_pct; % Checksum. if (in.Checksum == 1) out.Checksum = 'MD5'; else out.Checksum = 'None'; end % LeapSecondLastUpdated. if (in.LeapSecondLastUpdated >= 0) out.LeapSecondLastUpdated = in.LeapSecondLastUpdated; else out.LeapSecondLastUpdated = 'Not set'; end function str = find_datatype(num) if (isempty(num)) str = []; else switch (num) case {1, 41} str = 'int8'; case {2} str = 'int16'; case {4} str = 'int32'; case {8} str = 'int64'; case {11} str = 'uint8'; case {12} str = 'uint16'; case {14} str = 'uint32'; case {21, 44} str = 'single'; case {22, 45} str = 'double'; case {31} str = 'epoch'; case {32} str = 'epoch16'; case {33} str = 'tt2000'; case {51, 52} str = 'char'; end end function str = find_padvalue(num, value) if (isempty(value)) str = []; else switch (num) case {1, 41} str = int8(value); case {2} str = int16(value); case {11} str = uint8(value); case {12} str = uint16(value); case {21, 44} str = single(value); case {22, 45} str = double(value); case {51, 52} str = value; case {8, 33} str = int64(value); case {4} str = int32(value); case {14} str = uint32(value); case {31} str = double(value); case {32} str = value; end end function str = find_sparsity(num) if (isempty(num)) str = []; else switch (num) case 0 str = 'Full'; case 1 str = 'Sparse(padded)'; case 2 str = 'Sparse(previous)'; end end function str = find_encoding(num) if (isempty(num)) str = []; else switch (num) case 1 str = 'Network'; case 2 str = 'Sun'; case 3 str = 'Vax'; case 4 str = 'DECStation'; case 5 str = 'SGI'; case 6 str = 'IBM-PC'; case 7 str = 'IBM-RS'; case 8 str = 'Host'; case 9 str = 'Macintosh'; case 11 str = 'HP'; case 12 str = 'NeXT'; case 13 str = 'Alpha OSF1'; case 14 str = 'Alpha VMS d'; case 15 str = 'Alpha VMS g'; case 16 str = 'Alpha VMS i'; case 17 str = 'ARM Little'; case 18 str = 'ARM Big'; case 19 str = 'IA64 VMS i'; case 20 str = 'IA64 VMS d'; case 21 str = 'IA64 VMS g'; end end function [ctype, param, pct] = find_compression(ctype, param, pct) if (isempty(ctype)) ctype = []; param = []; pct = []; else switch (ctype) case 0 ctype = 'Uncompressed'; param = ''; pct = []; case 1 ctype = 'Run-length encoding'; if (param == 0) param = 'Encoding of zeros'; else param = ''; end case 2 ctype = 'Huffman'; if (param == 0) param = 'Optimal encoding trees'; else param = ''; end case 3 ctype = 'Adaptive Huffman'; if (param == 0) param = 'Optimal encoding trees'; else param = ''; end case 4 ctype = 'Rice'; param = ''; case 5 ctype = 'Gzip'; end end function SPDFCDFLEAPSECONDSINFO(varargin) %SPDFCDFLEAPSECONDSINFO shows the information how the leap seconds is used by %CDF. % % SPDFCDFLEAPSECONDSINFO() displays the basic setup the CDF library uses to % acquire the leap second table. % % SPDFCDFLEAPSECONDSINFO('DUMP', TF) the 'DUMP' option will show the contents % of the leap second table, in addition to the basic information, if TF is % true. % % See also CDFTT2000, SPDFENCODETT2000, SPDFCOMPUTETT2000, SPDFPARSETT2000, % SPDFBREAKDOWNTT2000. % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:SPDFCDFLEAPSECONDSINFO:badInputArguments', '%s', msg) end spdfcdfleapsecondsinfoc(args.Dump); %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.Dump = false; msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'dump'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) msg = 'Parameter name must be a string.'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'dump' if (k == length(varargin)) msg = 'No dump specified.'; return else dump = varargin{k + 1}; if (numel(dump) ~= 1) msg = 'The "Dump" value must be a scalar logical.'; end if (islogical(dump)) args.Dump = dump; elseif (isnumeric(dump)) args.Dump = logical(dump); else msg = 'The "Dump" value must be a scalar logical.'; end end end % switch end % for end % if (nargin > 1) function [out, info] = spdfcdfread(filename, varargin) %SPDFCDFREAD Read the data from a CDF file. % DATA = SPDFCDFREAD(FILE) reads all of the variables from each record of % FILE. Every piece of data from the CDF file is read and returned. % % Note: To improve the performance and reduce the size of returned data, % especially working with large data files, the previously designated as % optional option 'Combinerecords' (with 'true' value) has been changed to be % the default. No need to specify this option, unless 'false' is requested. % % DATA = SPDFCDFREAD(FILE, 'CombineRecords', TF, ...) combines all of the % records from each variable into a cell array with one row (1-by-N), where % N is the number of variables, if TF is true (the default). Each cell in % the cell array is either a scalar value or an array. Each cell may contain % a different number of data elements. For example, a single value(s) is % returned for a variable of non-record variant, while a multi-dimensional % array of data is returned for record-variant of scalar or dimensional % variables. For epoch data of CDF_EPOCH, CDF_EPOCH16 and CDF_TIME_TT2000 % types, their values are automatically converted into MATLAB's datenum. % (To overwrite the conversion, use 'KeepEpochAsIs' option.) % % If the option 'Combinerecords' is specified as false, DATA will be a cell % array of M-by-N, where M is the maximum number of record among the variables % and N is the number of variables. Each row corresponds to a record while % each column to a variable. This is the default output from MATLAB's % distributed CDFREAD module. The data from scalar variables are % imported into a column array. Importing dimensional and string data % extends the dimensionality of the variable. For example, % reading 1000 records of a 1-byte variable with dimensions of 20-by-30 % yields a cell containing a 20-by-30-by-1000 UINT8 array. For data % from non-record variant variables, as their values never change from % record to record, same value(s) will be repeated in all records. % % DATA = SPDFCDFREAD(FILE, 'Records', RECNUMS, ...) reads particular % records from a CDF file. RECNUMS is a vector of one or more % zero-based record numbers to read. DATA is a cell array with % length(RECNUM) number of rows. There are as many columns as % variables. % % DATA = SPDFCDFREAD(FILE, 'Variables', VARNAMES, ...) reads the variables % in the cell array VARNAMES from a CDF file. DATA is a vector array % with length(VARNAMES) number of columns. There is a row for each % record requested. % % DATA = SPDFCDFREAD(FILE, 'Slices', DIMENSIONVALUES, ...) reads specified % values from one variable in the CDF file. The matrix DIMENSIONVALUES % is an m-by-3 array of "start", "interval", and "count" values. The % "start" values are zero-based. % % The number of rows in DIMENSIONVALUES must be less than or equal to % the number dimensions of the variable. Unspecified rows are filled % with the values [0 1 N] to read every value from those dimensions. % % When using the 'Slices' parameter, only one variable can be read at a % time, so the 'Variables' parameter must be used. % % DATA = SPDFCDFREAD(FILE, 'ConvertEpochToDatenum', TF, ...) converts CDF % epoch data values to MATLAB datenum if TF is true (the default if the % 'CombineRecords' is true). In this case, variable data will be presented in % an array of datenum. If TF is false (the default if 'CombineRecords' is % false), data of CDF_EPOCH type are wrapped in CDFEPOCH objects and % CDF_TIME_TT2000 in CDFTT2000 objects, which can hurt performance for large % datasets. For higher time resolution types as CDF_EPOCH16 and CDF_TIME_TT2000, % this option will cause the loss of sub-milliseconds resolution and not % properly present the time at a leap second time. % % DATA = SPDFCDFREAD(FILE, 'ConvertEpochToDatestr', TF, ...) converts CDF % epoch data values to MATLAB datestr if TF is true. This option is % similar to 'ConvertEpochToDatenum', with each CDF epoch returning as the % form: dd-mmm-yyyy hh:mm:ss (all sub-milliseconds info is not displayed). % To display sub-milliseconds, use the 'CDFEpochToString' option. % % DATA = SPDFCDFREAD(FILE, 'KeepEpochAsIs', TF, ...) whether to keep CDF % Epoch data values as is. If TF is set as true, no data conversion % from CDF epoch to MATLAB datenum is performed. The data values can % be written back to CDF later again without MATLAB datenum to CDF epoch % conversion. Each epoch will be kept as a double for CDF_EPOCH data, array % of doubles for CDF_EPOCH16 data, or an INT64 (mxINT64_CLASS) for % CDF_TIME_TT2000. If false, the default, all CDF epoch data will be converted % to MATLAB's datenum. CDF epoch values can be encoded, broken down, etc, by % epoch handling modules, e.g., spdfencodeepoch, spdfencodett2000, % spdfbreakdownepoch, spdfbreakdowntt2000, etc. % % DATA = SPDFCDFREAD(FILE, 'CDFEpochToString', TF, ...) whether to return % CDF Epoch data values in strings, instead of numeric values. If TF % is set to true, each epoch data, by default, will be presented in the % form of dd-mon-yyyy hh:mm:ss.mmm for CDF_EPOCH, or % dd-mon-yyyy hh:mm:ss.mmm:uuu:nnn:ppp for CDF_EPOCH16, or % yyyy-mm-ddThh:mm:ss.mmmuuunnn for CDF_TIME_TT2000. % % DATASTRUCT = SPDFCDFREAD(FILE, 'Structure', TF, ...) returns a structure % array (instead of a cell array) that contains the following % fields for each member (a variable) in the array if TF is true: % VariableName - variable name % Data - variable data in M-by-1 cell array without 'CombineRecords' % option, or a multi-dimensional array with 'CombineRecords' % Attributes - a structure that contains all the attributes that % associated with this variable % % DATA = SPDFCDFREAD(FILE, 'DATAONLY', TF, ...) specifies whether to simply % just return the CDF variable data, without metadata, nor attribute info. % This option provides the quick way of retrieving variable data as is, if % true, without any data conversion. The retrieved data will be in the same % form as the non-dataonly option, either a cell array for multiple % variables or a vector for a single variable. It works with these defined % options: % "CombineRecords", true, "KeepEpochAsis', true, "CDFEpochtoDatenum", false % without calling spdfcdfinfo for any info about the variables. % If the 'Variables' option is provided, only selected variables' data are % returned. Otherwise, all variables are retrieved. An empty matrix is % returned for the variable that is not found in the CDF. The dataonly option % works faster as it only reads the data and it, unlike all other options, % will not call spdfcdfinfo to collect the vital CDF and variable info. % Such metadata and its variables' info can be acquired separately from % spdfcdfinfo call, if required. % % [DATA, INFO] = SPDFCDFREAD(FILE, ...) also returns details about the CDF % file in the INFO structure. % % Notes: % % SPDFCDFREAD creates temporary files when accessing CDF files. The % current working directory must be writable. % % Currently, it is not possible to provide a set of records to read % (using the 'Records' parameter) and to combine records (using the % 'CombineRecords' parameter). % % 'ConvertEpochToDatenum', 'ConvertEpochToDatestr', 'KeepEpochAsIs' % and 'CDFEpochToString' are mutually exclusive. % % Examples: % % % Read all of the data from example.cdf with the default of true for % 'Combinerecords' option, the most efficient way. % % data = spdfcdfread('example'); % % % Read the same file as above and also return any CDF EPOCH or EPOCH16 % variable data in the string form (dd-mon-yyyy hh:mm:ss.mmm for EPOCH, % dd-mon-yyyy hh:mm:ss.mmm.uuu.nnn.ppp for EPOCH16 or % yyyy-mm-ddThh:mm:ss.mmmuuunnn for CDF_TIME_TT2000) if they exist. % % data = spdfcdfread('example', 'CDFEpochtoString', true); % % % Read just the data from variable "Time". % % data = spdfcdfread('example', 'Variable', {'Time'}); % % % Read the first value in the first dimension, the second value in % % the second dimension, the first and third values in the third % % dimension, and all of the values in the remaining dimension of % % the variable "multidimensional". % % data = spdfcdfread('example', 'Variable', {'multidimensional'}, ... % 'Slices', [0 1 1; 1 1 1; 0 2 2]); % % % The example above is analogous to reading the whole variable % % into a variable called "data" and then using matrix indexing, % % as follows: % % data = spdfcdfread('example', ... % 'Variable', {'multidimensional'}); % data{1}(1, 2, [1 3], :) % % % Displays the name of the variable being processed. % % data = spdfcdfread('example', 'ShowProgress', true); % % See also CDFEPOCH, CDFTT2000, SPDFCDFINFO, SPDFCDFWRITE, SPDFCDFUPDATE, % SPDFENCODEEPOCH, SPDFCOMPUTEEPOCH, SPDFBREAKDOWNEPOCH, % SPDFPARSEEPOCH, SPDFEPOCHTODATENUM, SPDFENCODEEPOCH16, % SPDFCOMPUTEEPOCH16, SPDFBREAKDOWNEPOCH16, SPDFPARSEEPOCH16, % SPDFEPOCH16TODATENUM, SPDFENCODETT2000, SPDFCOMPUTETT2000, % SPDFBREAKDOWNTT2000, SPDFPARSETT2000, SPDFDATENUMTOEPOCH, % SPDFDATENUMTOEPOCH16, SPDFDATENUMTOTT2000. % HISTORY: % November 13, 2007 David Han The following changes have been made to % spdfcdfreadc.c: % - Added a logic to read CDF_EPOCH and % CDF_EPOCH16 data. % - Modified to return variable attributes % besides the variable data. % - Modified to read all the records in one % read by default. % % Removed the cdfepoch routine since it % 1) doesn't work with some CDF files % 2) is no longer needed with the new % spdfcdfreadc.c % % No longer calls the find_records function % (since all the variable data records are % read in one read by default). % % spdfcdfread.m now returns a structure (instead % of just variable data) that contains the % following fields for each variable: % % VariableName - variable name % Data - variable data % Attributes - a structure that contains % all the attributes that % associated with this % variable % % Added the 'ShowProgress' option that % displays the name of the variable being % processed. This option can be useful if % a CDF file contains a lot of variables or % takes a long time to read all the % variables. % % Mike Liu Addendum... For the backward compatibility: % 1) cdfepoch object is still supported, % but it can't handle CDF_EPOCH16 data % 2) data returned as a structure is now % an option % % October 20, 2008 Mike Liu The following change has been made to % spdfcdfreadc.c: % - Handled combining 'CombineRecords' and % 'ConvertEpochToDatenum' options % February 4, 2009 Mike Liu Added a dummy call to spdfcdfreadc after normal % calls. Previously, each spdfcdfreadc call % involves open/close the CDF file while % reading a variable's data. Now, only the % first spdfcdfreadc call opens the file, % but it does not close the file anymore. % Instead, the dummy spdfcdfreadc call % closes the file after all spdfcdfreadc % calls are done. % % February 23, 2009 Mike Liu Added 'KeepEpochAsIs' option to keep % CDF epoch values in MATLAB. Added % 'ConvertEpochToDatestr' option. Not call % convert_epoch anymore as CDF epoch values % to MATLAB datenum conversion is done in % spdfcdfreadc (much faster) and it calls % cdfepoch directly if needed. % September 9, 2011 Mike Liu Changed to return UTC strings for % CDF_EPOCH16 as the default. Use % epoch16todatenum to convert the strings % to MATLAB's datenum if % 'ConvertEpochToDatenum' option is specified. % March 5, 2013 Mike Liu Changed to 'KeepEpochAsIs' option to allow % returning CDF_EPOCH16 data into array of % doubles, instead of string. % % % Process arguments. % if (nargin < 1) error('MATLAB:spdfcdfread:inputArgumentCount', ... 'SPDFCDFREAD requires at least one input argument.') end if (nargout > 2) error('MATLAB:spdfcdfread:outputArguments', ... 'SPDFCDFREAD requires two or fewer output argument.') end [args, msg, structure, show_progress] = parse_inputs(varargin{:}); if (args.DataOnly && (nargout == 2)) error('MATLAB:spdfcdfread:outputArguments', ... 'SPDFCDFREAD requires only one output argument for dataonly option.') end if (~isempty(msg)) error('MATLAB:spdfcdfread:badInputArguments', '%s', msg) end validate_inputs(args); if (~args.DataOnly) if (args.CombineRecords) if (args.epochtodatenum == 1) args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; elseif (args.epochtodatestr == 1) args.ConvertEpochToDatenum = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; elseif (args.keepepoch == 1) args.ConvertEpochToDatenum = false; args.ConvertEpochToDatestr = false; args.CDFEpochToString = false; elseif (args.epochtostring == 1) args.ConvertEpochToDatenum = false; args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; else args.ConvertEpochToDatenum = true; args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; end else if (args.epochtodatenum == 1) args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; elseif (args.epochtodatestr == 1) args.ConvertEpochToDatenum = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; elseif (args.keepepoch == 1) args.ConvertEpochToDatenum = false; args.ConvertEpochToDatestr = false; args.CDFEpochToString = false; elseif (args.epochtostring == 1) args.ConvertEpochToDatenum = false; args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; else args.ConvertEpochToDatenum = false; args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; end end end % % Verify existence of filename. % % Get full filename. fid = fopen(filename); if (fid == -1) % Look for filename with extensions. fid = fopen([filename '.cdf']); if (fid == -1) fid = fopen([filename '.CDF']); end end if (fid == -1) error('MATLAB:spdfcdfread:fileOpen', 'Couldn''t open file (%s).', filename) else filename = fopen(fid); fclose(fid); end % CDFlib's OPEN_ routine is flakey when the extension ".cdf" is used. % Strip the extension from the file before calling the MEX-file. if ((length(filename) > 4) && (isequal(lower(filename((end-3):end)), '.cdf'))) filename((end-3):end) = ''; end if (args.DataOnly) out = spdfcdfreadc(filename, args.Variables, args.Records, ... [], args.CombineRecords, ... args.ConvertEpochToDatenum, structure, ... args.KeepEpochAsIs, args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (numel(args.Variables) == 1) out = out{1}; end else % % Get information about the variables. % info = spdfcdfinfo(filename); if (isempty(args.Variables)) args.Variables = info.Variables(:, 1)'; end % To make indexing info.Variables easier, reorder it to match the values in % args.Variables and remove unused values. Deblank variable list because % the intersection is based on the predicate of equality of strings. % Inconsistent trailing blanks in variable names from args and info may cause % inadvertent mismatch and consequent failure. [int, idx1, idx2] = intersect(deblank(args.Variables), ... deblank(info.Variables(:, 1))); if (length(int) < length(args.Variables)) % Determine which requested variables do not exist in the CDF. invalid = setdiff(args.Variables, int); msg = 'The following requested variables are not in this CDF:'; msg = [msg sprintf('\n\t%s',invalid{:})]; error('MATLAB:spdfcdfread:variableNotFound', '%s', msg) end % Remove unused variables. info.Variables = info.Variables(idx2, :); % Reorder the variables to match the order of args.Variables. [tmp, reorder_idx] = sort(idx1); info.Variables = info.Variables(reorder_idx, :); if (~structure) if (isempty(args.Records)) args.Records = find_records(info.Variables); elseif (any(args.Records < 0)) error('MATLAB:spdfcdfread:recordNumber', 'Record values must be nonnegative.') end end % % Read each variable. % if (length(args.Variables) == 1) % Special case for single variable. if (info.Variables{3} == 0) out = []; return; end if (~isempty(args.Slices)) [args.Slices, msg] = parse_slice_vals(args.Slices, info.Variables); if (~isempty(msg)) error('MATLAB:spdfcdfread:sliceValue', '%s', msg) end else args.Slices = fill_slice_vals([], info.Variables); end [data, attrs] = spdfcdfreadc(filename, args.Variables{1}, args.Records, ... args.Slices, args.CombineRecords, ... args.ConvertEpochToDatenum, structure, ... args.KeepEpochAsIs, args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (isequal(lower(info.Variables{4}), 'epoch16') && ... (args.KeepEpochAsIs)) data=transpose(data); end [dataX, dummy] = spdfcdfreadc('to_close', args.Variables{1}, args.Records, ... args.Slices, args.CombineRecords, ... args.ConvertEpochToDatenum, false, ... args.KeepEpochAsIs, args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (~structure) if (isequal(lower(info.Variables{4}), 'tt2000')) if (args.CombineRecords || args.ConvertEpochToDatenum || ... args.KeepEpochAsIs || args.ConvertEpochToDatestr) out = data; else if (length(data) > 1) for p = 1:length(data) if (length(data{p}) > 1) for q = 1:length(data{p}) databb(q) = cdftt2000(data{p}(q,1)); end dataaa{p,1} = databb; else dataaa(p,1) = cdftt2000(data{p}); end end out = dataaa; else out = cdftt2000(data); end end elseif (isequal(lower(info.Variables{4}), 'epoch')) if (args.ConvertEpochToDatenum || args.CDFEpochToString || ... args.KeepEpochAsIs || args.ConvertEpochToDatestr || ... args.CombineRecords) out = data; else if (~args.ConvertEpochToDatenum) % % None option - set up for cdfepoch object % if (length(data) > 1) for p = 1:length(data) if (length(data{p}) > 1) for q = 1:length(data{p}) databb(q) = cdfepoch(data{p}(q,1)); end dataaa{p,1} = databb; else dataaa(p,1) = cdfepoch(data{p}); end end out = dataaa; else out = cdfepoch(data); end else out = data; end end elseif (isequal(lower(info.Variables{4}), 'epoch16') && ... args.KeepEpochAsIs) out = transpose(data); else out = data; end else out.VariableName = args.Variables{1}; out.Data = data; out.Attributes = attrs; end elseif ((~isempty(args.Slices)) && (length(args.Variables) ~= 1)) error('MATLAB:spdfcdfread:sliceValue', 'Specifying variable slices requires just one variable.') else if (structure) % Regular reading. out1 = cell(length(args.Variables),3); for p = 1:length(args.Variables) if (show_progress) fprintf ('%d) Reading variable "%s"\n', p, args.Variables{p}); end if (info.Variables{p, 3} == 0) continue; end args.Slices = fill_slice_vals([], info.Variables(p,:)); out1{p,1} = args.Variables{p}; [datax, attrs] = spdfcdfreadc(filename, args.Variables{p}, args.Records, ... args.Slices, args.CombineRecords, ... args.ConvertEpochToDatenum, true, ... args.KeepEpochAsIs, ... args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (isequal(lower(info.Variables{p, 4}), 'epoch16')) if (args.KeepEpochAsIs) out1{p,2} = transpose(datax); else out1{p,2} = datax; end else out1{p,2} = datax; end out1{p,3} = attrs; end [dataX, dummy] = spdfcdfreadc('to_close', args.Variables{1}, args.Records, ... args.Slices, args.CombineRecords, ... args.ConvertEpochToDatenum, false, ... args.KeepEpochAsIs, ... args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); % Change a cell array to an array of structures. fields = {'VariableName', 'Data', 'Attributes'}; out = cell2struct(out1, fields, 2); if (~structure) out = arrayfun(@(x)x.Data,out,'UniformOutput',false); end else if (args.CombineRecords) data = cell(1, length(args.Variables)); else data = cell(length(args.Records), length(args.Variables)); end for p = 1:length(args.Variables) if (show_progress) fprintf ('%d) Reading variable "%s"\n', p, args.Variables{p}); end if (info.Variables{p, 3} == 0) continue; end args.Slices = fill_slice_vals([], info.Variables(p,:)); if (info.Variables{p, 5}(1) == 'F') % Non-record variant % Special case for variables which don't vary by record. [xdata, dummy] = spdfcdfreadc(filename, args.Variables{p}, 0, ... args.Slices, ... args.CombineRecords, ... args.ConvertEpochToDatenum, false, ... args.KeepEpochAsIs, ... args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (args.CombineRecords) if (isequal(lower(info.Variables{p, 4}), 'epoch16')) if (args.KeepEpochAsIs) data{p} = transpose(xdata); else data{p} = xdata; end else data{p} = xdata; end % data{p} = xdata; else data(:,p) = repmat(xdata, length(args.Records), 1); end else % Record variant [xdata, dummy] = spdfcdfreadc(filename, args.Variables{p}, ... args.Records, args.Slices, ... args.CombineRecords, ... args.ConvertEpochToDatenum, ... false, ... args.KeepEpochAsIs, ... args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); if (args.CombineRecords) if (isequal(lower(info.Variables{p, 4}), 'epoch16') && ... args.KeepEpochAsIs) data{p} = transpose(xdata); else data{p} = xdata; end else % M-by-N cell array.... % Convert epoch data. if (isequal(lower(info.Variables{p, 4}), 'tt2000')) if (args.CombineRecords || args.ConvertEpochToDatenum || ... args.KeepEpochAsIs || args.ConvertEpochToDatestr) data(:,p) = xdata; else for q = 1:length(xdata) if (length(xdata{q}) > 1) for r = 1:length(xdata{q}) databb(r,1) = cdftt2000(xdata{q}(r,1)); end data{q,p} = databb; else data{q,p} = cdftt2000(xdata{q}); end end end elseif (isequal(lower(info.Variables{p, 4}), 'epoch')) if (args.CDFEpochToString || args.KeepEpochAsIs || ... args.CombineRecords || ... args.ConvertEpochToDatenum || args.ConvertEpochToDatestr) data(:,p) = xdata; elseif (~args.ConvertEpochToDatenum) % % None option case - set up to cdfepoch object % if (length(xdata) > 1) for q = 1:length(xdata) if (length(xdata{q}) > 1) for r = 1:length(xdata{q}) databb(r,1) = cdfepoch(xdata{q}(r,1)); end data{q,p} = databb; else data{q,p} = cdfepoch(xdata{q}); end end end else data{1,p} = cdfepoch(xdata); end elseif (isequal(lower(info.Variables{p, 4}), 'epoch16')) if (args.KeepEpochAsIs) data(:,p) = transpose(xdata); else data(:,p) = xdata; end else data(:,p) = xdata; end end end end [dataX, dummy] = spdfcdfreadc('to_close', args.Variables{1}, args.Records, ... args.Slices, args.CombineRecords, ... args.ConvertEpochToDatenum, false, ... args.KeepEpochAsIs, args.CDFEpochToString, ... args.ConvertEpochToDatestr, args.DataOnly); out = data; end end end %%% %%% Function find_records %%% function records = find_records(var_details) % Find which variables to consider. rec_values = [var_details{:, 3}]; max_record = max(rec_values); if (isempty(max_record)) records = []; else records = 0:(max_record - 1); end %%% %%% Function parse_fill_vals %%% function [slices, msg] = parse_slice_vals(slices, var_details) msg = ''; % Find the number of dimensions that the CDF recognizes. This is given % explicitly in the variance specification as the number of values to the % right of the '/' (i.e., the length of the variance string minus two). vary = var_details{5}; num_cdf_dims = size(vary, 2) - 2; % % Check the user-provided slice values. % if (num_cdf_dims < size(slices, 1)) msg = sprintf(['Number of slice rows (%d) exceeds number of' ... ' dimensions (%d) in CDF variable.'], ... size(slices, 1), num_cdf_dims); return end if (any(slices(:,1) < 0)) msg = 'Slice indices must be nonnegative.'; return elseif (any(slices(:,2) < 1)) msg = 'Slice interval values must be positive.'; return elseif (any(slices(:,3) < 1)) msg = 'Slice count values must be positive.'; return end for p = 1:size(slices,1) % Indices are zero-based. max_idx = var_details{2}(p) - 1; last_requested = slices(p,1) + (slices(p,3) - 1) * slices(p,2); if (last_requested > max_idx) msg = sprintf(['Slice values for dimension %d exceed maximum' ... ' index (%d).'], p, max_idx); return end end % % Append unspecified slice values. % slices = fill_slice_vals(slices, var_details); %%% %%% Function fill_slice_vals %%% function slices = fill_slice_vals(slices, var_details) dims = var_details{2}; vary = var_details{5}; num_cdf_dims = size(vary, 2) - 2; if (num_cdf_dims > size(slices, 1)) % Fill extra dimensions. for p = (size(slices, 1) + 1):(num_cdf_dims) slices(p, :) = [0 1 dims(p)]; end elseif (num_cdf_dims == 0) % Special case for scalar values. slices = [0 1 1]; end %%% %%% Function parse_inputs %%% function [args, msg, structure, show_progress] = parse_inputs(varargin) % Set default values show_progress = false; structure = false; args.CombineRecords = true; args.ConvertEpochToDatenum = true; args.ConvertEpochToDatestr = false; args.KeepEpochAsIs = false; args.CDFEpochToString = false; args.DataOnly = false; args.Records = []; args.Slices = []; args.Variables = {}; args.epochtodatenum = 0; args.epochtodatestr = 0; args.keepepoch = 0; args.epochtostring = 0; msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'variables' 'records' 'slices' 'convertepochtodatenum' 'convertepochtodatestr' 'keepepochasis' 'combinerecords' 'structure' 'cdfepochtostring' 'dataonly' 'showprogress'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) msg = 'Parameter name must be a string.'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'variables' if (k == length(varargin)) msg = 'No variables specified.'; return else args.Variables = varargin{k + 1}; if (~iscell(args.Variables)) args.Variables = {args.Variables}; end for p = 1:length(args.Variables) if (~ischar(args.Variables{p})) msg = 'All variable names must be strings.'; return end end end case 'records' if (k == length(varargin)) msg = 'No records specified.'; return else records = varargin{k + 1}; if ((~isa(records, 'double')) || ... (length(records) ~= numel(records)) || ... (any(rem(records, 1)))) msg = 'Record list must be a vector of integers.'; end args.Records = records; args.CombineRecords = false; end case 'slices' if (k == length(varargin)) msg = 'No slice values specified.'; return else slices = varargin{k + 1}; if ((~isa(slices, 'double')) || ... (size(slices, 2) ~= 3) || ... (~isempty(find(rem(slices, 1) ~= 0)))) msg = 'Variable slice values must be n-by-3 array of integers.'; return end args.Slices = slices; end case 'convertepochtodatenum' if (k == length(varargin)) msg = 'No epoch conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Epoch conversion value must be a scalar logical.'; end if (islogical(convert)) args.ConvertEpochToDatenum = convert; elseif (isnumeric(convert)) args.ConvertEpochToDatenum = logical(convert); else msg = 'Epoch conversion value must be a scalar logical.'; end if (args.ConvertEpochToDatenum == 1) args.epochtodatenum=1; end end case 'convertepochtodatestr' if (k == length(varargin)) msg = 'No epoch conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Epoch conversion value must be a scalar logical.'; end if (islogical(convert)) args.ConvertEpochToDatestr = convert; elseif (isnumeric(convert)) args.ConvertEpochToDatestr = logical(convert); else msg = 'Epoch conversion value must be a scalar logical.'; end if (args.ConvertEpochToDatestr == 1) args.epochtodatestr=1; end end case 'combinerecords' if (k == length(varargin)) msg = 'Missing "CombineRecords" value.'; return else combine = varargin{k + 1}; if (numel(combine) ~= 1) msg = 'The "CombineRecords" value must be a scalar logical.'; end if (islogical(combine)) args.CombineRecords = combine; elseif (isnumeric(combine)) args.CombineRecords = logical(combine); else msg = 'The "CombineRecords" value must be a scalar logical.'; end end case 'showprogress' if (k == length(varargin)) msg = 'Missing "ShowProgress" value.'; return else sp = varargin{k + 1}; if (numel(sp) ~= 1) msg = 'The "ShowProgress" value must be a scalar logical.'; end if (islogical(sp)) show_progress = sp; elseif (isnumeric(sp)) show_progress = logical(sp); else msg = 'The "ShowProgress" value must be a scalar logical.'; end end case 'structure' if (k == length(varargin)) msg = 'Missing "Structure" value.'; return else sp = varargin{k + 1}; if (numel(sp) ~= 1) msg = 'The "Structure" value must be a scalar logical.'; end if (islogical(sp)) structure = sp; elseif (isnumeric(sp)) structure = logical(sp); else msg = 'The "Structure" value must be a scalar logical.'; end end case 'keepepochasis' if (k == length(varargin)) msg = 'No KeepEpochAsIs value specified.'; return else keepasis = varargin{k + 1}; if (numel(keepasis) ~= 1) msg = 'KeepEpochAsIs value must be a scalar logical.'; end if (islogical(keepasis)) args.KeepEpochAsIs = keepasis; elseif (isnumeric(keepasis)) args.KeepEpochAsIs = logical(keepasis); else msg = 'KeepEpochAsIs value must be a scalar logical.'; end if (args.KeepEpochAsIs ==1) args.keepepoch=1; end end case 'dataonly' if (k == length(varargin)) msg = 'No dataonly value specified.'; return else dataonly = varargin{k + 1}; if (numel(dataonly) ~= 1) msg = 'dataonly value must be a scalar logical.'; end if (islogical(dataonly)) args.DataOnly = dataonly; elseif (isnumeric(dataonly)) args.DataOnly = logical(dataonly); else msg = 'dataonly value must be a scalar logical.'; end if (args.DataOnly) args.CombineRecords = true; args.KeepEpochAsIs = true; args.ConvertEpochToDatenum = false; end end case 'cdfepochtostring' if (k == length(varargin)) msg = 'No CDFEpochToString value specified.'; return else epochtostring = varargin{k + 1}; if (numel(epochtostring) ~= 1) msg = 'CDFEpochToString value must be a scalar logical.'; end if (islogical(epochtostring)) args.CDFEpochToString = epochtostring; elseif (isnumeric(epochtostring)) args.CDFEpochToString = logical(epochtostring); else msg = 'CDFEpochToString value must be a scalar logical.'; end if (args.CDFEpochToString == 1) args.epochtostring=1; end end end % switch end % for end % if (nargin > 1) function epochs = convert_epoch(epoch_nums, convertToDatenum) %CONVERT_EPOCH Convert numeric epoch values to CDFEPOCH objects. % Note: MATLAB datenums are the number of days since 00-Jan-0000, while the % CDF epoch is the number of milliseconds since 01-Jan-0000. % Convert values from milliseconds to MATLAB serial dates. ml_nums = (epoch_nums ./ 86400000) + 1; % Convert MATLAB serial dates to CDFEPOCH objects. if (convertToDatenum) epochs = ml_nums; else epochs = cdfepoch(ml_nums); end function validate_inputs(args) %VALIDATE_INPUTS Ensure that the mutually exclusive options weren't provided. if ((args.CombineRecords) && (~isempty(args.Records))) error('MATLAB:spdfcdfread:combineRecordSubset', '%s\n%s', ... 'You cannot currently combine a subset of records.', ... 'Specify only one of ''CombineRecords'' and ''Records''.') end if ((args.epochtodatenum == 1) && (args.epochtodatestr == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''ConvertEpochToDatenum'' and ''ConvertEpochToDatestr'' to true.') end if ((args.epochtodatenum == 1) && (args.keepepoch == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''ConvertEpochToDatenum'' and ''KeepEpochAsIs'' to true.') end if ((args.epochtodatestr == 1) && (args.keepepoch == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''ConvertEpochToDatestr'' and ''KeepEpochAsIs'' to true.') end if ((args.epochtostring == 1) && (args.keepepoch == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''CDFEpochToString'' and ''KeepEpochAsIs'' to true.') end if ((args.epochtostring == 1) && (args.epochtodatenum == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''CDFEpochToString'' and ''ConvertEpochToDatenum'' to true.') end if ((args.epochtostring == 1) && (args.epochtodatestr == 1)) error('MATLAB:spdfcdfread:Epochmutualexclusive', '%s\n', ... 'Specify only one of ''CDFEpochToString'' and ''ConvertEpochToDatestr'' to true.') end function spdfcdfupdate(filename, varargin) %SPDFCDFUPDATE Update data in an existing CDF file. % % SPDFCDFUPDATE(FILE, 'VariableData', VARIABLELIST, ...) updates variable % data in a CDF file whose name is specified by FILE. VARIABLELIST is a % cell array of ordered pairs, which are comprised of a CDF variable name % (a string) and a corresponding value cell array. The value cell array % is comprised of a number of cells, each cell consisting of a record number, % a dimension indices, as well as the new data value. The record number and % dimension indices are all zero(0)-based. The number of dimension indices % depends on the dimensionality of the variable. The form for entering % multiple value changes for variables is as follows: % {'varname1' [ {rec_no_1, {index1, index2, ...}, value1}; ... % {rec_no_2, {index2, index2, ...}, value2}; ... % ... % ] ... % 'varname2' [ {rec_no_1, {index1, index2, ...}, value1}; ... % {rec_no_2, {index2, index2, ...}, value2}; ... % ... % ] ... % ... % } % % % SPDFCDFUPDATE(..., 'GlobalAttributes', GATTRIB, ...) updates the structure % GATTRIB as global meta-data for the CDF. Each field of the % struct is the name of a global attribute. The value of each % field contains the value of the attribute. To update % multiple values for an attribute, the field value should be a % cell array. % % SPDFCDFUPDATE(..., 'VariableAttributes', VATTRIB, ...) updates the % structure VATTRIB as variable meta-data for the CDF. Each % field of the struct is the name of a variable attribute. The % value of each field should be an mx2 cell array where m is the % number of variables with attributes. The first element in the % cell array is the name of the variable, a string, and the % second element, also a string, is the CDF specific data type of % the entry, and the third element is the new entry value of the % attribute for that variable. % % SPDFCDFUPDATE(..., 'CDFCompression', TF, ...) resets the CDF compression. % The CDF is set to use GZIP compression if TF is true. If TF is % is false, the CDF is set to be a uncompressed file. % % SPDFCDFUPDATE(..., 'CDFChecksum', TF, ...) resets the CDF checksum. % The CDF is set to use MD5 checksum if TF is true. If TF is % is false, the CDF is set not to use checksum. % % SPDFCDFUPDATE(..., 'CDFLeapSecondLastUpdated', value, ...) resets the CDF's % leap second last updated date. For CDFs created prior to V 3.6.0, this % field is not set. It is set to indicate what leap second table this CDF is % based upon. The value, in YYYYMMDD form, must be a valid entry in the % currently used leap second table, or zero (0) if the table is not used. % CDF will automatically fill the value with the last entry date in the leap % second table if this option is not specified. % % Notes: % % SPDFCDFUPDATE only updates the data values for the existing variables. % For Epoch and Epoch16 data type variables, the updated values should % be in the string form, e.g., 01-Jan-2008 07:06:05.004 and % 01-Jan-2008 07:06:05.004:100:200:300:400, respectively, instead of % the double form as they are stored. % % Examples: % % % Change data values for Longitude (a 1-dim of CDF_INT2 data type): % % 4th element in Record 0 to 100, 3rd element in Record 1 to 200; and % % change data value for variable Latitude (a 2-dim of CDF_REAL4 data type) % % at index [0,0] in Record 10 to 20.2; and change record 2 for variable % % Epoch (a 0-dim of CDF_EPOCH data type) to 01-Jan-2008 07:06:05.004 in % % the file 'example.cdf'. % % spdfcdfupdate('example', 'VariableData', {'Longitude' [{0,{3},100};{1,{2},200}] ... % 'Latitude' [{10,{0,0},20.2}] ... % 'Epoch' [{1,{0},'01-Jan-2008 07:06:05.004'}] ... % } ... % ); % Or, % var1 = {'Longitude' [{0,{3},100};{1,{2},200}]}; % var2 = {'Latitude' [{10,{0,0},20.2}]}; % var3 = {'Epoch' [{1,{0},'01-Jan-2008 07:06:05.004'}]}; % spdfcdfupdate('example', 'VariableData', [var1 var2 var3]); % % Make sure that the data values are of the data type for the variables. % % % Update the meta-data for the entry of variable attribute 'validmin' for % % variable 'Longitude' while updating its data values in the file 'example.cdf': % % varAttribStruct.validmin = {'Longitude' [10]}; % spdfcdfupdate('example', 'VariableData', {'Longitude' [{0,{3},100};{1,{2},200}]}, ... % 'VariableAttributes', varAttribStruct); % % % Update the global attribute, 'Name': the first entry to 'MyName', a CDF_CHAR % % data type, and the second entry to 10, of data type CDF_INT2, in the % % file 'example.cdf': % % globalAttribStruct.Name = [{0, 'CDF_CHAR', 'MyName'},{1, 'CDF_INT2', 10}]; % spdfcdfupdate('example', 'GlobalAttributes', globalAttribStruct); % % % Set the CDF file, 'example.cdf', to use the GZIP compression: % % spdfcdfupdate('example', 'cdfcompression', true); % % % Set the CDF file, 'example.cdf', to use the MD5 checksum: % % spdfcdfupdate('example', 'cdfchecksum', true); % % See also SPDFCDFREAD, SPDFCDFWRITE, SPDFCDFINFO, CDFEPOCH, CDFTT2000, % SPDFENCODEEPOCH, SPDFCOMPUTEEPOCH, SPDFPARSEEPOCH, % SPDFBREAKDOWNEPOCH, SPDFENCODEEPOCH16, SPDFCOMPUTEEPOCH16, % SPDFPARSEEPOCH16, SPDFBREAKDOWNEPOCH16, SPDFENCODETT2000, % SPDFCOMPUTETT2000, SPDFPARSETT2000, SPDFBREAKDOWNTT2000, % SPDFDATENUMTOEPOCH, SPDFDATENUMTOEPOCH16, SPDFDATENUMTOTT2000, % SPDFCDFLEAPSECONDSINFO % HISTORY: % January 13, 2009 Mike Liu The new function was created. % August 23, 2013 Mike Liu Added setting checksum operation. % % Process arguments. % if (nargin < 2) error('MATLAB:spdfcdfupdate:inputArgumentCount', ... 'CDFWRITE requires at least two input arguments.') end % parse_inputs sorts out all of the input args. Its return values: % % * args - an array of structs. args.VarNames contains the names % of the variables to be updated to the CDF. args.VarVals contains % the cell array for updating the data values. % * msg - an error message from parse_inputs that we pass on to the user. [args, varAttribStruct, globalAttribStruct, exception] = parse_inputs(varargin{:}); if (~isempty(exception.msg)) error(exception.id, '%s', exception.msg) end % % Create a proper filename for the CDF % % See if there is an extension [pname, fname, ext] = fileparts(filename); % If there is an extension, then remove it before passing it to CDFlib. if (~isempty(ext)) if (~isempty(strfind(ext, 'cdf'))) filename = fullfile(pname, fname); end end % % Call the underlying spdfcdfupdatec function which calls the CDFlib % spdfcdfupdatec(filename, args.VarNames, args.VarRecs, args.VarIndices, ... args.VarDataVals, varAttribStruct, globalAttribStruct, ... args.isCDFCompressed, args.CDFchecksum, ... args.CDFleapsecondlastupdated); %%% %%% Function parse_inputs %%% function [args, varAttribStruct, globalAttribStruct, exception] = parse_inputs(varargin) % Set default values args.VarNames = {}; args.VarRecs = {}; args.VarIndices = {}; args.VarDataVals = {}; varcell = {}; varAttribStruct = struct([]); globalAttribStruct = struct([]); exception.msg = ''; exception.id = ''; args.isCDFCompressed = int32(0); args.CDFchecksum = int32(0); args.CDFleapsecondlastupdated = int32(-999); % Parse arguments based on their number. if (nargin > 0) paramStrings = {'variabledata' 'globalattributes' 'variableattributes' 'cdfcompression' 'cdfchecksum' 'cdfleapsecondlastupdated'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) exception.msg = 'Parameter name must be a string.'; exception.id = 'MATLAB:spdfcdfupdate:paramNameNotString'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) exception.msg = sprintf('Unrecognized parameter name "%s".', param); exception.id = 'MATLAB:spdfcdfupdate:unrecognizedParam'; return elseif (length(idx) > 1) exception.msg = sprintf('Ambiguous parameter name "%s".', param); exception.id = 'MATLAB:spdfcdfupdate:ambiguousParam'; return end switch (paramStrings{idx}) case 'globalattributes' globalAttribStruct = varargin{k+1}; if ~isstruct(globalAttribStruct) exception.msg = ['''GlobalAttributes''' ' must be a struct.']; exception.id = 'MATLAB:spdfcdfupdate:globalAttributesNotStruct'; return end attribs = fieldnames(globalAttribStruct); % If the global attribute isn't a cell, then stuff it in one. for i = 1:length(attribs) attribVal = globalAttribStruct.(attribs{i}); s = size(attribVal); if ~iscell(attribVal) globalAttribStruct.(attribs{i}) = {attribVal}; end % The global attribute struct may have more than one set of % entry id, data type and value. However, there must only be % one associated value of the attribute for each entry, % hence the 3. if (s(2) == 3) % Transpose it because CDFlib reads the arrays column-wise. globalAttribStruct.(attribs{i}) = attribVal'; else % We have ordered pairs. globalAttribStruct.(attribs{i}) = reshape(globalAttribStruct.(attribs{i})(:),numel(globalAttribStruct.(attribs{i})(:))/3, 3); end end case 'variabledata' varcell = varargin{k+1}; if ~iscell(varcell) exception.msg = ['''VariableData''' ' must be a cell.']; exception.id = 'MATLAB:spdfcdfupdate:variabledatanotcell'; return end % First check that varcell meets all of our requirements args.VarNames = {varcell{1:2:end}}; args.VarVals = {varcell{2:2:end}}; if length(args.VarNames) ~= length(args.VarVals) exception.msg = 'All variable names must have a corresponding variable value cell array.'; exception.id = 'MATLAB:spdfcdfupdate:variableWithoutValue'; return end % args.VarVals % Check and make sure that all variable values are of the same % datatype, but ignore empties if ~isempty(args.VarVals) for i = 1:length(args.VarVals) a = args.VarVals{i}; if (~iscell(a)) a = {a}; end jj = numel(a)/length(a); args.VarRecs{i} = {a{1:jj}}; args.VarIndices{i} = {a{jj+1:2*jj}}; args.VarDataVals{i} = {a{2*jj+1:3*jj}}; end end case 'variableattributes' varAttribStruct = varargin{k+1}; if ~isstruct(varAttribStruct) exception.msg = ['''VariableAttributes''' ' must be a struct.']; exception.id = 'MATLAB:spdfcdfupdate:variableAttributesNotStruct'; return end attribs = fieldnames(varAttribStruct); % Check the VariableAttributes struct. for i = 1:length(attribs) % If the variable attribute isn't in a cell (because % it is scalar, then put it into a cell. attribVal = varAttribStruct.(attribs{i}); s = size(attribVal); if ~iscell(attribVal) varAttribStruct.(attribVal) = {attribVal}; end % The variable attribute struct may have more than one % variable-value pair. However, there must only be % one associated value of the attribute for each variable, % hence the 2. if (s(2) == 2) % Transpose it because CDFlib reads the arrays column-wise. varAttribStruct.(attribs{i}) = attribVal'; else % We have ordered pairs. varAttribStruct.(attribs{i}) = reshape(varAttribStruct.(attribs{i})(:),numel(varAttribStruct.(attribs{i})(:))/2, 2); end end case 'cdfcompression' args.isCDFCompressed = varargin{k+1}; if (numel(args.isCDFCompressed) ~= 1) exception.msg = 'CDF compression value must be a scalar logical.'; exception.id = 'MATLAB:spdfcdfupdate:cdfcompression'; return end if (islogical(args.isCDFCompressed)) if (args.isCDFCompressed) args.isCDFCompressed = int32(2); else args.isCDFCompressed = int32(1); end elseif (isnumeric(args.isCDFCompressed)) % args.isCDFCompressed = logical(args.isCDFCompressed); if (logical(args.isCDFCompressed)) args.isCDFCompressed = int32(2); else args.isCDFCompressed = int32(1); end else exception.msg = 'CDF compression value must be a scalar logical.'; exception.id = 'MATLAB:spdfcdfupdate:cdfcompression'; return end case 'cdfchecksum' args.CDFchecksum = varargin{k+1}; if (numel(args.CDFchecksum) ~= 1) exception.msg = 'CDF checksum value must be a scalar logical.'; exception.id = 'MATLAB:spdfcdfupdate:cdfchecksum'; return end if (islogical(args.CDFchecksum)) if (args.CDFchecksum) args.CDFchecksum = int32(2); else args.CDFchecksum = int32(1); end end case 'cdfleapsecondlastupdated' args.CDFleapsecondlastupdated = varargin{k+1}; if (isnumeric(args.CDFleapsecondlastupdated)) args.CDFleapsecondlastupdated = int32(args.CDFleapsecondlastupdated); else exception.msg = 'CDF leapsecondlastupdated value must be a numeric value (in YYYYMMDD form).'; exception.id = 'MATLAB:spdfcdfupdate:cdfleapsecondlastupdated'; return end end % switch end % for end function spdfcdfwrite(filename, varcell, varargin) %SPDFCDFWRITE Write data to a CDF file. % % SPDFCDFWRITE(FILE, VARIABLELIST, ...) writes out a CDF file whose name % is specified by FILE. VARIABLELIST is a cell array of ordered % pairs, which are comprised of a CDF variable name (a string) and % the corresponding CDF variable value. To write out multiple records % for a variable, there are two ways of doing it. One way is putting the % variable values in a cell array, where each element in the cell array % represents a record. Another way, the better one, is to place the % values in a vector (single or multi-dimensional) with the option % 'RecordBound' being specified. % % SPDFCDFWRITE(..., 'PadValues', PADVALS) writes out pad values for given % variable names. PADVALS is a cell array of pairs of a variable name (a % string) and a corresponding pad value. Pad values are the default value % associated with the variable when an out-of-bounds record is accessed. % Variable names that appear in PADVALS must be in VARIABLELIST. % % SPDFCDFWRITE(..., 'GlobalAttributes', GATTRIB, ...) writes the structure % GATTRIB as global meta-data for the CDF. Each field of the % struct is the name of a global attribute. The value of each % field contains the value of the attribute. To write out % multiple values for an attribute, the field value should be a % cell array. % % If there is a master CDF that has all the meta-data that the new CDF needs, % then SPDFCDFINFO module can be used to retrieve the infomation. The % 'GlobalAttributes' field from the returned structure can be % passed in for the GATTRIB. % % In order to specify a global attribute name that is illegal in % MATLAB, create a field called "CDFAttributeRename" in the % attribute struct. The "CDFAttribute Rename" field must have a value % which is a cell array of ordered pairs. The ordered pair consists % of the name of the original attribute, as listed in the % GlobalAttributes struct and the corresponding name of the attribute % to be written to the CDF. % % SPDFCDFWRITE(..., 'VariableAttributes', VATTRIB, ...) writes the % structure VATTRIB as variable meta-data for the CDF. Each % field of the struct is the name of a variable attribute. The % value of each field should be an Mx2 cell array where M is the % number of variables with attributes. The first element in the % cell array should be the name of the variable and the second % element should be the value of the attribute for that variable. % % If there is a master CDF that has all the meta-data that the new CDF needs, % then SPDFCDFINFO module can be used to retrieve the infomation. The % 'VariableAttributes' field from the returned structure can be passed % in for the VATTRIB. % Note: For string variable attributes, they can be either a single string % or a cell of strings. % % In order to specify a variable attribute name that is illegal in % MATLAB, create a field called "CDFAttributeRename" in the % attribute struct. The "CDFAttribute Rename" field must have a value % which is a cell array of ordered pairs. The ordered pair consists % of the name of the original attribute, as listed in the % VariableAttributes struct and the corresponding name of the attribute % to be written to the CDF. If you are specifying a variable attribute % of a CDF variable that you are re-naming, the name of the variable in % the VariableAttributes struct must be the same as the re-named variable. % % SPDFCDFWRITE(..., 'WriteMode', MODE, ...) where MODE is either 'overwrite' % or 'append' indicates whether or not the specified variables or attributes % should be appended to the CDF if the file already exists. The % default is 'overwrite', indicating that SPDFCDFWRITE will not append % variables and attributes. % % SPDFCDFWRITE(..., 'Format', FORMAT, ...) where FORMAT is either 'multifile' % or 'singlefile' indicates whether or not the data is written out % as a multi-file CDF. In a multi-file CDF, each variable is stored % in a *.vN file where N is the number of the variable that is % written out to the CDF. The default is 'singlefile', which indicates % that SPDFCDFWRITE will write out a single file CDF. When the 'WriteMode' % is set to 'Append', the 'Format' option is ignored, and the format % of the pre-existing CDF is used. % % SPDFCDFWRITE(..., 'Version', VERSION, ...) where VERSION is a string which % specifies the version of the CDF library to use in writing the file. % The default option is to use the latest version of the library % (currently version 3.2+), and has to be specified '3.0'. The % other available version is version 2.7 ('2.7'). Note that % versions of MATLAB before R2006b will not be able to read files % which were written with CDF versions greater than 3.0. % % SPDFCDFWRITE(..., 'RecordBound', RECBNDVARS) specifies data values in arrays % (1-D or multi-dimensional) are to be written into "records" for the given % variable. RECBNDVARS is a cell array of variable names. The M-by-N array % data will create M rows (records), while each row having N elements. For an % M-by-1 (column) or 1-by-M (row) vector, it will create M records, each % being a scalar. For a 3-D array M-by-N-by-R, R records will be written, % and each record with M-by-N elements. Without this option, an array of % M-by-N will be written into a single record of 2-dimensions. See sample % codes for its usage. % % SPDFCDFWRITE(..., 'Vardatatypes', VARDATATYPE) specifies the variable's % data types. By default, this module uses each variable's passed data to % determine its corresponding CDF data type. While it is fine for the most % cases, this will not work for the CDF epoch types, i.e., CDF_EPOCH (a double), % CDF_EPOCH16 (an array of 2 doubles) and CDF_TIME_TT2000 (an int64). This % option can be used to address such issue. VARDATATYPE is a cell array of % variable names and their respective data types (in string). % % The following table shows the valid type strings, either in CDF defined % forms, or alternatively in the forms presented at column 4 in the Variables % field of the structure returned from a SPDFCDFINFO module call to an % existing CDF or master CDF. % type CDF Types % ----- --------- % int8 CDF_INT1 or CDF_BYTE % int16 CDF_INT2 % int32 CDF_INT4 % int64 CDF_INT8 % uint8 CDF_UINT1 % uint16 CDF_UINT2 % uint32 CDF_UINT4 % single CDF_FLOAT or CDF_REAL4 % double CDF_DOUBLE or CDF_REAL8 % epoch CDF_EPOCH % epoch16 CDF_EPOCH16 % tt2000 CDF_TIME_TT2000 % char CDF_CHAR or CDF_UCHAR % % Note: Make sure variable's data match to the defined type. % % SPDFCDFWRITE(..., 'VarCompress', COMPRESSVARS) specifies which variables % will be compressed by what compression method (and level for GZIP). % COMPRESSVARS is a cell array of variable names and their respective % compression methods. For examples, to set the compression for 'var1' and % 'var2' with AHUFF and GZIP.6 respectively, COMPRESSVARS should be given % as {'var1', 'ahuff', 'var2', 'gzip.6'}. GZIP.6 compression provides the % best compression rate and performance. % % If there is a master CDF that has all the same variable info as the new CDF, % then SPDFCDFINFO module can be used to retrieve the infomation. The % 'Variables' field from the returned structure contain the compression info % (at element 7) for each variable, Set up a cell to use such compression % info. % % SPDFCDFWRITE(..., 'CDFCompress', COMPRESSVALUE) specifies the CDF will be % compressed at the file level by what compression method (and level for GZIP). % COMPRESSVALUE is a string of a valid compression method and level. % % If there is a master CDF that can be used to define the new CDF's settings, % then SPDFCDFINFO module can be used to retrieve the infomation. The % 'Compression' and 'CompressionParam' fields from the returned structure's % 'FileSettings' structure field contain the compression info. Combining these % fields will make a valid compression. See the example. % Alternatively, COMPRESSVALUE can be provided as one of the following strings: % 'none', 'gzip.x', 'rle' (Run-length encoding), 'huff' (Huffman), 'ahuff' % (Adaptive Huffman), where 'x' in 'gzip.x' is the level of 1-9 (6 being the % preferable). % % SPDFCDFWRITE(..., 'VarSparse', SPARSEVARS) specifies which variables have % sparse records. SPARSEVARS is a cell array of orderly pairs of a variable % name and its respective value. The valid value should be 'full', % 'Sparse(padded)' or 'Sparse(previous)' (the 6th column from Variables field % from spdfcdfinfo). % Value 'full' is the default if a variable does not have the sparse records. % For examples, to set the sparse record for 'var1' and 'var2' with 'full' % and 'Sparse(previous)', SPARSEVARS should be specified as {'var1', 'full', % 'var2', 'Sparse(padded)'}. (Actually, there is no need for 'var1'.) % Variable's record data should be provided in cell form for the sparse record % variables. Data for any virtual records should be presented as []s. See the % sample code for its usage. % % SPDFCDFWRITE(..., 'BlockingFactor', BFVARS) specifies the blocking factor % for the variables. The blocking factor is the number of variable records % that will be pre-allocated when a new record is to be written. The default % value could be too small for variables that have large record size or % number. A large blocking factor (up to a variable's maximum record number) % can make access to the full variable data more efficient as less blocks % are involved (thus less I/Os). It can also make the file less fragmented. % BFVARS is a cell array of pairs of variable name and its respective value. % The value should be a numeric. % % If there is a master CDF that has all the same variable info as the new CDF, % then SPDFCDFINFO module can be used to retrieve the infomation. The % 'Variables' field from the returned structure contain the record sparseness % info (at element 6) for each variable, Set up a cell to use such sparseness % info. % % SPDFCDFWRITE(..., 'ConvertDatenumToEpoch', TF, ...) converts MATLAB datenum % values to CDF epoch data if TF is true. This option works with the % variable(s) that is of CDF_EPOCH type in a CDF. % There are two ways to write data for epoch variable(s) of CDF_EPOCH into % a CDF. First, uses cdfepoch objects, each of which is from a datenum, % datestr, or even cdfepoch object, to pass data to spdfcdfwrite: % SPDFCDFWRITE(..., {'Epoch',cdfepoch([...], ...)}, ...) % This option is time and space consuming if large datasets are involved. % The second way uses 'ConvertDatenumToEpoch': % SPDFCDFWRITE(..., {'Epoch',[...], ...}, 'ConvertDatenumToEpoch', TF, ...) % If TF is set to true, the passed data are assumed as MATLAB datenum % values and a data conversion to CDF epoch values is performed. % Setting it to false (the default), All data will be considered already in % CDF_EPOCH form and will be filled, as is, to % CDF_EPOCH data type variable(s). The CDF_EPOCH data need to be numeric of % mxDouble_CLASS (double). % % SPDFCDFWRITE(..., 'ConvertDatenumToTT2000', TF, ...) converts MATLAB datenum % values to CDF TT2000 data if TF is true. This option works with the % variable(s) that is of CDF_TIME_TT2000 type in a CDF. % There are two ways to write data for epoch variable (s) of CDF_TIME_TT2000 % into a CDF. First, uses cdftt2000 objects, each of which is from a datenum, % datestr, or even cdftt2000 object, to pass data to spdfcdfwrite: % SPDFCDFWRITE(..., {'Epoch',cdftt2000([...], ...)}, ...) % This option is also time and space consuming if large datasets are involved. % The second way uses 'ConvertDatenumToTT2000': % SPDFCDFWRITE(..., {'Epoch',[...], ...}, 'ConvertDatenumToTT2000', TF, ...) % If TF is set to true, the passed data are assumed as MATLAB datenum % values and a data conversion to CDF TT2000 values is performed. % Setting it to false (the default), All data will be considered already in % CDF_TIME_TT2000 form and will be filled, as is, to % CDF_TIME_TT2000 data type variable(s). The CDF TT2000 values needs to be % numeric of mxINT64_CLASS (int64). % % SPDFCDFWRITE(..., 'Checksum', CHECKSUMVAL, ...) specifies whether the output % CDF should have its checksum computed. The valid values are 'MD5' or 'none'. % The default is 'none'. % % SPDFCDFWRITE(..., 'CDFLeapSecondLastUpdated', value, ...) resets the CDF's % leap second last updated date. For CDFs created prior to V 3.6.0, this % field is not set. It is set to indicate what leap second table this CDF is % based upon. The value, in YYYYMMDD form, must be a valid entry in the % currently used leap second table, or zero (0) if the table is not used. % CDF will automatically fill the value with the last entry date in the leap % second table if this option is not specified. % % SPDFCDFWRITE(..., 'Singleton', VARS, ...) indicates whether to keep the % singleton dimension(s) passed in from the multi-dimensional data. VARS is % a cell array of variable names, indicating each variable's singleton % dimension(s) is to be kept. % For example, variable with data dimensions like 10x1x100 will be written % as 2-dimensions (10x1) for 100 records if the record bound is specified. % For a row (1-by-M) or column (M-by-1) vector, the variable data will be % written as 2-dimension as is, unless the recordbound is specified. % The default setting is to have all singleton dimension(s) removed. % The above 10x1x100 variable will be written as 1-dimension % (with 10 elements). % % Notes: % % SPDFCDFWRITE creates temporary files when writing CDF files. Both the % target directory for the file and the current working directory % must be writable. % % To maximize performance, specify the 'ConvertDatenumToEpoch' % parameter with true (nonzero) value while providing datenum values % for 'Epoch' variable. % % CDF epoch is the number of milliseconds since 1-Jan-0000 0h:0m:0s:000ms. % CDF TT2000 is the number of nanoseconds since 1-Jan-2000 % 12h:0m:0s:000000000ns with leap seconds included. % % % Examples: % % % Write out a file 'example.cdf' containing a variable 'Longitude' % % with a single record (row) of a vector with 361 elements: % % spdfcdfwrite('example', {'Longitude', 0:360}); % % % Write out a file 'example.cdf', containing a variable 'Longitude' % % with the value [0:360] (one record of 361 values), and with a variable % % attribute of 'validmin' with the value 10: % % varAttribStruct.validmin = {'Longitude' [10]}; % spdfcdfwrite('example', {'Longitude' 0:360}, ... % 'VariableAttributes', varAttribStruct); % % % Write out a file 'example.cdf' containing variables 'Longitude' % % and 'Latitude' with the variable 'Longitude' being a Record-bound % % (361 records to be written):: % % spdfcdfwrite('example', {'Longitude', (0:360), 'Latitude', 10:20}, ... % 'RecordBound', {'Longitude'}); % % % These two commands should write out the data values identically: % SPDFCDFWRITE('example', {'Epoch', num2cell(1:100)}, ... % 'epochiscdfepoch', true); % SPDFCDFWRITE('example', {'Epoch', (1:100)'}, ... % 'recordbound', {'Epoch'}, ... % 'epochiscdfepoch', true); % % % Write out a file 'example.cdf' containing variables 'Longitude' % % and 'Latitude' with the variable 'Latitude' having a pad value % % of 10 for all out-of-bounds records that are accessed. The % % 'Longitude' variable has one record (row) of a vector with 361 elements % % 'Latitude' has one record of a vector with 11 elements. % % spdfcdfwrite('example', {'Longitude', (0:360)', 'Latitude', (10:20)'}, ... % 'RecordBound', {'Latitude', 'Longitude'}, ... % 'PadValues', {'Latitude', 10}); % % % Write out a file 'example.cdf', with multiple rows of time series data. % % Each row has a time and a sampled data, both being scalar. % % The following sample shows 100 records (rows): epoch is of CDF_EPOCH % % data type and Samples of CDF_DOUBLE. % % The epoch starts from 2010-01-01T00:00:00.000 with 1 second stride. % % Each sampled value starts from 0.0, with 5.0 stride. % % epoch=utc2cdfepoch(2010,1,1,0,0,0,0); % epochvalues = (epoch+[0:99]*1000)'; % values = ([0:99]*5.0)'; % spdfcdfwrite('example', {'Epoch', epochvalues, 'Samples', values}, ... % 'EpochisCDFEpoch', true, ... % 'RecordBound', {'Epoch', 'Samples'}); % % % 'EpochisCDFEpoch' option is needed as 'Epoch' is to be created of % % CDF_EPOCH type. % % % Alternatively, the same result can be accomplished by using the % % 'EpochType' option: % % spdfcdfwrite('example', {'Epoch', epochvalues, 'Samples', values}, ... % 'EpochType', {'Epoch'}, ... % 'RecordBound', {'Epoch', 'Samples'}); % % % Alternatively, the same result can be accomplished by making the epoch % % vector to cell. No 'RECORDBOUND' option is needed. % epoch=utc2cdfepoch(2010,1,1,0,0,0,0); % epochvalues = epoch+[0:99]*1000; % epochscell = num2cell(epochvalues); % values = num2cell([0:99]*5.0); % spdfcdfwrite('example', {'Epoch', epochvalues, 'Samples', values}, ... % 'EpochType', {'Epoch'}); % % % Write out a file 'example.cdf', with single or multiple rows of % % vectorized data. Variable 'one0' will have one record with 5 elements. % % Variable 'one1' has five records, each record having 1 value. Variable % % 'two0' has one 5-by-2 record, while Variable 'two2' has five (5) % % records, each record having 2 elements. Variable 'three0' has a % % single 3-D (3-by-2-by-2) record, while Variable 'three3' has two (2) % % records, each record being a 3-by-2 matrix. % % data0=1:5; % data1=data0'; % data2=[10 20;30 40;50 60;70 80;90 100]; % data2a=data2+100; % data3=[1 2;3 4;5 6]; % data3(:,:,2)=[11 22; 33 44; 55 66]; % data3a=data3+100; % spdfcdfwrite('example',{'one0',data0,'one1',data1,'two0',data2, ... % 'two2',data2a,'three0',data3,'three3',data3a}, ... % 'recordbound',{'one1','two2','three3'}); % % % For writing out two variables: 'Epoch' of CDF_EPOCH type, and % % 'Sample' of CDF_DOUBLE type. Four records are written for each. Epoch's % % record is a scalar, while Sample's is an 1-D with 4 elements. % % epoch=utc2cdfepoch(2010,1,1,0,0,0,0); % epochvalues = (epoch+[0:3]*1000)'; % value = [0:3]*5.0; % values = [value; value+10; value+20; value+30]; % spdfcdfwrite('example', {'Epoch', epochvalues, 'Sample', values}, ... % 'EpochType', {'Epoch'}, ... % 'RecordBound', {'Epoch', 'Sample'}); % % % Write out a file 'example.cdf', with 100 MATLAB datenum values, % % starting from 2010-01-01T00:00:00.000 with 1 second stride, % % into variable: 'Epoch' of CDF_EPOCH type. The first record has a date: % % 01-Jan-2010 00:00:00.000, the second record: % % 01-Jan-2010 00:00:01.000, the third record: % % 01-Jan-2010 00:00:02.000, etc. % % 'Epoch' has a pad value of 01-Jan-0000 00:00:00.001. % % datenum1=datenum(2010,1,1,0,0,0); % datenumvalues = (datenum1+[0:99]/86400)'; % spdfcdfwrite('example', {'Epoch', datenumvalues}, ... % 'ConvertDatenumToEpoch', true, ... % 'RecordBound', {'Epoch'}, ... % 'PadValue', {'Epoch', 1}); % % % Write out a file 'example.cdf', with three records for the variable % % 'Epoch' of CDF_TIME_TT2000 type. The first record has a date: % % 2010-10-10T01:02:03.456, the second record: 2010-11-11T02:04:06.789 % % and the third record: 2010-12-12T03:04:05.123. % % dates = datenum([2010 10 10 1 2 3.456; 2010 11 11 2 4 6.789; ... % 2010 12 12 3 4 5.123]); % spdfcdfwrite('example', {'Epoch', dates'}, ... % 'ConvertDatenumToTT2000', true, ... % 'RecordBound', {'Epoch'}); % % % Write out a file 'example.cdf', with 6 records for the variable % % 'Epoch', which will be of CDF_TIME_TT2000 data type. The data % $ crosses over a leap second. Convert the epoch in UTC string % $ to their TT2000 values before write out to the CDF file. % % time = {'2008-12-31T23:59:58.123456789'; ... % '2008-12-31T23:59:59.123456789'; ... % '2008-12-31T23:59:60.123456789'; ... % '2009-01-01T00:00:00.123456789'; ... % '2009-01-01T00:00:01.123456789'; ... % '2009-01-01T00:00:02.123456789'}; % values = spdfparsett2000(time); % spdfcdfwrite('example', {'Epoch', values}, ... % 'EpochType', {'Epoch'}, ... % 'RecordBound', {'Epoch'}); % % % Write out a file 'sample.cdf', with two variables. One variable, 'var2'. % % is compressed with GZIP.6. % % var1data=......; % var2data=......; % spdfcdfwrite('sample',{'Epoch',var1data,'var2',var2data}, ... % 'recordbound',{'Epoch','var2'}, ... % 'varcompress',{'var2','gzip.6'}); % % % Write out a file 'sparse.cdf', with a variable that has sparse records. % % The variable 'one' only has two (2) physical data: at record 0 and % % record 4. % % spdata={[123 321];[];[];[];[-321 -123]}; % spdfcdfwrite('sparse',{'one',spdata}, ... % 'varsparse', {'one','Sparse(previous)'}); % % % Write out a file 'real.cdf', based on the master cdf, which provides the % % file settings info, i.e., checksum, CDF file level compression, as well as % % meta-data for all of the global and variable attribute information. It % % also provides the variable spec, e.g., data type, record variance, record % % sparseness, blocking factor, pad value and compression, for each variable. % % 'Recordbound' option is used for specifying record-variant (RV) variables. % % Among the variables, Variable number 15, a single floating point array, has % % sparse records [at record 1 and 5]. Its data has to be in the cell array. % % info=spdfcdfinfo('master.cdf'); % for p = 1:length(info.Variables(:,1)) % compress{(2*p)-1} = info.Variables(p,1); % Variable name % compress{2*p} = info.Variables(p,7); % Variable compression % sparse{(2*p)-1} = info.Variables(p,1); % Variable name % sparse{2*p} = info.Variables(p,6); % Variable sparseness % bf{2*p-1} = info.Variables{p,1}; % Variable name % bf{2*p} = info.Variables{p,8}; % Variable blocking factor % pad{2*p-1} = info.Variables{p,1}; % Variable name % pad{2*p} = info.Variables{p,9}; % Variable pad value % datatypes{2*p-1} = info.Variables{p,1}; % Variable name % datatypes{2*p} = info.Variables{p,4}; % Variable data type % end % rbvars = {info.Variables{:,1}}; % Variable names for recordbound % for p = length(vars):-1:1 % if (strncmpi(info.Variables{p,5},'f',1)==1) % NRV variable % rbvars(:,p)=[]; % Remove it % end % end % if isnumeric(info.FileSettings.CompressionParam) % A number for Gzip parameter % cdfcompress=strcat(info.FileSettings.Compression, '.', ... % Make it 'gzip.x' % num2str(info.FileSettings.CompressionParam)); % else % cdfcompress=strcat(info.FileSettings.Compression, '.', ... % None or non-gzip % info.FileSettings.CompressionParam); % end % % % fill data % for p = 1:length(info.Variables(:,1)) % varsdata{2*p-1} = info.Variables(p,1); % if (p == 15) % A sparse record variable % var15data={single([123 321]);[];[];[];single([-321 -123])}; % varsdata{(2*15)} = var15data; % Sparse record data % else % varsdata{(2*p)} = [...]; % Normal data % end % end % spdfcdfwrite('real',varsdata, ... % 'GlobalAttributes', info.GlobalAttributes, ... % Global attributes % 'VariableAttributes', info.VariableAttributes, ... %Variable attributes % 'RecordBound', rbvars, ... % Var record bound % 'varcompress',compress, ... % Var compression % 'varsparse', sparse, ... % Var sparseness % 'blockingfactor', bf, ... % Var blocking factors % 'padvalues', pad, ... % Var Pad values % 'cdfcompress',cdfcompress, ... % CDF compression % 'checksum', info.FileSettings.Checksum, ... % Checksum % 'VarDatatypes', datatypes); % Var data types % % Note: The compatible data types between MATLAB and CDF are as follows: % MATLAB CDF % ------ -------- % int8 CDF_BYTE or CDF_INT1 % int16 CDF_INT2 % int32 CDF_INT4 % int64 CDF_INT8 or CDF_TIME_TT2000 % uint8 CDF_UINT1 % uint16 CDF_UINT2 % uint32 CDF_UINT4 % single CDF_FLOAT % double CDF_DOUBLE or CDF_EPOCH or CDF_EPOCH16 % char/string CDF_UCHAR or CDF_CHAR % % See also SPDFCDFREAD, SPDFCDFUPDATE, SPDFCDFINFO, CDFEPOCH, CDFTT2000, % SPDFENCODEEPOCH, SPDFCOMPUTEEPOCH, SPDFPARSEEPOCH, % SPDFBREAKDOWNEPOCH, SPDFENCODEEPOCH16, SPDFCOMPUTEEPOCH16, % SPDFPARSEEPOCH16, SPDFBREAKDOWNEPOCH16, SPDFENCODETT2000, % SPDFCOMPUTETT2000, SPDFPARSETT2000, SPDFBREAKDOWNTT2000, % SPDFDATENUMTOEPOCH, SPDFDATENUMTOEPOCH16, SPDFDATENUMTOTT2000, % SPDFCDFLEAPSECONDSINFO % HISTORY: % February 12, 2009 Mike Liu The following changes have been made to % spdfcdfwritec.c: % - Added parameter 'RecordBound'. % - Added parameter 'ConvertDatenumToEpoch'. % - Added a logic to check CDF_EPOCH and % CDF_EPOCH16 data. % % Process arguments. % if (nargin < 2) error('MATLAB:spdfcdfwrite:inputArgumentCount', ... 'SPDFCDFWRITE requires at least two input arguments.') end % parse_inputs sorts out all of the input args. Its return values: % % * args - an array of structs. args.VarNames contains the names % of the variables to be written to the CDF. args.VarVals contains % the corresponding values. args.PadVals contains corresponding pad % values. args.ConvertDatenum indicates whether to convert % MATLAB datenum to CDF epoch values. args.RecBnd contains variables % that are for Record-bound. args.EpochIsCDFEpoch is a flag % indicating whether datenum to cdf epoch conversion is needed. % * isAppending - whether or not to delete this file or if we need to % append to the file % * isMultifile - whether or not to write out as a multi-file CDF % * CDFversion - which version of the CDF library to use % * varAttribStruct - a struct containing the variable attributes % * globalAttribStruct - a struct containing the global CDF attributes % * msg - an error message from parse_inputs that we pass on to the user. [args, isAppending, isMultifile, CDFversion, varAttribStruct, ... globalAttribStruct, exception] = parse_inputs(varcell, varargin{:}); if (~isempty(exception.msg)) error(exception.id, '%s', exception.msg) end % % Create a proper filename for the CDF % % See if there is an extension [pname, fname, ext] = fileparts(filename); % If there is an extension, then remove it before passing it to CDFlib. if (~isempty(ext)) if (~isempty(strfind(ext, 'cdf'))) filename = fullfile(pname, fname); end end % % Call the underlying spdfcdfwritec function which calls the CDFlib % spdfcdfwritec(filename, args.VarNames, args.VarVals, args.PadVals, ... globalAttribStruct, varAttribStruct, isAppending, ... isMultifile, CDFversion, args.ConvertDatenum, args.RecBnd, ... args.EpochIsCDFEpoch, args.TT2000, args.ConvertDatenum2, ... args.EpochTp, args.VarCompVals, args.SparseVarVals, ... args.BFVarVals, args.DTVarVals, args.MD5, args.CDFComp, ... args.CDFleapsecondlastupdated, args.SingletonVars); %%% %%% Function parse_inputs %%% function [args, isAppending, isMultifile, CDFversion, varAttribStruct, ... globalAttribStruct, exception] = parse_inputs(varcell, varargin) % Set default values args.PadVals = {}; args.RecBnd = {}; args.VarCompVals = {}; args.SparseVarVals = {}; args.BFVarVals = {}; args.EpochTp = {}; args.EpochIsCDFEpoch = false; args.TT2000 = false; args.ConvertDatenum = false; args.ConvertDatenum2 = false; args.MD5 = false; args.CDFComp = ''; args.CDFleapsecondlastupdated = int32(-999); isAppending = 0; isMultifile = 0; varAttribStruct = struct([]); globalAttribStruct = struct([]); % The following value indicates no version preference. CDFversion = -1.0; exception.msg = ''; exception.id = ''; % First check that varcell meets all of our requirements args.VarNames = {varcell{1:2:end}}; args.VarVals = {varcell{2:2:end}}; % Wrap the scalars non-empties in cell arrays. for i = 1:length(args.VarVals) % if ~isempty(args.VarVals{i}) && (ischar(args.VarVals{i}) || (numel(args.VarVals{i}) == 1)) if ~isempty(args.VarVals{i}) && ischar(args.VarVals{i}) args.VarVals{i} = {args.VarVals{i}}; end end if length(args.VarNames) ~= length(args.VarVals) exception.msg = 'All variable names must have a corresponding variable value.'; exception.id = 'MATLAB:spdfcdfwrite:variableWithoutValue'; return end % Check and make sure that all variable values are of the same % datatype, but ignore empties if ~isempty(args.VarVals) for i = 1:length(args.VarVals) a = args.VarVals{i}; if iscell(a) nonEmpties = {a{~cellfun('isempty',a)}}; if iscell(nonEmpties) && ~isempty(nonEmpties) dtype = class(nonEmpties{1}); if ~all(cellfun('isclass',nonEmpties,dtype)) exception.msg = 'All record values for a given variable must be of the same type.'; exception.id = 'MATLAB:spdfcdfwrite:inconsistentRecordTypes'; end end % else % If it isn't a cell array, then it is an array and % all elements are of the same type. % args.VarVals{i} = (args.VarVals{i}); end end end args.PadVals = cell(1,length(args.VarNames)); args.RecBnd = cell(1,length(args.VarNames)); args.EpochTp = cell(1,length(args.VarNames)); args.VarCompVals = cell(1,length(args.VarNames)); args.SparseVarVals = cell(1,length(args.VarNames)); args.BFVarVals = cell(1,length(args.VarNames)); args.DTVarVals = cell(1,length(args.VarNames)); args.SingletonVars = cell(1,length(args.VarNames)); % Parse arguments based on their number. if (nargin > 0) paramStrings = {'padvalues' 'varcompress' 'cdfcompress' 'varsparse' 'blockingfactor' 'vardatatypes' 'globalattributes' 'variableattributes' 'writemode' 'format' 'recordbound' 'convertdatenumtoepoch' 'convertdatenumtott2000' 'epochiscdfepoch' 'version' 'tt2000' 'checksum' 'cdfleapsecondlastupdated' 'epochtype' 'singleton'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) exception.msg = 'Parameter name must be a string.'; exception.id = 'MATLAB:spdfcdfwrite:paramNameNotString'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) exception.msg = sprintf('Unrecognized parameter name "%s".', param); exception.id = 'MATLAB:spdfcdfwrite:unrecognizedParam'; return elseif (length(idx) > 1) exception.msg = sprintf('Ambiguous parameter name "%s".', param); exception.id = 'MATLAB:spdfcdfwrite:ambiguousParam'; return end switch (paramStrings{idx}) case 'padvalues' padCell = varargin{k+1}; % If we weren't passed an even pair, then a variable % name or value was left out. if rem(length(padCell), 2) exception.msg = ['Number of variables to write out with ' ... 'padding does not match number of pad values.']; exception.id = 'MATLAB:spdfcdfwrite:paddingMismatch'; return end vars = {padCell{1:2:end}}; padVals = {padCell{2:2:end}}; % Check that vars are in the list above. if ~iscellstr(vars) exception.msg = 'All variable names 1 must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(vars, args.VarNames)) exception.msg = ['Variables listed in the PadValues ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForPadValue'; return end for i = 1:length(padVals) padVal = padVals{i}; if (isempty(padVal)) continue end if isnumeric(padVal) || ischar(padVal) || isa(padVal,'cdfepoch') || ... isa(padVal,'cdftt2000') args.PadVals{strcmp(args.VarNames,vars{i})} = padVal; else exception.msg = 'Pad values must be numbers, strings, cdfepoch or cdftt2000.'; exception.id = 'MATLAB:spdfcdfwrite:badPadValue'; return end end case 'varcompress' varCompCell = varargin{k+1}; % If we weren't passed an even pair, then a variable % name or value was left out. if rem(length(varCompCell), 2) exception.msg = ['Number of variables to compress ' ... 'does not match number of compression values.']; exception.id = 'MATLAB:spdfcdfwrite:compressingMismatch'; return end if iscell(varCompCell{1}) vars = varCompCell{1:2:end}; else vars = {varCompCell{1:2:end}}; end varCompVals = {varCompCell{2:2:end}}; % Check that vars are in the list above. if ~iscellstr(vars) exception.msg = 'All variable names 2 must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(vars, args.VarNames)) exception.msg = ['Variables listed in the VarCompValues ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForVarCompValue'; return end for i = 1:length(varCompVals) varCompVal = varCompVals{i}; if (isempty(varCompVal)) continue end if ischar(varCompVal) ... args.VarCompVals{strcmp(args.VarNames,vars{i})} = varCompVal; else exception.msg = 'Compression 3 must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:badVarCompValue'; return end end case 'globalattributes' globalAttribStruct = varargin{k+1}; if ~isstruct(globalAttribStruct) exception.msg = ['''GlobalAttributes''' ' must be a struct.']; exception.id = 'MATLAB:spdfcdfwrite:globalAttributesNotStruct'; return end attribs = fieldnames(globalAttribStruct); % If the global attribute isn't a cell, then stuff it in one. for i = 1:length(attribs) attribVal = globalAttribStruct.(attribs{i}); if ~iscell(attribVal) globalAttribStruct.(attribs{i}) = {attribVal}; end end case 'variableattributes' varAttribStruct = varargin{k+1}; if ~isstruct(varAttribStruct) exception.msg = ['''VariableAttributes''' ' must be a struct.']; exception.id = 'MATLAB:spdfcdfwrite:variableAttributesNotStruct'; return end attribs = fieldnames(varAttribStruct); % Check the VariableAttributes struct. for i = 1:length(attribs) % If the variable attribute isn't in a cell (because % it is scalar, then put it into a cell. attribVal = varAttribStruct.(attribs{i}); s = size(attribVal); if ~iscell(attribVal) varAttribStruct.(attribVal) = {attribVal}; end % The variable attribute struct may have more than one % variable per attribute. However, there must only be % one associated value of the attribute for each variable, % hence the 2. if (s(2) == 2) % Transpose it because CDFlib reads the arrays column-wise. varAttribStruct.(attribs{i}) = attribVal'; else % We have ordered pairs. varAttribStruct.(attribs{i}) = reshape(varAttribStruct.(attribs{i})(:),numel(varAttribStruct.(attribs{i})(:))/2, 2); end % % Don't forget to ignore the "CDFAttributeRename" attribute % completeSet = {args.VarNames{:} 'CDFAttributeRename'}; % tmpVar = varAttribStruct.(attribs{i}); % varsWithAttributes = {tmpVar{1,:}}; % if ~all(ismember(varsWithAttributes, completeSet)) % exception.msg = ['Variables listed in the VariableAttributes ' ... % 'struct must be on the list of variables ' ... % 'to save.']; % return % end end case 'writemode' isAppending = varargin{k+1}; if strcmpi(isAppending, 'overwrite') isAppending = 0; elseif strcmpi(isAppending, 'append') isAppending = 1; else exception.msg = ['''WriteMode''' ' must be either ' '''overwrite''' ... ' or ' '''append''']; exception.id = 'MATLAB:spdfcdfwrite:badWriteModeValue'; return end case 'format' isMultifile = varargin{k+1}; if strcmpi(isMultifile, 'singlefile') isMultifile = 0; elseif strcmpi(isMultifile, 'multifile') isMultifile = 1; else exception.msg = ['''Format''' ' must be either ' '''singlefile''' ... ' or ' '''multifile''']; exception.id = 'MATLAB:spdfcdfwrite:badFormatValue'; return end case 'cdfcompress' compression = varargin{k+1}; args.CDFComp = find_compression(compression); case 'version' version = varargin{k+1}; if ischar(version) && ... (strcmp(version,'2.7') || strcmp(version,'3.0')) CDFversion = str2num(version); else exception.msg = '''Version'' must be either ''2.7'' or ''3.0'''; exception.id = 'MATLAB:spdfcdfwrite:badVersionValue'; return end case 'recordbound' RecBndCell = varargin{k+1}; % Check that vars are in the list above. if ~iscellstr(RecBndCell) exception.msg = 'All variable names for recordbound must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(RecBndCell, args.VarNames)) exception.msg = ['Variables listed in the RECORDBOUND ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForRecBnd'; return end for i = 1:length(RecBndCell) RecBndVar = RecBndCell{i}; args.RecBnd{strcmp(args.VarNames,RecBndCell{i})} = RecBndVar; end case 'checksum' if (k == length(varargin)) msg = 'Missing "checksum" value.'; return else checksum = varargin{k + 1}; if ~isstr(checksum) exception.msg = 'Checksum value must be a string.'; exception.id = 'MATLAB:spdfcdfwrite:checksumvalue'; return end args.MD5 = logical(find_checksum(checksum)); end case 'cdfleapsecondlastupdated' args.CDFleapsecondlastupdated = varargin{k+1}; if (isnumeric(args.CDFleapsecondlastupdated)) args.CDFleapsecondlastupdated = int32(args.CDFleapsecondlastupdated); else exception.msg = 'CDF leapsecondlastupdated value must be a numeric value (in YYYYMMDD form).'; exception.id = 'MATLAB:spdfcdfwrite:cdfleapsecondlastupdated'; return end case 'varsparse' SparseVarsCell = varargin{k+1}; % If we weren't passed an even pair, then a variable % name or value was left out. if rem(length(SparseVarsCell), 2) exception.msg = ['Number of variables to sparse records ' ... 'does not match number of their values.']; exception.id = 'MATLAB:spdfcdfwrite:sparserecordMismatch'; return end vars = {SparseVarsCell{1:2:end}}; sparseVals = {SparseVarsCell{2:2:end}}; % Check that vars are in the list above. if ~iscellstr(vars) exception.msg = 'All variable names must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(vars, args.VarNames)) exception.msg = ['Variables listed in the SparseValues ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForSparseValue'; return end for i = 1:length(sparseVals) sparseVal = sparseVals{i}; if (isempty(sparseVal)) continue end if ischar(sparseVal) args.SparseVarVals{strcmp(args.VarNames,vars{i})} = sparseVal; else exception.msg = 'Sparse Record must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:badSparseValue'; return end end case 'blockingfactor' BFVarsCell = varargin{k+1}; % If we weren't passed an even pair, then a variable % name or value was left out. if rem(length(BFVarsCell), 2) exception.msg = ['Number of variables to blocking factors ' ... 'does not match number of their values.']; exception.id = 'MATLAB:spdfcdfwrite:blockingfactorMismatch'; return end vars = {BFVarsCell{1:2:end}}; bfVals = {BFVarsCell{2:2:end}}; % Check that vars are in the list above. if ~iscellstr(vars) exception.msg = 'All variable names must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(vars, args.VarNames)) exception.msg = ['Variables listed in the BFValues ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForBFValue'; return end for i = 1:length(bfVals) bfVal = bfVals{i}; if (isempty(bfVal)) continue end if isnumeric(bfVal) args.BFVarVals{strcmp(args.VarNames,vars{i})} = int32(bfVal); else exception.msg = 'Blocking factor must be numeric.'; exception.id = 'MATLAB:spdfcdfwrite:badBlockingFactor'; return end end case 'vardatatypes' DTVarsCell = varargin{k+1}; % If we weren't passed an even pair, then a variable % name or value was left out. if rem(length(DTVarsCell), 2) exception.msg = ['Number of variables to blocking factors ' ... 'does not match number of their values.']; exception.id = 'MATLAB:spdfcdfwrite:blockingfactorMismatch'; return end vars = {DTVarsCell{1:2:end}}; dtVals = {DTVarsCell{2:2:end}}; % Check that vars are in the list above. if ~iscellstr(vars) exception.msg = 'All variable names must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~iscellstr(dtVals) exception.msg = 'All variable data types must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:vardatatypeNotString'; return end if ~all(ismember(vars, args.VarNames)) exception.msg = ['Variables listed in the DTValues ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForDTValue'; return end for i = 1:length(dtVals) dtVal = dtVals{i}; if (~isempty(dtVal)) args.DTVarVals{strcmp(args.VarNames,vars{i})} = ... int32(find_datatype(dtVal)); end end case 'epochtype' EpochTpCell = varargin{k+1}; % Check that vars are in the list above. if ~iscellstr(EpochTpCell) exception.msg = 'All variable names 7 must be strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end if ~all(ismember(EpochTpCell, args.VarNames)) exception.msg = ['Variables listed in the EPOCHTYPE ' ... 'cell must be on the list of variables ' ... 'to save.']; exception.id = 'MATLAB:spdfcdfwrite:notSavingVarForEpochTp'; return end for i = 1:length(EpochTpCell) EpochTpVar = EpochTpCell{i}; args.EpochTp{strcmp(args.VarNames,EpochTpCell{i})} = EpochTpVar; end case 'convertdatenumtoepoch' if (k == length(varargin)) msg = 'No datenum conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Datenum conversion value must be a scalar logical.'; end if (islogical(convert)) args.ConvertDatenum = convert; elseif (isnumeric(convert)) args.ConvertDatenum = logical(convert); else msg = 'Datenum conversion value must be a scalar logical.'; end end case 'convertdatenumtott2000' if (k == length(varargin)) msg = 'No datenum conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Datenum conversion value must be a scalar logical.'; end if (islogical(convert)) args.ConvertDatenum2 = convert; elseif (isnumeric(convert)) args.ConvertDatenum2 = logical(convert); else msg = 'Datenum conversion value must be a scalar logical.'; end end case 'epochiscdfepoch' if (k == length(varargin)) msg = 'No EpochIsCDFEpoch value specified.'; return else noconvert = varargin{k + 1}; if (numel(noconvert) ~= 1) msg = 'EpochIsCDFEpoch value must be a scalar logical.'; end if (islogical(noconvert)) args.EpochIsCDFEpoch = noconvert; elseif (isnumeric(noconvert)) args.EpochIsCDFEpoch = logical(noconvert); else msg = 'Datenum conversion value must be a scalar logical.'; end end case 'tt2000' if (k == length(varargin)) msg = 'No TT2000 value specified.'; return else noconvert = varargin{k + 1}; if (numel(noconvert) ~= 1) msg = 'TT2000 value must be a scalar logical.'; end if (islogical(noconvert)) args.TT2000 = noconvert; elseif (isnumeric(noconvert)) args.TT2000 = logical(noconvert); else msg = 'TT2000 conversion value must be a scalar logical.'; end end case 'singleton' if (k == length(varargin)) msg = 'No variables specified for Singleton.'; return else singletonVars = varargin{k+1}; if ~iscellstr(singletonVars) exception.msg = 'Singleton variable names must be a cell of strings.'; exception.id = 'MATLAB:spdfcdfwrite:varNameNotString'; return end % Check that vars are in the list above. for i = 1:length(singletonVars) singletonVar = singletonVars{i}; args.SingletonVars{strcmp(args.VarNames,singletonVar)} = singletonVar; end end end % switch end % for % Do a sanity check on the sizes of what we are passing back if ~isequal(length(args.VarNames), length(args.VarVals), ... length(args.PadVals)) exception.msg = 'Number of variable names, values, and pad values do not match.'; exception.id = 'MATLAB:spdfcdfwrite:sanityCheckMismatch'; return end if ~isequal(length(args.VarNames), length(args.VarVals)) exception.msg = 'Number of variable names and values do not match.'; exception.id = 'MATLAB:spdfcdfwrite:sanityCheckMismatch'; return end % validate_inputs(args); end % if (nargin > 1) function validate_inputs(args) %VALIDATE_INPUTS Ensure that the mutually exclusive options weren't provided. % if ((args.TT2000) && (args.EpochIsCDFEpoch)) error('MATLAB:spdfcdfwrite:TT2000', '%s\n%s', ... 'You cannot currently specify these two options.', ... 'Specify only one of ''TT2000'' and ''EpochIsCDFEpoch''.') end if ((args.TT2000) && (args.ConvertDatenum)) error('MATLAB:spdfcdfwrite:TT2000', '%s\n%s', ... 'You cannot currently specify these two options.', ... 'Specify only one of ''TT2000'' and ''ConvertDatenumToEpoch''.') end if ((args.ConvertDatenum) && (args.ConvertDatenum2)) error('MATLAB:spdfcdfwrite:convertdatenum', '%s\n%s', ... 'You cannot currently specify these two options.', ... 'Specify only one of ''ConvertDatenumToEpoch'' and ''ConvertDatenumToTT2000''.') end if (((args.epochtype) && (args.EpochIsCDFEpoch)) || ... ((args.epochtype) && (args.TT2000))) error('MATLAB:spdfcdfwrite:epochtype', '%s\n%s', ... 'You cannot currently specify these two options.', ... 'Specify only one of ''TT2000'', ''EpochIsCDFEpoch'' and ''EpochType''.') end function num = find_datatype(str) if (strcmpi(str,'double') == 1 || strcmpi(str,'cdf_double') == 1 || ... strcmpi(str,'cdf_real8') == 1) num = 45; elseif (strcmpi(str,'single') == 1 || strcmpi(str,'cdf_float') == 1 || ... strcmpi(str,'cdf_real4') == 1) num = 44; elseif (strcmpi(str,'int8') == 1 || strcmpi(str,'cdf_int1') == 1 || ... strcmpi(str,'cdf_byte') == 1) num = 1; elseif (strcmpi(str,'int16') == 1 || strcmpi(str,'cdf_int2') == 1) num = 2; elseif (strcmpi(str,'int32') == 1 || strcmpi(str,'cdf_int4') == 1) num = 4; elseif (strcmpi(str,'int64') == 1 || strcmpi(str,'cdf_int8') == 1) num = 8; elseif (strcmpi(str,'uint8') == 1 || strcmpi(str,'cdf_uint1') == 1) num = 11; elseif (strcmpi(str,'uint16') == 1 || strcmpi(str,'cdf_uint2') == 1) num = 12; elseif (strcmpi(str,'uint32') == 1 || strcmpi(str,'cdf_uint4') == 1) num = 14; elseif (strcmpi(str,'epoch') == 1 || strcmpi(str,'cdf_epoch') == 1) num = 31; elseif (strcmpi(str,'epoch16') == 1 || strcmpi(str,'cdf_epoch16') == 1) num = 32; elseif (strcmpi(str,'tt2000') == 1 || strcmpi(str,'cdf_time_tt2000') == 1) num = 33; elseif (strcmpi(str,'char') == 1 || strcmpi(str,'cdf_char') == 1 || ... strcmpi(str,'cdf_uchar') == 1) num = 52; else error('MATLAB:spdfcdfwrite:enteredvardatatype', '%s:%s\n', ... 'One of the entered variable data types is not valid. ', str); end function num = find_checksum(str) if (strcmpi(str,'none') == 1) num = 0; elseif (strcmpi(str,'md5') == 1) num = 1; else error('MATLAB:spdfcdfwrite:checksumvalue', '%s:%s\n', ... 'The checksum value is not valid. ', str); end function compress = find_compression(str) compress = ''; lstr=lower(str); item1=findstr(lstr, 'uncompressed'); item2=findstr(lstr, 'none'); if ~isempty(item1) || ~isempty(item2) compress = 'none'; else item1=findstr(lstr, 'gzip'); if ~isempty(item1) len = length(lstr); if (isstrprop(lstr(len),'digit') && len < 7) level = str2num(lstr(len)); if (level > 0 && level < 10) if (len == 6) compress = lstr; elseif (len == 5) compress = strcat(lstr(1,4), ',', lstr(5)); end end end else item1=findstr(lstr, 'run-length'); item2=findstr(lstr, 'rle'); if ~isempty(item1) || ~isempty(item2) compress = 'rle'; else item1=findstr(lstr, 'adaptive'); item2=findstr(lstr, 'ahuff'); if ~isempty(item1) || ~isempty(item2) compress = 'ahuff'; else item1=findstr(lstr, 'huffman'); item2=findstr(lstr, 'huff'); if ~isempty(item1) || ~isempty(item2) compress = 'huff'; end end end end end if (length(compress) == 0) error('MATLAB:spdfcdfwrite:compression', '%s:%s\n', ... 'The compression value is not valid. ', str); end function out = SPDFCOMPUTEEPOCH16(datetime) %SPDFCOMPUTEEPOCH16 converts the UTC date/time components to CDF_EPOCH16 time, % in nanoseconds since 2000-01-01 12:00:00 with leap seconds. % % OUT = SPDFCOMPUTEEPOCH16(datetime) returns the CDF_EPOCH16 time. OUT is % an array of N by 2 double values of mxDOUBLE_CLASS (double), each row % having two double values.. % % datetime An array with each row having ten (10) numerical % values for year, month, day, hour, minute, second, % millisecond, microsecond and nanosecond. % % Examples: % % % Compute two UTC times into CDF_EPOCH16. % % data = [2009 01 01 0 0 0 123 456 789 123; % 2009 01 01 12 0 0 987 654 321 987]; % out = SPDFCOMPUTEEPOCH16(data); % % SPDFENCODEEPOCH16(out) will show: % ans = % % '01-JAN-2009 00:00:00.123456789123' % '01-JAN-2009 12:00:00.987654321987' % % % See also SPDFENCODEEPOCH16, SPDFPARSEEPOCH16, SPDFBREAKDOWNEPOCH16 % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFCOMPUTEEPOCH16:inputArgumentCount', ... 'SPDFCOMPUTEEPOCH16 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFCOMPUTEEPOCH16:outputArguments', ... 'SPDFCOMPUTEEPOCH16 requires only one output argument.') end if (~isa(datetime,'numeric')) error('MATLAB:SPDFCOMPUTEEPOCH16:inputArguments', ... 'SPDFCOMPUTEEPOCH16 requires the input to be in numeric.') end ss=size(datetime); if (ss(1) < 1 || ss(2) ~= 10) error('MATLAB:SPDFCOMPUTEEPOCH16:inputArguments', ... 'SPDFCOMPUTEEPOCH16 requires each row to have ten (10) date/time fields.') end out = spdfcomputeepoch16c (datetime); function out = SPDFCOMPUTEEPOCH(datetime) %SPDFCOMPUTEEPOCH converts the UTC date/time components to CDF_EPOCH time, % in milliseconds since 00-01-01. % % OUT = SPDFCOMPUTEEPOCH(datetime) returns the CDF_EPOCH time. OUT is % a vector of double values of mxDOUBLE_CLASS (double). % % datetime An array with each row having seven (7) numerical % values for year, month, day, hour, minute, second, % millisecond. % % Examples: % % % Compute two UTC times into CDF_EPOCH. % % data = [2009 01 01 0 0 0 123; % 2009 01 01 12 0 0 987]; % out = SPDFCOMPUTEEPOCH(data); % % SPDFENCODEEPOCH(out) will show: % ans = % % '01-JAN-2009 00:00:00.123' % '01-JAB-2009 12:00:00.987' % % % See also CDFEPOCH, SPDFENCODEEPOCH, SPDFPARSEEPOCH, SPDFBREAKDOWNEPOCH % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFCOMPUTEEPOCH:inputArgumentCount', ... 'SPDFCOMPUTEEPOCH requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFCOMPUTEEPOCH:outputArguments', ... 'SPDFCOMPUTEEPOCH requires only one output argument.') end if (~isa(datetime,'numeric')) error('MATLAB:SPDFCOMPUTEEPOCH:inputArguments', ... 'SPDFCOMPUTEEPOCH requires the input to be in numeric.') end ss=size(datetime); if (ss(1) < 1 || ss(2) ~= 7) error('MATLAB:SPDFCOMPUTEEPOCH:inputArguments', ... 'SPDFCOMPUTEEPOCH requires each row to have seven (7) date/time fields.') end out = spdfcomputeepochc (datetime); function out = SPDFCOMPUTETT2000(datetime) %SPDFCOMPUTETT2000 converts the UTC date/time components to CDF TT2000 time, % in nanoseconds since 2000-01-01 12:00:00 with leap seconds. % % OUT = SPDFCOMPUTETT2000(datetime) returns the CDF TT2000 time. OUT is % a vector of integer values of mxINT64_CLASS (int64). % % datetime An array with each row having nine (9) numerical % values for year, month, day, hour, minute, second, % millisecond, microsecond and nanosecond. % % Examples: % % % Compute two UTC times into CDF TT2000. % % data = [2009 01 01 0 0 0 123 456 789; % 2009 01 01 12 0 0 987 654 321]; % out = SPDFCOMPUTETT2000(data); % % SPDFENCODETT2000(out) will show: % ans = % % '2009-01-01T00:00:00.123456789' % '2009-01-01T12:00:00.987654321' % % % See also CDFTT2000, SPDFENCODETT2000, SPDFPARSETT2000, SPDFBREAKDOWNTT2000 % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFCOMPUTETT2000:inputArgumentCount', ... 'SPDFCOMPUTETT2000 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFCOMPUTETT2000:outputArguments', ... 'SPDFCOMPUTETT2000 requires only one output argument.') end if (~isa(datetime,'numeric')) error('MATLAB:SPDFCOMPUTETT2000:inputArguments', ... 'SPDFCOMPUTETT2000 requires the input to be in numeric.') end ss=size(datetime); if (ss(1) < 1 || ss(2) ~= 9) error('MATLAB:SPDFCOMPUTETT2000:inputArguments', ... 'SPDFCOMPUTETT2000 requires each row to have nine (9) date/time fields.') end out = spdfcomputett2000c (datetime); function epoch16 = spdfdatenumtoepoch16(varargin) %SPDFDATENUMtoEPOCH16 Convert MATLAB's datenum to CDF_EPOCH16 values. % % E = SPDFDATENUMtoEPOCH16(DATE) convert a DATE, a valid string (datestr) or % number (datenum) representing a date, to CDF_EPOCH16 value. % % Note that a CDF_EPOCH16 is the number of picoseconds since % 1-Jan-0000 while MATLAB datenums are the number of days since 0-Jan-0000. % % See also SPDFEPOCH16TODATENUM, SPDFCOMPUTEEPOCH16, SPDFENCODEEPOCH16. % SPDFPARSEEPOCH16, SPDFBREAKDOWNEPOCH16. if (nargin > 1) error('MATLAB:SPDFDATENUMtoEPOCH16:SPDFDATENUMtoEPOCH16:tooManyInput', ... 'Only one argument is allowed.'); elseif (nargin < 1) error('MATLAB:SPDFDATENUMtoEPOCH16:SPDFDATENUMtoEPOCH16:tooFewInput', ... 'Only one argument is allowed.'); else input = varargin{1}; end if iscellstr(input) input = char(input); end if ~ischar(input) & ~isnumeric(input) error('MATLAB:SPDFDATENUMtoEPOCH16:SPDFDATENUMtoEPOCH16:badInputs', ... 'Input must be a number, string, cellstr.'); end if ischar(input) % If the input is a string, then you have to convert % Convert to MATLAB datenum. If this bombs out, an invalid % datestr was passed to datenum. n = datenum(input); else % It's numeric, so if it's a matrix, go element by element % and convert each and then reshape. n = input(:); end epoch16 = spdfdatenumtoepoch16c(n); function epoch = spdfdatenumtoepoch(varargin) %SPDFDATENUMtoEPOCH Convert MATLAB's datenum to CDF_EPOCH values. % % E = SPDFDATENUMtoEPOCH(DATE) convert a DATE, a valid string (datestr) or % number (datenum) representing a date, to CDF_EPOCH value. % % Note that a CDF epoch is the number of milliseconds since % 1-Jan-0000 while MATLAB datenums are the number of days since 0-Jan-0000. % % See also CDFEPOCH, SPDFEPOCHTODATENUM, SPDFCOMPUTEEPOCH, SPDFENCODEEPOCH. % SPDFPARSEEPOCH, SPDFBREAKDOWNEPOCH. if (nargin > 1) error('MATLAB:SPDFDATENUMtoEPOCH:SPDFDATENUMtoEPOCH:tooManyInput', ... 'Only one argument is allowed.'); elseif (nargin < 1) error('MATLAB:SPDFDATENUMtoEPOCH:SPDFDATENUMtoEPOCH:tooFewInput', ... 'Only one argument is allowed.'); else input = varargin{1}; end if iscellstr(input) input = char(input); end if ~ischar(input) & ~isnumeric(input) error('MATLAB:SPDFDATENUMtoEPOCH:SPDFDATENUMtoEPOCH:badInputs', ... 'Input must be a number, string, cellstr.'); end if ischar(input) % If the input is a string, then you have to convert % Convert to MATLAB datenum. If this bombs out, an invalid % datestr was passed to datenum. n = datenum(input); else % It's numeric, so if it's a matrix, go element by element % and convert each and then reshape. n = input(:); end epoch = spdfdatenumtoepochc(n); function tt2000 = spdfdatenumtott2000(varargin) %SPDFDATENUMtoTT2000 Convert MATLAB's datenum to CDF_TIME_TT2000 values. % % E = SPDFDATENUMtoTT2000(DATE) convert a DATE, a valid string (datestr) or % number (datenum) representing a date, to CDF TT2001 value. % % Note that a CDF TT2000 is the number of nanoseconds since % 1-Jan-0000T12:00:00 with leap seconds included and that MATLAB % datenums are the number of days since 0-Jan-0000. % % See also CDFTT2000, SPDFTT2000TODATENUM, SPDFCOMPUTETT2000, SPDFENCODETT2000, % SPDFPARSETT2000, SPDFBREAKDOWNTT2000. if (nargin > 1) error('MATLAB:SPDFDATENUMtoTT2000:SPDFDATENUMtoTT2000:tooManyInput', ... 'Only one argument is allowed.'); elseif (nargin < 1) error('MATLAB:SPDFDATENUMtoTT2000:SPDFDATENUMtoTT2000:tooFewInput', ... 'Only one argument is allowed.'); else input = varargin{1}; end if iscellstr(input) input = char(input); end if ~ischar(input) & ~isnumeric(input) error('MATLAB:SPDFDATENUMtoTT2000:SPDFDATENUMtoTT2000:badInputs', ... 'Input must be a number, string, cellstr.'); end if ischar(input) % If the input is a string, then you have to convert % Convert to MATLAB datenum. If this bombs out, an invalid % datestr was passed to datenum. n = datenum(input); else % It's numeric, so if it's a matrix, go element by element % and convert each and then reshape. n = input(:); end tt2000 = spdfdatenumtott2000c(n); function out = SPDFENCODEEPOCH16(epoch, varargin) %SPDFENCODEEPOCH16 encodes an epoch of CDF_EPOCH16 data type, an double array value % % OUT = SPDFENCODEEPOCH16(epoch) % Returns a UTC string(s). % % epoch An epoch % % The encoded epoch string will have the following ISO 8601 format: % yyyy-mm-ddThh:mm:ss.mmmuuunnnppp % e.g., "2000-01-01T12:34:56.123456789999" % Originally, it was in this form: % dd-mmm-yyyy hh:mm:ss.mmm.uuu.nnn.ppp % e.g., "01-Jan-2000 12:34:56.123.456.789.999" % % OUT = SPDFENCODEEPOCH16(epoch, 'Format', FORMAT) encodes the UTC % string into the specified format. FORMAT is a number from 0 to 4. % FORMAT: % 0: dd-mmm-yyyy hh:mm:ss.mmm.uuu.nnn.ppp % e.g., "01-JAN-2000 12:34:56.123.456.789.999" % 1: yyyymmdd.ddddddd e.g., "20000101.1200000" % 2: yyyymmddhhmmss e.g., "20000101123456" % 3: yyyy-mm-ddThh:mm:ss.mmm.uuu.nnn.pppZ % e.g., "2000-01-01T12:34:56.123.456.789.999Z" % 4: yyyy-mm-ddThh:mm:ss.mmmuuunnnppp % e.g., "2000-01-01T12:34:56.123456789999" % where mmm is milliseconds, % where uuu is microseconds, % where nnn is nanoseconds, % where ppp is picoseconds. % % Examples: % % % Acquire 'Epoch' variable data as is (two double values) from 'sample' CDF % % and encode the epoch values. % % epochs = spdfcdfread('Sample', 'Variables', {'Epoch'}, % "KeepEpochAsIs", true); % spdfencodeepoch16(epochs) % % See also SPDFBREAKDOWNEPOCH16, SPDFCOMPUTEEPOCH16, SPDFPARSEEPOCH16 % HISTORY: % March 5, 2013 Mike Liu The initial version. if (nargin < 1) error('MATLAB:SPDFENCODEEPOCH16:inputArgumentCount', ... 'SPDFENCODEEPOCH16 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFENCODEEPOCH16:outputArguments', ... 'SPDFENCODEEPOCH16 requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:SPDFENCODEEPOCH:badInputArguments', '%s', msg) end out = spdfencodeepoch16c(epoch, args.Format); %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.Format = int32(4); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'format'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) msg = 'Parameter name must be a string.'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'format' if (k == length(varargin)) msg = 'No format specified.'; return else format = varargin{k + 1}; if (~isa(format, 'double') || ~isscalar(format)) msg = 'Format must be a single integer.'; return; end if (int32(format) < 0 || int32(format) > 4) msg = sprintf('format value "%d" is out or 0-4 range.', format); return; end args.Format = int32(format); end end % switch end % for end % if (nargin > 1) function out = SPDFENCODEEPOCH(epoch, varargin) %SPDFENCODEEPOCH encodes an epoch of CDF_EPOCH data type, a double value or %cdfepoch object.. % % OUT = SPDFENCODEEPOCH(epoch) % Returns a UTC string. % % epoch An epoch % % The encoded epoch string will have the following ISO 8601 format: % yyyy-mm-ddThh:mm:ss.mmm, e.g., "2000-01-01T12:34:56.123" % Originally, it was in this form: % dd-mmm-yyyy hh:mm:ss.mmm, e.g., "01-Jan-2000 12:34:56.123" % % OUT = SPDFENCODEEPOCH(epoch, 'Format', FORMAT) encodes the UTC % string into the specified format. FORMAT is a number from 0 to 4. % FORMAT: % 0: dd-mmm-yyyy hh:mm:ss.mmm, e.g., "01-JAN-2000 12:34:56.123" % 1: yyyymmdd.ddddddd, e.g., "20000101.1200000" % 2: yyyymmddhhmmss, e.g., "20000101123456" % 3: yyyy-mm-ddThh:mm:ss.mmmZ, e.g., "2000-01-01T12:34:56.123Z" % 4: yyyy-mm-ddThh:mm:ss.mmm, e.g., "2000-01-01T12:34:56.123" % where mmm is milliseconds. % Format: 0 is the only allowed form for cdfepoch object. % % Note: If the epoch values come from spdfcdfread function call, the values % can be in one of the three forms: in cdfepoch object, in MATLAB % datenum (the default), or in their original CDF_EPOCH % data via an extra 'keepepochasis' option. This function works for % cdfepoch objects or the data retrieved with 'keepepochasis' option. % For datenum values, use MATLAB's datestr instead. % % Examples: % % % Encode epoch from date/time: 2012-10-10T10:10:10.010Z: % % utc = '2012-10-10T10:10:10.010'; % epoch = UTC2CDFEpoch(utc); % SPDFENCODEEPOCH(epoch) % ans = % '10-Oct-2012 10:10:10.010' % SPDFENCODEEPOCH(epoch, 'format', 3) % ans = % '2012-10-10T10:10:10.010Z' % % % Acquire 'Epoch' variable data as is (double values) from 'sample' CDF % % and encode the epoch values. % % epochs = spdfcdfread('Sample', 'Variables', {'Epoch'}, 'KEEPEPOCHASIS', true); % spdfencodeepoch(epochs) % % See also CDFEPOCH, SPDFBREAKDOWNEPOCH, SPDFCOMPUTEEPOCH, SPDFPARSEEPOCH % HISTORY: % August 16, 2011 Mike Liu The initial version. % October 16, 2018 Mike Liu The default format is now 4 (from 0). if (nargin < 1) error('MATLAB:SPDFENCODEEPOCH:inputArgumentCount', ... 'SPDFENCODEEPOCH requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFENCODEEPOCH:outputArguments', ... 'SPDFENCODEEPOCH requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:SPDFENCODEEPOCH:badInputArguments', '%s', msg) end if (isa(epoch,'cdfepoch')) if (length(epoch) > 1) for p = 1:length(epoch) if (~isa(epoch, 'cell')) dataaa(p,1) = datestr((todatenum(epoch(p,1))), 0); else if (length(epoch{p}) > 1) for q = 1:length(epoch{p}) dataaa(q) = datastr((todatenum(epoch{p}(q,1))), 0); end else dataaa(p,1) = datastr((todatenum(epoch{p})), 0); end end end out = dataaa; end else out = spdfencodeepochc(epoch, args.Format); end %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.Format = int32(4); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'format'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) msg = 'Parameter name must be a string.'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'format' if (k == length(varargin)) msg = 'No format specified.'; return else format = varargin{k + 1}; if (~isa(format, 'double') || ~isscalar(format)) msg = 'Format must be a single integer.'; return; end if (int32(format) < 0 || int32(format) > 4) msg = sprintf('format value "%d" is out or 0-4 range.', format); return; end args.Format = int32(format); end end % switch end % for end % if (nargin > 1) function out = SPDFENCODETT2000(tt2000, varargin) %SPDFENCODETT2000 encodes the CDF epoch data in TT2000 data type to UTC %strings. % % OUT = SPDFENCODETT2000(tt2000) returns the CDF epoch in string. OUT is % a cell of strings. % % tt2000 A single or vector of numerical values of % CDF_TIME_TT2000 (an mxINT64_CLASS) data type. % % The encoded epoch string will have the following format: % yyyy-mm-ddThh:mm:ss.mmmuuunnn, e.g., "2000-01-01T12:34:56.123456789" % % OUT = SPDFENCODETT2000(tt2000, 'Format', FORMAT) encodes the UTC % string into the specified format. FORMAT is a number from 0 to 4. % FORMAT: % 0: dd-mmm-yyyy hh:mm:ss.mmmuuunnn, e.g., "01-JAN-2000 12:34:56.123456789" % 1: yyyymmdd.dddddddddd, e.g., "20000101.1200000000" % 2: yyyymmddhhmmss, e.g., "20000101123456" % 3: yyyy-mm-ddThh:mm:ss.mmmuuunnn, e.g., "2000-01-01T12:34:56.123456789" % 4: yyyy-mm-ddThh:mm:ss.mmmuuunnnZ, e.g., "2000-01-01T12:34:56.123456789Z" % where mmmuuunnn is milliseconds, microseconds and nanoseconds. % Format 3 is the default (as ISO 8601) if this option is not provided. % % Examples: % % % Read all of the data from the same file, the most efficient way, % % and encode the Variable Epoch, of CDF_TIME_TT2000 data type, to UTC % % string. % % data = spdfcdfread('example', 'Variables', {'Epoch'}, "KEEPEPOCHASIS", true); % out = SPDFENCODETT2000(data); % % % See also CDFTT2000, SPDFPARSETT2000, SPDFCOMPUTETT2000, SPDFBREAKDOWNTT2000, % HISTORY: % August 16, 2011 Mike Liu The initial version. % October 6, 2018 Mike Liu Added format 4. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFENCODETT2000:inputArgumentCount', ... 'SPDFENCODETT2000 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFENCODETT2000:outputArguments', ... 'SPDFENCODETT2000 requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:SPDFENCODETT2000:badInputArguments', '%s', msg) end if (isa(tt2000,'cdftt2000')) if (length(tt2000) > 1) for p = 1:length(tt2000) if (~isa(tt2000, 'cell')) dataaa(p,1) = spdfencodett2000c(int64(todatenum(tt2000(p,1))), args.Format); else if (length(tt2000{p}) > 1) for q = 1:length(tt2000{p}) dataaa(q) = spdfencodett2000c(int64(todatenum(tt2000{p}(q,1))), args.Format); end else dataaa(p,1) = spdfencodett2000c(int64(todatenum(tt2000{p})), args.Format); end end end out = dataaa; end elseif (isa(tt2000,'double')) out = datestr(tt2000); else out = spdfencodett2000c(tt2000, args.Format); end %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.Format = int32(3); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'format'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); if (~ischar(param)) msg = 'Parameter name must be a string.'; return end idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'format' if (k == length(varargin)) msg = 'No format specified.'; return else format = varargin{k + 1}; if (~isa(format, 'double') || ~isscalar(format)) msg = 'Format must be a single integer.'; return; end if (int32(format) < 0 || int32(format) > 4) msg = sprintf('format value "%d" is out of 0-4 range.', format); return; end args.Format = int32(format); end end % switch end % for end % if (nargin > 1) function out = SPDFEPOCH16toDATENUM(epoch16) %SPDFEPOCH16toDATENUM converts the time in UTC string (returned from % spdfcdfread) or date/time values for CDF_EPOCH16 to % MATLAB datenum % % OUT = SPDFEPOCH16toDATENUM(epoch16) returns MATLAB datenum. % OUT a column vector of numerical values of MATLAB date numbers. % % epoch16 A vector or cell of UTC string or an M-by-10 matrix % containing M full or partial date vectors for % year, month, day, hour, minute, second, millisecond, % microsecond, nanosecond and picosecond, in that % order. % % Note: % The valid epoch string should have one of the following forms: % 1. dd-mmm-yyyy hh:mm:ss.mmm.uuu.nnn.ppp (length of 36), e.g., % "01-JAN-2000 12:00:00.123.456.789.000" % 2. yyyymmdd.ddddddddddddddd (length of 24), e.g., % "20000101.120000000000000" % 3. yyyymmddhhmmss (length of 14), e.g., % "20000101120000" % 4. yyyy-mm-ddThh:mm:ss.mmmuuunnnppp (length of 32), e.g., % "2000-01-01T12:00:00.123456789000" % where mmmuuunnnppp is for milliseconds, microseconds, nanoseconds and % picoseconds. % % Examples: % % % Read all the variable data in a CDF file. Among them, the variable of % CDF_EPOCH16 data type is returned in UTC strings. Convert the strings % to MATLAB datenum. The variable is at index of 17 from the output of % 1 by 20 array of cells from spdfcdfread, the efficient way. % % data = spdfcdfread('test'); % epoch = data(1,17); % datenums = SPDFEPOCH16toDATENUM(epoch); % % % Similar to the above example. But, read in the data into 40 by 20 array % of cells by spdfcdfread. Convert the variable of CDF_EPOCH16 data type in % UTC strings and convert them to MATLAB datenum. % % data = spdfcdfread('test', 'Combinerecords', false); % epoch = data(:,17); % datenums = SPDFEPOCH16toDATENUM(epoch); % % % Convert the UTC strings in vector to MATLAB datenum. % % epoch1 = ['2009-01-01T00:00:00.123456789000'; % '2009-01-01T12:00:00.123456789000']; % datenums = SPDFEPOCH16toDATENUM(epoch1); % % % Convert the date/times in matrix to MATLAB datenum. % % epoch2 = [2009 01 01 00 00 00 123 456 789 000; % 2009 01 01 12 00 00 123 456 789 000]; % datenums = SPDFEPOCH16toDATENUM(epoch2); % % See also SPDFCDFREAD. % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFEPOCH16toDATENUM:inputArgumentCount', ... 'SPDFEPOCH16toDATENUM requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFEPOCH16toDATENUM:outputArguments', ... 'SPDFEPOCH16toDATENUM requires only one output argument.') end s = size(epoch16); if (iscell(epoch16(1,1))) if (s(1) == 1) epoch16 = epoch16{1,1}; else if (iscellstr(epoch16)) epoch16 = char(epoch16); else if (s(2) == 1) for x=1:s(1) epoch16(x,1) = epoch16{x,1}; end end end end end if (iscell(epoch16)) epoch16 = cell2mat(epoch16); end if (isnumeric(epoch16)) s = size(epoch16); if (s(2) ~= 10) error('MATLAB:SPDFEPOCH16toDATENUM:inputArgumentvector', ... 'SPDFEPOCH16toDATENUM requires an M by 10 vector for date/time fields.') end dates=epoch16(:,1:6); for p =1:s(1) dates(p,6) = epoch16(p,6) + epoch16(p,7)/1000 + epoch16(p,8)/1000000 + ... epoch16(p,9)/1000000000 + epoch16(p,10)/1000000000000; end out = datenum(dates); else dates = spdfparseepoch16c(epoch16); out = datenum(dates); end function out = SPDFEPOCH16UnixTime(time, varargin) %SPDFEPOCH16UnixTime converts the CDF_EPOCH16 time (picoseconds since % 01-01-0000 00:00:00.000) to unix time (seconds from % 01-01-1970 00:00:00.000) or vice verse. % % OUT = SPDFEPOCH16UnixTime(time, 'TOEPOCH16', TF) returns converted time(s). % OUT a column vector of numerical values of converted times. % % time A vector or scalar of time(s), based on CDF_EPOCH16 data % type or unix time. % % The option 'TOEPOCH16' is specified to true if the time conversion is from % unix time to CDF_EPOCH16. If false, or not specified, the conversion is % from CDF_EPOCH16 to unix time. % % Note: Unix time to CDF_EPOCH16 might not be properly converted at % sub-microseconds portion. % % Examples: % % % Convert a CDF_EPOCH16 data, a scalar at % 01-01-2000 00:00:00.123.456.789.000 to a unix % time value. % % epoch = spdfcomputeepoch16([2000,1,1,0,0,0,123,456,789,000]); % unixtime = SPDFEPOCH16UnixTime(epoch); % % % Convert CDF_EPOCH16 data, a vector of % 01-01-2000 00:00:00.123.456.789.000 and % 02-02-2001 01:01:01.456.789.012.345 to unix time values. % % epochs = spdfcomputeepoch16([2000,1,1,0,0,0,123,456,789,0; % 2001,2,2,1,1,1,456,789,012,345]); % unixtimes = SPDFEPOCH16UnixTime(epochs); % % % Convert a unix time to CDF_EPOCH16 epoch. % % epoch = SPDFEPOCH16UnixTime(unixtime, 'TOEPOCH16', true); % % % Convert a vector of unix times to CDF_EPOCH16 epochs. % % epochs = SPDFEPOCH16UnixTime(unixtimes, 'TOEPOCH16', true); % % HISTORY: % November 22, 2018 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFEPOCH16UnixTime:inputArgumentCount', ... 'SPDFEPOCH16UnixTime requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFEPOCH16UnixTime:outputArguments', ... 'SPDFEPOCH16UnixTime requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:spdfepochunixtime:badInputArguments', '%s', msg) end if (args.toepoch == 0) time = transpose(time); end out = spdfepoch16unixtimec(time, args.toepoch); if (args.toepoch == 1) out = transpose(out); end end %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.toepoch = int32(0); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'toepoch16'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'toepoch16' if (k == length(varargin)) msg = 'No epoch conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Conversion value must be a scalar logical.'; end if (islogical(convert)) if (convert) args.toepoch = int32(1); else args.toepoch = int32(0); end elseif (isnumeric(convert)) if (convert > 0) args.toepoch = int32(1); else args.toepoch = int32(0); end else msg = 'Epoch conversion value must be a scalar logical.'; end end end % switch end % for end % if (nargin > 1) end function out = SPDFEPOCHtoDATENUM(epoch) %SPDFEPOCHtoDATENUM converts the time in UTC string (returned from spdfcdfread) or % date/time values for CDF_EPOCH to MATLAB datenum % % OUT = SPDFEPOCHtoDATENUM(epoch) returns MATLAB datenum. % OUT a column vector of numerical values of MATLAB date numbers. % % epoch A vector or cell of UTC string or an M-by-7 matrix % containing M full or partial date vectors for % year, month, day, hour, minute, second, millisecond, % in that order. % % Note: % The valid epoch string should have one of the following forms: % 1. dd-mmm-yyyy hh:mm:ss.lll (length of 24), e.g., % "01-JAN-2000 12:00:00.123" % 2. yyyymmdd.ddddddd (length of 16), e.g., % "20000101.1200000" % 3. yyyymmddhhmmss (length of 14), e.g., % "20000101120000" % 4. yyyy-mm-ddThh:mm:ss.lll (length of 23), e.g., % "2000-01-01T12:00:00.123" % % Examples: % % % Read all the variable data in a CDF file. Among them, the variable of % CDF_EPOCH data type is returned in UTC strings. Convert the strings % to MATLAB datenum. The variable is at index of 17 from the output of % 1 by 20 array of cells from spdfcdfread, the efficient way. % % data = spdfcdfread('test', 'KeepEpochAsIs', true); % epoch = data(1,17); % datenums = SPDFEPOCHtoDATENUM(epoch); % % % Similar to the above example. But, read in the data into 40 by 20 array % of cells by spdfcdfread. Convert the variable of CDF_EPOCH data type in % UTC strings and convert them to MATLAB datenum. % % data = spdfcdfread('test'); % epoch = data(:,17); % datenums = SPDFEPOCHtoDATENUM(epoch); % % % Convert the UTC strings in vector to MATLAB datenum. % % epoch1 = ['2009-01-01T00:00:00.123'; % '2009-01-01T12:00:00.123']; % datenums = SPDFEPOCHtoDATENUM(epoch1); % % % Convert the date/times in matrix to MATLAB datenum. % % epoch2 = [2009 01 01 00 00 00 123; % 2009 01 01 12 00 00 123]; % datenums = SPDFEPOCHtoDATENUM(epoch2); % % See also SPDFCDFREAD. % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFEPOCHtoDATENUM:inputArgumentCount', ... 'SPDFEPOCHtoDATENUM requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFEPOCHtoDATENUM:outputArguments', ... 'SPDFEPOCHtoDATENUM requires only one output argument.') end if (isa(epoch, 'cdfepoch')) error('MATLAB:SPDFEPOCHtoDATENUM:inputobject', ... 'SPDFEPOCHtoDATENUM can not handle input data in cdfepoch object class.') end s = size(epoch); if (iscell(epoch(1,1))) if (s(1) == 1) epoch = epoch{1,1}; else if (iscellstr(epoch)) epoch = char(epoch); else if (s(2) == 1) for x=1:s(1) epoch(x,1) = epoch{x,1}; end end end end end if (iscell(epoch)) epoch = cell2mat(epoch); end if (isnumeric(epoch)) s = size(epoch); if (s(2) == 1) out = datenum(epoch./86400000.0+1); else if (s(2) ~= 7) error('MATLAB:SPDFEPOCHtoDATENUM:inputArgumentvector', ... 'SPDFEPOCHtoDATENUM requires an M by 7 vector for date/time fields.') end dates=epoch(:,1:6); for p =1:s(1) dates(p,6) = epoch(p,6) + epoch(p,7)/1000.0; end out = datenum(dates); end else dates = spdfparseepochc(epoch); out = datenum(dates); end function out = SPDFEPOCHUnixTime(time, varargin) %SPDFEPOCHUnixTime converts the CDF_EPOCH time (milliseconds since % 01-01-0000 00:00:00.000) to unix time (seconds from % 01-01-1970 00:00:00.000) or vice verse. % % OUT = SPDFEPOCHUnixTime(time, 'TOEPOCH', TF) returns converted time(s). % OUT a column vector of numerical values of converted times. % % time A vector or scalar of time(s), based on CDF_EPOCH data type % or unix time. % % The option 'TOEPOCH' is specified to true if the time conversion is from % unix time to CDF_EPOCH. If false, or not specified, the conversion is % from CDF_EPOCH to unix time. % % Examples: % % % Convert a CDF_EPOCH data, a scalar at 01-01-2000 00:00:00.123 to a unix % time value. % % epoch = spdfcomputeepoch([2000,1,1,0,0,0,123]); % unixtime = SPDFEPOCHUnixTime(epoch); % % % Convert CDF_EPOCH data, a vector at 01-01-2000 00:00:00.123 and % 02-02-2001 01:01:01.456 to unix time values. % % epochs = spdfcomputeepoch([2000,1,1,0,0,0,123; 2001,2,2,1,1,1,456]); % unixtimes = SPDFEPOCHUnixTime(epochs); % % % Convert a unix time to CDF_EPOCH epoch. % % epoch = SPDFEPOCHUnixTime(unixtime, 'TOEPOCH', true); % % % Convert a vector of unix times to CDF_EPOCH epochs. % % epochs = SPDFEPOCHUnixTime(unixtimes, 'TOEPOCH', true); % % HISTORY: % November 22, 2018 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFEPOCHUnixTime:inputArgumentCount', ... 'SPDFEPOCHUnixTime requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFEPOCHUnixTime:outputArguments', ... 'SPDFEPOCHUnixTime requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:spdfepochunixtime:badInputArguments', '%s', msg) end out = spdfepochunixtimec(time, args.toepoch); end %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.toepoch = int32(0); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'toepoch'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'toepoch' if (k == length(varargin)) msg = 'No epoch conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Conversion value must be a scalar logical.'; end if (islogical(convert)) if (convert) args.toepoch = int32(1); else args.toepoch = int32(0); end elseif (isnumeric(convert)) args.toepoch = int32(convert); else msg = 'Epoch conversion value must be a scalar logical.'; end end end % switch end % for end % if (nargin > 1) end function out = SPDFPARSEEPOCH16(epoch16) %SPDFPARSEEPOCH16 converts the epoch in UTC string to CDF_EPOCH16 %data type. % % OUT = SPDFPARSEEPOCH16(epoch16) returns the CDF epoch in CDF_EPOCH16 type. % OUT an array of numerical values of mxDOUBLE_CLASS (double). % % epoch16 A cell or vector of UTC string % % Note: the valid epoch string must be one of the following forms: % 0: dd-mmm-yyyy hh:mm:ss.mmm.uuu.nnn.ppp, e.g., "01-JAN-2010 12:00:00.000.000.000.000" % 1: yyyymmdd.ddddddddddddddd, e.g., "20100101.120000000000000" % 2: yyyymmddhhmmss, e.g., "20100101120000" % 3: yyyy-mm-ddThh:mm:ss.mmm.uuu.nnn.pppZ, e.g., "2010-01-01T12:00:00.000.000.000.000Z" % where mmm is milliseconds, uuu microseconds, nnn nanoseconds, % ppp picoseconds. % 4: yyyy-mm-ddThh:mm:ss.mmmuuunnnppp, e.g., "2010-01-01T12:00:00.000000000000" % where mmm is milliseconds, uuu microseconds, nnn nanoseconds, % ppp picoseconds. % % Examples: % % % Convert the UTC strings in cell to CDF_EPOCH16 and write it to Epoch % % variable of CDF CDF_EPOCH16 data type in a CDF. % % utcs = {'2009-01-01T00:00:00.123'; '2009-01-01T12:00:00.123'}; % epoch16 = SPDFPARSEEPOCH16(utcs); % SPDFCDFWRITE('example', {'Epoch', epoch16}, ... % 'recordbound', {'Epoch'}); % % See also SPDFENCODEEPOCH16, SPDFCOMPUTEEPOCH16, SPDFBREAKDOWNEPOCH16 % HISTORY: % August 16, 2014 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFPARSEEPOCH16:inputArgumentCount', ... 'SPDFPARSEEPOCH16 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFPARSEEPOCH16:outputArguments', ... 'SPDFPARSEEPOCH16 requires only one output argument.') end out = spdfparseepoch16c(epoch16); function out = SPDFPARSEEPOCH(epoch) %SPDFPARSEEPOCH converts the epoch in UTC string to CDF_EPOCH %data type. % % OUT = SPDFPARSEEPOCH(epoch) returns the CDF epoch in EPOCH type. % OUT a vector of numerical values of mxDOUBLE_CLASS (double). % % epoch A cell or vector of UTC string % % Note: the valid epoch string must be one of the following forms: % 0: dd-mmm-yyyy hh:mm:ss.mmm, e.g., "01-JAN-2010 12:00:00.000" % 1: yyyymmdd.ddddddd, e.g., "20100101.1200000" % 2: yyyymmddhhmmss, e.g., "20100101120000" % 3: yyyy-mm-ddThh:mm:ss.mmmZ, e.g., "2010-01-01T12:00:00.000Z" % where mmm is milliseconds. % 4: yyyy-mm-ddThh:mm:ss.mmm, e.g., "2010-01-01T12:00:00.000" % where mmm is milliseconds. % % Examples: % % % Convert the UTC strings in cell to CDF_EPOCH and write it to Epoch % % variable of CDF CDF_EPOCH data type in a CDF. % % utcs = {'2009-01-01 00:00:00.123'; '2009-01-01 12:00:00.123'}; % epoch = SPDFPARSEEPOCH(utcs); % SPDFCDFWRITE('example', {'Epoch', epoch}, ... % 'recordbound', {'Epoch'}); % % See also CDFEPOCH, SPDFENCODEEPOCH, SPDFCOMPUTEEPOCH, SPDFBREAKDOWNEPOCH % HISTORY: % August 16, 2014 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFPARSEEPOCH:inputArgumentCount', ... 'SPDFPARSEEPOCH requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFPARSEEPOCH:outputArguments', ... 'SPDFPARSEEPOCH requires only one output argument.') end out = spdfparseepochc(epoch); function out = SPDFPARSETT2000(tt2000) %SPDFPARSETT2000 converts the CDF epoch in UTC string to CDF_TIME_TT2000 %data type. % % OUT = SPDFPARSETT2000(tt2000) returns the CDF epoch in TT2000 data type. % OUT a vector of numerical values of mxINT64_CLASS (int64). % % tt2000 A cell or vector of TT2000 UTC string % % Note: the valid epoch string should be one of the following forms: % 0: dd-mmm-yyyy hh:mm:ss.mmmuuunnn, e.g., "01-JAN-2010 12:00:00.000000000" % 1: yyyymmdd.dddddddddd, e.g., "20100101.1200000000" % 2: yyyymmddhhmmss, e.g., "20100101120000" % 3: yyyy-mm-ddThh:mm:ss.mmmuuunnn, e.g., "2010-01-01T12:00:00.000000000" % where mmmuuunnn is for milliseconds, microseconds and nanoseconds. % 4: yyyy-mm-ddThh:mm:ss.mmmuuunnnZ, e.g., "2010-01-01T12:00:00.000000000Z" % where mmmuuunnn is for milliseconds, microseconds and nanoseconds. % % Examples: % % % Convert the UTC strings in cell to TT2000 and write it to Epoch % % variable of CDF TT2000 data type in a CDF. % % utcs = {'2009-01-01T00:00:00.123456789'; '2009-01-01T12:00:00.123456789'}; % tt2000 = SPDFPARSETT2000(utcs); % SPDFCDFWRITE('example', {'Epoch', tt2000}, 'TT2000', true, ... % 'recordbound', {'Epoch'}); % % See also CDFTT2000, SPDFENCODETT2000, SPDFCOMPUTETT2000, SPDFBREAKDOWNTT2000 % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFPARSETT2000:inputArgumentCount', ... 'SPDFPARSETT2000 requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFPARSETT2000:outputArguments', ... 'SPDFPARSETT2000 requires only one output argument.') end out = spdfparsett2000c(tt2000); function out = SPDFTT2000toDATENUM(tt2000) %SPDFTT2000toDATENUM converts the time in UTC string (returned from spdfcdfread) % or date/time values for CDF_TIME_TT2000 to MATLAB datenum % % OUT = SPDFTT2000toDATENUM(tt2000) returns MATLAB datenum. % OUT a column vector of numerical values of MATLAB date numbers. % % tt2000 A vector or cell of UTC string or an either % M-by-1 matrix of CDF_TIME_TT2000 values or % M-by-9 matrix containing M rows, each with date/time % fields for year, month, day, hour, minute, second, % millisecond, microsecond, and nanosecond, in that % order. % % Note: % The valid tt2000 string should have one of the following forms: % 1. dd-mmm-yyyy hh:mm:ss.mmmuuunnn (length of 30), e.g., % "01-JAN-2000 12:00:00.123456789" % 2. yyyymmdd.dddddddddd (length of 19), e.g., % "20000101.1200000000" % 3. yyyymmddhhmmss (length of 14), e.g., % "20000101120000" % 4. yyyy-mm-ddThh:mm:ss.mmmuuunnn (ISO 8601, length of 29), e.g., % "2000-01-01T12:00:00.123456789" % where mmmuuunnn is milliseconds, microseconds and nanoseconds. % % Examples: % % % Read all the variable data in a CDF file. Among them, the variable of % CDF_TIME_TT2000 data type, at index of 17, is returned. Convert the % variable of CDF_TIME_TT2000 data type in cdftt2000 objects to MATLAB % datenum. % % data = spdfcdfread('test','KeepEpochAsIs',true); % tt2000 = data(1,17); % datenums = SPDFTT2000toDATENUM(tt2000); % % % Convert the UTC strings in vector to MATLAB datenum. % % tt2000 = ['2009-01-01T00:00:00.123456789'; % '2009-01-01T12:00:00.123456789']; % datenums = SPDFTT2000toDATENUM(tt2000); % % % Convert the date/times in matrix to MATLAB datenum. % % tt2000 = [2009 01 01 00 00 00 123 456 789; % 2009 01 01 12 00 00 123 456 789]; % datenums = SPDFTT2000toDATENUM(tt2000); % % See also CDFTT2000, SPDFENCODETT2000, SPDFCOMPUTETT2000, SPDFPARSETT2000 % HISTORY: % August 16, 2011 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFTT2000toDATENUM:inputArgumentCount', ... 'SPDFTT2000toDATENUM requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFTT2000toDATENUM:outputArguments', ... 'SPDFTT2000toDATENUM requires only one output argument.') end if (isa(tt2000, 'cdftt2000')) error('MATLAB:SPDFTT2000toDATENUM:inputobject', ... 'SPDFTT2000toDATENUM can not handle input data in cdftt2000 object class.') end s = size(tt2000); if (iscell(tt2000(1,1))) if (s(1) == 1) tt2000 = tt2000{1,1}; else if (iscellstr(tt2000)) tt2000 = char(tt2000); else if (s(2) == 1) for x=1:s(1) tt2000(x,1) = tt2000{x,1}; end end end end end if (iscell(tt2000)) tt2000 = cell2mat(tt2000); end if (isnumeric(tt2000)) s = size(tt2000); if (s(2) == 1) dates = spdfbreakdowntt2000(tt2000); dates3 = dates(:, 1:6); for p =1:s(1) dates3(p,6) = dates(p,6) + dates(p,7)/1000 + dates(p,8)/1000000 + ... dates(p,9)/1000000000; end out = datenum(dates3); else if (s(2) ~= 9) error('MATLAB:SPDFTT2000toDATENUM:inputArgumentvector', ... 'SPDFTT2000toDATENUM requires an M by 9 vector for date/time fields.') end dates=tt2000(:,1:6); for p =1:s(1) dates(p,6) = tt2000(p,6) + tt2000(p,7)/1000 + tt2000(p,8)/1000000 + ... tt2000(p,9)/1000000000; end out = datenum(dates); end else dates = spdfparsett2000(tt2000); dates2 = spdfbreakdowntt2000(dates); dates3 = dates2(:, 1:6); for p =1:s(1) dates3(p,6) = dates2(p,6) + dates2(p,7)/1000 + dates2(p,8)/1000000 + ... dates2(p,9)/1000000000; end out = datenum(dates3); end function out = SPDFTT2000UnixTime(time, varargin) %SPDFTT2000UnixTime converts the CDF_TIME_TT2000 time (nanoseconds since % 2000-01-01 12:00:00.000 with leap seconds) to unix time % (seconds from 1970-01-01 00:00:00.000) or vice verse. % % OUT = SPDFTT2000UnixTime(time, 'TOTT2000', TF) returns converted time(s). % OUT a column vector of numerical values of converted times. % % time A vector or scalar of time(s), based on CDF_TIME_TT2000 data type % or unix time. % % The option 'TOTT2000' is specified to true if the time conversion is from % unix time to CDF_TIME_TT2000. If false, or not specified, the conversion is % from CDF_TIME_TT2000 to unix time. % % Note: Since unix time does not include leap seconds, the time conversion will % not be properly handled if a time falls on a leap second. The TT2000 % time has a higher time resolution, sub-milliseonds might not be preserved % in unix time. % % Examples: % % % Convert a CDF_TIME_TT2000 data, a scalar at 2000-01-01 00:00:00.123 to a unix % time value. % % epoch = spdfcomputett2000([2000,1,1,0,0,0,123,0,0]); % unixtime = SPDFTT2000UnixTime(epoch); % % % Convert CDF_TIME_TT2000 data, a vector at 2000-01-01-2000 00:00:00.123 and % 2001-02-02 01:01:01.456 to unix time values. % % epochs = spdfcomputett2000([2000,1,1,0,0,0,123,0,0; 2001,2,2,1,1,1,456,0,0]); % unixtimes = SPDFTT2000UnixTime(epochs); % % % Convert a unix time to CDF_TIME_TT2000 epoch. % % epoch = SPDFTT2000UnixTime(unixtime, 'TOTT2000', true); % % % Convert a vector of unix times to CDF_TIME_TT2000 epochs. % % epochs = SPDFTT2000UnixTime(unixtimes, 'TOTT2000', true); % % HISTORY: % November 22, 2018 Mike Liu The initial version. % % Process arguments. % if (nargin < 1) error('MATLAB:SPDFTT2000UnixTime:inputArgumentCount', ... 'SPDFTT2000UnixTime requires at least one input argument.') end if (nargout > 1) error('MATLAB:SPDFTT2000UnixTime:outputArguments', ... 'SPDFTT2000UnixTime requires only one output argument.') end [args, msg] = parse_inputs(varargin{:}); if (~isempty(msg)) error('MATLAB:spdftt2000unixtime:badInputArguments', '%s', msg) end out = spdftt2000unixtimec(time, args.toepoch); end %%% %%% Function parse_inputs %%% function [args, msg] = parse_inputs(varargin) % Set default values args.toepoch = int32(0); msg = ''; % Parse arguments based on their number. if (nargin > 0) paramStrings = {'tott2000'}; % For each pair for k = 1:2:length(varargin) param = lower(varargin{k}); idx = strmatch(param, paramStrings); if (isempty(idx)) msg = sprintf('Unrecognized parameter name "%s".', param); return elseif (length(idx) > 1) msg = sprintf('Ambiguous parameter name "%s".', param); return end switch (paramStrings{idx}) case 'tott2000' if (k == length(varargin)) msg = 'No epoch conversion value specified.'; return else convert = varargin{k + 1}; if (numel(convert) ~= 1) msg = 'Conversion value must be a scalar logical.'; end if (islogical(convert)) if (convert) args.toepoch = int32(1); else args.toepoch = int32(0); end elseif (isnumeric(convert)) args.toepoch = int32(convert); else msg = 'Epoch conversion value must be a scalar logical.'; end end end % switch end % for end % if (nargin > 1) end function epochObj = cdfepoch(varargin) %CDFEPOCH Construct epoch object for CDF export. % % E = CDFEPOCH(DATE) constructs a cdfepoch object where DATE is % a valid string (datestr) or number (datenum) representing a % date. DATE may also be a cdfepoch object. % % CDFEPOCH objects should be constructed to create EPOCH data in CDF's. % using SPDFCDFWRITE. Note that a CDF epoch is the number of milliseconds % since 1-Jan-0000 and that MATLAB datenums are the number of days % since 0-Jan-0000. % % See also SPDFCDFWRITE, DATENUM, SPDFCDFREAD, SPDFCDFINFO. if (nargin == 0) s.date = []; epochObj = class(s, 'cdfepoch'); return; elseif (nargin > 1) error('MATLAB:cdfepoch:cdfepoch:tooManyInputs', ... 'Too many input arguments.'); else input = varargin{1}; end if isa(input,'cdfepoch') epochObj = input; return; end if iscellstr(input) input = char(input); end if ~ischar(input) & ~isnumeric(input) error('MATLAB:cdfepoch:cdfepoch:badInputs', ... 'Input must be a number, string, cellstr, or cdfepoch object.'); end % Initialize in case passed empty s.date = []; if ischar(input) % If the input is a string, then you have to convert cdfepochs = []; % Convert to MATLAB datenum. If this bombs out, an invalid % datestr was passed to datenum. n = datenum(input); else % It's numeric, so if it's a matrix, go element by element % and convert each and then reshape. n = input(:); end s = struct('date',num2cell((n - 1) * 24 * 3600000)'); s = s'; if isnumeric(input) & ~isempty(input) s = reshape(s, size(input)); end epochObj = class(s, 'cdfepoch'); if isnumeric(input) & ~isempty(input) s = reshape(s, size(input)); end function disptt2000(obj) %DISPTT2000 DISP for CDFTT2000 object. % If obj is not scalar, then just display the size s = size(obj); if ~isequal(s,[1 1]) disp(sprintf([' [%dx%d cdftt2000]'], s(1), s(2))); else disp( [spdfencodett2000(obj)]); end