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
RevLine 
[301]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// -----------------------------------------------------------------------
[254]29#include <string>
30#include <vector>
31#include <iostream>
32#include <sstream>
[393]33#include <duchamp/Utils/Section.hh>
34#include <duchamp/duchamp.hh>
[254]35
[378]36namespace duchamp
[365]37{
38
[378]39  Section::Section()
40  {
41    this->numSections = 0;
[879]42    this->flagParsed = false;
[378]43  }
44
45  Section::Section(const Section& s)
46  {
47    operator=(s);
48  }
49  //--------------------------------------------
[254]50 
[378]51  Section& Section::operator= (const Section& s)
52  {
53    if(this == &s) return *this;
[879]54    this->flagParsed    = s.flagParsed;
[378]55    this->subsection  = s.subsection;
[818]56    this->sections    = s.sections;
[378]57    this->numSections = s.numSections;
[818]58    this->starts      = s.starts;
[378]59    this->dims        = s.dims;
60    return *this;
61  }
62  //--------------------------------------------
[254]63
[698]64  OUTCOME Section::parse(long *dimAxes, int size)
[497]65  {
[884]66    std::vector<size_t> vecDim(size);
[497]67    for(int i=0;i<size;i++) vecDim[i] = dimAxes[i];
68    return this->parse(vecDim);
69  }
70
[884]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
[698]78  OUTCOME Section::parse(std::vector<int> dimAxes)
[639]79  {
[884]80    std::vector<size_t> vecDim(dimAxes.size());
[639]81    for(size_t i=0;i<dimAxes.size();i++) vecDim[i] = long(dimAxes[i]);
82    return this->parse(vecDim);
83  }
84
[698]85  OUTCOME Section::parse(std::vector<long> dimAxes)
[378]86  {
[884]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  {
[528]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)
[254]112
[378]113    std::stringstream errmsg;
[254]114
[378]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    }
[254]124
[378]125    this->starts.clear();
126    this->dims.clear();
[254]127 
[378]128    this->numSections=1;
[623]129    for(size_t i=0;i<this->subsection.size();i++)
[378]130      if(this->subsection[i]==',') this->numSections++;
[254]131
[378]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    }
[254]141
[378]142    this->starts.resize(this->numSections);
143    this->dims.resize(this->numSections);
[507]144    this->sections.resize(this->numSections);
[254]145
[507]146    std::vector<std::string> tempsections(numSections);
[378]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;
[254]153
[378]154    getline(ss,temp,'[');
[623]155    for(size_t i=0;i<numSections-1;i++){
[378]156      getline(ss,temp,',');
[507]157      tempsections[i]=temp;
[378]158    }
159    getline(ss,temp,']');
[507]160    tempsections[numSections-1]=temp;
[254]161
[623]162    for(size_t str=0;str<numSections;str++){
[507]163      if(tempsections[str]=="*"){
[378]164        this->starts[str] = 0;
165        this->dims[str]= dimAxes[str];
[507]166        this->sections[str] = tempsections[str];
[254]167      }
[378]168      else{
169        int numColon=0;
[623]170        for(size_t i=0;i<tempsections[str].size();i++){
[507]171          if(tempsections[str][i]==':'){
172            tempsections[str][i]=' ';
[378]173            numColon++;
174          }
[289]175        }
[378]176        int a,b,c;
177        std::stringstream readString,fixedString;
[507]178        readString.str(tempsections[str]);
[378]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;
[507]184          fixedString << a << ":" << b;
185          this->sections[str] = fixedString.str();
[378]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;
[507]202          this->sections[str] = fixedString.str();
[378]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;
[507]211          this->sections[str] = fixedString.str();
[378]212          removeStep=true;
213          break;
214        }
215
[254]216      }
[378]217    }
[254]218
[378]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 ";
[254]225    }
226
[378]227    if(removeStep || doingBorders){
228      // rewrite subsection without any step sizes and with correct borders.
[507]229      this->subsection = "[" + this->sections[0];
[623]230      for(size_t str=1;str<numSections;str++)
[507]231        this->subsection += ',' + this->sections[str];
[378]232      this->subsection += "]";
233    }
[254]234
[378]235    if(removeStep){
236      errmsg << this->subsection << std::endl;
237      duchampWarning("Section parsing", errmsg.str());
238    }
[254]239
[879]240    this->flagParsed = true;
[378]241    return SUCCESS;
242 
[254]243  }
244
[507]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
[816]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
[818]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++){
[828]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();
[818]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
[828]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
[879]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
[254]355}
Note: See TracBrowser for help on using the repository browser.