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

Last change on this file since 1190 was 1190, checked in by MatthewWhiting, 11 years ago

A better way of initialising the Section - the subsection string is set to the null string, and checks are made against that in the parsing.

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