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 0 : vector<uInt> ParameterParser::consolidateAndOrderRanges(
38 : uInt& nSelected, const vector<uInt>& ranges
39 : ) {
40 0 : uInt arrSize = ranges.size()/2;
41 0 : uInt arrMin[arrSize];
42 0 : uInt arrMax[arrSize];
43 0 : for (uInt i=0; i<arrSize; i++) {
44 0 : arrMin[i] = ranges[2*i];
45 0 : arrMax[i] = ranges[2*i + 1];
46 : }
47 0 : Sort sort;
48 0 : sort.sortKey (arrMin, TpUInt);
49 0 : sort.sortKey (arrMax, TpUInt, 0, Sort::Descending);
50 0 : Vector<uInt> inxvec;
51 0 : vector<uInt> consol(0);
52 0 : sort.sort(inxvec, arrSize);
53 0 : for (uInt i=0; i<arrSize; i++) {
54 0 : uInt idx = inxvec(i);
55 0 : uInt size = consol.size();
56 0 : uInt min = arrMin[idx];
57 0 : uInt max = arrMax[idx];
58 0 : uInt lastMax = (i == 0) ? 0 : consol[size-1];
59 0 : if (i==0) {
60 : // consol.resize(2, true);
61 : // consol[0] = min;
62 : // consol[1] = max;
63 0 : consol.push_back(min);
64 0 : consol.push_back(max);
65 : }
66 0 : else if (
67 : // overlaps previous range, so extend
68 0 : (min < lastMax && max > lastMax)
69 : // or contiguous with previous range, so extend
70 0 : || min == lastMax + 1
71 : ) {
72 : // overwriting the end value, so do not resize
73 0 : consol[size-1] = max;
74 : }
75 :
76 0 : else if (min > lastMax + 1) {
77 : // non overlap of and not contiguous with previous range,
78 : // so create new end point pair
79 0 : consol.push_back(min);
80 0 : consol.push_back(max);
81 : }
82 : }
83 0 : nSelected = 0;
84 0 : for (uInt i=0; i<consol.size()/2; i++) {
85 0 : nSelected += consol[2*i + 1] - consol[2*i] + 1;
86 : }
87 0 : return consol;
88 0 : }
89 :
90 0 : std::vector<uInt> ParameterParser::spectralRangesFromChans(
91 : uInt& nSelectedChannels, const String& specification, const uInt nChannels
92 : ) {
93 : // First split on commas
94 0 : Vector<String> parts = stringToVector(specification, std::regex("[,;]"));
95 0 : static const Regex regexuInt("^[0-9]+$");
96 0 : static const Regex regexRange("^[0-9]+[ \n\t\r\v\f]*~[ \n\t\r\v\f]*[0-9]+$");
97 0 : static const Regex regexLT("^<.*$");
98 0 : static const Regex regexLTEq("^<=.*$");
99 0 : static const Regex regexGT("^>.*$");
100 0 : static const Regex regexGTEq("^>=.*$");
101 0 : vector<uInt> ranges(0);
102 :
103 0 : for (uInt i=0; i<parts.size(); i++) {
104 0 : parts[i].trim();
105 0 : uInt min = 0;
106 0 : uInt max = 0;
107 0 : if (parts[i].matches(regexuInt)) {
108 : // just one channel
109 0 : min = String::toInt(parts[i]);
110 0 : max = min;
111 : }
112 0 : else if(parts[i].matches(regexRange)) {
113 : // a range of channels
114 0 : Vector<String> values = stringToVector(parts[i], '~');
115 0 : ThrowIf(
116 : values.size() != 2,
117 : "Incorrect specification for channel range " + parts[i]
118 : );
119 0 : values[0].trim();
120 0 : values[1].trim();
121 0 : for(uInt j=0; j < 2; j++) {
122 0 : 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 0 : min = String::toInt(values[0]);
130 0 : max = String::toInt(values[1]);
131 0 : }
132 0 : 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 0 : else if (parts[i].matches(regexGT)) {
152 0 : String mins = parts[i].matches(regexGTEq)
153 0 : ? parts[i].substr(2)
154 0 : : parts[i].substr(1);
155 0 : mins.trim();
156 0 : ThrowIf(
157 : ! mins.matches(regexuInt),
158 : "In channel specification, " + mins
159 : + " is not an integer in " + parts[i]
160 : );
161 0 : max = nChannels - 1;
162 0 : min = String::toInt(mins);
163 0 : if(! parts[i].matches(regexGTEq)) {
164 0 : min++;
165 : }
166 0 : 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 0 : }
172 : else {
173 0 : ThrowCc(
174 : "Invalid channel specification in " + parts[i]
175 : + " of spec " + specification
176 : );
177 : }
178 0 : 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 0 : 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 0 : ranges.push_back(min);
190 0 : ranges.push_back(max);
191 : }
192 0 : vector<uInt> consolidatedRanges = consolidateAndOrderRanges(nSelectedChannels, ranges);
193 0 : return consolidatedRanges;
194 0 : }
195 :
196 0 : std::vector<String> ParameterParser::stokesFromString(
197 : String& specification
198 : ) {
199 0 : specification.trim();
200 0 : specification.ltrim('[');
201 0 : specification.rtrim(']');
202 0 : specification.upcase();
203 :
204 0 : Vector<String> parts = stringToVector(specification, std::regex("[,;]"));
205 0 : Vector<String> polNames = Stokes::allNames(false);
206 0 : uInt nNames = polNames.size();
207 0 : Vector<uInt> nameLengths(nNames);
208 0 : for (uInt i=0; i<nNames; ++i) {
209 0 : nameLengths[i] = polNames[i].length();
210 : }
211 0 : uInt *lengthData = nameLengths.data();
212 :
213 0 : Vector<uInt> idx(nNames);
214 0 : Sort sorter;
215 0 : sorter.sortKey(lengthData, TpUInt, 0, Sort::Descending);
216 0 : sorter.sort(idx, nNames);
217 :
218 0 : Vector<String> sortedNames(nNames);
219 0 : for (uInt i=0; i<nNames; i++) {
220 0 : sortedNames[i] = polNames[idx[i]];
221 0 : sortedNames[i].upcase();
222 : }
223 0 : vector<String> myStokes;
224 0 : for (uInt i=0; i<parts.size(); i++) {
225 0 : String part = parts[i];
226 0 : part.trim();
227 0 : Vector<String>::iterator iter = sortedNames.begin();
228 0 : vector<Int> stokes;
229 0 : while (iter != sortedNames.end() && ! part.empty()) {
230 0 : if (part.startsWith(*iter)) {
231 0 : myStokes.push_back(*iter);
232 : // consume the string
233 0 : part = part.substr(iter->length());
234 0 : if (! part.empty()) {
235 : // reset the iterator to start over at the beginning of the list for
236 : // the next specified polarization
237 0 : iter = sortedNames.begin();
238 : }
239 : }
240 : else {
241 0 : ++iter;
242 : }
243 : }
244 0 : ThrowIf(
245 : ! part.empty(),
246 : "(Sub)String " + part + " in stokes specification part " + parts[i]
247 : + " does not match a known polarization."
248 : );
249 0 : }
250 0 : return myStokes;
251 0 : }
252 :
253 :
254 : }
|