Line data Source code
1 : #include <stdcasa/UtilJ.h>
2 : #include <msvis/MSVis/ViFrequencySelection.h>
3 : #include <msvis/MSVis/MSUtil.h>
4 : #include <casacore/ms/MSSel/MSSelection.h>
5 :
6 : #include <utility>
7 :
8 : using namespace std;
9 :
10 : using namespace casacore;
11 : namespace casa { //# NAMESPACE CASA - BEGIN
12 :
13 : namespace vi {
14 :
15 : void
16 18 : FrequencySelection::addCorrelationSlices (const Vector <Vector <Slice> > & slices)
17 : {
18 18 : correlationSlices_p = slices;
19 18 : }
20 :
21 : void
22 19 : FrequencySelection::filterByWindow (Int windowId) const
23 : {
24 19 : filterWindowId_p = windowId;
25 19 : }
26 :
27 : Int
28 0 : FrequencySelection::filterWindow() const
29 : {
30 0 : return filterWindowId_p;
31 : }
32 :
33 : String
34 0 : FrequencySelection::frameName (Int referenceFrame)
35 : {
36 0 : String result;
37 :
38 0 : if (referenceFrame >= 0 && referenceFrame < MFrequency::N_Types){
39 :
40 0 : result = MFrequency::showType (referenceFrame);
41 : }
42 0 : else if (referenceFrame == ByChannel){
43 : }
44 : else{
45 :
46 0 : ThrowIf (true, String::format ("Unknown frame of reference: id=%d", referenceFrame));
47 : }
48 :
49 0 : return result;
50 0 : }
51 :
52 : Vector <Slice>
53 19 : FrequencySelection::getCorrelationSlices (Int polarizationId) const
54 : {
55 19 : if (correlationSlices_p.nelements() == 0){
56 1 : return Vector<Slice> (); // empty vector implies all elements
57 : }
58 :
59 18 : Assert (polarizationId >= 0 && polarizationId < (int) correlationSlices_p.nelements());
60 :
61 18 : return correlationSlices_p [polarizationId];
62 : }
63 :
64 : Int
65 765387 : FrequencySelection::getFrameOfReference () const
66 : {
67 765387 : return referenceFrame_p;
68 : }
69 :
70 : void
71 0 : FrequencySelectionUsingChannels::add (Int spectralWindow, Int firstChannel,
72 : Int nChannels, Int increment)
73 : {
74 0 : Assert (spectralWindow >= 0);
75 0 : Assert (firstChannel >= 0);
76 0 : Assert (nChannels > 0);
77 0 : Assert (increment != 0 || nChannels == 1);
78 :
79 0 : elements_p.push_back (Element (spectralWindow, firstChannel, nChannels, increment));
80 0 : }
81 :
82 55 : FrequencySelectionUsingChannels::FrequencySelectionUsingChannels (const FrequencySelectionUsingChannels & other)
83 : : FrequencySelection (other),
84 55 : elements_p (other.elements_p),
85 55 : filtered_p (other.filtered_p),
86 110 : refinements_p (nullptr)
87 : {
88 55 : if (other.refinements_p){
89 0 : refinements_p.reset (new FrequencySelectionUsingFrame (* other.refinements_p.get()));
90 : }
91 55 : }
92 :
93 : void
94 18 : FrequencySelectionUsingChannels::add (const MSSelection & msSelectionConst,
95 : const MeasurementSet * ms)
96 : {
97 : // Add in the frequency selection from the provided MSSelection object
98 : //
99 : // Meanings of columns in the "matrix" (actually used as a parallel array)
100 :
101 : enum {SpectralWindowId, FirstChannel, StopChannel, Step};
102 :
103 18 : MSSelection & msSelection = const_cast <MSSelection &> (msSelectionConst);
104 : // Needed because many msSelection methods are not const for some reason
105 :
106 18 : Matrix<Int> channelList = msSelection.getChanList();
107 :
108 18 : for (Int row = 0; row < (Int) channelList.nrow(); row ++){
109 :
110 0 : Int nChannels = channelList (row, StopChannel) - channelList (row, FirstChannel);
111 0 : nChannels = nChannels / channelList (row, Step) + 1;
112 :
113 0 : add (channelList (row, SpectralWindowId),
114 0 : channelList (row, FirstChannel),
115 : nChannels,
116 0 : channelList (row, Step));
117 : }
118 :
119 : // Extract and add the correlation selection.
120 :
121 18 : Vector <Vector<Slice> > correlationSlices;
122 18 : msSelection.getCorrSlices (correlationSlices, ms);
123 :
124 18 : addCorrelationSlices (correlationSlices);
125 :
126 18 : }
127 :
128 : FrequencySelectionUsingChannels::const_iterator
129 19 : FrequencySelectionUsingChannels::begin () const
130 : {
131 19 : filtered_p.clear();
132 :
133 19 : for (Elements::const_iterator i = elements_p.begin();
134 19 : i != elements_p.end();
135 0 : i ++){
136 :
137 0 : if (filterWindow () < 0 || i->spectralWindow_p == filterWindow()){
138 0 : filtered_p.push_back (* i);
139 : }
140 : }
141 :
142 19 : return filtered_p.begin();
143 : }
144 :
145 :
146 : FrequencySelection *
147 55 : FrequencySelectionUsingChannels::clone () const
148 : {
149 55 : return new FrequencySelectionUsingChannels (* this);
150 : }
151 :
152 : Bool
153 2028 : FrequencySelectionUsingChannels::empty () const
154 : {
155 2028 : return elements_p.empty();
156 : }
157 :
158 :
159 : FrequencySelectionUsingChannels::const_iterator
160 19 : FrequencySelectionUsingChannels::end () const
161 : {
162 19 : return filtered_p.end();
163 : }
164 :
165 : set<int>
166 37 : FrequencySelectionUsingChannels::getSelectedWindows () const
167 : {
168 37 : set <int> result;
169 37 : for (Elements::const_iterator i = elements_p.begin();
170 37 : i != elements_p.end();
171 0 : i ++){
172 :
173 0 : result.insert (i->spectralWindow_p);
174 :
175 : }
176 :
177 37 : return result;
178 0 : }
179 :
180 : Int
181 0 : FrequencySelectionUsingChannels::getNChannels (Int spectralWindowId) const
182 : {
183 :
184 0 : Int result = 0;
185 :
186 0 : if (elements_p.empty()){
187 :
188 : }
189 : else {
190 :
191 0 : for (Elements::const_iterator i = elements_p.begin();
192 0 : i != elements_p.end();
193 0 : i ++){
194 :
195 0 : if (i->spectralWindow_p == spectralWindowId){
196 0 : result += i->nChannels_p;
197 : }
198 : }
199 : }
200 0 : return result;
201 : }
202 :
203 : void
204 0 : FrequencySelectionUsingChannels::refine (const FrequencySelectionUsingFrame & refiningSelection)
205 : {
206 0 : refinements_p.reset (new FrequencySelectionUsingFrame (refiningSelection));
207 0 : }
208 :
209 : void
210 0 : FrequencySelectionUsingChannels::applyRefinement (std::function <casacore::Slice (int, double, double)> spwcFetcher) const
211 : {
212 : // Loop through each of the parts of the refining selection.
213 :
214 0 : for (auto refiningElement : * refinements_p.get()){
215 :
216 : // Get the spectral window and then look for parts of the original selection which
217 : // apply to the same spectral window.
218 :
219 0 : int spectralWindow = refiningElement.getSpectralWindow();
220 :
221 0 : for (auto & originalSelection : elements_p){
222 :
223 0 : if (originalSelection.spectralWindow_p != spectralWindow){
224 0 : continue; // wrong window, so skip it
225 : }
226 :
227 : // Convert the element into channels in the current spectral window.
228 :
229 0 : Slice s = spwcFetcher (spectralWindow,
230 : refiningElement.getBeginFrequency(),
231 : refiningElement.getEndFrequency());
232 :
233 0 : int firstRefiningChannel = s.start();
234 0 : int lastRefiningChannel = s.end();
235 :
236 : // Refine the original selection so that it only applies to the intersection between
237 : // the refining channel range and the original range.
238 : //
239 : // This only applies if the two intersect; otherwise the original selection element
240 : // is left unchanged.
241 :
242 0 : refineSelection (originalSelection, firstRefiningChannel, lastRefiningChannel);
243 : }
244 : }
245 :
246 0 : refinements_p.reset (nullptr); // All done so destroy them.
247 0 : }
248 :
249 : bool
250 19 : FrequencySelectionUsingChannels::refinementNeeded () const
251 : {
252 19 : return !! refinements_p;
253 : }
254 :
255 : void
256 0 : FrequencySelectionUsingChannels::refineSelection (FrequencySelectionUsingChannels::Element & originalElement,
257 : int firstRefiningChannel, int lastRefiningChannel) const
258 : {
259 0 : int originalLastChannel = originalElement.firstChannel_p +
260 0 : (originalElement.nChannels_p - 1) * originalElement.increment_p;
261 :
262 : // If the two ranges do not overlap, then skip this operation since there's not basis
263 : // for refinement. Presumably the refinement operation will apply to a different
264 : // selection range in this spectral window.
265 :
266 0 : if (firstRefiningChannel > originalLastChannel ||
267 0 : lastRefiningChannel < originalElement.firstChannel_p)
268 : {
269 0 : return; // No overlap, so refinement not possible
270 : }
271 :
272 : // Refine the channel interval of the existing selection.
273 :
274 0 : int newFirstChannel = max (originalElement.firstChannel_p, firstRefiningChannel);
275 0 : int newLastChannel = min (originalLastChannel, lastRefiningChannel);
276 :
277 0 : originalElement.firstChannel_p = newFirstChannel;
278 0 : originalElement.nChannels_p = (newLastChannel - newFirstChannel) / originalElement.increment_p + 1;
279 : }
280 :
281 : size_t
282 0 : FrequencySelectionUsingChannels::size () const
283 : {
284 0 : return elements_p.size();
285 : }
286 :
287 :
288 : String
289 0 : FrequencySelectionUsingChannels::toString () const
290 : {
291 0 : String s = String::format ("{frame='%s' {", frameName (getFrameOfReference()).c_str());
292 :
293 0 : for (Elements::const_iterator e = elements_p.begin();
294 0 : e != elements_p.end();
295 0 : e ++){
296 :
297 0 : s += String::format ("(spw=%d, 1st=%d, n=%d, inc=%d)",
298 0 : e->spectralWindow_p,
299 0 : e->firstChannel_p,
300 0 : e->nChannels_p,
301 0 : e->increment_p);
302 : }
303 0 : s += "}}";
304 :
305 0 : return s;
306 0 : }
307 :
308 0 : FrequencySelectionUsingFrame::FrequencySelectionUsingFrame (MFrequency::Types frameOfReference)
309 0 : : FrequencySelection (frameOfReference)
310 0 : {}
311 :
312 : void
313 0 : FrequencySelectionUsingFrame::add (Int spectralWindow, Double bottomFrequency,
314 : Double topFrequency)
315 : {
316 0 : elements_p.push_back (Element (spectralWindow, bottomFrequency, topFrequency));
317 0 : }
318 :
319 : //void
320 : //FrequencySelectionUsingFrame::add (Int spectralWindow, Double bottomFrequency,
321 : // Double topFrequency, Double increment)
322 : //{
323 : // elements_p.push_back (Elements (spectralWindow, bottomFrequency, topFrequency, increment));
324 : //}
325 :
326 :
327 : FrequencySelectionUsingFrame::const_iterator
328 0 : FrequencySelectionUsingFrame::begin () const
329 : {
330 0 : filtered_p.clear();
331 :
332 0 : for (Elements::const_iterator i = elements_p.begin();
333 0 : i != elements_p.end();
334 0 : i ++){
335 :
336 0 : if (filterWindow () < 0 || i->spectralWindow_p == filterWindow()){
337 0 : filtered_p.push_back (* i);
338 : }
339 : }
340 :
341 0 : return filtered_p.begin();
342 : }
343 :
344 : FrequencySelection *
345 0 : FrequencySelectionUsingFrame::clone () const
346 : {
347 0 : return new FrequencySelectionUsingFrame (* this);
348 : }
349 :
350 : Bool
351 0 : FrequencySelectionUsingFrame::empty () const
352 : {
353 0 : return elements_p.empty();
354 : }
355 :
356 :
357 : FrequencySelectionUsingFrame::const_iterator
358 0 : FrequencySelectionUsingFrame::end () const
359 : {
360 0 : return filtered_p.end();
361 : }
362 :
363 : set<int>
364 0 : FrequencySelectionUsingFrame::getSelectedWindows () const
365 : {
366 0 : set<int> result;
367 0 : for (Elements::const_iterator i = elements_p.begin();
368 0 : i != elements_p.end();
369 0 : i ++){
370 :
371 0 : result.insert (i->spectralWindow_p);
372 : }
373 :
374 0 : return result;
375 0 : }
376 :
377 : Double
378 0 : FrequencySelectionUsingFrame::Element::getBeginFrequency () const
379 : {
380 0 : return beginFrequency_p;
381 : }
382 :
383 : Double
384 0 : FrequencySelectionUsingFrame::Element::getEndFrequency () const
385 : {
386 0 : return endFrequency_p;
387 : }
388 :
389 : int
390 0 : FrequencySelectionUsingFrame::Element::getSpectralWindow () const
391 : {
392 0 : return spectralWindow_p;
393 : }
394 :
395 : String
396 0 : FrequencySelectionUsingFrame::toString () const
397 : {
398 0 : String s = String::format ("{frame='%s' {", frameName (getFrameOfReference()).c_str());
399 :
400 0 : for (Elements::const_iterator e = elements_p.begin();
401 0 : e != elements_p.end();
402 0 : e ++){
403 :
404 0 : s += String::format ("(spw=%d, 1st=%g, n=%g, inc=%g)",
405 0 : e->spectralWindow_p,
406 0 : e->beginFrequency_p,
407 0 : e->endFrequency_p,
408 0 : e->increment_p);
409 : }
410 :
411 0 : s += "}}";
412 :
413 0 : return s;
414 0 : }
415 0 : std::map<int, std::pair<int, int> > FrequencySelectionUsingFrame::getChannelRange (const casacore::MeasurementSet& ms) const {
416 :
417 0 : map<int, pair<int, int> > retval;
418 0 : MFrequency::Types freqframe=MFrequency::castType(getFrameOfReference());
419 0 : Vector<Int> outspw;
420 0 : Vector<Int> outstart;
421 0 : Vector<Int> outnchan;
422 0 : for (Elements::const_iterator j = elements_p.begin(); j != elements_p.end(); j++){
423 : //cerr << "elements " << (j->spectralWindow_p) << " " << (j->beginFrequency_p)<< " " << (j->endFrequency_p)<< endl;
424 :
425 : Int outstart;
426 : Int outnchan;
427 0 : Int spw=j->spectralWindow_p;
428 0 : Double begFreq=j->beginFrequency_p;
429 0 : Double endFreq=j->endFrequency_p;
430 : //cerr << "spw " << spw << " BegFreq " << begFreq << " EndFreq " << endFreq << endl;
431 0 : MSUtil::getChannelRangeFromFreqRange(outstart,
432 : outnchan, ms, spw, begFreq, endFreq, 1.0e-6,freqframe);
433 0 : if(outstart > -1){
434 0 : auto old=retval.find(spw);
435 0 : if(old != retval.end()){
436 0 : pair<int, int> oldrange=old->second;
437 0 : if(oldrange.second >= outstart){
438 0 : if(outnchan > (oldrange.second-outstart+1+oldrange.first))
439 0 : oldrange.first=outnchan;
440 : else
441 0 : oldrange.first=oldrange.second-outstart+1+oldrange.first;
442 0 : oldrange.second=outstart;
443 : }
444 : else{
445 0 : if((oldrange.first -(outstart - oldrange.second)) <outnchan){
446 0 : oldrange.first=outnchan+outstart-oldrange.second+1;
447 : }
448 : }
449 0 : old->second=oldrange;
450 : }
451 : else{
452 :
453 0 : retval[int(spw)]=make_pair(int(outnchan), int(outstart));
454 : }
455 : }
456 : }
457 0 : return retval;
458 :
459 0 : }
460 37 : FrequencySelections::FrequencySelections ()
461 37 : : filterWindow_p (-1)
462 37 : {}
463 :
464 18 : FrequencySelections::FrequencySelections (const FrequencySelections & other)
465 : {
466 18 : for (Selections::const_iterator s = other.selections_p.begin();
467 36 : s != other.selections_p.end(); s++){
468 18 : selections_p.push_back ((* s)->clone());
469 : }
470 :
471 18 : filterWindow_p = other.filterWindow_p;
472 18 : selectedWindows_p = other.selectedWindows_p;
473 18 : }
474 :
475 110 : FrequencySelections::~FrequencySelections ()
476 : {
477 55 : for (Selections::const_iterator s = selections_p.begin();
478 110 : s != selections_p.end(); s++){
479 55 : delete (* s);
480 : }
481 55 : }
482 :
483 : void
484 37 : FrequencySelections::add (const FrequencySelection & selection)
485 : {
486 37 : if (! selections_p.empty()){
487 0 : ThrowIf (getFrameOfReference() != selection.getFrameOfReference(),
488 : String::format ("Frequency selection #%d has incompatible frame of reference %d:%s "
489 : "(!= %d:%s)",
490 : selections_p.size() + 1,
491 : selection.getFrameOfReference(),
492 : FrequencySelection::frameName (selection.getFrameOfReference()).c_str(),
493 : getFrameOfReference(),
494 : FrequencySelection::frameName (getFrameOfReference()).c_str()));
495 : }
496 :
497 37 : selections_p.push_back (selection.clone());
498 37 : Int msIndex = selections_p.size() - 1;
499 37 : set<int> windows = selection.getSelectedWindows();
500 :
501 37 : for (set<int>::const_iterator w = windows.begin(); w != windows.end(); w++){
502 0 : selectedWindows_p.insert (make_pair (msIndex, * w));
503 : }
504 :
505 37 : }
506 :
507 : FrequencySelections *
508 18 : FrequencySelections::clone () const
509 : {
510 18 : return new FrequencySelections (* this);
511 : }
512 :
513 : const FrequencySelection &
514 380250 : FrequencySelections::get (Int msIndex) const
515 : {
516 380250 : if (selections_p.empty()){
517 0 : return defaultSelection_p;
518 : }
519 :
520 380250 : ThrowIf (msIndex < 0 || msIndex >= (int) selections_p.size(),
521 : String::format ("MS index, %d, out of bounds [0,%d]", msIndex, selections_p.size() - 1));
522 :
523 380250 : return * selections_p [msIndex];
524 : }
525 :
526 :
527 : Int
528 385118 : FrequencySelections::getFrameOfReference () const
529 : {
530 385118 : if (selections_p.empty()){
531 0 : return FrequencySelection::ByChannel;
532 : }
533 : else {
534 385118 : return selections_p.front()->getFrameOfReference();
535 : }
536 : }
537 :
538 : Bool
539 2028 : FrequencySelections::isSpectralWindowSelected (Int msIndex, Int spectralWindowId) const
540 : {
541 : // Empty selections means everything is selected
542 :
543 2028 : if (selections_p.empty()){
544 0 : return true;
545 : }
546 :
547 2028 : Assert (msIndex >= 0 && msIndex < (int) selections_p.size() && selections_p [msIndex] != 0);
548 :
549 2028 : if (selections_p [msIndex]->empty()){
550 2028 : return true;
551 : }
552 :
553 : SelectedWindows::const_iterator swi =
554 0 : selectedWindows_p.find (make_pair (msIndex, spectralWindowId));
555 :
556 0 : return swi != selectedWindows_p.end();
557 : }
558 :
559 :
560 : Int
561 18 : FrequencySelections::size () const
562 : {
563 18 : return (Int) selections_p.size();
564 : }
565 :
566 : } // end namespace vi
567 :
568 : using namespace casacore;
569 : } // end namespace casa
|