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

Last change on this file was 828, checked in by MatthewWhiting, 13 years ago

Had problems if the

File size: 9.3 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  }
43
44  Section::Section(const Section& s)
45  {
46    operator=(s);
47  }
48  //--------------------------------------------
49 
50  Section& Section::operator= (const Section& s)
51  {
52    if(this == &s) return *this;
53    this->subsection  = s.subsection;
54    this->sections    = s.sections;
55    this->numSections = s.numSections;
56    this->starts      = s.starts;
57    this->dims        = s.dims;
58    return *this;
59  }
60  //--------------------------------------------
61
62  OUTCOME Section::parse(long *dimAxes, int size)
63  {
64    std::vector<long> vecDim(size);
65    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
66    return this->parse(vecDim);
67  }
68
69  OUTCOME Section::parse(std::vector<int> dimAxes)
70  {
71    std::vector<long> vecDim(dimAxes.size());
72    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
73    return this->parse(vecDim);
74  }
75
76  OUTCOME Section::parse(std::vector<long> dimAxes)
77  {
78    /// @details
79    /// This function reads the subsection string, and registers the
80    /// starting values and lengths for each dimension. The array of axis
81    /// dimensions is needed to know how long each axis really is, and
82    /// whether we have strayed over the limit or not.
83    ///
84    /// Note that steps in the subsection string are not dealt with -- a
85    /// warning message is written to the screen, and the step values are
86    /// removed from the subsection string.
87    ///
88    /// The function also does basic checks to make sure it is of the
89    /// correct format (ie. has square brackets delimiting it) and the
90    /// correct number of sections, returning a FAILURE if either of
91    /// these checks fail.
92    ///
93    /// \param dimAxes The array of axis dimensions, of which the
94    ///                 Section is a subsection.
95    /// \return SUCCESS/FAILURE (from duchamp.hh)
96
97    std::stringstream errmsg;
98
99    // First Make sure subsection has [ and ] at ends
100    if((this->subsection[0]!='[') ||
101       (this->subsection[this->subsection.size()-1]!=']')){
102      errmsg.str("");
103      errmsg << "Subsection needs to be delimited by square brackets\n"
104             << "You provided: " << this->subsection << std::endl;
105      duchampError("Section parsing",errmsg.str());
106      return FAILURE;
107    }
108
109    this->starts.clear();
110    this->dims.clear();
111 
112    this->numSections=1;
113    for(size_t i=0;i<this->subsection.size();i++)
114      if(this->subsection[i]==',') this->numSections++;
115
116    if(numSections!=dimAxes.size()){
117      errmsg.str("");
118      errmsg << "Subsection has "<<numSections
119             <<" sections, compared to a cube with "
120             << dimAxes.size() << " axes\n"
121             << "Subsection provided was: " << this->subsection << std::endl;
122      duchampError("Section parsing",errmsg.str());
123      return FAILURE;
124    }
125
126    this->starts.resize(this->numSections);
127    this->dims.resize(this->numSections);
128    this->sections.resize(this->numSections);
129
130    std::vector<std::string> tempsections(numSections);
131    // this will hold the section strings for each dimension
132    std::stringstream ss;
133    ss.str(this->subsection);
134    bool removeStep = false;
135    bool doingBorders = false;
136    std::string temp;
137
138    getline(ss,temp,'[');
139    for(size_t i=0;i<numSections-1;i++){
140      getline(ss,temp,',');
141      tempsections[i]=temp;
142    }
143    getline(ss,temp,']');
144    tempsections[numSections-1]=temp;
145
146    for(size_t str=0;str<numSections;str++){
147      if(tempsections[str]=="*"){
148        this->starts[str] = 0;
149        this->dims[str]= dimAxes[str];
150        this->sections[str] = tempsections[str];
151      }
152      else{
153        int numColon=0;
154        for(size_t i=0;i<tempsections[str].size();i++){
155          if(tempsections[str][i]==':'){
156            tempsections[str][i]=' ';
157            numColon++;
158          }
159        }
160        int a,b,c;
161        std::stringstream readString,fixedString;
162        readString.str(tempsections[str]);
163        switch(numColon){
164        case 1: // usual case
165          readString >> a >> b;
166          this->starts[str] = a-1;
167          this->dims[str] = b-a+1;
168          fixedString << a << ":" << b;
169          this->sections[str] = fixedString.str();
170          break;
171        case 0: // borders case -- so many off each border
172          readString >> a;
173          if(a>=dimAxes[str]/2){
174            errmsg.str("");
175            errmsg<< "You requested the subsection " << this->subsection
176                  << " but axis #" << str+1
177                  <<" has zero size, since its dimension is " << dimAxes[str]
178                  <<".\nI'm not going to parse this! Go and fix it.\n";
179            duchampError("Section parsing", errmsg.str());
180            return FAILURE;
181          }
182          this->starts[str] = a;
183          this->dims[str] = dimAxes[str]-2*a;
184          fixedString << this->starts[str]+1 << ":"
185                      << this->getEnd(str)+1;
186          this->sections[str] = fixedString.str();
187          doingBorders=true;
188          break;
189        case 2: // subsection involves a step
190        default:
191          readString>> a >> b >> c;
192          this->starts[str] = a-1;
193          this->dims[str] = b-a+1;
194          fixedString << a << ":" << b;
195          this->sections[str] = fixedString.str();
196          removeStep=true;
197          break;
198        }
199
200      }
201    }
202
203    if(removeStep){  // if there was a step present
204      errmsg.str("");
205      errmsg << "The subsection given is " << this->subsection <<".\n"
206             << "Duchamp is currently unable to deal with pixel steps"
207             << " in the subsection.\n"
208             << "These have been ignored, and so the subection used is ";
209    }
210
211    if(removeStep || doingBorders){
212      // rewrite subsection without any step sizes and with correct borders.
213      this->subsection = "[" + this->sections[0];
214      for(size_t str=1;str<numSections;str++)
215        this->subsection += ',' + this->sections[str];
216      this->subsection += "]";
217    }
218
219    if(removeStep){
220      errmsg << this->subsection << std::endl;
221      duchampWarning("Section parsing", errmsg.str());
222    }
223
224    return SUCCESS;
225 
226  }
227
228  std::string nullSection(int ndim)
229  {
230    std::stringstream ss;
231    ss << "[";
232    for(int i=0;i<ndim-1;i++) ss << "*,";
233    ss << "*]";
234    return ss.str();
235  }
236
237  bool Section::isValid()
238  {
239    /// @details A test to see whether each of the axis sections have
240    /// a positive length. If at least one of them has zero or
241    /// negative length, or if the section has not yet been parsed,
242    /// then false is returned. If everything is OK, then we get true.
243
244    bool valid = (this->numSections>0);
245    for(size_t i=0;i<this->dims.size()&&valid;i++){
246      valid = valid && dims[i]>0;
247    }
248    return valid;
249  }
250
251  Section Section::intersect(Section &other)
252  {
253    /// @details Return a Section object that is the intersection
254    /// between the current section and another. The returned section
255    /// only has its section string set, so it will need to be parsed
256    /// afterwards.
257   
258    if(this->numSections != other.numSections){
259      duchampError("Section::intersect", "Sizes of sections not equal - returning initial section");
260      return *this;
261    }
262
263    std::vector<std::string> outputsections(this->numSections);
264    for(size_t i=0;i<this->numSections;i++){
265      std::stringstream ss;
266      ss << std::max(this->starts[i],other.starts[i])+1 << ":" << std::min(this->getEnd(i),other.getEnd(i))+1;
267      outputsections[i] = ss.str();
268    }
269         
270    std::stringstream section;
271    section << "[" << outputsections[0];
272    for(size_t i=1;i<this->numSections;i++) section<<"," << outputsections[i];
273    section << "]";
274    duchamp::Section output;
275    output.setSection(section.str());
276    return output;
277
278  }
279
280  Section Section::intersect(long *dimAxes, int size)
281  {
282    std::vector<long> vecDim(size);
283    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
284    return this->intersect(vecDim);
285  }
286
287  Section Section::intersect(std::vector<int> dimAxes)
288  {
289    std::vector<long> vecDim(dimAxes.size());
290    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
291    return this->intersect(vecDim);
292  }
293
294  Section Section::intersect(std::vector<long> dimAxes)
295  {
296   
297    std::string nullSec = nullSection(dimAxes.size());
298    Section null(nullSec);
299    null.parse(dimAxes);
300    return this->intersect(null);
301
302  }
303
304}
Note: See TracBrowser for help on using the repository browser.