Home > matpower7.1 > lib > psse_parse_section.m

psse_parse_section

PURPOSE ^

PSSE_PARSE_SECTION Parses the data from a section of a PSS/E RAW data file

SYNOPSIS ^

function [data, warns] = psse_parse_section(warns, records, sections, s, verbose, label, template)

DESCRIPTION ^

PSSE_PARSE_SECTION  Parses the data from a section of a PSS/E RAW data file
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
                                           VERBOSE, LABEL, TEMPLATE)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
                                           VERBOSE, LABEL)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
                                           VERBOSE)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE, LABEL, ...
                                           TEMPLATE)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE, LABEL)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE)
   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS)

   Inputs:
       WARNINGS :  cell array of strings containing accumulated
                   warning messages
       RECORDS :   a cell array of strings returned by PSSE_READ
       SECTIONS :  a struct array returned by PSSE_READ
       SIDX :      (optional) index if the section to be read
                   if included, the RECORD indices are taken from
                   SECTIONS(SIDX), otherwise use all RECORDS
       VERBOSE :   1 to display progress info, 0 (default) otherwise
       LABEL :     (optional) name for the section, to be compared with
                   the section name typically found in the
                   END OF <LABEL> DATA comment at the end of each section
       TEMPLATE :  (optional) string of characters indicating how to
                   interpret the type of the corresponding column, options
                   are as follows:
               d, f or g : integer floating point number to be converted
                   via SSCANF with %d, %f or %g, respectively.
               D, F or G : integer floating point number, possibly enclosed
                   in single or double quotes, to be converted via
                   SSCANF with %d, %f or %g, respectively.
               c or s : character or string, possibly enclosed in single
                   or double quotes, which are stripped from the string
           Note:   Data columns in RECORDS that have no valid corresponding
                   entry in TEMPLATE (beyond end of TEMPLATE, or a character
                   other than those listed, e.g. '.') are returned in DATA.txt
                   with no conversion. TEMPLATE entries for which there is
                   no corresponding column in RECORDS are returned as NaN and
                   empty, respectively, in DATA.num and DATA.txt.

   Output:
       DATA :      a struct with two fields:
           num :   matrix containing the numeric data for the section, for
                   columns with no numeric data, num contain NaNs.
           txt :   a cell array containing the non-numeric (char/string)
                   data for the section, for columns with numeric data,
                   txt entries are empty
       WARNINGS :  cell array of strings containing updated accumulated
                   warning messages

   See also PSSE2MPC, PSSE_PARSE

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [data, warns] = psse_parse_section(warns, records, sections, s, verbose, label, template)
0002 %PSSE_PARSE_SECTION  Parses the data from a section of a PSS/E RAW data file
0003 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
0004 %                                           VERBOSE, LABEL, TEMPLATE)
0005 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
0006 %                                           VERBOSE, LABEL)
0007 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX, ...
0008 %                                           VERBOSE)
0009 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, SECTIONS, SIDX)
0010 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE, LABEL, ...
0011 %                                           TEMPLATE)
0012 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE, LABEL)
0013 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS, VERBOSE)
0014 %   [DATA, WARNINGS] = PSSE_PARSE_SECTION(WARNINGS, RECORDS)
0015 %
0016 %   Inputs:
0017 %       WARNINGS :  cell array of strings containing accumulated
0018 %                   warning messages
0019 %       RECORDS :   a cell array of strings returned by PSSE_READ
0020 %       SECTIONS :  a struct array returned by PSSE_READ
0021 %       SIDX :      (optional) index if the section to be read
0022 %                   if included, the RECORD indices are taken from
0023 %                   SECTIONS(SIDX), otherwise use all RECORDS
0024 %       VERBOSE :   1 to display progress info, 0 (default) otherwise
0025 %       LABEL :     (optional) name for the section, to be compared with
0026 %                   the section name typically found in the
0027 %                   END OF <LABEL> DATA comment at the end of each section
0028 %       TEMPLATE :  (optional) string of characters indicating how to
0029 %                   interpret the type of the corresponding column, options
0030 %                   are as follows:
0031 %               d, f or g : integer floating point number to be converted
0032 %                   via SSCANF with %d, %f or %g, respectively.
0033 %               D, F or G : integer floating point number, possibly enclosed
0034 %                   in single or double quotes, to be converted via
0035 %                   SSCANF with %d, %f or %g, respectively.
0036 %               c or s : character or string, possibly enclosed in single
0037 %                   or double quotes, which are stripped from the string
0038 %           Note:   Data columns in RECORDS that have no valid corresponding
0039 %                   entry in TEMPLATE (beyond end of TEMPLATE, or a character
0040 %                   other than those listed, e.g. '.') are returned in DATA.txt
0041 %                   with no conversion. TEMPLATE entries for which there is
0042 %                   no corresponding column in RECORDS are returned as NaN and
0043 %                   empty, respectively, in DATA.num and DATA.txt.
0044 %
0045 %   Output:
0046 %       DATA :      a struct with two fields:
0047 %           num :   matrix containing the numeric data for the section, for
0048 %                   columns with no numeric data, num contain NaNs.
0049 %           txt :   a cell array containing the non-numeric (char/string)
0050 %                   data for the section, for columns with numeric data,
0051 %                   txt entries are empty
0052 %       WARNINGS :  cell array of strings containing updated accumulated
0053 %                   warning messages
0054 %
0055 %   See also PSSE2MPC, PSSE_PARSE
0056 
0057 %   MATPOWER
0058 %   Copyright (c) 2014-2016, Power Systems Engineering Research Center (PSERC)
0059 %   by Ray Zimmerman, PSERC Cornell
0060 %
0061 %   This file is part of MATPOWER.
0062 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0063 %   See https://matpower.org for more info.
0064 
0065 %% defaults
0066 if nargin < 3
0067     have_sections = 0;
0068     verbose = 0;
0069     template = '';
0070 elseif isstruct(sections)
0071     have_sections = 1;
0072     if nargin < 7
0073         template = '';
0074         if nargin < 6
0075             label = '';
0076             if nargin < 5
0077                 verbose = 0;
0078             else
0079                 error('psse_parse_section: too few input arguments');
0080             end
0081         end
0082     end
0083 else
0084     have_sections = 0;
0085     if nargin >= 5
0086         template = verbose;
0087     else
0088         template = '';
0089     end
0090     if nargin >= 4
0091         label = s;
0092     else
0093         label = '';
0094     end
0095     verbose = sections;
0096 end
0097 
0098 %% get relevant records, check section name
0099 nt = length(template);
0100 if have_sections
0101     nr = sections(s).last - sections(s).first + 1;
0102     recs = records(sections(s).first:sections(s).last);
0103     if ~isempty(sections(s).name) && ~strcmpi(label, sections(s).name)
0104         warns{end+1} = sprintf('Section label mismatch, found ''%s'', expected ''%s''', ...
0105             sections(s).name, upper(label));
0106         if verbose
0107             fprintf('-----  WARNING:  Found section labeled:    ''%s''\n', sections(s).name);
0108             fprintf('-----            Expected section labeled: ''%s''\n', upper(label));
0109         end
0110     end
0111 else
0112     nr = length(records);
0113     recs = records;
0114 end
0115 if verbose
0116     spacers = repmat('.', 1, 42-length(label));
0117     fprintf('Parsing %6d lines of %s data %s', nr, label, spacers);
0118 end
0119 
0120 if nr
0121     %% set up regexp to parse cols, comments of each record
0122     delim = '\s*(,|\s)\s*';     %% general delimiter
0123     repeatdelim = '\s*,\s*|\t'; %% delimiter that allows repeated delimiters
0124     non_quote_field = '[^''",\s/]+';
0125     single_quote_field = '''([^'']|'''')*''';
0126     double_quote_field = '"([^"]|"")*"';
0127     any_field = sprintf('(?<col>%s|%s|%s)', non_quote_field, single_quote_field, double_quote_field);
0128     pat = sprintf('%s%s|%s|%s|(?<comment>/.*)?', any_field, delim, repeatdelim, any_field);
0129     % pat = '(?<col>[^''",\s/]+|''([^'']|'''')*''|"([^"]|"")*")\s*(,|\s)\s*|\s*,\s*|\t|(?<col>[^''",\s/]+|''([^'']|'''')*''|"([^"]|"")*")|(?<comment>/.*)?';
0130 
0131     %% set up functions for use with cellfun
0132     if have_feature('octave') && have_feature('octave', 'vnum') < 4.003
0133         parser  = @(ln){{regexp(ln, pat, 'names')}};  %% parse cols, comments of each rec
0134         numcols = @(ss)length(ss{1}.col);   %% number of columns in each record
0135     else
0136         parser  = @(ln){regexp(ln, pat, 'names')};  %% parse cols, comments of each rec
0137         numcols = @(ss)length(ss);      %% number of columns in each record
0138     end
0139 
0140     %% parse the table into cell array of structs (with col, comment fields)
0141     dd = cellfun(parser, recs);
0142 
0143 %     %% extract possible comments
0144 %     if nargout > 2
0145 %     %   extract_comment = @(n){n(end).comment};
0146 %         if have_feature('octave') && have_feature('octave', 'vnum') < 4.003
0147 %             comment = cellfun(@(n){n{1}.comment(end)}, dd);
0148 %         else
0149 %             comment = cellfun(@(n){n(end).comment}, dd);
0150 %         end
0151 %     end
0152 
0153     %% find max number of columns
0154     nc = cellfun(numcols, dd);      %% number of columns
0155     ncmax = max(nc);
0156     ncmin = min(nc);
0157 
0158     %% extract data by column
0159     % nc = length(dd{1});
0160     % if nc && isempty(dd{1}(nc).col)   %% comment present
0161     %   nc = nc - 1;                %% reduce number of columns by 1 to discard
0162     % end
0163     data.num = NaN(nr, max(ncmax, nt));
0164     data.txt = cell(nr, max(ncmax, nt));
0165     for c = 1:ncmax
0166         %% template for conversion?
0167         if c <= nt
0168             t = template(c);
0169         else
0170             t = '';
0171         end
0172         if have_feature('octave') && have_feature('octave', 'vnum') < 4.003 %% running under Octave
0173             switch t
0174                 case {'d', 'f', 'g', 'D', 'F', 'G'} %% numeric data
0175                     if t == upper(t)                %% possibly quoted
0176                         xc_fcn  = @(n)extract_col_qnum_octave(n, c, lower(t));
0177                     else                            %% not quoted (more efficient)
0178                         xc_fcn  = @(n)extract_col_num_octave(n, c, t);
0179                     end
0180                 case {'s', 'c'}
0181                     xc_fcn  = @(n){extract_col_dequote_octave(n, c)};
0182                 otherwise
0183                     if c <= ncmin
0184                         xc_fcn  = @(n)n{1}.col(c);
0185                     else
0186                         xc_fcn  = @(n){extract_col_octave(n, c)};
0187                     end
0188             end
0189         else                    %% running under MATLAB (or Octave 4.3 or later)
0190             switch t
0191                 case {'d', 'f', 'g', 'D', 'F', 'G'} %% numeric data
0192                     if t == upper(t)                %% possibly quoted
0193                         xc_fcn  = @(n)extract_col_qnum(n, c, lower(t));
0194                     else                            %% not quoted (more efficient)
0195                         xc_fcn  = @(n)extract_col_num(n, c, t);
0196                     end
0197                 case {'s', 'c'}
0198                     xc_fcn  = @(n){extract_col_dequote(n, c)};
0199                 otherwise
0200                     if c <= ncmin
0201                         xc_fcn  = @(n){n(c).col};
0202                     else
0203                         xc_fcn  = @(n){extract_col(n, c)};
0204                     end
0205             end
0206         end
0207         switch upper(t)
0208             case {'D', 'F', 'G'}
0209                 data.num(:, c) = cellfun(xc_fcn, dd);
0210             otherwise
0211                 data.txt(:, c) = cellfun(xc_fcn, dd);
0212         end
0213     end
0214 else
0215     data.num = NaN(nr, nt);
0216     data.txt = cell(nr, nt);
0217 end
0218 if verbose
0219     fprintf(' done.\n');
0220 %     if have_sections
0221 %         fprintf('%s\n', upper(label));
0222 %         fprintf('%s\n', sections(s).name);
0223 %     end
0224 end
0225 
0226 %%---------------------------------------------------------------------
0227 function str = extract_col(n, c)
0228 if c <= length(n)
0229     str = n(c).col;
0230 else
0231     str = '';
0232 end
0233 
0234 %%---------------------------------------------------------------------
0235 function str = extract_col_octave(n, c)
0236 if c <= length(n{1}.col)
0237     str = n{1}.col{c};
0238 else
0239     str = '';
0240 end
0241 
0242 %%---------------------------------------------------------------------
0243 function str = extract_col_dequote(n, c)
0244 if c <= length(n)
0245     str = n(c).col;
0246     if ~isempty(str) && (str(1) == '''' || str(1) == '"')
0247         str = str(2:end-1);
0248     end
0249 else
0250     str = '';
0251 end
0252 
0253 %%---------------------------------------------------------------------
0254 function str = extract_col_dequote_octave(n, c)
0255 if c <= length(n{1}.col)
0256     str = n{1}.col{c};
0257     if ~isempty(str) && (str(1) == '''' || str(1) == '"')
0258         str = str(2:end-1);
0259     end
0260 else
0261     str = '';
0262 end
0263 
0264 %%---------------------------------------------------------------------
0265 function num = extract_col_num(n, c, t)
0266 if c <= length(n) && ~isempty(n(c).col)
0267     num = sscanf(n(c).col, ['%' t]);
0268 else
0269     num = NaN;
0270 end
0271 
0272 %%---------------------------------------------------------------------
0273 function num = extract_col_num_octave(n, c, t)
0274 if c <= length(n{1}.col) && ~isempty(n{1}.col{c})
0275     num = sscanf(n{1}.col{c}, ['%' t]);
0276 else
0277     num = NaN;
0278 end
0279 
0280 %%---------------------------------------------------------------------
0281 function num = extract_col_qnum(n, c, t)
0282 if c <= length(n)
0283     str = n(c).col;
0284     if isempty(str)
0285         num = NaN;
0286     elseif str(1) == '''' || str(1) == '"'
0287         str = str(2:end-1);
0288     end
0289     num = sscanf(str, ['%' t]);
0290 else
0291     num = NaN;
0292 end
0293 
0294 %%---------------------------------------------------------------------
0295 function num = extract_col_qnum_octave(n, c, t)
0296 if c <= length(n{1}.col)
0297     str = n{1}.col{c};
0298     if isempty(str)
0299         num = NaN;
0300     elseif str(1) == '''' || str(1) == '"'
0301         str = str(2:end-1);
0302     end
0303     num = sscanf(str, ['%' t]);
0304 else
0305     num = NaN;
0306 end

Generated on Fri 09-Oct-2020 11:21:31 by m2html © 2005