LCOV - code coverage report
Current view: top level - imageanalysis/IO - ParameterParser.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 117 127 92.1 %
Date: 2024-12-11 20:54:31 Functions: 3 3 100.0 %

          Line data    Source code
       1             : //# ParameterParser.h
       2             : //# Copyright (C) 2007
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This program is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU General Public License as published by the Free
       7             : //# Software Foundation; either version 2 of the License, or (at your option)
       8             : //# any later version.
       9             : //#
      10             : //# This program is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             : //# more details.
      14             : //#
      15             : //# You should have received a copy of the GNU General Public License along
      16             : //# with this program; if not, write to the Free Software Foundation, Inc.,
      17             : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : 
      26             : #include <imageanalysis/IO/ParameterParser.h>
      27             : 
      28             : #include <casacore/casa/Arrays/Vector.h>
      29             : #include <casacore/casa/Utilities/Regex.h>
      30             : #include <casacore/casa/Utilities/Sort.h>
      31             : #include <casacore/measures/Measures/Stokes.h>
      32             : #include <casacore/casa/IO/ArrayIO.h>
      33             : 
      34             : using namespace casacore;
      35             : namespace casa {
      36             : 
      37         632 : vector<uInt> ParameterParser::consolidateAndOrderRanges(
      38             :     uInt& nSelected, const vector<uInt>& ranges
      39             : ) {
      40        1264 :     uInt arrSize = ranges.size()/2;
      41         632 :     uInt arrMin[arrSize];
      42         632 :     uInt arrMax[arrSize];
      43        1287 :     for (uInt i=0; i<arrSize; i++) {
      44         655 :         arrMin[i] = ranges[2*i];
      45         655 :         arrMax[i] = ranges[2*i + 1];
      46             :     }    
      47         632 :     Sort sort;
      48         632 :     sort.sortKey (arrMin, TpUInt);
      49         632 :     sort.sortKey (arrMax, TpUInt, 0, Sort::Descending);
      50         632 :     Vector<uInt> inxvec;
      51         632 :     vector<uInt> consol(0);
      52         632 :     sort.sort(inxvec, arrSize);
      53        1287 :     for (uInt i=0; i<arrSize; i++) {
      54         655 :         uInt idx = inxvec(i);
      55         655 :         uInt size = consol.size();
      56         655 :         uInt min = arrMin[idx];
      57         655 :         uInt max = arrMax[idx];
      58         655 :         uInt lastMax = (i == 0) ? 0 : consol[size-1];
      59         655 :         if (i==0) {
      60             :             // consol.resize(2, true);
      61             :             // consol[0] = min;
      62             :             // consol[1] = max;
      63         632 :             consol.push_back(min);
      64         632 :             consol.push_back(max);
      65             :         }
      66          23 :         else if ( 
      67             :             // overlaps previous range, so extend
      68          23 :             (min < lastMax && max > lastMax)
      69             :             // or contiguous with previous range, so extend
      70          23 :             || min == lastMax + 1
      71             :         ) {
      72             :             // overwriting the end value, so do not resize
      73          17 :             consol[size-1] = max; 
      74             :         }
      75             : 
      76           6 :         else if (min > lastMax + 1) { 
      77             :             // non overlap of and not contiguous with previous range,
      78             :             // so create new end point pair
      79           6 :             consol.push_back(min);
      80           6 :             consol.push_back(max);
      81             :         }
      82             :     }    
      83         632 :     nSelected = 0; 
      84        1270 :     for (uInt i=0; i<consol.size()/2; i++) {
      85         638 :         nSelected += consol[2*i + 1] - consol[2*i] + 1; 
      86             :     }    
      87        1264 :     return consol;
      88        1264 : }
      89             :     
      90         353 : std::vector<uInt> ParameterParser::spectralRangesFromChans(
      91             :         uInt& nSelectedChannels, const String& specification,  const uInt nChannels
      92             : ) {
      93             :         // First split on commas
      94         353 :         Vector<String> parts = stringToVector(specification, std::regex("[,;]"));
      95         353 :         static const Regex regexuInt("^[0-9]+$");
      96         353 :         static const Regex regexRange("^[0-9]+[ \n\t\r\v\f]*~[ \n\t\r\v\f]*[0-9]+$");
      97         353 :         static const Regex regexLT("^<.*$");
      98         353 :         static const Regex regexLTEq("^<=.*$");
      99         353 :         static const Regex regexGT("^>.*$");
     100         353 :         static const Regex regexGTEq("^>=.*$");
     101         353 :         vector<uInt> ranges(0);
     102             : 
     103         689 :         for (uInt i=0; i<parts.size(); i++) {
     104         357 :                 parts[i].trim();
     105         357 :                 uInt min = 0;
     106         357 :                 uInt max = 0;
     107         357 :                 if (parts[i].matches(regexuInt)) {
     108             :                         // just one channel
     109         310 :                         min = String::toInt(parts[i]);
     110         310 :                         max = min;
     111             :                 }
     112          47 :                 else if(parts[i].matches(regexRange)) {
     113             :                         // a range of channels
     114          33 :                         Vector<String> values = stringToVector(parts[i], '~');
     115          33 :                         ThrowIf(
     116             :                                 values.size() != 2,
     117             :                                 "Incorrect specification for channel range " + parts[i]
     118             :                         );
     119          33 :                         values[0].trim();
     120          33 :                         values[1].trim();
     121          99 :                         for(uInt j=0; j < 2; j++) {
     122          66 :                                 ThrowIf(
     123             :                                         ! values[j].matches(regexuInt),
     124             :                                         "For channel specification " + values[j]
     125             :                                         + " is not a non-negative integer in "
     126             :                                         + parts[i]
     127             :                                 );
     128             :                         }
     129          33 :                         min = String::toInt(values[0]);
     130          33 :                         max = String::toInt(values[1]);
     131          33 :                 }
     132          14 :                 else if (parts[i].matches(regexLT)) {
     133           0 :                         String maxs = parts[i].matches(regexLTEq) ? parts[i].substr(2) : parts[i].substr(1);
     134           0 :                         maxs.trim();
     135           0 :                         ThrowIf(
     136             :                                 ! maxs.matches(regexuInt),
     137             :                                 "In channel specification, " + maxs
     138             :                                         + " is not a non-negative integer in " + parts[i]
     139             :                         );
     140           0 :                         min = 0;
     141           0 :                         max = String::toInt(maxs);
     142           0 :                         if (! parts[i].matches(regexLTEq)) {
     143           0 :                                 ThrowIf(
     144             :                                         max == 0,
     145             :                                         "In channel specification, max channel cannot "
     146             :                                         "be less than zero in " + parts[i]
     147             :                                 );
     148           0 :                                 max--;
     149             :                         }
     150           0 :                 }
     151          14 :                 else if (parts[i].matches(regexGT)) {
     152           1 :                         String mins = parts[i].matches(regexGTEq)
     153           0 :                         ? parts[i].substr(2)
     154           1 :                         : parts[i].substr(1);
     155           1 :                         mins.trim();
     156           1 :                         ThrowIf(
     157             :                                 ! mins.matches(regexuInt),
     158             :                                 "In channel specification, " + mins
     159             :                                         + " is not an integer in " + parts[i]
     160             :                         );
     161           1 :                         max = nChannels - 1;
     162           1 :                         min = String::toInt(mins);
     163           1 :                         if(! parts[i].matches(regexGTEq)) {
     164           1 :                                 min++;
     165             :                         }
     166           1 :                         ThrowIf(
     167             :                                 min > nChannels - 1,
     168             :                                 "Min channel cannot be greater than the (zero-based) number of channels ("
     169             :                                 + String::toString(nChannels - 1) + ") in the image"
     170             :                         );
     171           1 :                 }
     172             :                 else {
     173          13 :                         ThrowCc(
     174             :                                 "Invalid channel specification in " + parts[i]
     175             :                             + " of spec " + specification
     176             :                         );
     177             :                 }
     178         344 :                 ThrowIf(
     179             :                         min > max,
     180             :                         "Min channel " + String::toString(min) + " cannot be greater than max channel "
     181             :                         + String::toString(max) + " in " + parts[i]
     182             :                 );
     183         400 :                 ThrowIf(
     184             :                         max >= nChannels,
     185             :                         "Zero-based max channel " + String::toString(max)
     186             :                         + " must be less than the total number of channels ("
     187             :                         + String::toString(nChannels) + ") in the channel specification " + parts[i]
     188             :                 );
     189         336 :                 ranges.push_back(min);
     190         336 :                 ranges.push_back(max);
     191             :         }
     192         332 :         vector<uInt> consolidatedRanges = consolidateAndOrderRanges(nSelectedChannels, ranges);
     193         664 :         return consolidatedRanges;
     194         374 : }
     195             : 
     196           1 : std::vector<String> ParameterParser::stokesFromString(
     197             :         String& specification
     198             : ) {
     199           1 :         specification.trim();
     200           1 :         specification.ltrim('[');
     201           1 :         specification.rtrim(']');
     202           1 :         specification.upcase();
     203             : 
     204           1 :         Vector<String> parts = stringToVector(specification, std::regex("[,;]"));
     205           1 :         Vector<String> polNames = Stokes::allNames(false);
     206           1 :         uInt nNames = polNames.size();
     207           1 :         Vector<uInt> nameLengths(nNames);
     208          33 :         for (uInt i=0; i<nNames; ++i) {
     209          32 :                 nameLengths[i] = polNames[i].length();
     210             :         }
     211           1 :         uInt *lengthData = nameLengths.data();
     212             : 
     213           1 :         Vector<uInt> idx(nNames);
     214           1 :         Sort sorter;
     215           1 :         sorter.sortKey(lengthData, TpUInt, 0, Sort::Descending);
     216           1 :         sorter.sort(idx, nNames);
     217             : 
     218           1 :         Vector<String> sortedNames(nNames);
     219          33 :         for (uInt i=0; i<nNames; i++) {
     220          32 :                 sortedNames[i] = polNames[idx[i]];
     221          32 :                 sortedNames[i].upcase();
     222             :         }
     223           1 :         vector<String> myStokes;
     224           2 :         for (uInt i=0; i<parts.size(); i++) {
     225           1 :                 String part = parts[i];
     226           1 :                 part.trim();
     227           1 :                 Vector<String>::iterator iter = sortedNames.begin();
     228           1 :                 vector<Int> stokes;
     229          63 :                 while (iter != sortedNames.end() && ! part.empty()) {
     230          62 :                         if (part.startsWith(*iter)) {
     231           2 :                                 myStokes.push_back(*iter);
     232             :                                 // consume the string
     233           2 :                                 part = part.substr(iter->length());
     234           2 :                                 if (! part.empty()) {
     235             :                                         // reset the iterator to start over at the beginning of the list for
     236             :                                         // the next specified polarization
     237           1 :                                         iter = sortedNames.begin();
     238             :                                 }
     239             :                         }
     240             :                         else {
     241          60 :                                 ++iter;
     242             :                         }
     243             :                 }
     244           1 :                 ThrowIf(
     245             :                         ! part.empty(),
     246             :                         "(Sub)String " + part + " in stokes specification part " + parts[i]
     247             :                             + " does not match a known polarization."
     248             :                 );
     249           1 :         }
     250           2 :         return myStokes;
     251           1 : }
     252             : 
     253             : 
     254             : }

Generated by: LCOV version 1.16