source: trunk/src/Utils/Section.cc @ 890

Last change on this file since 890 was 884, checked in by MatthewWhiting, 12 years ago

A large set of changes aimed at making the use of indexing variables consistent. We have moved to size_t as much as possible to represent the location in memory. This includes making the dimension array within DataArray? and derived classes an array of size_t variables. Still plenty of compilation warnings (principally comparing signed and unsigned variables) - these will need to be cleaned up.

File size: 11.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    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      errmsg.str("");
119      errmsg << "Subsection needs to be delimited by square brackets\n"
120             << "You provided: " << this->subsection << std::endl;
121      duchampError("Section parsing",errmsg.str());
122      return FAILURE;
123    }
124
125    this->starts.clear();
126    this->dims.clear();
127 
128    this->numSections=1;
129    for(size_t i=0;i<this->subsection.size();i++)
130      if(this->subsection[i]==',') this->numSections++;
131
132    if(numSections!=dimAxes.size()){
133      errmsg.str("");
134      errmsg << "Subsection has "<<numSections
135             <<" sections, compared to a cube with "
136             << dimAxes.size() << " axes\n"
137             << "Subsection provided was: " << this->subsection << std::endl;
138      duchampError("Section parsing",errmsg.str());
139      return FAILURE;
140    }
141
142    this->starts.resize(this->numSections);
143    this->dims.resize(this->numSections);
144    this->sections.resize(this->numSections);
145
146    std::vector<std::string> tempsections(numSections);
147    // this will hold the section strings for each dimension
148    std::stringstream ss;
149    ss.str(this->subsection);
150    bool removeStep = false;
151    bool doingBorders = false;
152    std::string temp;
153
154    getline(ss,temp,'[');
155    for(size_t i=0;i<numSections-1;i++){
156      getline(ss,temp,',');
157      tempsections[i]=temp;
158    }
159    getline(ss,temp,']');
160    tempsections[numSections-1]=temp;
161
162    for(size_t str=0;str<numSections;str++){
163      if(tempsections[str]=="*"){
164        this->starts[str] = 0;
165        this->dims[str]= dimAxes[str];
166        this->sections[str] = tempsections[str];
167      }
168      else{
169        int numColon=0;
170        for(size_t i=0;i<tempsections[str].size();i++){
171          if(tempsections[str][i]==':'){
172            tempsections[str][i]=' ';
173            numColon++;
174          }
175        }
176        int a,b,c;
177        std::stringstream readString,fixedString;
178        readString.str(tempsections[str]);
179        switch(numColon){
180        case 1: // usual case
181          readString >> a >> b;
182          this->starts[str] = a-1;
183          this->dims[str] = b-a+1;
184          fixedString << a << ":" << b;
185          this->sections[str] = fixedString.str();
186          break;
187        case 0: // borders case -- so many off each border
188          readString >> a;
189          if(a>=dimAxes[str]/2){
190            errmsg.str("");
191            errmsg<< "You requested the subsection " << this->subsection
192                  << " but axis #" << str+1
193                  <<" has zero size, since its dimension is " << dimAxes[str]
194                  <<".\nI'm not going to parse this! Go and fix it.\n";
195            duchampError("Section parsing", errmsg.str());
196            return FAILURE;
197          }
198          this->starts[str] = a;
199          this->dims[str] = dimAxes[str]-2*a;
200          fixedString << this->starts[str]+1 << ":"
201                      << this->getEnd(str)+1;
202          this->sections[str] = fixedString.str();
203          doingBorders=true;
204          break;
205        case 2: // subsection involves a step
206        default:
207          readString>> a >> b >> c;
208          this->starts[str] = a-1;
209          this->dims[str] = b-a+1;
210          fixedString << a << ":" << b;
211          this->sections[str] = fixedString.str();
212          removeStep=true;
213          break;
214        }
215
216      }
217    }
218
219    if(removeStep){  // if there was a step present
220      errmsg.str("");
221      errmsg << "The subsection given is " << this->subsection <<".\n"
222             << "Duchamp is currently unable to deal with pixel steps"
223             << " in the subsection.\n"
224             << "These have been ignored, and so the subection used is ";
225    }
226
227    if(removeStep || doingBorders){
228      // rewrite subsection without any step sizes and with correct borders.
229      this->subsection = "[" + this->sections[0];
230      for(size_t str=1;str<numSections;str++)
231        this->subsection += ',' + this->sections[str];
232      this->subsection += "]";
233    }
234
235    if(removeStep){
236      errmsg << this->subsection << std::endl;
237      duchampWarning("Section parsing", errmsg.str());
238    }
239
240    this->flagParsed = true;
241    return SUCCESS;
242 
243  }
244
245  std::string nullSection(int ndim)
246  {
247    std::stringstream ss;
248    ss << "[";
249    for(int i=0;i<ndim-1;i++) ss << "*,";
250    ss << "*]";
251    return ss.str();
252  }
253
254  bool Section::isValid()
255  {
256    /// @details A test to see whether each of the axis sections have
257    /// a positive length. If at least one of them has zero or
258    /// negative length, or if the section has not yet been parsed,
259    /// then false is returned. If everything is OK, then we get true.
260
261    bool valid = (this->numSections>0);
262    for(size_t i=0;i<this->dims.size()&&valid;i++){
263      valid = valid && dims[i]>0;
264    }
265    return valid;
266  }
267
268  Section Section::intersect(Section &other)
269  {
270    /// @details Return a Section object that is the intersection
271    /// between the current section and another. The returned section
272    /// only has its section string set, so it will need to be parsed
273    /// afterwards.
274   
275    if(this->numSections != other.numSections){
276      duchampError("Section::intersect", "Sizes of sections not equal - returning initial section");
277      return *this;
278    }
279
280    std::vector<std::string> outputsections(this->numSections);
281    for(size_t i=0;i<this->numSections;i++){
282      std::stringstream ss;
283      ss << std::max(this->starts[i],other.starts[i])+1 << ":" << std::min(this->getEnd(i),other.getEnd(i))+1;
284      outputsections[i] = ss.str();
285    }
286         
287    std::stringstream section;
288    section << "[" << outputsections[0];
289    for(size_t i=1;i<this->numSections;i++) section<<"," << outputsections[i];
290    section << "]";
291    duchamp::Section output;
292    output.setSection(section.str());
293    return output;
294
295  }
296
297  Section Section::intersect(long *dimAxes, int size)
298  {
299    std::vector<long> vecDim(size);
300    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
301    return this->intersect(vecDim);
302  }
303
304  Section Section::intersect(std::vector<int> dimAxes)
305  {
306    std::vector<long> vecDim(dimAxes.size());
307    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
308    return this->intersect(vecDim);
309  }
310
311  Section Section::intersect(std::vector<long> dimAxes)
312  {
313   
314    std::string nullSec = nullSection(dimAxes.size());
315    Section null(nullSec);
316    null.parse(dimAxes);
317    return this->intersect(null);
318
319  }
320
321  Section operator* (Section &lhs, Section &rhs)
322  {
323    /// @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).
324    /// So, [10:20,20:40] * [4:7,12:15] = [13:16,31:34]
325    /// Note this is not commutative!
326   
327    if(lhs.numSections != rhs.numSections){
328      std::stringstream ss;
329      ss << "Sizes of sections not equal - you requested " << lhs.subsection << " * " << rhs.subsection << ", with " << lhs.numSections << " and " << rhs.numSections << " sections each.\n";
330      duchampError("Section::operator*", ss.str());
331      return lhs;
332    }
333
334    std::vector<std::string> outputsections(lhs.numSections);
335    for(size_t i=0;i<lhs.numSections;i++){
336      std::stringstream ss;
337      int minval=std::min(lhs.starts[i]+rhs.starts[i],lhs.starts[i]+lhs.dims[i])+1;
338      int maxval=std::min(lhs.starts[i]+rhs.starts[i]+rhs.dims[i],lhs.starts[i]+lhs.dims[i]);
339      //      ss << lhs.starts[i]+rhs.starts[i]+1 << ":" << lhs.starts[i]+rhs.starts[i]+rhs.dims[i];
340      ss << minval << ":"<<maxval;
341      outputsections[i] = ss.str();
342    }
343         
344    std::stringstream section;
345    section << "[" << outputsections[0];
346    for(size_t i=1;i<lhs.numSections;i++) section<<"," << outputsections[i];
347    section << "]";
348    duchamp::Section output;
349    output.setSection(section.str());
350    return output;
351
352  }
353
354
355}
Note: See TracBrowser for help on using the repository browser.