Line data Source code
1 : //# AsciiRegionFile.cc
2 : //# Copyright (C) 1998,1999,2000,2001
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 :
27 : #include <imageanalysis/Annotations/RegionTextList.h>
28 :
29 : #include <casacore/casa/OS/File.h>
30 : #include <imageanalysis/Annotations/AnnRegion.h>
31 : #include <casacore/images/Regions/WCDifference.h>
32 : #include <casacore/casa/BasicSL/STLIO.h>
33 :
34 : using namespace casacore;
35 : namespace casa {
36 :
37 0 : RegionTextList::RegionTextList() {}
38 :
39 :
40 0 : RegionTextList::RegionTextList(
41 : const CoordinateSystem& csys,
42 : const IPosition shape
43 0 : ) : _csys(csys), _shape(shape), _canGetRegion(true) {}
44 :
45 34 : RegionTextList::RegionTextList(
46 : const String& filename, const CoordinateSystem& csys,
47 : const IPosition shape,
48 : const String& prependRegion, const String& globalOverrideChans, const String& globalOverrrideStokes,
49 : const Int requireAtLeastThisVersion, Bool verbose, Bool requireImageRegion
50 34 : ) : _csys(csys), _shape(shape), _canGetRegion(true) {
51 : RegionTextParser parser(
52 : filename, csys, shape, requireAtLeastThisVersion,
53 : prependRegion,
54 : globalOverrideChans, globalOverrrideStokes,
55 : verbose, requireImageRegion
56 34 : );
57 29 : const auto lines = parser.getLines();
58 186 : for (const auto& line: lines) {
59 157 : addLine(line);
60 : }
61 64 : }
62 :
63 39 : RegionTextList::RegionTextList(
64 : const CoordinateSystem& csys, const String& text,
65 : const IPosition shape, const String& prependRegion,
66 : const String& globalOverrideChans, const String& globalOverrrideStokes,
67 : Bool verbose, Bool requireImageRegion
68 39 : ) : _csys(csys), _shape(shape), _canGetRegion(true) {
69 : RegionTextParser parser(
70 : csys, shape, text, prependRegion, globalOverrideChans,
71 : globalOverrrideStokes, verbose, requireImageRegion
72 39 : );
73 38 : const auto lines = parser.getLines();
74 78 : for (const auto& line: lines) {
75 40 : addLine(line);
76 : }
77 45 : }
78 :
79 67 : RegionTextList::~RegionTextList() {}
80 :
81 197 : void RegionTextList::addLine(const AsciiAnnotationFileLine& line) {
82 197 : const auto x = line;
83 197 : _lines.resize(_lines.size()+1, true);
84 197 : _lines[_lines.size()-1] = x;
85 197 : if (x.getType() == AsciiAnnotationFileLine::ANNOTATION && _canGetRegion) {
86 138 : const auto annotation = x.getAnnotationBase();
87 138 : if (annotation->isRegion()) {
88 138 : const auto *region = dynamic_cast<const AnnRegion *>(annotation.get());
89 138 : if (! region->isAnnotationOnly()) {
90 138 : auto wcregion = region->getRegion2();
91 138 : if (region->isDifference() && _regions.size() == 0) {
92 0 : Vector<Double> blc, trc;
93 0 : _csys.toWorld(blc, IPosition(_csys.nPixelAxes(), 0));
94 0 : _csys.toWorld(trc, _shape);
95 0 : Vector<Quantity> qblc(blc.size()), qtrc(trc.size());
96 0 : const auto wUnits = _csys.worldAxisUnits();
97 0 : Vector<Int> absRel(blc.size(), RegionType::Abs);
98 0 : for (uInt i=0; i<qblc.size(); i++) {
99 0 : qblc[i] = Quantity(blc[i], wUnits[i]);
100 0 : qtrc[i] = Quantity(blc[i], wUnits[i]);
101 : }
102 0 : _regions.push_back(
103 0 : std::shared_ptr<const WCRegion>(
104 0 : new WCBox(qblc, qtrc, _csys, absRel)
105 : )
106 : );
107 0 : _union.push_back(true);
108 0 : }
109 138 : _regions.push_back(wcregion);
110 138 : _union.push_back(! region->isDifference());
111 138 : _composite = NULL;
112 138 : }
113 : }
114 138 : }
115 197 : }
116 :
117 67 : Record RegionTextList::regionAsRecord() const {
118 67 : ThrowIf(_regions.size() == 0, "No regions found");
119 134 : return getRegion()->toRecord("");
120 : }
121 :
122 67 : CountedPtr<const WCRegion> RegionTextList::getRegion() const {
123 67 : if (_composite) {
124 0 : return _composite;
125 : }
126 67 : ThrowIf(
127 : ! _canGetRegion,
128 : "Object constructed with too little information "
129 : "for forming composite region. Use another constructor."
130 : );
131 67 : if (_regions.size() == 0) {
132 0 : return nullptr;
133 : }
134 67 : if (_regions.size() == 1) {
135 47 : _composite = _regions[0];
136 47 : return _composite;
137 : }
138 20 : const auto end = _union.cend();
139 20 : const auto foundDifference = std::find(_union.cbegin(), end, false) != end;
140 20 : PtrBlock<const WCRegion *> unionRegions;
141 20 : if (! foundDifference) {
142 : // no complementary regions, just union the whole lot
143 19 : unionRegions.resize(_regions.size());
144 108 : for (uInt i=0; i<_regions.size(); ++i) {
145 89 : unionRegions[i] = _regions[i].get();
146 : }
147 19 : _composite.reset(new WCUnion(false, unionRegions));
148 19 : return _composite;
149 : }
150 1 : uInt count = 0;
151 3 : for (const auto isUnion: _union) {
152 2 : if (isUnion) {
153 1 : auto newSize = unionRegions.size() + 1;
154 1 : unionRegions.resize(newSize);
155 1 : unionRegions[newSize - 1] = _regions[count].get();
156 : }
157 : else {
158 1 : WCUnion myUnion(false, unionRegions);
159 1 : const WCDifference *myDiff = new WCDifference(myUnion, *_regions[count]);
160 : // _ptrMgr is used solely for pointer management, so that the pointers are
161 : // deleted when this object goes out of scope, because PtrBlocks do no
162 : // memory management
163 1 : _ptrMgr.push_back(std::shared_ptr<const WCDifference>(myDiff));
164 1 : unionRegions.resize(1, true);
165 1 : unionRegions[0] = myDiff;
166 1 : }
167 2 : ++count;
168 : }
169 1 : if (unionRegions.size() == 1) {
170 1 : _composite = _ptrMgr[_ptrMgr.size() - 1];
171 : }
172 : else {
173 0 : _composite.reset(new WCUnion(false, unionRegions));
174 : }
175 1 : return _composite;
176 20 : }
177 :
178 0 : uInt RegionTextList::nLines() const {
179 0 : return _lines.size();
180 : }
181 :
182 0 : AsciiAnnotationFileLine RegionTextList::lineAt(
183 : const uInt i
184 : ) const {
185 0 : ThrowIf(i >= _lines.size(), "Index out of range");
186 0 : return _lines[i];
187 : }
188 :
189 0 : ostream& RegionTextList::print(ostream& os) const {
190 0 : const auto vString = String::toString(RegionTextParser::CURRENT_VERSION);
191 0 : os << "#CRTFv" + vString
192 0 : << " CASA Region Text Format version "
193 0 : << vString << endl;
194 0 : for (
195 0 : auto iter=_lines.cbegin();
196 0 : iter != _lines.cend(); iter++
197 : ) {
198 0 : if (
199 0 : iter == _lines.cbegin()
200 0 : && iter->getType() == AsciiAnnotationFileLine::COMMENT
201 0 : && iter->getComment().contains(
202 0 : Regex(RegionTextParser::MAGIC.regexp() + "v[0-9]+")
203 : )
204 : ) {
205 : // skip writing header line if it already exists, we write
206 : // our own here to avoid clashes with previous spec versions
207 0 : continue;
208 : }
209 0 : os << *iter << endl;
210 : }
211 0 : return os;
212 0 : }
213 :
214 : }
|