source: tags/release-1.2.2/src/Utils/Section.cc

Last change on this file was 935, checked in by MatthewWhiting, 12 years ago

A bunch of int --> size_t conversions.

File size: 11.1 KB
Line 
1// -----------------------------------------------------------------------
2// Section.cc: Member functions for the Section class, particularly
3//             how to interpret the subsection string.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29#include <string>
30#include <vector>
31#include <iostream>
32#include <sstream>
33#include <duchamp/Utils/Section.hh>
34#include <duchamp/duchamp.hh>
35
36namespace duchamp
37{
38
39  Section::Section()
40  {
41    this->numSections = 0;
42    this->flagParsed = false;
43  }
44
45  Section::Section(const Section& s)
46  {
47    operator=(s);
48  }
49  //--------------------------------------------
50 
51  Section& Section::operator= (const Section& s)
52  {
53    if(this == &s) return *this;
54    this->flagParsed    = s.flagParsed;
55    this->subsection  = s.subsection;
56    this->sections    = s.sections;
57    this->numSections = s.numSections;
58    this->starts      = s.starts;
59    this->dims        = s.dims;
60    return *this;
61  }
62  //--------------------------------------------
63
64  OUTCOME Section::parse(long *dimAxes, int size)
65  {
66    std::vector<size_t> vecDim(size);
67    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
68    return this->parse(vecDim);
69  }
70
71  OUTCOME Section::parse(size_t *dimAxes, int size)
72  {
73    std::vector<size_t> vecDim(size);
74    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
75    return this->parse(vecDim);
76  }
77
78  OUTCOME Section::parse(std::vector<int> dimAxes)
79  {
80    std::vector<size_t> vecDim(dimAxes.size());
81    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
82    return this->parse(vecDim);
83  }
84
85  OUTCOME Section::parse(std::vector<long> dimAxes)
86  {
87    std::vector<size_t> vecDim(dimAxes.size());
88    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
89    return this->parse(vecDim);
90  }
91
92  OUTCOME Section::parse(std::vector<size_t> dimAxes)
93  {
94    /// @details
95    /// This function reads the subsection string, and registers the
96    /// starting values and lengths for each dimension. The array of axis
97    /// dimensions is needed to know how long each axis really is, and
98    /// whether we have strayed over the limit or not.
99    ///
100    /// Note that steps in the subsection string are not dealt with -- a
101    /// warning message is written to the screen, and the step values are
102    /// removed from the subsection string.
103    ///
104    /// The function also does basic checks to make sure it is of the
105    /// correct format (ie. has square brackets delimiting it) and the
106    /// correct number of sections, returning a FAILURE if either of
107    /// these checks fail.
108    ///
109    /// \param dimAxes The array of axis dimensions, of which the
110    ///                 Section is a subsection.
111    /// \return SUCCESS/FAILURE (from duchamp.hh)
112
113    std::stringstream errmsg;
114
115    // First Make sure subsection has [ and ] at ends
116    if((this->subsection[0]!='[') ||
117       (this->subsection[this->subsection.size()-1]!=']')){
118      DUCHAMPERROR("Section parsing","Subsection needs to be delimited by square brackets -- You provided: " << this->subsection);
119      return FAILURE;
120    }
121
122    this->starts.clear();
123    this->dims.clear();
124 
125    this->numSections=1;
126    for(size_t i=0;i<this->subsection.size();i++)
127      if(this->subsection[i]==',') this->numSections++;
128
129    if(numSections!=dimAxes.size()){
130      DUCHAMPERROR("Section parsing","Subsection " << this->subsection << " has "<<numSections <<" sections, compared to a cube with " << dimAxes.size() << " axes");
131      return FAILURE;
132    }
133
134    this->starts.resize(this->numSections);
135    this->dims.resize(this->numSections);
136    this->sections.resize(this->numSections);
137
138    std::vector<std::string> tempsections(numSections);
139    // this will hold the section strings for each dimension
140    std::stringstream ss;
141    ss.str(this->subsection);
142    bool removeStep = false;
143    bool doingBorders = false;
144    std::string temp;
145
146    getline(ss,temp,'[');
147    for(size_t i=0;i<numSections-1;i++){
148      getline(ss,temp,',');
149      tempsections[i]=temp;
150    }
151    getline(ss,temp,']');
152    tempsections[numSections-1]=temp;
153
154    for(size_t str=0;str<numSections;str++){
155      if(tempsections[str]=="*"){
156        this->starts[str] = 0;
157        this->dims[str]= dimAxes[str];
158        this->sections[str] = tempsections[str];
159      }
160      else{
161        int numColon=0;
162        for(size_t i=0;i<tempsections[str].size();i++){
163          if(tempsections[str][i]==':'){
164            tempsections[str][i]=' ';
165            numColon++;
166          }
167        }
168        int a,b,c;
169        std::stringstream readString,fixedString;
170        readString.str(tempsections[str]);
171        switch(numColon){
172        case 1: // usual case
173          readString >> a >> b;
174          this->starts[str] = a-1;
175          this->dims[str] = b-a+1;
176          fixedString << a << ":" << b;
177          this->sections[str] = fixedString.str();
178          break;
179        case 0: // borders case -- so many off each border
180          readString >> a;
181          if(a>=int(dimAxes[str])/2){
182            DUCHAMPERROR("Section parsing", "You requested the subsection " << this->subsection << " but axis #" << str+1 <<" has zero size, since its dimension is " << dimAxes[str]);
183            return FAILURE;
184          }
185          this->starts[str] = a;
186          this->dims[str] = dimAxes[str]-2*a;
187          fixedString << this->starts[str]+1 << ":"
188                      << this->getEnd(str)+1;
189          this->sections[str] = fixedString.str();
190          doingBorders=true;
191          break;
192        case 2: // subsection involves a step
193        default:
194          readString>> a >> b >> c;
195          this->starts[str] = a-1;
196          this->dims[str] = b-a+1;
197          fixedString << a << ":" << b;
198          this->sections[str] = fixedString.str();
199          removeStep=true;
200          break;
201        }
202
203      }
204    }
205
206    if(removeStep){  // if there was a step present
207      errmsg.str("");
208      errmsg << "The subsection given is " << this->subsection <<".\n"
209             << "Duchamp is currently unable to deal with pixel steps"
210             << " in the subsection.\n"
211             << "These have been ignored, and so the subection used is ";
212    }
213
214    if(removeStep || doingBorders){
215      // rewrite subsection without any step sizes and with correct borders.
216      this->subsection = "[" + this->sections[0];
217      for(size_t str=1;str<numSections;str++)
218        this->subsection += ',' + this->sections[str];
219      this->subsection += "]";
220    }
221
222    if(removeStep){
223      errmsg << this->subsection;
224      DUCHAMPWARN("Section parsing", errmsg);
225    }
226
227    this->flagParsed = true;
228    return SUCCESS;
229 
230  }
231
232  std::string nullSection(int ndim)
233  {
234    std::stringstream ss;
235    ss << "[";
236    for(int i=0;i<ndim-1;i++) ss << "*,";
237    ss << "*]";
238    return ss.str();
239  }
240
241  bool Section::isValid()
242  {
243    /// @details A test to see whether each of the axis sections have
244    /// a positive length. If at least one of them has zero or
245    /// negative length, or if the section has not yet been parsed,
246    /// then false is returned. If everything is OK, then we get true.
247
248    bool valid = (this->numSections>0);
249    for(size_t i=0;i<this->dims.size()&&valid;i++){
250      valid = valid && dims[i]>0;
251    }
252    return valid;
253  }
254
255  Section Section::intersect(Section &other)
256  {
257    /// @details Return a Section object that is the intersection
258    /// between the current section and another. The returned section
259    /// only has its section string set, so it will need to be parsed
260    /// afterwards.
261   
262    if(this->numSections != other.numSections){
263      DUCHAMPERROR("Section::intersect", "Sizes of sections not equal - returning initial section");
264      return *this;
265    }
266
267    std::vector<std::string> outputsections(this->numSections);
268    for(size_t i=0;i<this->numSections;i++){
269      std::stringstream ss;
270      ss << std::max(this->starts[i],other.starts[i])+1 << ":" << std::min(this->getEnd(i),other.getEnd(i))+1;
271      outputsections[i] = ss.str();
272    }
273         
274    std::stringstream section;
275    section << "[" << outputsections[0];
276    for(size_t i=1;i<this->numSections;i++) section<<"," << outputsections[i];
277    section << "]";
278    duchamp::Section output;
279    output.setSection(section.str());
280    return output;
281
282  }
283
284  Section Section::intersect(long *dimAxes, int size)
285  {
286    std::vector<long> vecDim(size);
287    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
288    return this->intersect(vecDim);
289  }
290
291  Section Section::intersect(std::vector<int> dimAxes)
292  {
293    std::vector<long> vecDim(dimAxes.size());
294    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
295    return this->intersect(vecDim);
296  }
297
298  Section Section::intersect(std::vector<long> dimAxes)
299  {
300   
301    std::string nullSec = nullSection(dimAxes.size());
302    Section null(nullSec);
303    null.parse(dimAxes);
304    return this->intersect(null);
305
306  }
307
308  Section operator* (Section &lhs, Section &rhs)
309  {
310    /// @details Return a Section object that is the combination of two subsections. The second subsection indicates the pixel ranges *within* the ranges of the first, and the output is in the same global units as the first (this).
311    /// So, [10:20,20:40] * [4:7,12:15] = [13:16,31:34]
312    /// Note this is not commutative!
313   
314    if(lhs.numSections != rhs.numSections){
315      std::stringstream ss;
316      ss << "Sizes of sections not equal - you requested " << lhs.subsection << " * " << rhs.subsection << ", with " << lhs.numSections << " and " << rhs.numSections << " sections each.\n";
317      DUCHAMPERROR("Section::operator*", "Sizes of sections not equal - you requested " << lhs.subsection << " * " << rhs.subsection << ", with " << lhs.numSections << " and " << rhs.numSections << " sections each.");
318      return lhs;
319    }
320
321    std::vector<std::string> outputsections(lhs.numSections);
322    for(size_t i=0;i<lhs.numSections;i++){
323      std::stringstream ss;
324      int minval=std::min(lhs.starts[i]+rhs.starts[i],lhs.starts[i]+lhs.dims[i])+1;
325      int maxval=std::min(lhs.starts[i]+rhs.starts[i]+rhs.dims[i],lhs.starts[i]+lhs.dims[i]);
326      //      ss << lhs.starts[i]+rhs.starts[i]+1 << ":" << lhs.starts[i]+rhs.starts[i]+rhs.dims[i];
327      ss << minval << ":"<<maxval;
328      outputsections[i] = ss.str();
329    }
330         
331    std::stringstream section;
332    section << "[" << outputsections[0];
333    for(size_t i=1;i<lhs.numSections;i++) section<<"," << outputsections[i];
334    section << "]";
335    duchamp::Section output;
336    output.setSection(section.str());
337    return output;
338
339  }
340
341
342}
Note: See TracBrowser for help on using the repository browser.